awaitly 1.31.0 → 1.32.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/adapters.cjs +2 -2
- package/dist/adapters.cjs.map +1 -1
- package/dist/adapters.d.cts +3 -1
- package/dist/adapters.d.ts +3 -1
- package/dist/adapters.js +2 -2
- package/dist/adapters.js.map +1 -1
- package/dist/batch.cjs +2 -2
- package/dist/batch.cjs.map +1 -1
- package/dist/batch.d.cts +3 -1
- package/dist/batch.d.ts +3 -1
- package/dist/batch.js +2 -2
- package/dist/batch.js.map +1 -1
- package/dist/circuit-breaker.cjs +2 -2
- package/dist/circuit-breaker.cjs.map +1 -1
- package/dist/circuit-breaker.d.cts +3 -1
- package/dist/circuit-breaker.d.ts +3 -1
- package/dist/circuit-breaker.js +2 -2
- package/dist/circuit-breaker.js.map +1 -1
- package/dist/conditional.d.cts +3 -1
- package/dist/conditional.d.ts +3 -1
- package/dist/core.cjs +2 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +2 -1
- package/dist/core.d.ts +2 -1
- package/dist/core.js +2 -2
- package/dist/core.js.map +1 -1
- package/dist/diagnostics.cjs +8 -0
- package/dist/diagnostics.cjs.map +1 -0
- package/dist/diagnostics.d.cts +67 -0
- package/dist/diagnostics.d.ts +67 -0
- package/dist/diagnostics.js +8 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/durable.cjs +3 -3
- package/dist/durable.cjs.map +1 -1
- package/dist/durable.d.cts +8 -361
- package/dist/durable.d.ts +8 -361
- package/dist/durable.js +3 -3
- package/dist/durable.js.map +1 -1
- package/dist/engine.cjs +11 -0
- package/dist/engine.cjs.map +1 -0
- package/dist/engine.d.cts +114 -0
- package/dist/engine.d.ts +114 -0
- package/dist/engine.js +11 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors-entry-CMH73Eym.d.cts +339 -0
- package/dist/errors-entry-DOt5UUl4.d.ts +339 -0
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +2 -318
- package/dist/errors.d.ts +2 -318
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/fetch.cjs +2 -2
- package/dist/fetch.cjs.map +1 -1
- package/dist/fetch.d.cts +3 -1
- package/dist/fetch.d.ts +3 -1
- package/dist/fetch.js +2 -2
- package/dist/fetch.js.map +1 -1
- package/dist/functional.cjs +1 -1
- package/dist/functional.cjs.map +1 -1
- package/dist/functional.d.cts +2 -0
- package/dist/functional.d.ts +2 -0
- package/dist/functional.js +1 -1
- package/dist/functional.js.map +1 -1
- package/dist/{guards-Cujq_17E.d.cts → guards-B79mP5Q8.d.cts} +3 -3
- package/dist/{guards-rK0_ZPJk.d.ts → guards-BUq6NJCM.d.ts} +3 -3
- package/dist/{hitl-Cqyu9HqC.d.cts → hitl-BCqkMAHw.d.cts} +2 -2
- package/dist/{hitl-DtewAZuT.d.ts → hitl-BZtPx0aU.d.ts} +2 -2
- package/dist/hitl.cjs +2 -2
- package/dist/hitl.cjs.map +1 -1
- package/dist/hitl.d.cts +9 -6
- package/dist/hitl.d.ts +9 -6
- package/dist/hitl.js +2 -2
- package/dist/hitl.js.map +1 -1
- package/dist/index-BVUAOWGG.d.ts +417 -0
- package/dist/index-CQnpmUcC.d.cts +417 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/otel.cjs +1 -1
- package/dist/otel.cjs.map +1 -1
- package/dist/otel.d.cts +3 -1
- package/dist/otel.d.ts +3 -1
- package/dist/otel.js +1 -1
- package/dist/otel.js.map +1 -1
- package/dist/{persistence-entry-BlWCtxSV.d.ts → persistence-entry-ClFhxd2Q.d.ts} +11 -5
- package/dist/{persistence-entry-D4z7BXV_.d.cts → persistence-entry-jflY61az.d.cts} +11 -5
- package/dist/persistence.d.cts +6 -3
- package/dist/persistence.d.ts +6 -3
- package/dist/policies.d.cts +3 -1
- package/dist/policies.d.ts +3 -1
- package/dist/ratelimit.cjs +2 -2
- package/dist/ratelimit.cjs.map +1 -1
- package/dist/ratelimit.d.cts +3 -1
- package/dist/ratelimit.d.ts +3 -1
- package/dist/ratelimit.js +2 -2
- package/dist/ratelimit.js.map +1 -1
- package/dist/reliability.cjs +2 -2
- package/dist/reliability.cjs.map +1 -1
- package/dist/reliability.d.cts +3 -1
- package/dist/reliability.d.ts +3 -1
- package/dist/reliability.js +2 -2
- package/dist/reliability.js.map +1 -1
- package/dist/resolver.cjs +2 -2
- package/dist/resolver.cjs.map +1 -1
- package/dist/resolver.d.cts +5 -3
- package/dist/resolver.d.ts +5 -3
- package/dist/resolver.js +2 -2
- package/dist/resolver.js.map +1 -1
- package/dist/resource.cjs +2 -2
- package/dist/resource.cjs.map +1 -1
- package/dist/resource.d.cts +3 -1
- package/dist/resource.d.ts +3 -1
- package/dist/resource.js +2 -2
- package/dist/resource.js.map +1 -1
- package/dist/result/retry.cjs +1 -1
- package/dist/result/retry.cjs.map +1 -1
- package/dist/result/retry.d.cts +2 -0
- package/dist/result/retry.d.ts +2 -0
- package/dist/result/retry.js +1 -1
- package/dist/result/retry.js.map +1 -1
- package/dist/result.cjs +1 -1
- package/dist/result.cjs.map +1 -1
- package/dist/result.d.cts +8 -23
- package/dist/result.d.ts +8 -23
- package/dist/result.js +1 -1
- package/dist/result.js.map +1 -1
- package/dist/{run-entry-CFLkUvqw.d.cts → run-entry-rw7zll_G.d.ts} +183 -45
- package/dist/{run-entry-CFLkUvqw.d.ts → run-entry-yQu63Yj9.d.cts} +183 -45
- package/dist/run.cjs +2 -2
- package/dist/run.cjs.map +1 -1
- package/dist/run.d.cts +3 -1
- package/dist/run.d.ts +3 -1
- package/dist/run.js +2 -2
- package/dist/run.js.map +1 -1
- package/dist/saga.cjs +2 -2
- package/dist/saga.cjs.map +1 -1
- package/dist/saga.d.cts +3 -1
- package/dist/saga.d.ts +3 -1
- package/dist/saga.js +2 -2
- package/dist/saga.js.map +1 -1
- package/dist/singleflight.d.cts +3 -1
- package/dist/singleflight.d.ts +3 -1
- package/dist/streaming.cjs +4 -4
- package/dist/streaming.cjs.map +1 -1
- package/dist/streaming.d.cts +5 -3
- package/dist/streaming.d.ts +5 -3
- package/dist/streaming.js +4 -4
- package/dist/streaming.js.map +1 -1
- package/dist/testing.cjs +8 -4
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +87 -4
- package/dist/testing.d.ts +87 -4
- package/dist/testing.js +8 -4
- package/dist/testing.js.map +1 -1
- package/dist/{types-DiG4vCyB.d.ts → types-CuWK5AlK.d.ts} +1 -1
- package/dist/{types-Dmw78_CL.d.cts → types-uR3JpwvF.d.cts} +1 -1
- package/dist/webhook.cjs +2 -2
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +7 -4
- package/dist/webhook.d.ts +7 -4
- package/dist/webhook.js +2 -2
- package/dist/webhook.js.map +1 -1
- package/dist/workflow.cjs +3 -3
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +47 -11
- package/dist/workflow.d.ts +47 -11
- package/dist/workflow.js +3 -3
- package/dist/workflow.js.map +1 -1
- package/package.json +21 -2
package/dist/adapters.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters-entry.ts","../src/core/index.ts","../src/adapters.ts"],"sourcesContent":["/**\n * awaitly/adapters\n *\n * Convenience adapters to wrap common non-Promise async patterns into Results.\n *\n * @example\n * ```typescript\n * import { fromCallback, fromEvent } from 'awaitly/adapters';\n *\n * // Node.js callback style\n * const data = await fromCallback<string>(\n * (cb) => fs.readFile('file.txt', 'utf8', cb)\n * );\n *\n * // One-shot event emitter\n * const response = await fromEvent<Response>(\n * request,\n * { success: 'response', error: 'error' }\n * );\n * ```\n */\n\nexport {\n // Functions\n fromCallback,\n fromEvent,\n\n // Type guards\n isEventTimeoutError,\n isInvalidEmitterError,\n isEventEmitterLike,\n\n // Types\n type NodeCallback,\n type EventConfig,\n type EventEmitterLike,\n type EventTimeoutError,\n type InvalidEmitterError,\n} from \"./adapters\";\n","/**\n * awaitly/core\n *\n * Core Result primitives and run() function.\n * Use this module for minimal bundle size when you don't need the full workflow capabilities\n * (like retries, timeout, or state persistence) provided by `createWorkflow`.\n *\n * This module provides:\n * 1. `Result` types for error handling without try/catch\n * 2. `run()` function for executing steps with standardized error management\n * 3. Utilities for transforming and combining Results\n */\n\n// Inline duration type and parser to avoid importing the full duration module\n// This keeps the core bundle minimal (~1KB saved)\n\n/** Duration object with tagged type for type safety */\ntype DurationObject = { readonly _tag: \"Duration\"; readonly millis: number };\n\n/** Duration input: either a string (\"5s\", \"100ms\") or a Duration object */\ntype DurationInput = string | DurationObject;\n\n/** Parse a duration string like \"100ms\", \"5s\", \"2m\", \"1h\", \"1d\" */\nfunction parseDurationString(input: string): DurationObject | undefined {\n const match = input.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d)$/i);\n if (!match) return undefined;\n const value = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n const multipliers: Record<string, number> = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };\n return { _tag: \"Duration\", millis: value * (multipliers[unit] ?? 1) };\n}\n\n// =============================================================================\n// Core Result Types\n// =============================================================================\n\n/**\n * Represents a successful result.\n * Use `ok(value)` to create instances.\n *\n * @template T - The type of the success value\n *\n * @example\n * ```typescript\n * const success = Awaitly.ok(42);\n * // Type shown: Ok<number>\n * ```\n */\nexport type Ok<T> = {\n ok: true;\n value: T;\n};\n\n/**\n * Represents a failed result.\n * Use `err(error)` to create instances.\n *\n * @template E - The type of the error value\n * @template C - The type of the cause (defaults to unknown)\n * @template T - Phantom type for the success value (preserved after narrowing)\n *\n * @example\n * ```typescript\n * const failure = Awaitly.err({ type: \"NOT_FOUND\", message: \"User not found\" });\n * // Type shown: Err<{ type: string; message: string }>\n * ```\n */\nexport type Err<E, C = unknown> = {\n ok: false;\n error: E;\n cause?: C;\n};\n\n/**\n * Represents a successful computation or a failed one.\n * Use this type to represent the outcome of an operation that might fail,\n * instead of throwing exceptions.\n *\n * @template T - The type of the success value\n * @template E - The type of the error value (defaults to unknown)\n * @template C - The type of the cause (defaults to unknown)\n */\nexport type Result<T, E = unknown, C = unknown> = Ok<T> | Err<E, C>;\n\n/**\n * A Promise that resolves to a Result.\n * Use this for asynchronous operations that might fail.\n */\nexport type AsyncResult<T, E = unknown, C = unknown> = Promise<Result<T, E, C>>;\n\n/**\n * Cause of a step failure: either a Result error or a thrown value.\n * Used inside UnexpectedError when a step returns Err or throws.\n */\nexport type UnexpectedStepFailureCause =\n | {\n type: \"STEP_FAILURE\";\n origin: \"result\";\n error: unknown;\n cause?: unknown;\n }\n | {\n type: \"STEP_FAILURE\";\n origin: \"throw\";\n error: unknown;\n thrown: unknown;\n };\n\n/**\n * Union of causes for unexpected errors: uncaught exception or step failure.\n * Used as the cause field of UnexpectedError.\n */\nexport type UnexpectedCause =\n | { type: \"UNCAUGHT_EXCEPTION\"; thrown: unknown }\n | UnexpectedStepFailureCause;\n\n/** Discriminant for UnexpectedError type - use in switch statements */\nexport const UNEXPECTED_ERROR = \"UNEXPECTED_ERROR\" as const;\n\n/** Discriminant for PromiseRejectedError type - use in switch statements */\nexport const PROMISE_REJECTED = \"PROMISE_REJECTED\" as const;\n\n// =============================================================================\n// Named Error Constants (for static analysis)\n// =============================================================================\n\n/**\n * Named error constant for unexpected/unhandled errors.\n * Used by the analyzer when a step doesn't declare errors.\n */\nexport const AWAITLY_UNEXPECTED = \"AWAITLY_UNEXPECTED\" as const;\n\n/**\n * Named error constant for cancelled operations.\n */\nexport const AWAITLY_CANCELLED = \"AWAITLY_CANCELLED\" as const;\n\n/**\n * Named error constant for timed-out operations.\n */\nexport const AWAITLY_TIMEOUT = \"AWAITLY_TIMEOUT\" as const;\n\n// =============================================================================\n// Static Analysis Helpers\n// =============================================================================\n\n/**\n * Helper to create a tuple of string literal tags with preserved literal types.\n * Use this when you need to store error tags in a variable while keeping\n * TypeScript's literal type inference (avoiding widening to string[]).\n *\n * @param t - The string literal tags\n * @returns The same array with preserved literal types\n *\n * @example\n * ```typescript\n * // Without tags() - type widens to string[]\n * const errs = ['CART_NOT_FOUND', 'CART_EMPTY']; // string[]\n *\n * // With tags() - literal types preserved\n * const errs = tags('CART_NOT_FOUND', 'CART_EMPTY'); // ['CART_NOT_FOUND', 'CART_EMPTY']\n *\n * await step('getCart', () => getCart(id), {\n * errors: errs, // Analyzer can extract literal types\n * out: 'cart',\n * });\n * ```\n */\nexport const tags = <const T extends readonly string[]>(...t: T): T => t;\n\nexport type UnexpectedError = {\n type: typeof UNEXPECTED_ERROR;\n cause: UnexpectedCause;\n};\n\n/**\n * Default mapper for unexpected causes (uncaught exceptions, cancellation, etc.).\n * Returns the UNEXPECTED_ERROR string constant. The thrown value is preserved\n * in the Result's cause field, so no information is lost.\n * Used when run() is called without catchUnexpected.\n *\n * @param _cause - The thrown value (preserved in Result cause, not embedded here)\n * @returns The UNEXPECTED_ERROR string constant\n */\nexport function defaultCatchUnexpected(_cause: unknown): typeof UNEXPECTED_ERROR {\n return UNEXPECTED_ERROR;\n}\n\nexport type PromiseRejectedError = { type: typeof PROMISE_REJECTED; cause: unknown };\n/** Cause type for promise rejections in async batch helpers */\nexport type PromiseRejectionCause = { type: \"PROMISE_REJECTION\"; reason: unknown };\nexport type EmptyInputError = { type: \"EMPTY_INPUT\"; message: string };\nexport type MaybeAsyncResult<T, E, C = unknown> = Result<T, E, C> | Promise<Result<T, E, C>>;\n\n// =============================================================================\n// Result Constructors\n// =============================================================================\n\n/**\n * Creates a successful Result.\n * Use this when an operation completes successfully.\n *\n * @remarks When to use: Wrap a successful value in a Result for consistent return types.\n *\n * @param value - The success value to wrap\n * @returns An Ok object with `{ ok: true, value }`\n *\n * @example\n * ```typescript\n * const success = Awaitly.ok(42);\n * // Type: Ok<number>\n *\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) return Awaitly.err(\"Division by zero\");\n * return Awaitly.ok(a / b);\n * }\n * ```\n */\nexport function ok<T>(value: T): Ok<T> {\n return { ok: true as const, value };\n}\n\n/**\n * Creates a failed Result.\n * Use this when an operation fails.\n *\n * @remarks When to use: Return a typed failure without throwing so callers can handle it explicitly.\n *\n * @param error - The error value describing what went wrong (e.g., error code, object)\n * @returns An Err object with `{ ok: false, error }`\n *\n * @example\n * ```typescript\n * // Simple error\n * const r1 = Awaitly.err(\"NOT_FOUND\");\n * // Type: Err<\"NOT_FOUND\">\n *\n * // Error with context (include in error object)\n * const r2 = Awaitly.err({ type: \"PROCESSING_FAILED\", cause: originalError });\n * // Type: Err<{ type: string; cause: Error }>\n * ```\n */\nexport function err<E, C = unknown>(error: E, options?: { cause?: C }): Err<E, C> {\n const cause = options?.cause;\n return { ok: false as const, error, ...(cause !== undefined ? { cause } : {}) } as Err<E, C>;\n}\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Checks if a Result is successful.\n * Use this to narrow the type of a Result to the success case.\n *\n * @remarks When to use: Prefer functional-style checks or array filtering over `result.ok`.\n *\n * @param r - The Result to check\n * @returns `true` if successful, allowing access to `r.value`\n *\n * @example\n * ```typescript\n * const r = someOperation();\n * if (isOk(r)) {\n * // Use r.value (Type is T)\n * processValue(r.value);\n * } else {\n * // Handle r.error (Type is E)\n * handleError(r.error);\n * }\n * ```\n */\nexport const isOk = <T, E, C>(r: Result<T, E, C>): r is Ok<T> => r.ok;\n\n/**\n * Checks if a Result is a failure.\n * Use this to narrow the type of a Result to the error case.\n *\n * @remarks When to use: Prefer functional-style checks or array filtering over `result.ok`.\n *\n * @param r - The Result to check\n * @returns `true` if failed, allowing access to `r.error` and `r.cause`\n *\n * @example\n * ```typescript\n * if (isErr(r)) {\n * // Handle error case early\n * return;\n * }\n * // Proceed with success case\n * ```\n */\nexport const isErr = <T, E, C>(r: Result<T, E, C>): r is Err<E, C> => !r.ok;\n\n/**\n * Checks if an error is an UnexpectedError.\n * Used internally by the framework but exported for advanced custom handling.\n * Indicates an error that wasn't typed/expected in the `run` signature.\n *\n * @remarks When to use: Distinguish unexpected failures from your typed error union.\n */\nexport const isUnexpectedError = (e: unknown): e is UnexpectedError | typeof UNEXPECTED_ERROR =>\n e === UNEXPECTED_ERROR ||\n (typeof e === \"object\" &&\n e !== null &&\n (e as UnexpectedError).type === \"UNEXPECTED_ERROR\");\n\n/**\n * Checks if an error is a PromiseRejectedError.\n * Occurs when a Promise rejects in batch operations (allAsync, anyAsync, zipAsync).\n *\n * @example\n * ```typescript\n * onError: (error): FetchError => {\n * if (isPromiseRejectedError(error)) return 'FETCH_FAILED';\n * return error; // TypeScript narrows to FetchError\n * }\n * ```\n */\nexport const isPromiseRejectedError = (e: unknown): e is PromiseRejectedError =>\n typeof e === \"object\" &&\n e !== null &&\n (e as PromiseRejectedError).type === PROMISE_REJECTED;\n\n// =============================================================================\n// Error Matching\n// =============================================================================\n\n/**\n * Type for exhaustive error handlers mapping string literal errors and UnexpectedError.\n * Each key in E gets a handler, plus UNEXPECTED_ERROR is required.\n * Note: \"UNEXPECTED_ERROR\" is excluded from E to avoid intersection conflicts when users\n * have that literal in their error union - the UNEXPECTED_ERROR handler always receives\n * the UnexpectedError object type, not the string literal.\n */\nexport type MatchErrorHandlers<E extends string, R> = {\n [K in Exclude<E, \"UNEXPECTED_ERROR\">]: (error: K) => R;\n} & {\n UNEXPECTED_ERROR: (error: UnexpectedError) => R;\n};\n\n/**\n * Exhaustive pattern matching for error types.\n * Handles both string literal errors and UnexpectedError, ensuring all cases are covered.\n *\n * @param error - The error to match (string literal or UnexpectedError)\n * @param handlers - Object with a handler for each error case plus UNEXPECTED_ERROR\n * @returns The result of the matched handler\n *\n * @example\n * ```typescript\n * type FetchError = \"NOT_FOUND\" | \"FETCH_ERROR\";\n * const result: Result<User, FetchError | UnexpectedError> = await fetchUser();\n *\n * if (!result.ok) {\n * return matchError(result.error, {\n * NOT_FOUND: () => 404,\n * FETCH_ERROR: () => 500,\n * UNEXPECTED_ERROR: (e) => { throw e.cause; } // Required by types\n * });\n * }\n * ```\n */\nexport function matchError<E extends string, R>(\n error: E | UnexpectedError,\n handlers: MatchErrorHandlers<E, R>\n): R {\n // Handle the string literal \"UNEXPECTED_ERROR\" first - wrap it in an UnexpectedError object\n // to maintain the typed contract that UNEXPECTED_ERROR handler receives an object.\n // Must check before isUnexpectedError() since that also matches the string form.\n if (error === \"UNEXPECTED_ERROR\") {\n const syntheticError: UnexpectedError = {\n type: UNEXPECTED_ERROR,\n cause: { type: \"UNCAUGHT_EXCEPTION\", thrown: error },\n };\n return handlers.UNEXPECTED_ERROR(syntheticError);\n }\n // Handle UnexpectedError objects\n if (isUnexpectedError(error)) {\n return handlers.UNEXPECTED_ERROR(error as UnexpectedError);\n }\n // Cast to the excluded type since we've handled UNEXPECTED_ERROR above\n type StringErrors = Exclude<E, \"UNEXPECTED_ERROR\">;\n return handlers[error as StringErrors](error as StringErrors);\n}\n\n// =============================================================================\n// Type Utilities\n// =============================================================================\n\ntype AnyFunction = (...args: never[]) => unknown;\n\n/**\n * Helper to extract the error type from Result or AsyncResult return values.\n * Works even when a function is declared to return a union of both forms.\n */\ntype ErrorOfReturn<R> = Extract<Awaited<R>, { ok: false }> extends { error: infer E }\n ? E\n : never;\n\n/**\n * Extract error type from a single function's return type\n */\nexport type ErrorOf<T extends AnyFunction> = ErrorOfReturn<ReturnType<T>>;\n\n/**\n * Extract union of error types from multiple functions\n */\nexport type Errors<T extends AnyFunction[]> = {\n [K in keyof T]: ErrorOf<T[K]>;\n}[number];\n\n/**\n * Extract value type from Result\n */\nexport type ExtractValue<T> = T extends { ok: true; value: infer U }\n ? U\n : never;\n\n/**\n * Extract error type from Result\n */\nexport type ExtractError<T> = T extends { ok: false; error: infer E }\n ? E\n : never;\n\n/**\n * Extract cause type from Result\n */\nexport type ExtractCause<T> = T extends { ok: false; cause?: infer C }\n ? C\n : never;\n\n/**\n * Helper to extract the cause type from Result or AsyncResult return values.\n * Works even when a function is declared to return a union of both forms.\n */\ntype CauseOfReturn<R> = Extract<Awaited<R>, { ok: false }> extends { cause?: infer C }\n ? C\n : never;\n\n/**\n * Extract cause type from a function's return type\n */\nexport type CauseOf<T extends AnyFunction> = CauseOfReturn<ReturnType<T>>;\n\n// =============================================================================\n// Step Options\n// =============================================================================\n\n/**\n * Options for configuring a step within a workflow.\n * Use these to enable tracing, caching, state persistence, and static analysis.\n */\nexport type StepOptions<\n Errs extends readonly string[] = readonly string[],\n Out extends string | undefined = undefined,\n> = {\n /**\n * Stable identity key for the step.\n * REQUIRED for:\n * 1. Caching: Used as the cache key.\n * 2. Resuming: Used to identify which steps have already completed.\n *\n * Must be unique within the workflow.\n */\n key?: string;\n\n /**\n * Short description for labels/tooltips.\n * Used by static analysis visualization tools.\n */\n description?: string;\n\n /**\n * Full markdown documentation for the step.\n * Used by static analysis visualization tools.\n */\n markdown?: string;\n\n /**\n * Retry configuration for transient failures.\n * When specified, the step will retry on errors according to this config.\n */\n retry?: RetryOptions;\n\n /**\n * Timeout configuration for the operation.\n * When specified, each attempt will be aborted after the timeout duration.\n */\n timeout?: TimeoutOptions;\n\n /**\n * Time-to-live for this step's cache entry in milliseconds.\n * Overrides any global cache TTL. Requires `key` for caching.\n */\n ttl?: number;\n\n // ==========================================================================\n // Static Analysis Options\n // ==========================================================================\n\n /**\n * Declared tagged errors this step may return.\n * Used by the static analyzer to build error flow graphs.\n *\n * Use `tags()` helper when storing in a variable:\n * @example\n * ```typescript\n * const cartErrors = tags('CART_NOT_FOUND', 'CART_EMPTY');\n * await step('getCart', () => getCart(id), { errors: cartErrors });\n *\n * // Or inline (no helper needed)\n * await step('getCart', () => getCart(id), {\n * errors: ['CART_NOT_FOUND', 'CART_EMPTY'],\n * });\n * ```\n */\n errors?: Errs;\n\n /**\n * Write the step's return value to this context key.\n * Replaces manual `ctx.set()` calls for the happy path.\n *\n * @example\n * ```typescript\n * await step('getCart', () => getCart(id), { out: 'cart' });\n * // Now ctx.cart contains the result\n * ```\n */\n out?: Out;\n\n /**\n * Override auto-detected reads from context.\n * Use when the analyzer can't trace complex data dependencies.\n *\n * @example\n * ```typescript\n * await step('charge', () => chargeCard(getCartTotal()), {\n * reads: ['cart'], // Explicitly declare dependency\n * });\n * ```\n */\n reads?: readonly string[];\n\n /**\n * Hint for dependency source tracking.\n * Use when the callback is complex and the analyzer can't detect\n * which dependency function is being called.\n *\n * @example\n * ```typescript\n * await step('getCart', () => {\n * const id = transform(ctx.input.cartId);\n * return deps.getCart(id);\n * }, {\n * dep: 'getCart', // Hint for analyzer\n * });\n * ```\n */\n dep?: string;\n};\n\n// =============================================================================\n// Retry and Timeout Types\n// =============================================================================\n\n/**\n * Backoff strategy for retry operations.\n */\nexport type BackoffStrategy = \"fixed\" | \"linear\" | \"exponential\";\n\n/**\n * Configuration for step retry behavior.\n */\nexport type RetryOptions = {\n /**\n * Total number of attempts (1 = no retry, 3 = initial + 2 retries).\n * Must be >= 1.\n */\n attempts: number;\n\n /**\n * Backoff strategy between retries.\n * - 'fixed': Same delay each time (initialDelay)\n * - 'linear': Delay increases linearly (initialDelay * attempt)\n * - 'exponential': Delay doubles each time (initialDelay * 2^(attempt-1))\n * @default 'exponential'\n */\n backoff?: BackoffStrategy;\n\n /**\n * Initial delay in milliseconds before first retry.\n * @default 100\n */\n initialDelay?: number;\n\n /**\n * Maximum delay cap in milliseconds.\n * Prevents exponential backoff from growing too large.\n * @default 30000 (30 seconds)\n */\n maxDelay?: number;\n\n /**\n * Whether to add random jitter (0-25% of delay).\n * Helps prevent thundering herd when multiple workflows retry simultaneously.\n * @default true\n */\n jitter?: boolean;\n\n /**\n * Predicate to determine if a retry should occur.\n * Receives the error and current attempt number (1-indexed).\n * Return true to retry, false to fail immediately.\n * @default Always retry on any error\n */\n retryOn?: (error: unknown, attempt: number) => boolean;\n\n /**\n * Callback invoked before each retry attempt.\n * Useful for logging, metrics, or side effects.\n */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n};\n\n/**\n * Timeout behavior when the timeout is reached.\n *\n * - 'error' (default): Return an error result with StepTimeoutError\n * - 'option': Return Ok(undefined) instead of an error (useful for optional operations)\n * - 'disconnect': Let the operation complete in background, return timeout error immediately\n * - function: Custom handler to generate the timeout error\n */\nexport type TimeoutBehavior =\n | \"error\"\n | \"option\"\n | \"disconnect\"\n | ((stepInfo: { name?: string; key?: string; ms: number }) => unknown);\n\n/**\n * Configuration for step timeout behavior.\n */\nexport type TimeoutOptions = {\n /**\n * Timeout duration in milliseconds per attempt.\n * When combined with retry, each attempt gets its own timeout.\n */\n ms: number;\n\n /**\n * Custom error to use when timeout occurs.\n * @default StepTimeoutError with step details\n */\n error?: unknown;\n\n /**\n * Whether to pass an AbortSignal to the operation.\n * When true, the operation function receives (signal: AbortSignal) as argument.\n * Useful for fetch() and other APIs that support cancellation.\n * @default false\n */\n signal?: boolean;\n\n /**\n * Behavior when timeout is reached.\n *\n * - 'error' (default): Return StepTimeoutError (or custom error if provided)\n * - 'option': Return Ok(undefined) instead of error (operation treated as optional)\n * - 'disconnect': Let operation complete in background, return error immediately\n * - function: Custom handler `(stepInfo) => customError`\n *\n * @default 'error'\n *\n * @example\n * ```typescript\n * // Default: Return timeout error\n * step.withTimeout(() => slowOp(), { ms: 5000 });\n *\n * // Optional: Return undefined if times out\n * step.withTimeout(() => optionalOp(), { ms: 5000, onTimeout: 'option' });\n *\n * // Disconnect: Don't wait for slow operation\n * step.withTimeout(() => fireAndForget(), { ms: 5000, onTimeout: 'disconnect' });\n *\n * // Custom error\n * step.withTimeout(() => apiCall(), {\n * ms: 5000,\n * onTimeout: ({ name, ms }) => ({ type: 'API_TIMEOUT', name, ms })\n * });\n * ```\n */\n onTimeout?: TimeoutBehavior;\n};\n\n/**\n * Standard timeout error type.\n */\nexport type StepTimeoutError = {\n type: \"STEP_TIMEOUT\";\n stepName?: string;\n stepKey?: string;\n timeoutMs: number;\n attempt?: number;\n};\n\n/**\n * Symbol used to mark any error (including custom errors) as a timeout error.\n * This allows detection of timeout errors even when users provide custom error payloads.\n */\nexport const STEP_TIMEOUT_MARKER: unique symbol = Symbol.for(\"step_timeout_marker\");\n\n/**\n * Metadata attached to timeout-marked errors.\n */\nexport type StepTimeoutMarkerMeta = {\n timeoutMs: number;\n stepName?: string;\n stepKey?: string;\n attempt?: number;\n};\n\n/**\n * Type guard to check if an error is a StepTimeoutError.\n * This checks both the standard type field AND the timeout marker symbol,\n * so custom errors provided via timeout.error are also detected.\n */\nexport function isStepTimeoutError(e: unknown): e is StepTimeoutError {\n if (typeof e !== \"object\" || e === null) {\n return false;\n }\n // Check for standard type field\n if ((e as StepTimeoutError).type === \"STEP_TIMEOUT\") {\n return true;\n }\n // Check for timeout marker (custom errors)\n return STEP_TIMEOUT_MARKER in e;\n}\n\n/**\n * Get timeout metadata from a timeout error (works with both standard and custom errors).\n * Returns undefined if the error is not a timeout error.\n */\nexport function getStepTimeoutMeta(e: unknown): StepTimeoutMarkerMeta | undefined {\n if (typeof e !== \"object\" || e === null) {\n return undefined;\n }\n // Check for standard type field first\n if ((e as StepTimeoutError).type === \"STEP_TIMEOUT\") {\n const err = e as StepTimeoutError;\n return {\n timeoutMs: err.timeoutMs,\n stepName: err.stepName,\n stepKey: err.stepKey,\n attempt: err.attempt,\n };\n }\n // Check for timeout marker (custom errors)\n if (STEP_TIMEOUT_MARKER in e) {\n return (e as Record<symbol, StepTimeoutMarkerMeta>)[STEP_TIMEOUT_MARKER];\n }\n return undefined;\n}\n\n// =============================================================================\n// RunStep Interface\n// =============================================================================\n\n/**\n * The `step` object passed to the function in `run(async ({ step }) => { ... })`.\n * acts as the bridge between your business logic and the workflow engine.\n *\n * It provides methods to:\n * 1. Execute operations that return `Result` types.\n * 2. safely wrap operations that might throw exceptions (using `step.try`).\n * 3. Assign names and keys to operations for tracing and caching.\n *\n * @template E - The union of all known error types expected in this workflow.\n */\nexport interface RunStep<E = unknown> {\n /**\n * Execute a Result-returning operation with explicit step ID.\n *\n * The ID is used for:\n * - Static analysis visualization\n * - Error flow tracking\n * - Step identification in diagrams\n * - Caching and resume (ID is used as the cache key)\n *\n * @param id - Unique step identifier (string literal for static analysis)\n * @param operation - A function that returns a Result or AsyncResult\n * @param options - Step options\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the result is an error (stops execution safely)\n *\n * @example\n * ```typescript\n * const cart = await step('getCart', () => getCart(ctx.input.cartId), {\n * errors: ['CART_NOT_FOUND', 'CART_EMPTY'],\n * out: 'cart',\n * });\n * ```\n */\n <T, StepE extends E, StepC = unknown>(\n id: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n options?: StepOptions\n ): Promise<T>;\n\n /**\n * Execute a standard throwing operation safely.\n * Catches exceptions and maps them to a typed error, or wraps them if no mapper is provided.\n *\n * Use this when integrating with libraries that throw exceptions.\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param operation - A function that returns a value or Promise (may throw)\n * @param options - Configuration including error mapping\n * @returns The success value\n * @throws {EarlyExit} If the operation throws (stops execution safely)\n *\n * @example\n * ```typescript\n * const data = await step.try(\n * \"db-query\",\n * () => db.query(),\n * { onError: (e) => ({ type: \"DB_ERROR\", cause: e }) }\n * );\n * ```\n */\n try: <T, const Err extends E>(\n id: string,\n operation: () => T | Promise<T>,\n options:\n | { error: Err; key?: string; ttl?: number }\n | { onError: (cause: unknown) => Err; key?: string; ttl?: number }\n ) => Promise<T>;\n\n /**\n * Execute a Result-returning function and map its error to a typed error.\n *\n * Use this when calling functions that return Result<T, E> and you want to\n * map their typed errors to your workflow's error type. Unlike step.try(),\n * the error passed to onError is typed (not unknown).\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param operation - A function that returns a Result or AsyncResult\n * @param options - Configuration including error mapping\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the result is an error (stops execution safely)\n *\n * @example\n * ```typescript\n * const response = await step.fromResult(\n * \"call-provider\",\n * () => callProvider(input),\n * {\n * onError: (providerError) => ({\n * type: \"PROVIDER_FAILED\",\n * provider: providerError.provider,\n * cause: providerError\n * })\n * }\n * );\n * ```\n */\n fromResult: <T, ResultE, const Err extends E>(\n id: string,\n operation: () => Result<T, ResultE, unknown> | AsyncResult<T, ResultE, unknown>,\n options:\n | { error: Err; key?: string; ttl?: number }\n | { onError: (resultError: ResultE) => Err; key?: string; ttl?: number }\n ) => Promise<T>;\n\n /**\n * Execute an operation that may return null/undefined and convert to a typed error.\n *\n * Shorthand for wrapping `fromNullable()` in a step — avoids boilerplate when\n * looking up optional values (database finds, map lookups, etc.).\n *\n * @param id - Unique step identifier\n * @param operation - A function that returns `T | null | undefined` (or a Promise thereof)\n * @param onNull - Returns the typed error when operation returns null/undefined\n *\n * @example\n * ```typescript\n * const user = await step.fromNullable(\n * 'getUser',\n * () => db.users.findById(id),\n * () => ({ type: 'NOT_FOUND' as const, id })\n * );\n * ```\n */\n fromNullable: <T, const Err extends E>(\n id: string,\n operation: () => T | null | undefined | Promise<T | null | undefined>,\n onNull: () => Err,\n options?: { key?: string; ttl?: number }\n ) => Promise<T>;\n\n /**\n * Execute parallel operations with scope events for visualization.\n *\n * This wraps the operations with scope_start and scope_end events, enabling\n * visualization of parallel execution branches.\n *\n * @overload Object form - step.parallel(name, { key: () => ... })\n * @overload Array form - step.parallel(name, () => allAsync([...]))\n *\n * @example Object form\n * ```typescript\n * const { user, posts } = await step.parallel('Fetch user data', {\n * user: () => fetchUser(id),\n * posts: () => fetchPosts(id),\n * });\n * ```\n *\n * @example Canonical form (strict mode)\n * ```typescript\n * const { user, posts } = await step.parallel('Fetch user data', {\n * user: { fn: () => fetchUser(id), errors: ['NOT_FOUND'] },\n * posts: { fn: () => fetchPosts(id), errors: ['FETCH_ERROR'] },\n * });\n * ```\n *\n * @example Array form\n * ```typescript\n * const [user, posts] = await step.parallel('Fetch all data', () =>\n * allAsync([fetchUser(id), fetchPosts(id)])\n * );\n * ```\n */\n parallel: {\n // Object form: step.parallel(name, { key: () => ... })\n <\n TOperations extends Record<\n string,\n () => MaybeAsyncResult<unknown, E, unknown>\n >\n >(\n name: string,\n operations: TOperations\n ): Promise<{\n [K in keyof TOperations]: TOperations[K] extends () => MaybeAsyncResult<\n infer V,\n E,\n unknown\n >\n ? V\n : never;\n }>;\n\n // Object form canonical: step.parallel(name, { key: { fn, errors } })\n <\n TOperations extends Record<\n string,\n ParallelOperationDescriptor<unknown, readonly string[]>\n >\n >(\n name: string,\n operations: TOperations\n ): Promise<{\n [K in keyof TOperations]: TOperations[K] extends ParallelOperationDescriptor<\n infer V,\n readonly string[]\n >\n ? V\n : never;\n }>;\n\n // Array form: step.parallel(name, () => allAsync([...]))\n <T, StepE extends E, StepC = unknown>(\n name: string,\n operation: () => Result<T[], StepE, StepC> | AsyncResult<T[], StepE, StepC>\n ): Promise<T[]>;\n };\n\n /**\n * Execute a race operation (anyAsync) with scope events for visualization.\n *\n * This wraps the operation with scope_start and scope_end events, enabling\n * visualization of racing execution branches.\n *\n * @param name - Name for this race block (used in visualization)\n * @param operation - A function that returns a Result from anyAsync\n * @returns The success value (first to succeed)\n *\n * @example\n * ```typescript\n * const data = await step.race('Fastest API', () =>\n * anyAsync([fetchFromPrimary(id), fetchFromFallback(id)])\n * );\n * ```\n */\n race: <T, StepE extends E, StepC = unknown>(\n name: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>\n ) => Promise<T>;\n\n /**\n * Execute an allSettled operation with scope events for visualization.\n *\n * This wraps the operation with scope_start and scope_end events, enabling\n * visualization of allSettled execution branches. Unlike step.parallel,\n * allSettled collects all results even if some fail.\n *\n * @param name - Name for this allSettled block (used in visualization)\n * @param operation - A function that returns a Result from allSettledAsync\n * @returns The success value (unwrapped array)\n *\n * @example\n * ```typescript\n * const [user, posts] = await step.allSettled('Fetch all data', () =>\n * allSettledAsync([fetchUser(id), fetchPosts(id)])\n * );\n * ```\n */\n allSettled: <T, StepE extends E, StepC = unknown>(\n name: string,\n operation: () => Result<T[], StepE, StepC> | AsyncResult<T[], StepE, StepC>\n ) => Promise<T[]>;\n\n /**\n * Execute a primary operation with a fallback if the primary fails.\n *\n * If the primary operation returns an error, the fallback is executed instead.\n * When `on` is specified, the fallback only runs for that specific error;\n * other errors propagate without invoking the fallback.\n *\n * Returns `Promise<T>` — errors escape via earlyExit into the workflow's error channel.\n * The error union `E1 | E2` is the generic constraint propagated to the workflow.\n *\n * @overload Fallback on ANY error from primary\n * @overload Fallback on SPECIFIC error literal only (via `on`)\n *\n * @param id - Unique step identifier (single step ID for events)\n * @param operation - Primary operation that returns AsyncResult\n * @param options - Fallback configuration\n * @returns The success value from primary or fallback\n *\n * @example\n * ```typescript\n * const user = await step.withFallback(\n * 'getUser',\n * () => fetchFromPrimary(id),\n * { fallback: () => fetchFromCache(id) }\n * );\n *\n * // With specific error filter\n * const data = await step.withFallback(\n * 'getData',\n * () => fetchFromApi(id),\n * { on: 'NOT_FOUND', fallback: () => getDefault(id) }\n * );\n * ```\n */\n withFallback: {\n // Overload 1: fallback on ANY error from primary\n <T, E1 extends E, E2 extends E>(\n id: string,\n operation: () => AsyncResult<T, E1>,\n options: { fallback: () => AsyncResult<T, E2>; key?: string }\n ): Promise<T>;\n\n // Overload 2: fallback on SPECIFIC error literal only\n <T, E1 extends E & string, E2 extends E>(\n id: string,\n operation: () => AsyncResult<T, E1>,\n options: { on: E1; fallback: () => AsyncResult<T, E2>; key?: string }\n ): Promise<T>;\n };\n\n /**\n * Execute an operation with automatic resource lifecycle management.\n *\n * Acquires a resource, uses it, and guarantees release regardless of outcome.\n * Release always runs after use completes (even on error or throw).\n * Release errors are logged via console.warn but never override the use result.\n *\n * No caching support — caching resource-using steps is dangerous.\n *\n * @param id - Unique step identifier\n * @param options - Resource lifecycle configuration\n * @returns The success value from the use function\n *\n * @example\n * ```typescript\n * const data = await step.withResource('useDb', {\n * acquire: () => connectToDb(),\n * use: (db) => db.query('SELECT * FROM users'),\n * release: (db) => db.close(),\n * });\n * ```\n */\n withResource: <T, R, AcquireE extends E, UseE extends E>(\n id: string,\n options: {\n acquire: () => AsyncResult<R, AcquireE>;\n use: (resource: R) => AsyncResult<T, UseE>;\n release: (resource: R) => void | Promise<void>;\n }\n ) => Promise<T>;\n\n /**\n * Execute an operation with retry and optional timeout.\n *\n * Use this for operations that may fail transiently (network issues, rate limits)\n * and benefit from automatic retry with backoff.\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param operation - A function that returns a Result or AsyncResult\n * @param options - Retry configuration and optional timeout\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If all retries are exhausted (stops execution safely)\n *\n * @example\n * ```typescript\n * const data = await step.retry(\n * \"fetch-external\",\n * () => fetchFromExternalApi(id),\n * {\n * attempts: 3,\n * backoff: 'exponential',\n * initialDelay: 200,\n * retryOn: (error) => error === 'RATE_LIMITED' || error === 'TRANSIENT',\n * onRetry: (error, attempt, delay) => {\n * console.log(`Retry ${attempt} after ${delay}ms`);\n * },\n * }\n * );\n * ```\n */\n retry: <T, StepE extends E, StepC = unknown>(\n id: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n options: RetryOptions & { key?: string; timeout?: TimeoutOptions }\n ) => Promise<T>;\n\n /**\n * Execute an operation with a timeout.\n *\n * Use this for operations that may hang indefinitely (external APIs, connections)\n * and need to be aborted after a certain duration.\n *\n * When `signal: true` is set, an AbortSignal is passed to your operation,\n * which you can use with APIs like fetch() for proper cancellation.\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param operation - A function that returns a Result (may receive AbortSignal)\n * @param options - Timeout configuration\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the operation times out (stops execution safely)\n *\n * @example\n * ```typescript\n * // Without AbortSignal\n * const data = await step.withTimeout(\n * \"fetch-data\",\n * () => fetchData(id),\n * { ms: 5000 }\n * );\n *\n * // With AbortSignal for fetch()\n * const data = await step.withTimeout(\n * \"fetch-url\",\n * (signal) => fetch(url, { signal }).then(r => ok(r.json())),\n * { ms: 5000, signal: true }\n * );\n * ```\n */\n withTimeout: <T, StepE extends E, StepC = unknown>(\n id: string,\n operation:\n | (() => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>)\n | ((signal: AbortSignal) => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>),\n options: TimeoutOptions & { key?: string }\n ) => Promise<T>;\n\n /**\n * Pause execution for a specified duration.\n *\n * Use this for intentional delays between operations (rate limiting,\n * polling intervals, debouncing). Respects workflow cancellation.\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param duration - Duration as string (\"5s\", \"100ms\") or Duration object\n * @param options - Optional key for per-iteration identity, ttl, description\n * @returns Promise that resolves after the duration\n * @throws {AbortError} If the workflow is cancelled during sleep\n *\n * @example\n * ```typescript\n * // String duration\n * await step.sleep(\"rate-limit-delay\", \"5s\");\n *\n * // Duration object\n * await step.sleep(\"my-sleep\", seconds(5));\n * ```\n */\n sleep(\n id: string,\n duration: DurationInput,\n options?: { key?: string; ttl?: number; description?: string; signal?: AbortSignal }\n ): Promise<void>;\n\n // ===========================================================================\n // Streaming Methods\n // ===========================================================================\n\n /**\n * Get a writable stream for this workflow.\n *\n * Use this to write values that can be consumed by readers\n * (e.g., HTTP response streaming, AI token streaming).\n *\n * @param options - Stream options (namespace, highWaterMark)\n * @returns StreamWriter for writing values\n *\n * @example\n * ```typescript\n * const writer = step.getWritable<string>({ namespace: 'ai-response' });\n *\n * await step(() => generateAI({\n * prompt: 'Hello',\n * onToken: async (token) => { await writer.write(token); }\n * }), { key: 'generate' });\n *\n * await writer.close();\n * ```\n */\n getWritable: <T>(options?: StreamWritableOptions) => StreamWriterInterface<T>;\n\n /**\n * Get a readable stream for this workflow.\n *\n * Use this to consume values from a stream, with support for\n * resuming from a specific position.\n *\n * @param options - Read options (namespace, startIndex)\n * @returns StreamReader for reading values\n *\n * @example\n * ```typescript\n * const reader = step.getReadable<string>({ namespace: 'ai-response' });\n *\n * let result = await reader.read();\n * while (result.ok) {\n * response.write(result.value);\n * result = await reader.read();\n * }\n * ```\n */\n getReadable: <T>(options?: StreamReadableOptions) => StreamReaderInterface<T>;\n\n /**\n * Process stream items with checkpointing.\n *\n * Combines streaming with batch processing - each item is processed\n * and checkpointed, enabling resume from the last successful item.\n *\n * @param source - StreamReader or AsyncIterable to process\n * @param processor - Function to process each item\n * @param options - Processing options\n * @returns Results from all processed items\n *\n * @example\n * ```typescript\n * const reader = step.getReadable<Message>({ namespace: 'messages' });\n *\n * const result = await step.streamForEach(\n * reader,\n * async (message, index) => {\n * const processed = await processMessage(message);\n * return ok(processed);\n * },\n * { name: 'process-messages', checkpointInterval: 10 }\n * );\n *\n * console.log(`Processed ${result.value.processedCount} messages`);\n * ```\n */\n streamForEach: <T, R, StepE extends E>(\n source: StreamReaderInterface<T> | AsyncIterable<T>,\n processor: (item: T, index: number) => AsyncResult<R, StepE>,\n options?: StreamForEachStepOptions\n ) => Promise<StreamForEachResultType<R>>;\n\n // ===========================================================================\n // Static Analysis Methods\n // ===========================================================================\n\n /**\n * Mark a conditional for static analysis with a stable ID and condition label.\n * Runtime: returns the boolean result of condition().\n * Analysis: emits a DecisionNode with stable id and conditionLabel, and attaches\n * the then/else subgraphs from the if/else branches.\n *\n * @param id - Stable identifier for this decision point (string literal for static analysis)\n * @param conditionLabel - Human-readable label describing the condition\n * @param condition - Function that returns the boolean condition\n * @returns The result of the condition function\n *\n * @example\n * ```typescript\n * if (step.if('payment', 'cart.total > 0', () => ctx.ref('cart').total > 0)) {\n * await step('chargeCard', () => deps.chargeCard(ctx.ref('cart').total), {\n * errors: ['CARD_DECLINED'],\n * });\n * } else {\n * await step('skipPayment', async () => ({ skipped: true }), {\n * errors: [],\n * });\n * }\n * ```\n */\n if: <T extends boolean>(\n id: string,\n conditionLabel: string,\n condition: () => T\n ) => T;\n\n /**\n * Alias for `step.if()`. Mark a conditional for static analysis with a stable ID.\n * Use this to label conditionals in strict mode when they contain step calls.\n *\n * @param id - Stable identifier for this decision point\n * @param conditionLabel - Human-readable label describing the condition\n * @param condition - Function that returns the boolean condition\n * @returns The result of the condition function\n *\n * @example\n * ```typescript\n * if (step.label('email-type', 'user.isPremium', () => user.isPremium)) {\n * await step('premium', () => sendPriorityEmail(user), { errors: ['EMAIL_FAILED'] });\n * } else {\n * await step('free', () => sendRegularEmail(user), { errors: ['EMAIL_FAILED'] });\n * }\n * ```\n */\n label: <T extends boolean>(\n id: string,\n conditionLabel: string,\n condition: () => T\n ) => T;\n\n /**\n * Execute a branch with explicit metadata for static analysis.\n * Use when you want richer analyzer metadata (conditionLabel, per-arm errors).\n * For most cases, use natural if/else with step.label() instead.\n *\n * @param id - Stable identifier for this branch point\n * @param options - Branch configuration with condition, then/else arms, and errors\n * @returns The result from the executed arm\n *\n * @example\n * ```typescript\n * const charge = await step.branch('payment', {\n * conditionLabel: 'cart.total > 0',\n * condition: () => ctx.ref('cart').total > 0,\n * out: 'charge',\n * then: () => chargeCard(ctx.ref('cart').total),\n * thenErrors: ['CARD_DECLINED'],\n * else: () => ok({ skipped: true }),\n * elseErrors: [],\n * });\n * ```\n */\n branch: <\n T,\n const ThenErrs extends readonly string[] = readonly [],\n const ElseErrs extends readonly string[] = readonly [],\n const Out extends string | undefined = undefined,\n >(\n id: string,\n options: BranchOptions<T, ThenErrs, ElseErrs, Out>\n ) => Promise<T>;\n\n /**\n * Create an arm definition for use with step.branch().\n * Runtime: returns the arm definition unchanged.\n * Analyzer: extracts arm metadata for visualization.\n *\n * @param fn - The arm function\n * @param errors - Declared errors for this arm\n * @returns The arm definition\n *\n * @example\n * ```typescript\n * const thenArm = step.arm(() => chargeCard(total), ['CARD_DECLINED']);\n * const elseArm = step.arm(() => ok({ skipped: true }), []);\n * ```\n */\n arm: <T, const Errs extends readonly string[] = readonly []>(\n fn: () => T | Promise<T>,\n errors?: Errs\n ) => ArmDefinition<T, Errs>;\n\n /**\n * Execute a forEach loop with static analysis support.\n * Supports both simple (run) and complex (item) forms.\n *\n * @param id - Stable identifier for this loop\n * @param items - Iterable to loop over\n * @param options - Loop configuration\n * @returns Array of results from each iteration\n *\n * @example Simple form:\n * ```typescript\n * await step.forEach('process-items', items, {\n * maxIterations: 100,\n * stepIdPattern: 'process-{i}',\n * errors: ['PROCESS_ERROR'],\n * run: (item) => processItem(item),\n * });\n * ```\n *\n * @example Complex form with multiple steps:\n * ```typescript\n * await step.forEach('process-items', items, {\n * maxIterations: 100,\n * item: step.item((item, i, innerStep) => {\n * await innerStep('validate', () => validate(item), { errors: ['INVALID'] });\n * await innerStep('process', () => process(item), { errors: ['FAILED'] });\n * }),\n * });\n * ```\n */\n forEach: {\n // Simple form with run callback\n <T, R, const Errs extends readonly string[] = readonly []>(\n id: string,\n items: Iterable<T> | AsyncIterable<T>,\n options: ForEachRunOptions<T, R, Errs>\n ): Promise<R[]>;\n\n // Complex form with item callback\n <T, R>(\n id: string,\n items: Iterable<T> | AsyncIterable<T>,\n options: ForEachItemOptions<T, R>\n ): Promise<R[]>;\n };\n\n /**\n * Create an item handler for use with step.forEach().\n * Runtime: returns the handler unchanged.\n * Analyzer: extracts the inner step structure.\n *\n * @param handler - Function to process each item\n * @returns The item handler\n *\n * @example\n * ```typescript\n * step.item((item, index, innerStep) => {\n * await innerStep('validate', () => validate(item));\n * await innerStep('process', () => process(item));\n * });\n * ```\n */\n item: <T, R>(\n handler: (item: T, index: number, step: RunStep<E>) => R | Promise<R>\n ) => ForEachItemHandler<T, R>;\n\n /**\n * Wrap a dependency function for static analysis tracking.\n * Returns the function unchanged but marks it for the analyzer.\n *\n * @param name - Name of the dependency (for analyzer tracking)\n * @param fn - The dependency function to wrap\n * @returns The same function, unchanged\n *\n * @example\n * ```typescript\n * await step('getCart', step.dep('getCart', () => deps.getCart(ctx.input.cartId)), {\n * errors: ['CART_NOT_FOUND'],\n * out: 'cart',\n * });\n * ```\n */\n dep: <T extends (...args: unknown[]) => unknown>(name: string, fn: T) => T;\n\n // ===========================================================================\n // Effect-Style Ergonomics\n // ===========================================================================\n\n /**\n * Unwrap an AsyncResult directly within a workflow step.\n *\n * Use this when you already have an AsyncResult and want to unwrap it\n * without wrapping it in a function. Automatically exits on error.\n *\n * @param id - Unique step identifier\n * @param result - The AsyncResult to unwrap\n * @param options - Step options\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the result is an error\n *\n * @example\n * ```typescript\n * const userResult = fetchUser(userId); // AsyncResult<User, 'NOT_FOUND'>\n * const user = await step.run('fetchUser', userResult);\n * // Automatically unwraps and exits on error\n * ```\n */\n run: <T, StepE extends E, StepC = unknown>(\n id: string,\n result: AsyncResult<T, StepE, StepC>,\n options?: StepOptions\n ) => Promise<T>;\n\n /**\n * Run a sub-workflow (or any AsyncResult-returning operation) as a step.\n * Use for workflow composition; the getter's error type (SubE) flows into the parent's error union.\n *\n * @param id - Unique step identifier\n * @param getter - Function that returns AsyncResult (e.g. () => subWorkflow.run(fn))\n * @param options - Step options (key, ttl, etc.)\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the result is an error\n *\n * @example\n * ```typescript\n * const authResult = await step.workflow(\"authorize\", () => authorizeWorkflow.run(fn));\n * ```\n */\n workflow: <T, SubE extends E, StepC = unknown>(\n id: string,\n getter: () => AsyncResult<T, SubE, StepC>,\n options?: StepOptions\n ) => Promise<T>;\n\n /**\n * Chain AsyncResult operations with step tracking.\n *\n * Use this for composing AsyncResult operations where each step\n * depends on the previous one's success value.\n *\n * @param id - Unique step identifier\n * @param value - The value to pass to the function\n * @param fn - Function that takes the value and returns an AsyncResult\n * @param options - Step options\n * @returns The final success value (unwrapped)\n * @throws {EarlyExit} If the result is an error\n *\n * @example\n * ```typescript\n * const user = await step.run('fetchUser', fetchUser(id));\n * const enriched = await step.andThen('enrich', user, (user) =>\n * enrichUser(user) // Returns AsyncResult<EnrichedUser, E>\n * );\n * ```\n */\n andThen: <T, U, StepE extends E, StepC = unknown>(\n id: string,\n value: T,\n fn: (value: T) => AsyncResult<U, StepE, StepC>,\n options?: StepOptions\n ) => Promise<U>;\n\n /**\n * Pattern match on a Result with step tracking for both branches.\n *\n * Use this for handling Result values where both success and error\n * paths need to be tracked as separate steps.\n *\n * @param id - Unique step identifier\n * @param result - The Result to match on\n * @param handlers - Object with ok and err handler functions\n * @param options - Step options\n * @returns The value returned by the matched handler\n *\n * @example\n * ```typescript\n * const user = await step.run('fetchUser', fetchUser(id));\n *\n * const message = await step.match('handleUser', user, {\n * ok: async (user) => {\n * await step('sendWelcome', () => sendEmail(user.email));\n * return 'Sent welcome email';\n * },\n * err: async (error) => {\n * await step('logError', () => logError(error));\n * return 'Failed to fetch user';\n * }\n * });\n * ```\n */\n match: <T, StepE extends E, U, StepC = unknown>(\n id: string,\n result: Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n handlers: {\n ok: (value: T) => U | Promise<U>;\n err: (error: StepE, cause?: StepC) => U | Promise<U>;\n },\n options?: StepOptions\n ) => Promise<U>;\n\n /**\n * Alias for step.parallel - Effect.all-style API for parallel execution.\n *\n * Executes multiple operations in parallel and returns named results.\n * Identical to step.parallel but with a name more familiar to Effect users.\n *\n * @param name - Name for this parallel block\n * @param operations - Object mapping keys to operations\n * @returns Object with results mapped to the same keys\n *\n * @example\n * ```typescript\n * const { user, posts, comments } = await step.all('fetchAll', {\n * user: () => fetchUser('1'),\n * posts: () => fetchPosts('1'),\n * comments: () => fetchComments('1')\n * });\n * ```\n */\n all: RunStep<E>[\"parallel\"];\n\n /**\n * Map over an array with parallel execution and error tracking.\n *\n * Similar to Effect.forEach - executes mapper function for each item\n * in parallel and collects results.\n *\n * @param id - Unique step identifier\n * @param items - Array of items to process\n * @param mapper - Function to process each item (returns AsyncResult)\n * @param options - Optional concurrency limit and cache key\n * @returns Array of results in original order\n *\n * @example\n * ```typescript\n * const users = await step.map('fetchUsers', userIds, (id) =>\n * fetchUser(id)\n * );\n * // Automatic parallel execution with error union\n * ```\n */\n map: <T, U, StepE extends E, StepC = unknown>(\n id: string,\n items: T[],\n mapper: (item: T, index: number) => AsyncResult<U, StepE, StepC>,\n options?: { concurrency?: number; key?: string }\n ) => Promise<U[]>;\n\n}\n\n// =============================================================================\n// Parallel Types\n// =============================================================================\n\n/**\n * Operation descriptor for canonical parallel form.\n * Use this for analyzable parallel operations with explicit error declarations.\n */\nexport type ParallelOperationDescriptor<\n T,\n Errs extends readonly string[] = readonly [],\n> = {\n /** The operation function */\n fn: () => MaybeAsyncResult<T, unknown, unknown>;\n /** Declared errors for this operation (for static analysis) */\n errors?: Errs;\n};\n\n// =============================================================================\n// Branch and ForEach Types\n// =============================================================================\n\n/**\n * Options for step.branch().\n */\nexport type BranchOptions<\n T,\n ThenErrs extends readonly string[] = readonly [],\n ElseErrs extends readonly string[] = readonly [],\n Out extends string | undefined = undefined,\n> = {\n /** Human-readable label describing the condition */\n conditionLabel: string;\n /** Function that evaluates the condition */\n condition: () => boolean;\n /** Output key for data flow (writes result to ctx[out]) */\n out?: Out;\n /** Function to execute when condition is true */\n then: () => T | Promise<T>;\n /** Declared errors for the then arm */\n thenErrors?: ThenErrs;\n /** Function to execute when condition is false */\n else?: () => T | Promise<T>;\n /** Declared errors for the else arm */\n elseErrors?: ElseErrs;\n};\n\n/**\n * Arm definition for step.branch().\n */\nexport type ArmDefinition<T, Errs extends readonly string[] = readonly []> = {\n fn: () => T | Promise<T>;\n errors?: Errs;\n};\n\n/**\n * Options for step.forEach() with simple run form.\n */\nexport type ForEachRunOptions<T, R, Errs extends readonly string[] = readonly []> = {\n /** Maximum iterations (for bounded analysis) */\n maxIterations?: number;\n /** Step ID pattern for iterations (e.g., 'process-{i}') */\n stepIdPattern?: string;\n /** Declared errors for the loop body */\n errors?: Errs;\n /** Output key for results (requires collect option in strict mode) */\n out?: string;\n /** How to collect results when out is specified */\n collect?: \"array\" | \"last\";\n /** Simple callback for each item */\n run: (item: T, index: number) => R | Promise<R>;\n};\n\n/**\n * Options for step.forEach() with complex item form.\n */\nexport type ForEachItemOptions<T, R> = {\n /** Maximum iterations (for bounded analysis) */\n maxIterations?: number;\n /** Step ID pattern for iterations (e.g., 'process-{i}') */\n stepIdPattern?: string;\n /** Output key for results (requires collect option in strict mode) */\n out?: string;\n /** How to collect results when out is specified */\n collect?: \"array\" | \"last\";\n /** Complex item handler with inner step access */\n item: ForEachItemHandler<T, R>;\n};\n\n/**\n * Item handler for step.forEach() with inner step access.\n */\nexport type ForEachItemHandler<T, R> = {\n __forEachItemHandler: true;\n handler: (item: T, index: number, step: RunStep<unknown>) => R | Promise<R>;\n};\n\n// =============================================================================\n// Streaming Types (minimal interfaces for RunStep)\n// =============================================================================\n\n/**\n * Options for getWritable.\n */\nexport interface StreamWritableOptions {\n /** Named streams (default: 'default') */\n namespace?: string;\n /** Backpressure threshold (default: 16) */\n highWaterMark?: number;\n}\n\n/**\n * Options for getReadable.\n */\nexport interface StreamReadableOptions {\n /** Named streams (default: 'default') */\n namespace?: string;\n /** Resume from position (0-indexed) */\n startIndex?: number;\n /** Poll interval in ms when waiting for new items (default: 10) */\n pollInterval?: number;\n /** Stop polling after this many ms with no new items (default: 30000) */\n pollTimeout?: number;\n}\n\n/**\n * Options for streamForEach.\n */\nexport interface StreamForEachStepOptions {\n /** Checkpoint after every N items (default: 1) */\n checkpointInterval?: number;\n /** Maximum concurrent processors (default: 1 = sequential) */\n concurrency?: number;\n}\n\n/**\n * Result from streamForEach operation.\n */\nexport interface StreamForEachResultType<R> {\n /** Results from each processed item */\n results: R[];\n /** Total items processed */\n processedCount: number;\n /** Position of last processed item */\n lastPosition: number;\n}\n\n/**\n * Writable stream interface used in RunStep.\n * @see StreamWriter in awaitly/streaming for full interface\n */\nexport interface StreamWriterInterface<T> {\n write(value: T): AsyncResult<void, StreamWriteErrorType>;\n close(): AsyncResult<void, StreamCloseErrorType>;\n abort(reason: unknown): void;\n readonly writable: boolean;\n readonly position: number;\n readonly namespace: string;\n}\n\n/**\n * Readable stream interface used in RunStep.\n * @see StreamReader in awaitly/streaming for full interface\n */\nexport interface StreamReaderInterface<T> {\n read(): AsyncResult<T, StreamReadErrorType | StreamEndedMarkerType>;\n close(): void;\n readonly readable: boolean;\n readonly position: number;\n readonly namespace: string;\n}\n\n/**\n * Stream write error type.\n */\nexport interface StreamWriteErrorType {\n type: \"STREAM_WRITE_ERROR\";\n reason: \"closed\" | \"aborted\" | \"store_error\";\n message: string;\n cause?: unknown;\n}\n\n/**\n * Stream read error type.\n */\nexport interface StreamReadErrorType {\n type: \"STREAM_READ_ERROR\";\n reason: \"closed\" | \"store_error\";\n message: string;\n cause?: unknown;\n}\n\n/**\n * Stream close error type.\n */\nexport interface StreamCloseErrorType {\n type: \"STREAM_CLOSE_ERROR\";\n reason: \"already_closed\" | \"store_error\";\n message: string;\n cause?: unknown;\n}\n\n/**\n * Stream ended marker type.\n */\nexport interface StreamEndedMarkerType {\n type: \"STREAM_ENDED\";\n finalPosition: number;\n}\n\n// =============================================================================\n// Event Types (for run() optional event support)\n// =============================================================================\n\n/**\n * Unified event stream for workflow execution.\n *\n * Note: step_complete.result uses Result<unknown, unknown, unknown> because events\n * aggregate results from heterogeneous steps. At runtime, the actual Result object\n * preserves its original types, but the event type cannot statically represent them.\n * Use runtime checks or the meta field to interpret cause values.\n */\n/**\n * Scope types for parallel and race operations.\n */\nexport type ScopeType = \"parallel\" | \"race\" | \"allSettled\";\n\nexport type WorkflowEvent<E, C = unknown> =\n | { type: \"workflow_start\"; workflowId: string; workflowName?: string; ts: number; context?: C }\n | { type: \"workflow_success\"; workflowId: string; workflowName?: string; ts: number; durationMs: number; context?: C }\n | { type: \"workflow_error\"; workflowId: string; workflowName?: string; ts: number; durationMs: number; error: E; context?: C }\n | { type: \"step_start\"; workflowId: string; workflowName?: string; stepId: string; stepKey?: string; name?: string; description?: string; ts: number; context?: C }\n | { type: \"step_success\"; workflowId: string; workflowName?: string; stepId: string; stepKey?: string; name?: string; description?: string; ts: number; durationMs: number; context?: C }\n | { type: \"step_error\"; workflowId: string; workflowName?: string; stepId: string; stepKey?: string; name?: string; description?: string; ts: number; durationMs: number; error: E; context?: C }\n | { type: \"step_aborted\"; workflowId: string; workflowName?: string; stepId: string; stepKey?: string; name?: string; description?: string; ts: number; durationMs: number; context?: C }\n | { type: \"step_complete\"; workflowId: string; workflowName?: string; stepKey: string; name?: string; description?: string; ts: number; durationMs: number; result: Result<unknown, unknown, unknown>; meta?: StepFailureMeta; context?: C }\n | { type: \"step_cache_hit\"; workflowId: string; workflowName?: string; stepKey: string; name?: string; ts: number; context?: C }\n | { type: \"step_cache_miss\"; workflowId: string; workflowName?: string; stepKey: string; name?: string; ts: number; context?: C }\n | { type: \"step_skipped\"; workflowId: string; workflowName?: string; stepKey?: string; name?: string; reason?: string; decisionId?: string; ts: number; context?: C }\n | { type: \"scope_start\"; workflowId: string; workflowName?: string; scopeId: string; scopeType: ScopeType; name?: string; ts: number; context?: C }\n | { type: \"scope_end\"; workflowId: string; workflowName?: string; scopeId: string; ts: number; durationMs: number; winnerId?: string; context?: C }\n // Retry events\n | {\n type: \"step_retry\";\n workflowId: string;\n workflowName?: string;\n stepId: string;\n stepKey?: string;\n name?: string;\n ts: number;\n attempt: number;\n maxAttempts: number;\n delayMs: number;\n error: E;\n context?: C;\n }\n | {\n type: \"step_retries_exhausted\";\n workflowId: string;\n workflowName?: string;\n stepId: string;\n stepKey?: string;\n name?: string;\n ts: number;\n durationMs: number;\n attempts: number;\n lastError: E;\n context?: C;\n }\n // Timeout event\n | {\n type: \"step_timeout\";\n workflowId: string;\n workflowName?: string;\n stepId: string;\n stepKey?: string;\n name?: string;\n ts: number;\n timeoutMs: number;\n attempt?: number;\n context?: C;\n }\n // Hook events\n | {\n type: \"hook_should_run\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n result: boolean;\n skipped: boolean;\n context?: C;\n }\n | {\n type: \"hook_should_run_error\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n error: E;\n context?: C;\n }\n | {\n type: \"hook_before_start\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n result: boolean;\n skipped: boolean;\n context?: C;\n }\n | {\n type: \"hook_before_start_error\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n error: E;\n context?: C;\n }\n | {\n type: \"hook_after_step\";\n workflowId: string;\n workflowName?: string;\n stepKey: string;\n ts: number;\n durationMs: number;\n context?: C;\n }\n | {\n type: \"hook_after_step_error\";\n workflowId: string;\n workflowName?: string;\n stepKey: string;\n ts: number;\n durationMs: number;\n error: E;\n context?: C;\n }\n // Stream events\n | {\n type: \"stream_created\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_write\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n position: number;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_read\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n position: number;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_close\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n finalPosition: number;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_error\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n error: unknown;\n position: number;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_backpressure\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n bufferedCount: number;\n state: \"paused\" | \"flowing\";\n ts: number;\n context?: C;\n }\n // Workflow cancellation event\n | {\n type: \"workflow_cancelled\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n /** Reason from AbortSignal.reason (if provided) */\n reason?: string;\n /** Last successfully completed keyed step before cancellation (for resume purposes) */\n lastStepKey?: string;\n context?: C;\n };\n\n// =============================================================================\n// Run Options\n// =============================================================================\n\nexport type RunOptionsWithCatch<E, C = void> = {\n /**\n * Handler for expected errors.\n * Called when a step fails with a known error type.\n */\n onError?: (error: E, stepName?: string, ctx?: C) => void;\n /**\n * Listener for workflow events (start, success, error, step events).\n * Use this for logging, telemetry, or debugging.\n *\n * Context is automatically included in `event.context` when provided via the `context` option.\n * The separate `ctx` parameter is provided for convenience.\n */\n onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;\n /**\n * Catch-all mapper for unexpected exceptions.\n * Converts unknown exceptions (and cancellation) into your typed error union E.\n */\n catchUnexpected: (cause: unknown) => E;\n /**\n * Unique ID for this workflow execution.\n * Defaults to a random UUID.\n * Useful for correlating logs across distributed systems.\n */\n workflowId?: string;\n /**\n * Human-readable workflow name included on emitted events.\n * Useful for observability and visualization.\n */\n workflowName?: string;\n /**\n * Arbitrary context object passed to onEvent and onError.\n * Useful for passing request IDs, user IDs, or loggers.\n */\n context?: C;\n /**\n * @internal External signal for workflow-level cancellation.\n * Used by createWorkflow() to pass the workflow signal to steps.\n */\n _workflowSignal?: AbortSignal;\n};\n\nexport type RunOptionsWithoutCatch<E, C = void> = {\n /**\n * Handler for expected errors AND unexpected errors.\n * Unexpected errors will be wrapped in `UnexpectedError`.\n */\n onError?: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;\n /**\n * Listener for workflow events (start, success, error, step events).\n *\n * Note: Context is available both on `event.context` and as the separate `ctx` parameter.\n * The `ctx` parameter is provided for convenience and backward compatibility.\n */\n onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;\n catchUnexpected?: undefined;\n workflowId?: string;\n /**\n * Human-readable workflow name included on emitted events.\n * Useful for observability and visualization.\n */\n workflowName?: string;\n context?: C;\n /**\n * @internal External signal for workflow-level cancellation.\n * Used by createWorkflow() to pass the workflow signal to steps.\n */\n _workflowSignal?: AbortSignal;\n};\n\nexport type RunOptions<E, C = void> = RunOptionsWithCatch<E, C> | RunOptionsWithoutCatch<E, C>;\n\n// =============================================================================\n// Early Exit Mechanism (exported for caching layer)\n// =============================================================================\n\n/**\n * Symbol used to identify early exit throws.\n * Exported for the caching layer in workflow.ts.\n * @internal\n */\nexport const EARLY_EXIT_SYMBOL: unique symbol = Symbol(\"early-exit\");\n\n/**\n * Metadata about how a step failed.\n * @internal\n */\nexport type StepFailureMeta =\n | { origin: \"result\"; resultCause?: unknown }\n | { origin: \"throw\"; thrown: unknown }\n | { origin: \"fallback\"; fallbackUsed: true; fallbackReason: string };\n\n/**\n * Early exit object thrown to short-circuit workflow execution.\n * @internal\n */\nexport type EarlyExit<E> = {\n [EARLY_EXIT_SYMBOL]: true;\n error: E;\n meta: StepFailureMeta;\n};\n\n/**\n * Create an early exit throw object.\n * Used by the caching layer to synthesize early exits for cached errors.\n * @internal\n */\nexport function createEarlyExit<E>(error: E, meta: StepFailureMeta): EarlyExit<E> {\n return {\n [EARLY_EXIT_SYMBOL]: true,\n error,\n meta,\n };\n}\n\n/**\n * Type guard for early exit objects.\n * @internal\n */\nexport function isEarlyExit<E>(e: unknown): e is EarlyExit<E> {\n return (\n typeof e === \"object\" &&\n e !== null &&\n (e as Record<PropertyKey, unknown>)[EARLY_EXIT_SYMBOL] === true\n );\n}\n\n/**\n * Symbol to mark exceptions thrown by catchUnexpected mappers.\n * These should propagate without being re-processed.\n * @internal\n */\nconst MAPPER_EXCEPTION_SYMBOL: unique symbol = Symbol(\"mapper-exception\");\n\ntype MapperException = {\n [MAPPER_EXCEPTION_SYMBOL]: true;\n thrown: unknown;\n};\n\nfunction createMapperException(thrown: unknown): MapperException {\n return { [MAPPER_EXCEPTION_SYMBOL]: true, thrown };\n}\n\nfunction isMapperException(e: unknown): e is MapperException {\n return (\n typeof e === \"object\" &&\n e !== null &&\n (e as Record<PropertyKey, unknown>)[MAPPER_EXCEPTION_SYMBOL] === true\n );\n}\n\n// =============================================================================\n// Retry and Timeout Utilities\n// =============================================================================\n\n/**\n * Calculate the delay for a retry attempt based on the backoff strategy.\n * @internal\n */\nfunction calculateRetryDelay(\n attempt: number,\n options: {\n backoff: BackoffStrategy;\n initialDelay: number;\n maxDelay: number;\n jitter: boolean;\n }\n): number {\n const { backoff, initialDelay, maxDelay, jitter } = options;\n\n let delay: number;\n\n switch (backoff) {\n case \"fixed\":\n delay = initialDelay;\n break;\n case \"linear\":\n delay = initialDelay * attempt;\n break;\n case \"exponential\":\n delay = initialDelay * Math.pow(2, attempt - 1);\n break;\n }\n\n // Apply max cap\n delay = Math.min(delay, maxDelay);\n\n // Apply jitter (0-25% of delay)\n if (jitter) {\n const jitterAmount = delay * 0.25 * Math.random();\n delay = delay + jitterAmount;\n }\n\n return Math.floor(delay);\n}\n\n/**\n * Sleep for a specified number of milliseconds.\n * @internal\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nconst DEFAULT_RETRY_ASYNC_CONFIG = {\n backoff: \"exponential\" as BackoffStrategy,\n initialDelay: 100,\n maxDelay: 30000,\n jitter: true,\n retryOn: (_error: unknown, _attempt: number) => true,\n onRetry: (_error: unknown, _attempt: number, _delayMs: number) => {},\n} as const;\n\n/**\n * Run an async function with retry. Reuses the same backoff and retryOn semantics as step.retry.\n * Use this when you want retries without the workflow/step machinery (e.g. in fetch).\n *\n * @param fn - Function that returns a Promise<Result<T, E>>\n * @param options - Retry configuration (attempts, backoff, retryOn, etc.)\n * @returns Promise that resolves to the last Result (ok or err). Rejects only if fn throws and retryOn returns false.\n */\nexport async function retryAsync<T, E>(\n fn: () => Promise<Result<T, E>>,\n options: RetryOptions\n): Promise<Result<T, E>> {\n const attempts = Math.max(1, options.attempts);\n const effective = {\n backoff: options.backoff ?? DEFAULT_RETRY_ASYNC_CONFIG.backoff,\n initialDelay: options.initialDelay ?? DEFAULT_RETRY_ASYNC_CONFIG.initialDelay,\n maxDelay: options.maxDelay ?? DEFAULT_RETRY_ASYNC_CONFIG.maxDelay,\n jitter: options.jitter ?? DEFAULT_RETRY_ASYNC_CONFIG.jitter,\n retryOn: options.retryOn ?? DEFAULT_RETRY_ASYNC_CONFIG.retryOn,\n onRetry: options.onRetry ?? DEFAULT_RETRY_ASYNC_CONFIG.onRetry,\n };\n\n let lastResult: Result<T, E> | undefined;\n for (let attempt = 1; attempt <= attempts; attempt++) {\n try {\n const result = await fn();\n if (result.ok) return result;\n lastResult = result;\n if (attempt < attempts && effective.retryOn(result.error, attempt)) {\n const delay = calculateRetryDelay(attempt, effective);\n effective.onRetry(result.error, attempt, delay);\n await sleep(delay);\n continue;\n }\n return result;\n } catch (thrown) {\n if (attempt < attempts && effective.retryOn(thrown, attempt)) {\n const delay = calculateRetryDelay(attempt, effective);\n effective.onRetry(thrown, attempt, delay);\n await sleep(delay);\n continue;\n }\n throw thrown;\n }\n }\n return lastResult!;\n}\n\n/**\n * Symbol used internally to identify timeout rejection.\n */\nconst TIMEOUT_SYMBOL: unique symbol = Symbol(\"timeout\");\nconst TIMEOUT_OPTION_SYMBOL: unique symbol = Symbol(\"timeout-option\");\n\n/**\n * Check if an error is a timeout option marker (should return undefined instead of error).\n * @internal\n */\nfunction isTimeoutOptionMarker(\n value: unknown\n): value is { [TIMEOUT_OPTION_SYMBOL]: true; ms: number } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as Record<symbol, unknown>)[TIMEOUT_OPTION_SYMBOL] === true\n );\n}\n\n/**\n * Execute an operation with a timeout using Promise.race.\n * @internal\n */\nasync function executeWithTimeout<T>(\n operation: (() => Promise<T>) | ((signal: AbortSignal) => Promise<T>),\n options: TimeoutOptions,\n stepInfo: { name?: string; key?: string; attempt?: number },\n /** External signal (e.g., workflow cancellation) to combine with timeout signal */\n externalSignal?: AbortSignal\n): Promise<T> {\n const controller = new AbortController();\n const behavior = options.onTimeout ?? \"error\";\n\n // Create the timeout error based on behavior\n const createTimeoutError = (): unknown => {\n // For function behavior, call the handler to generate the error\n if (typeof behavior === \"function\") {\n return behavior({\n name: stepInfo.name,\n key: stepInfo.key,\n ms: options.ms,\n });\n }\n\n // For other behaviors, use custom error or default StepTimeoutError\n return (\n (options.error as StepTimeoutError) ?? {\n type: \"STEP_TIMEOUT\",\n stepName: stepInfo.name,\n stepKey: stepInfo.key,\n timeoutMs: options.ms,\n attempt: stepInfo.attempt,\n }\n );\n };\n\n // Track the timeout ID for cleanup\n let timeoutId: ReturnType<typeof setTimeout>;\n\n // If external signal is already aborted, abort immediately\n if (externalSignal?.aborted) {\n controller.abort(externalSignal.reason);\n }\n\n // Forward external signal abort to internal controller\n let externalAbortHandler: (() => void) | undefined;\n if (externalSignal && !externalSignal.aborted) {\n externalAbortHandler = () => controller.abort(externalSignal.reason);\n externalSignal.addEventListener(\"abort\", externalAbortHandler, { once: true });\n }\n\n // Create a timeout promise that rejects after the specified duration\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n // For 'disconnect', don't abort - let operation continue in background\n if (behavior !== \"disconnect\") {\n controller.abort();\n }\n\n // For 'option', throw special marker to return undefined\n if (behavior === \"option\") {\n reject({ [TIMEOUT_OPTION_SYMBOL]: true, ms: options.ms });\n return;\n }\n\n // For all other behaviors, throw the timeout error\n reject({ [TIMEOUT_SYMBOL]: true, error: createTimeoutError() });\n }, options.ms);\n });\n\n // Execute the operation\n let operationPromise: Promise<T>;\n if (options.signal) {\n // Operation expects an AbortSignal\n // Pass the internal controller's signal which is linked to both timeout and external signal\n operationPromise = Promise.resolve(\n (operation as (signal: AbortSignal) => Promise<T>)(controller.signal)\n );\n } else {\n // Standard operation\n operationPromise = Promise.resolve((operation as () => Promise<T>)());\n }\n\n try {\n // Race between operation and timeout\n const result = await Promise.race([operationPromise, timeoutPromise]);\n return result;\n } catch (error) {\n // Check if this was an 'option' timeout - return undefined as success\n if (\n typeof error === \"object\" &&\n error !== null &&\n (error as Record<symbol, unknown>)[TIMEOUT_OPTION_SYMBOL] === true\n ) {\n // Throw special marker that step handler will convert to ok(undefined)\n throw { [TIMEOUT_OPTION_SYMBOL]: true, ms: options.ms };\n }\n\n // Check if this was our timeout\n if (\n typeof error === \"object\" &&\n error !== null &&\n (error as Record<symbol, unknown>)[TIMEOUT_SYMBOL] === true\n ) {\n // For 'disconnect' behavior, the operation continues in the background\n // Attach a catch handler to prevent unhandled rejection if it fails later\n if (behavior === \"disconnect\") {\n operationPromise.catch(() => {\n // Intentionally swallowed - operation was disconnected\n });\n }\n\n const errorToThrow = (error as { error: unknown }).error;\n\n // Mark the error with STEP_TIMEOUT_MARKER if it's a custom error (not already a StepTimeoutError)\n // This allows isStepTimeoutError() and getStepTimeoutMeta() to work with custom errors\n // Note: Always update metadata to reflect the current attempt (same error may be reused across retries)\n if (\n typeof errorToThrow === \"object\" &&\n errorToThrow !== null &&\n (errorToThrow as StepTimeoutError).type !== \"STEP_TIMEOUT\"\n ) {\n const meta: StepTimeoutMarkerMeta = {\n timeoutMs: options.ms,\n stepName: stepInfo.name,\n stepKey: stepInfo.key,\n attempt: stepInfo.attempt,\n };\n\n if (STEP_TIMEOUT_MARKER in errorToThrow) {\n // Update existing marker with current attempt's metadata\n (errorToThrow as Record<symbol, StepTimeoutMarkerMeta>)[STEP_TIMEOUT_MARKER] = meta;\n } else {\n // Define new marker (writable so it can be updated on retry)\n Object.defineProperty(errorToThrow, STEP_TIMEOUT_MARKER, {\n value: meta,\n enumerable: false,\n writable: true,\n configurable: false,\n });\n }\n }\n\n throw errorToThrow;\n }\n // Re-throw other errors\n throw error;\n } finally {\n // Always clear the timeout to prevent leaks\n clearTimeout(timeoutId!);\n // Clean up external signal listener\n if (externalAbortHandler && externalSignal) {\n externalSignal.removeEventListener(\"abort\", externalAbortHandler);\n }\n }\n}\n\n/**\n * Default retry configuration values.\n * @internal\n */\nconst DEFAULT_RETRY_CONFIG = {\n backoff: \"exponential\" as BackoffStrategy,\n initialDelay: 100,\n maxDelay: 30000,\n jitter: true,\n retryOn: () => true,\n onRetry: () => {},\n} as const;\n\n// =============================================================================\n// run() Function\n// =============================================================================\n\n/**\n * Execute a workflow with step-based error handling.\n *\n * ## When to Use run()\n *\n * Use `run()` when:\n * - Dependencies are dynamic (passed at runtime, not known at compile time)\n * - You don't need step caching or resume state\n * - Error types are known upfront and can be specified manually\n * - Building lightweight, one-off workflows\n *\n * For automatic error type inference from static dependencies, use `createWorkflow()`.\n *\n * ## Error union\n *\n * `run()` returns:\n * - **`catchUnexpected`**: Maps uncaught exceptions to your type E → `Result<T, E>`\n * - **No catchUnexpected**: Step errors pass through + `\"UNEXPECTED_ERROR\"` for exceptions → `Result<T, E | \"UNEXPECTED_ERROR\">`\n *\n * When `E` is not specified, it defaults to `never`, giving `Result<T, \"UNEXPECTED_ERROR\">`.\n *\n * @see createWorkflow - For static dependencies with auto error inference\n */\n\n/**\n * run() with catchUnexpected: closed union Result<T, E>.\n */\nexport function run<T, E, C = void>(\n fn: (context: { step: RunStep<E> }) => Promise<T> | T,\n options: RunOptionsWithCatch<E, C>\n): AsyncResult<T, E, unknown>;\n\n/**\n * run() without catchUnexpected.\n * Always adds typeof UNEXPECTED_ERROR to the error union so callers know\n * uncaught exceptions are possible. Step errors pass through as-is.\n * When E is never (default), step is RunStep<unknown> so any operation is allowed.\n */\nexport function run<T, E = never, C = void>(\n fn: (context: {\n step: [E] extends [never] ? RunStep<unknown> : RunStep<E>;\n }) => Promise<T> | T,\n options?: {\n onError?: (error: E | typeof UNEXPECTED_ERROR, stepName?: string, ctx?: C) => void;\n onEvent?: (event: WorkflowEvent<E | typeof UNEXPECTED_ERROR, C>, ctx: C) => void;\n workflowId?: string;\n workflowName?: string;\n context?: C;\n /** @internal External signal for workflow-level cancellation. */\n _workflowSignal?: AbortSignal;\n }\n): AsyncResult<T, E | typeof UNEXPECTED_ERROR, unknown>;\n\n// Implementation\nexport async function run<T, E, C = void>(\n fn: (context: { step: RunStep<E> }) => Promise<T> | T,\n options?: RunOptions<E, C>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): AsyncResult<T, any> {\n const {\n onError,\n onEvent,\n catchUnexpected,\n workflowId: providedWorkflowId,\n workflowName,\n context,\n _workflowSignal,\n } = options && typeof options === \"object\"\n ? (options as RunOptions<E, C>)\n : ({} as RunOptions<E, C>);\n\n const workflowId = providedWorkflowId ?? crypto.randomUUID();\n const effectiveCatchUnexpected = catchUnexpected ?? defaultCatchUnexpected;\n\n // Track active scopes as a stack for proper nesting\n // When a step succeeds, only the innermost race scope gets the winner\n const activeScopeStack: Array<{ scopeId: string; type: ScopeType; winnerId?: string }> = [];\n\n // Counter for generating unique step IDs\n let stepIdCounter = 0;\n\n // Generate a unique step ID\n // Uses stepKey when provided (for cache stability), otherwise generates a unique ID.\n // Note: name is NOT used for stepId because multiple concurrent steps may share a name,\n // which would cause them to collide in activeSteps tracking and race winner detection.\n const generateStepId = (stepKey?: string): string => {\n return stepKey ?? `step_${++stepIdCounter}`;\n };\n\n const emitEvent = (event: WorkflowEvent<E | UnexpectedError, C>) => {\n // Add context to event only if:\n // 1. Event doesn't already have context (preserves replayed events or per-step overrides)\n // 2. Workflow actually has a context (don't add context: undefined property)\n const eventWithContext =\n event.context !== undefined || context === undefined\n ? event\n : ({ ...event, context: context as C } as WorkflowEvent<E | UnexpectedError, C>);\n\n const eventWithName =\n workflowName !== undefined && eventWithContext.workflowName === undefined\n ? ({ ...eventWithContext, workflowName } as WorkflowEvent<E | UnexpectedError, C>)\n : eventWithContext;\n \n // Track first successful step in the innermost race scope for winnerId\n if (eventWithName.type === \"step_success\") {\n // Use the stepId from the event (already generated at step start)\n const stepId = eventWithName.stepId;\n\n // Find innermost race scope (search from end of stack)\n for (let i = activeScopeStack.length - 1; i >= 0; i--) {\n const scope = activeScopeStack[i];\n if (scope.type === \"race\" && !scope.winnerId) {\n scope.winnerId = stepId;\n break; // Only update innermost race scope\n }\n }\n }\n onEvent?.(eventWithName, context as C);\n };\n\n // Use the exported early exit function with proper type parameter\n const earlyExit = createEarlyExit<E>;\n\n // Local type guard that narrows to EarlyExit<E> specifically\n const isEarlyExitE = (e: unknown): e is EarlyExit<E> => isEarlyExit(e);\n\n // Step errors always pass through — they are typed Result errors.\n // Only truly uncaught exceptions get mapped via effectiveCatchUnexpected.\n const wrapForStep = (\n error: unknown,\n _meta?: StepFailureMeta\n ): E => {\n return error as E;\n };\n\n // Helper to check if a value is a Result (has ok property) vs a function\n const isResultLike = (value: unknown): value is Result<unknown, unknown, unknown> | Promise<Result<unknown, unknown, unknown>> => {\n if (typeof value === 'function') return false;\n if (value && typeof value === 'object' && 'ok' in value) return true;\n // Check for Promise<Result> - it will have a then method\n if (value && typeof value === 'object' && 'then' in value && typeof (value as Promise<unknown>).then === 'function') return true;\n return false;\n };\n\n try {\n // Step function: requires step('id', fn, opts) or step('id', result, opts)\n const stepFn = <T, StepE, StepC = unknown>(\n id: string,\n operationOrResult: (() => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>) | Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n stepOptions?: StepOptions\n ): Promise<T> => {\n return (async () => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step() requires an explicit string ID as the first argument. ' +\n 'Example: step(\"fetchUser\", () => fetchUser(id))'\n );\n }\n\n const parsedOptions: StepOptions = stepOptions ?? {};\n\n // Name is always derived from ID\n const stepName = id;\n const stepKey = parsedOptions.key ?? id; // For general events (step_start, step_success, etc.)\n const explicitKey = parsedOptions.key ?? id; // For step_complete and caching (ID is used when no key)\n const { description: stepDescription, retry: retryConfig, timeout: timeoutConfig } = parsedOptions;\n const stepId = generateStepId(stepKey);\n const hasEventListeners = onEvent;\n const overallStartTime = hasEventListeners ? performance.now() : 0;\n\n // Determine if this is a direct Result or a function\n const isDirectResult = isResultLike(operationOrResult);\n const operation = isDirectResult\n ? () => operationOrResult as Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>\n : operationOrResult as () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>;\n\n // Build effective retry config with defaults\n // Ensure at least 1 attempt (0 would skip the loop entirely and crash)\n const maxAttempts = Math.max(1, retryConfig?.attempts ?? 1);\n const effectiveRetry = {\n attempts: maxAttempts,\n backoff: retryConfig?.backoff ?? DEFAULT_RETRY_CONFIG.backoff,\n initialDelay: retryConfig?.initialDelay ?? DEFAULT_RETRY_CONFIG.initialDelay,\n maxDelay: retryConfig?.maxDelay ?? DEFAULT_RETRY_CONFIG.maxDelay,\n jitter: retryConfig?.jitter ?? DEFAULT_RETRY_CONFIG.jitter,\n retryOn: retryConfig?.retryOn ?? DEFAULT_RETRY_CONFIG.retryOn,\n onRetry: retryConfig?.onRetry ?? DEFAULT_RETRY_CONFIG.onRetry,\n };\n\n // Emit step_start only once (before first attempt)\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n });\n }\n\n let lastResult: Result<T, StepE, StepC> | undefined;\n\n for (let attempt = 1; attempt <= effectiveRetry.attempts; attempt++) {\n const attemptStartTime = hasEventListeners ? performance.now() : 0;\n\n try {\n // Execute operation with optional timeout\n let result: Result<T, StepE, StepC>;\n\n if (timeoutConfig) {\n // Wrap with timeout, passing workflow signal for { signal: true } steps\n result = await executeWithTimeout(\n operation as () => Promise<Result<T, StepE, StepC>>,\n timeoutConfig,\n { name: stepName, key: stepKey, attempt },\n _workflowSignal\n );\n } else {\n result = await operation();\n }\n\n // Success case\n if (result.ok) {\n const durationMs = performance.now() - overallStartTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs,\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs,\n result,\n });\n }\n return result.value;\n }\n\n // Result error case - check if we should retry\n lastResult = result;\n\n if (attempt < effectiveRetry.attempts && effectiveRetry.retryOn(result.error, attempt)) {\n const delay = calculateRetryDelay(attempt, effectiveRetry);\n\n // Emit retry event\n emitEvent({\n type: \"step_retry\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n attempt: attempt + 1,\n maxAttempts: effectiveRetry.attempts,\n delayMs: delay,\n error: result.error as unknown as E,\n });\n\n effectiveRetry.onRetry(result.error, attempt, delay);\n await sleep(delay);\n continue;\n }\n\n // No more retries or retryOn returned false - emit exhausted event if we retried\n if (effectiveRetry.attempts > 1) {\n emitEvent({\n type: \"step_retries_exhausted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n attempts: attempt,\n lastError: result.error as unknown as E,\n });\n }\n\n // Fall through to final error handling below\n break;\n\n } catch (thrown) {\n const durationMs = performance.now() - attemptStartTime;\n\n // Handle timeout with 'option' behavior - return undefined as success\n if (isTimeoutOptionMarker(thrown)) {\n const timeoutMs = thrown.ms;\n emitEvent({\n type: \"step_timeout\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n timeoutMs,\n attempt,\n });\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n result: ok(undefined),\n });\n }\n // Return undefined as success value (timeout was treated as optional)\n return undefined as T;\n }\n\n // Handle early exit - propagate immediately\n if (isEarlyExitE(thrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs,\n });\n throw thrown;\n }\n\n // Handle timeout error\n if (isStepTimeoutError(thrown)) {\n // Get timeout metadata from the error (works for both standard and custom errors)\n const timeoutMeta = getStepTimeoutMeta(thrown);\n const timeoutMs = timeoutConfig?.ms ?? timeoutMeta?.timeoutMs ?? 0;\n emitEvent({\n type: \"step_timeout\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n timeoutMs,\n attempt,\n });\n\n // Check if we should retry after timeout\n if (attempt < effectiveRetry.attempts && effectiveRetry.retryOn(thrown, attempt)) {\n const delay = calculateRetryDelay(attempt, effectiveRetry);\n\n emitEvent({\n type: \"step_retry\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n attempt: attempt + 1,\n maxAttempts: effectiveRetry.attempts,\n delayMs: delay,\n error: thrown as unknown as E,\n });\n\n effectiveRetry.onRetry(thrown, attempt, delay);\n await sleep(delay);\n continue;\n }\n\n // No more retries - emit exhausted if we retried\n if (effectiveRetry.attempts > 1) {\n emitEvent({\n type: \"step_retries_exhausted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n attempts: attempt,\n lastError: thrown as unknown as E,\n });\n }\n\n // Treat STEP_TIMEOUT as a typed error - exit directly without UNEXPECTED_ERROR wrapper\n // This provides better DX: users get STEP_TIMEOUT directly in result.error\n const totalDurationMs = performance.now() - overallStartTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n error: thrown as unknown as E,\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n result: err(thrown as unknown as E, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n });\n }\n onError?.(thrown as unknown as E, stepName, context);\n throw earlyExit(thrown as unknown as E, { origin: \"throw\", thrown });\n }\n\n // Handle other thrown errors (continue to error handling below)\n\n // Check if we should retry thrown errors\n if (attempt < effectiveRetry.attempts && effectiveRetry.retryOn(thrown, attempt)) {\n const delay = calculateRetryDelay(attempt, effectiveRetry);\n\n emitEvent({\n type: \"step_retry\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n attempt: attempt + 1,\n maxAttempts: effectiveRetry.attempts,\n delayMs: delay,\n error: thrown as unknown as E,\n });\n\n effectiveRetry.onRetry(thrown, attempt, delay);\n await sleep(delay);\n continue;\n }\n\n // No more retries for thrown errors - emit exhausted if we retried\n if (effectiveRetry.attempts > 1 && !isStepTimeoutError(thrown)) {\n emitEvent({\n type: \"step_retries_exhausted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n attempts: attempt,\n lastError: thrown as unknown as E,\n });\n }\n\n // Handle the error using effectiveCatchUnexpected\n const totalDurationMs = performance.now() - overallStartTime;\n\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(thrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n error: mappedError,\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n result: err(mappedError, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown });\n }\n }\n\n // All retries exhausted with Result error - handle final error\n // At this point lastResult must be an error result (we only reach here on error)\n const errorResult = lastResult as Err<StepE, StepC>;\n const totalDurationMs = performance.now() - overallStartTime;\n const wrappedError = wrapForStep(errorResult.error, {\n origin: \"result\",\n resultCause: errorResult.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n error: wrappedError,\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n result: errorResult,\n meta: { origin: \"result\", resultCause: errorResult.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: errorResult.cause,\n });\n })();\n };\n\n stepFn.try = <T, Err>(\n id: string,\n operation: () => T | Promise<T>,\n opts:\n | { error: Err; key?: string }\n | { onError: (cause: unknown) => Err; key?: string }\n ): Promise<T> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.try() requires an explicit string ID as the first argument. ' +\n 'Example: step.try(\"parse\", () => JSON.parse(str), { error: \"PARSE_ERROR\" })'\n );\n }\n\n const stepKey = opts.key ?? id; // Use id as key if not provided\n const stepName = id; // Name is always the id\n const stepId = id;\n const mapToError = \"error\" in opts ? () => opts.error : opts.onError;\n const hasEventListeners = onEvent;\n\n return (async () => {\n const startTime = hasEventListeners ? performance.now() : 0;\n\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n });\n }\n\n try {\n const value = await operation();\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n // Emit step_complete for keyed steps (for state persistence)\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: ok(value),\n });\n }\n return value;\n } catch (error) {\n const mapped = mapToError(error);\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(mapped, { origin: \"throw\", thrown: error });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n // Emit step_complete for keyed steps (for state persistence)\n // Note: For step.try errors, we encode the mapped error, not the original thrown\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mapped, { cause: error }),\n meta: { origin: \"throw\", thrown: error },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, { origin: \"throw\", thrown: error });\n }\n })();\n };\n\n // step.fromResult: Execute a Result-returning function and map its typed error\n stepFn.fromResult = <T, ResultE, Err>(\n id: string,\n operation: () => Result<T, ResultE, unknown> | AsyncResult<T, ResultE, unknown>,\n opts:\n | { error: Err; key?: string }\n | { onError: (resultError: ResultE) => Err; key?: string }\n ): Promise<T> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.fromResult() requires an explicit string ID as the first argument. ' +\n 'Example: step.fromResult(\"callProvider\", () => callProvider(input), { onError: (e) => ({ type: \"FAILED\" }) })'\n );\n }\n\n const stepKey = opts.key ?? id; // Use id as key if not provided\n const stepName = id; // Name is always the id\n const stepId = id;\n const mapToError = \"error\" in opts ? () => opts.error : opts.onError;\n const hasEventListeners = onEvent;\n\n return (async () => {\n const startTime = hasEventListeners ? performance.now() : 0;\n\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n });\n }\n\n const result = await operation();\n\n if (result.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n // Emit step_complete for keyed steps (for state persistence)\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: ok(result.value),\n });\n }\n return result.value;\n } else {\n const mapped = mapToError(result.error);\n const durationMs = performance.now() - startTime;\n // For fromResult, the cause is the original result.error (what got mapped)\n // This is analogous to step.try using thrown exception as cause\n const wrappedError = wrapForStep(mapped, {\n origin: \"result\",\n resultCause: result.error,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n // Emit step_complete for keyed steps (for state persistence)\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mapped, { cause: result.error }),\n meta: { origin: \"result\", resultCause: result.error },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: result.error,\n });\n }\n })();\n };\n\n // step.fromNullable: Execute an operation returning T | null/undefined and convert to typed error\n stepFn.fromNullable = <T, Err>(\n id: string,\n operation: () => T | null | undefined | Promise<T | null | undefined>,\n onNull: () => Err,\n options?: { key?: string; ttl?: number }\n ): Promise<T> => {\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.fromNullable() requires an explicit string ID as the first argument. ' +\n 'Example: step.fromNullable(\"getUser\", () => db.find(id), () => ({ type: \"NOT_FOUND\" }))'\n );\n }\n return stepFn(\n id,\n async () => {\n const value = await operation();\n return value != null ? ok(value) : err(onNull());\n },\n options\n );\n };\n\n // step.retry: Execute an operation with retry and optional timeout\n stepFn.retry = <T, StepE, StepC = unknown>(\n id: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n options: RetryOptions & { key?: string; timeout?: TimeoutOptions }\n ): Promise<T> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.retry() requires an explicit string ID as the first argument. ' +\n 'Example: step.retry(\"fetchData\", () => fetchData(), { attempts: 3 })'\n );\n }\n\n // Delegate to stepFn with retry options merged into StepOptions\n // Use key for caching if provided, otherwise use id\n return stepFn(id, operation, {\n key: options.key ?? id,\n retry: {\n attempts: options.attempts,\n backoff: options.backoff,\n initialDelay: options.initialDelay,\n maxDelay: options.maxDelay,\n jitter: options.jitter,\n retryOn: options.retryOn,\n onRetry: options.onRetry,\n },\n timeout: options.timeout,\n });\n };\n\n // step.withTimeout: Execute an operation with a timeout\n stepFn.withTimeout = <T, StepE, StepC = unknown>(\n id: string,\n operation:\n | (() => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>)\n | ((signal: AbortSignal) => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>),\n options: TimeoutOptions & { key?: string }\n ): Promise<T> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.withTimeout() requires an explicit string ID as the first argument. ' +\n 'Example: step.withTimeout(\"slowOp\", () => slowOp(), { ms: 5000 })'\n );\n }\n\n // Delegate to stepFn with timeout options\n // The signal handling happens in executeWithTimeout when timeout.signal is true\n // Use key for caching if provided, otherwise use id\n return stepFn(\n id,\n operation as () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n {\n key: options.key ?? id,\n timeout: options,\n }\n );\n };\n\n // step.sleep: Pause execution for a specified duration\n stepFn.sleep = (\n id: string,\n duration: DurationInput,\n options?: { key?: string; ttl?: number; description?: string; signal?: AbortSignal }\n ): Promise<void> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.sleep() requires an explicit string ID as the first argument. ' +\n 'Example: step.sleep(\"delay\", \"5s\")'\n );\n }\n\n // Parse duration - inline to avoid importing duration module\n const d = typeof duration === \"string\" ? parseDurationString(duration) : duration;\n if (!d) {\n throw new Error(`step.sleep: invalid duration '${duration}'`);\n }\n const ms = d.millis;\n const userSignal = options?.signal;\n\n // Delegate to stepFn with a cancellation-aware sleep operation\n // Use key for caching if provided, otherwise use id\n return stepFn(\n id,\n async (): AsyncResult<void, never> => {\n // Check if already aborted (workflow or user signal)\n if (_workflowSignal?.aborted || userSignal?.aborted) {\n const e = new Error(\"Sleep aborted\");\n e.name = \"AbortError\";\n throw e;\n }\n\n return new Promise<Result<void, never>>((resolve, reject) => {\n // Using object to avoid prefer-const warning while allowing\n // onAbort to reference the timeout before it's assigned\n const state = { timeoutId: undefined as ReturnType<typeof setTimeout> | undefined };\n\n const onAbort = () => {\n if (state.timeoutId) clearTimeout(state.timeoutId);\n const e = new Error(\"Sleep aborted\");\n e.name = \"AbortError\";\n reject(e);\n };\n\n _workflowSignal?.addEventListener(\"abort\", onAbort, { once: true });\n userSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n state.timeoutId = setTimeout(() => {\n _workflowSignal?.removeEventListener(\"abort\", onAbort);\n userSignal?.removeEventListener(\"abort\", onAbort);\n resolve(ok(undefined));\n }, ms);\n });\n },\n {\n key: options?.key ?? id,\n description: options?.description,\n }\n );\n };\n\n // step.parallel: Execute parallel operations with scope events\n // 1. Object form: step.parallel(name, { key: fn | { fn, errors } })\n // 2. Array form: step.parallel(name, () => allAsync([...]))\n stepFn.parallel = ((...args: unknown[]): Promise<unknown> => {\n if (typeof args[0] !== \"string\") {\n throw new TypeError(\n \"step.parallel(name, ...): first argument must be a string (step name). Example: step.parallel('Fetch data', { user: () => fetchUser(), posts: () => fetchPosts() })\"\n );\n }\n const name = args[0] as string;\n const second = args[1];\n if (typeof second === \"function\") {\n return executeParallelArray(name, second as () => MaybeAsyncResult<unknown[], unknown, unknown>);\n }\n if (second && typeof second === \"object\" && !Array.isArray(second)) {\n const rawOperations = second as Record<string, (() => MaybeAsyncResult<unknown, unknown, unknown>) | ParallelOperationDescriptor<unknown, readonly string[]>>;\n const normalizedOperations = normalizeParallelOperations(rawOperations);\n return executeParallelNamed(normalizedOperations, { name });\n }\n throw new TypeError(\n \"step.parallel(name, ...): second argument must be a function (array form) or an object of operations (object form).\"\n );\n }) as RunStep<E>[\"parallel\"];\n\n function normalizeParallelOperations(\n rawOperations: Record<string, (() => MaybeAsyncResult<unknown, unknown, unknown>) | ParallelOperationDescriptor<unknown, readonly string[]>>\n ): Record<string, () => MaybeAsyncResult<unknown, unknown, unknown>> {\n const out: Record<string, () => MaybeAsyncResult<unknown, unknown, unknown>> = {};\n for (const [key, value] of Object.entries(rawOperations)) {\n if (typeof value === \"function\") {\n out[key] = value;\n } else if (value && typeof value === \"object\" && \"fn\" in value) {\n out[key] = value.fn;\n } else {\n throw new TypeError(`step.parallel: operation \"${key}\" must be a function or { fn, errors? } object`);\n }\n }\n return out;\n }\n\n // Array form implementation\n function executeParallelArray<T>(\n name: string,\n operation: () => MaybeAsyncResult<T[], unknown, unknown>\n ): Promise<T[]> {\n const scopeId = `scope_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n\n return (async () => {\n const startTime = performance.now();\n let scopeEnded = false;\n\n // Push this scope onto the stack for proper nesting tracking\n activeScopeStack.push({ scopeId, type: \"parallel\" });\n\n // Helper to emit scope_end exactly once\n const emitScopeEnd = () => {\n if (scopeEnded) return;\n scopeEnded = true;\n // Pop this scope from the stack\n const idx = activeScopeStack.findIndex(s => s.scopeId === scopeId);\n if (idx !== -1) activeScopeStack.splice(idx, 1);\n emitEvent({\n type: \"scope_end\",\n workflowId,\n scopeId,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n };\n\n // Emit scope_start event\n emitEvent({\n type: \"scope_start\",\n workflowId,\n scopeId,\n scopeType: \"parallel\",\n name,\n ts: Date.now(),\n });\n\n try {\n const result = await operation();\n\n // Emit scope_end before processing result\n emitScopeEnd();\n\n if (!result.ok) {\n onError?.(result.error as unknown as E, name, context);\n throw earlyExit(result.error as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n }\n\n return result.value;\n } catch (error) {\n // Always emit scope_end in finally-like fashion\n emitScopeEnd();\n throw error;\n }\n })();\n }\n\n // Named object form implementation - execute each operation in parallel\n function executeParallelNamed<T extends Record<string, unknown>>(\n operations: Record<string, () => MaybeAsyncResult<unknown, unknown, unknown>>,\n options: { name?: string }\n ): Promise<T> {\n const keys = Object.keys(operations);\n const name = options.name ?? `Parallel(${keys.join(\", \")})`;\n const scopeId = `scope_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n\n return (async () => {\n const startTime = performance.now();\n let scopeEnded = false;\n\n // Push this scope onto the stack for proper nesting tracking\n activeScopeStack.push({ scopeId, type: \"parallel\" });\n\n // Helper to emit scope_end exactly once\n const emitScopeEnd = () => {\n if (scopeEnded) return;\n scopeEnded = true;\n const idx = activeScopeStack.findIndex(s => s.scopeId === scopeId);\n if (idx !== -1) activeScopeStack.splice(idx, 1);\n emitEvent({\n type: \"scope_end\",\n workflowId,\n scopeId,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n };\n\n // Emit scope_start event with operation names in metadata\n emitEvent({\n type: \"scope_start\",\n workflowId,\n scopeId,\n scopeType: \"parallel\",\n name,\n ts: Date.now(),\n });\n\n try {\n // Execute all operations in parallel, fail-fast on first error\n const results = await new Promise<{ key: string; result: Result<unknown, unknown, unknown> }[]>((resolve) => {\n if (keys.length === 0) {\n resolve([]);\n return;\n }\n\n let settled = false;\n let pendingCount = keys.length;\n const resultArray: { key: string; result: Result<unknown, unknown, unknown> }[] = new Array(keys.length);\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const index = i;\n\n Promise.resolve(operations[key]())\n .catch((reason) => err(\n { type: \"PROMISE_REJECTED\" as const, cause: reason },\n { cause: { type: \"PROMISE_REJECTION\" as const, reason } }\n ))\n .then((result) => {\n if (settled) return;\n\n // Fail-fast: if any operation fails, resolve immediately with just the failed entry\n if (!result.ok) {\n settled = true;\n resolve([{ key, result }]);\n return;\n }\n\n resultArray[index] = { key, result };\n pendingCount--;\n\n if (pendingCount === 0) {\n resolve(resultArray);\n }\n });\n }\n });\n\n // Emit scope_end before processing results\n emitScopeEnd();\n\n // Check for errors and build result object\n const output: Record<string, unknown> = {};\n for (const { key, result } of results) {\n if (!result.ok) {\n onError?.(result.error as unknown as E, key, context);\n throw earlyExit(result.error as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n }\n output[key] = result.value;\n }\n\n return output as T;\n } catch (error) {\n // Always emit scope_end in finally-like fashion\n emitScopeEnd();\n throw error;\n }\n })();\n }\n\n // step.race: Execute a race operation with scope events\n stepFn.race = <T, StepE, StepC>(\n name: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>\n ): Promise<T> => {\n const scopeId = `scope_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n\n return (async () => {\n const startTime = performance.now();\n let scopeEnded = false;\n\n // Push this race scope onto the stack to track the first successful step as winner\n const scopeEntry = { scopeId, type: \"race\" as const, winnerId: undefined as string | undefined };\n activeScopeStack.push(scopeEntry);\n\n // Helper to emit scope_end exactly once, including winnerId\n const emitScopeEnd = () => {\n if (scopeEnded) return;\n scopeEnded = true;\n // Pop this scope from the stack\n const idx = activeScopeStack.findIndex(s => s.scopeId === scopeId);\n if (idx !== -1) activeScopeStack.splice(idx, 1);\n emitEvent({\n type: \"scope_end\",\n workflowId,\n scopeId,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n winnerId: scopeEntry.winnerId,\n });\n };\n\n // Emit scope_start event\n emitEvent({\n type: \"scope_start\",\n workflowId,\n scopeId,\n scopeType: \"race\",\n name,\n ts: Date.now(),\n });\n\n try {\n const result = await operation();\n\n // Emit scope_end before processing result\n emitScopeEnd();\n\n if (!result.ok) {\n onError?.(result.error as unknown as E, name, context);\n throw earlyExit(result.error as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n }\n\n return result.value;\n } catch (error) {\n // Always emit scope_end in finally-like fashion\n emitScopeEnd();\n throw error;\n }\n })();\n };\n\n // step.allSettled: Execute an allSettled operation with scope events\n stepFn.allSettled = <T, StepE, StepC>(\n name: string,\n operation: () => Result<T[], StepE, StepC> | AsyncResult<T[], StepE, StepC>\n ): Promise<T[]> => {\n const scopeId = `scope_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n\n return (async () => {\n const startTime = performance.now();\n let scopeEnded = false;\n\n // Push this scope onto the stack for proper nesting tracking\n activeScopeStack.push({ scopeId, type: \"allSettled\" });\n\n // Helper to emit scope_end exactly once\n const emitScopeEnd = () => {\n if (scopeEnded) return;\n scopeEnded = true;\n // Pop this scope from the stack\n const idx = activeScopeStack.findIndex(s => s.scopeId === scopeId);\n if (idx !== -1) activeScopeStack.splice(idx, 1);\n emitEvent({\n type: \"scope_end\",\n workflowId,\n scopeId,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n };\n\n // Emit scope_start event\n emitEvent({\n type: \"scope_start\",\n workflowId,\n scopeId,\n scopeType: \"allSettled\",\n name,\n ts: Date.now(),\n });\n\n try {\n const result = await operation();\n\n // Emit scope_end before processing result\n emitScopeEnd();\n\n if (!result.ok) {\n onError?.(result.error as unknown as E, name, context);\n throw earlyExit(result.error as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n }\n\n return result.value;\n } catch (error) {\n // Always emit scope_end in finally-like fashion\n emitScopeEnd();\n throw error;\n }\n })();\n };\n\n // step.if: Mark a conditional for static analysis\n // Runtime: just executes the condition and returns the result\n // Analyzer: extracts the id and conditionLabel for DecisionNode\n stepFn.if = <T extends boolean>(\n _id: string,\n _conditionLabel: string,\n condition: () => T\n ): T => {\n return condition();\n };\n\n // step.label: Alias for step.if - mark a conditional for static analysis\n // Use step.label for strict mode when conditionals contain step calls\n stepFn.label = stepFn.if;\n\n // step.branch: Execute a branch with explicit metadata for static analysis\n // Runtime: evaluates condition and executes appropriate arm\n // Analyzer: extracts branch metadata (conditionLabel, per-arm errors, out)\n stepFn.branch = async <\n T,\n const ThenErrs extends readonly string[] = readonly [],\n const ElseErrs extends readonly string[] = readonly [],\n const Out extends string | undefined = undefined,\n >(\n _id: string,\n options: BranchOptions<T, ThenErrs, ElseErrs, Out>\n ): Promise<T> => {\n const { condition, then: thenFn, else: elseFn } = options;\n const conditionResult = condition();\n if (conditionResult) {\n return await thenFn();\n } else if (elseFn) {\n return await elseFn();\n }\n return undefined as T;\n };\n\n // step.arm: Create an arm definition for use with step.branch\n // Runtime: returns the arm definition unchanged\n // Analyzer: extracts arm metadata\n stepFn.arm = <T, const Errs extends readonly string[] = readonly []>(\n fn: () => T | Promise<T>,\n errors?: Errs\n ): ArmDefinition<T, Errs> => {\n return { fn, errors };\n };\n\n // step.forEach: Execute a forEach loop with static analysis support\n // Supports both simple (run) and complex (item) forms\n stepFn.forEach = async <T, R>(\n _id: string,\n items: Iterable<T> | AsyncIterable<T>,\n options: ForEachRunOptions<T, R, readonly string[]> | ForEachItemOptions<T, R>\n ): Promise<R[]> => {\n const results: R[] = [];\n const maxIterations = options.maxIterations;\n let index = 0;\n\n // Check if this is the run form or item form\n const isRunForm = 'run' in options;\n\n // Convert items to async iterable for uniform handling\n const asyncItems = Symbol.asyncIterator in (items as object)\n ? (items as AsyncIterable<T>)\n : (async function* () { yield* items as Iterable<T>; })();\n\n for await (const item of asyncItems) {\n if (maxIterations !== undefined && index >= maxIterations) {\n break;\n }\n\n let result: R;\n if (isRunForm) {\n const runOptions = options as ForEachRunOptions<T, R, readonly string[]>;\n result = await runOptions.run(item, index);\n } else {\n const itemOptions = options as ForEachItemOptions<T, R>;\n result = await itemOptions.item.handler(item, index, stepFn as unknown as RunStep<unknown>);\n }\n\n results.push(result);\n index++;\n }\n\n return results;\n };\n\n // step.item: Create an item handler for use with step.forEach\n // Runtime: returns the handler wrapped in a marker object\n // Analyzer: extracts the inner step structure\n stepFn.item = <T, R>(\n handler: (item: T, index: number, step: RunStep<unknown>) => R | Promise<R>\n ): ForEachItemHandler<T, R> => {\n return {\n __forEachItemHandler: true as const,\n handler,\n };\n };\n\n // step.dep: Wrap a dependency function for static analysis tracking\n // Runtime: returns the function unchanged\n // Analyzer: records the dependency name\n stepFn.dep = <T extends (...args: unknown[]) => unknown>(\n _name: string,\n fn: T\n ): T => {\n return fn;\n };\n\n // ===========================================================================\n // Effect-Style Ergonomics\n // ===========================================================================\n\n // step.run: Unwrap an AsyncResult directly\n stepFn.run = <T, StepE, StepC = unknown>(\n id: string,\n result: AsyncResult<T, StepE, StepC>,\n options?: StepOptions\n ): Promise<T> => {\n return stepFn(id, () => result, options);\n };\n\n // step.workflow: Run sub-workflow (or any AsyncResult getter) as a step; same engine as step(id, getter, opts)\n stepFn.workflow = <T, SubE, StepC = unknown>(\n id: string,\n getter: () => AsyncResult<T, SubE, StepC>,\n options?: StepOptions\n ): Promise<T> => {\n return stepFn(id, getter as () => AsyncResult<T, E, StepC>, options);\n };\n\n // step.andThen: Chain AsyncResult operations\n stepFn.andThen = <T, U, StepE, StepC = unknown>(\n id: string,\n value: T,\n fn: (value: T) => AsyncResult<U, StepE, StepC>,\n options?: StepOptions\n ): Promise<U> => {\n return stepFn(id, () => fn(value), options);\n };\n\n // step.match: Pattern match on Result with step tracking (runs through step engine for lifecycle events)\n stepFn.match = async <T, StepE, U, StepC = unknown>(\n id: string,\n result: Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n handlers: {\n ok: (value: T) => U | Promise<U>;\n err: (error: StepE, cause?: StepC) => U | Promise<U>;\n },\n options?: StepOptions\n ): Promise<U> => {\n return stepFn(id, async () => {\n const resolved = await result;\n if (resolved.ok) {\n return ok(await handlers.ok(resolved.value));\n } else {\n return ok(await handlers.err(resolved.error, resolved.cause));\n }\n }, options);\n };\n\n // step.all: Alias for step.parallel (Effect.all-style API)\n stepFn.all = stepFn.parallel;\n\n // step.map: Map over array with parallel execution\n stepFn.map = async <T, U, StepE, StepC = unknown>(\n id: string,\n items: T[],\n mapper: (item: T, index: number) => AsyncResult<U, StepE, StepC>,\n options?: { concurrency?: number; key?: string }\n ): Promise<U[]> => {\n const concurrency = options?.concurrency ?? items.length;\n\n // Use allAsync for parallel execution with fail-fast\n return stepFn(\n id,\n () => {\n if (concurrency >= items.length) {\n // Full parallelism - execute all at once\n return allAsync(items.map((item, index) => mapper(item, index)));\n } else {\n // Limited concurrency - batch execution\n return (async () => {\n const results: U[] = [];\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n const batchResult = await allAsync(\n batch.map((item, batchIndex) => mapper(item, i + batchIndex))\n );\n // allAsync returns Result<U[], E, C>, so we need to check if it's ok\n if (!batchResult.ok) {\n return batchResult; // Propagate the error\n }\n results.push(...batchResult.value);\n }\n return ok(results);\n })();\n }\n },\n { key: options?.key }\n );\n };\n\n // step.withFallback: Execute primary with fallback on error\n stepFn.withFallback = <T, E1, E2>(\n id: string,\n operation: () => AsyncResult<T, E1>,\n options: { on?: E1 & string; fallback: () => AsyncResult<T, E2>; key?: string }\n ): Promise<T> => {\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.withFallback() requires an explicit string ID as the first argument. ' +\n 'Example: step.withFallback(\"getUser\", () => fetchUser(id), { fallback: () => fetchFromCache(id) })'\n );\n }\n\n const stepKey = options.key ?? id;\n const stepName = id;\n const stepId = generateStepId(stepKey);\n const hasEventListeners = onEvent;\n\n return (async () => {\n const startTime = hasEventListeners ? performance.now() : 0;\n\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n });\n }\n\n // Try the primary operation\n let primaryResult: Result<T, E1>;\n try {\n primaryResult = await operation();\n } catch (thrown) {\n // If it's an earlyExit from a nested step, propagate\n if (isEarlyExitE(thrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n throw thrown;\n }\n\n // Primary threw — map to UNEXPECTED_ERROR\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(thrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n\n // If `on` is specified, only run fallback if it matches the mapped error\n if (options.on !== undefined && options.on !== mappedError) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: mappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mappedError, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown });\n }\n\n // Run fallback for thrown error\n let fallbackResultFromThrow: Result<T, E2>;\n try {\n fallbackResultFromThrow = await options.fallback();\n } catch (fallbackThrown) {\n if (isEarlyExitE(fallbackThrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n throw fallbackThrown;\n }\n let fallbackMappedError: E | UnexpectedError;\n try {\n fallbackMappedError = effectiveCatchUnexpected(fallbackThrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: fallbackMappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(fallbackMappedError, { cause: fallbackThrown }),\n meta: { origin: \"throw\", thrown: fallbackThrown },\n });\n }\n onError?.(fallbackMappedError as E, stepName, context);\n throw earlyExit(fallbackMappedError as E, { origin: \"throw\", thrown: fallbackThrown });\n }\n\n if (fallbackResultFromThrow.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: fallbackResultFromThrow,\n meta: { origin: \"fallback\" as const, fallbackUsed: true as const, fallbackReason: String(mappedError) },\n });\n }\n return fallbackResultFromThrow.value;\n } else {\n // Fallback also failed\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(fallbackResultFromThrow.error, {\n origin: \"result\",\n resultCause: fallbackResultFromThrow.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: fallbackResultFromThrow,\n meta: { origin: \"result\", resultCause: fallbackResultFromThrow.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: fallbackResultFromThrow.cause,\n });\n }\n }\n\n // Primary returned a result (didn't throw)\n if (primaryResult.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: primaryResult,\n });\n }\n return primaryResult.value;\n }\n\n // Primary returned an error\n const primaryError = primaryResult.error;\n\n // If `on` is specified and doesn't match, earlyExit with primary error (no fallback)\n if (options.on !== undefined && options.on !== primaryError) {\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(primaryError, {\n origin: \"result\",\n resultCause: primaryResult.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: primaryResult,\n meta: { origin: \"result\", resultCause: primaryResult.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: primaryResult.cause,\n });\n }\n\n // Run fallback\n let fallbackResult: Result<T, E2>;\n try {\n fallbackResult = await options.fallback();\n } catch (thrown) {\n if (isEarlyExitE(thrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n throw thrown;\n }\n // Fallback threw — map via effectiveCatchUnexpected\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(thrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: mappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mappedError, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown });\n }\n\n if (fallbackResult.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: fallbackResult,\n meta: { origin: \"fallback\" as const, fallbackUsed: true as const, fallbackReason: String(primaryError) },\n });\n }\n return fallbackResult.value;\n }\n\n // Fallback also returned an error\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(fallbackResult.error, {\n origin: \"result\",\n resultCause: fallbackResult.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: fallbackResult,\n meta: { origin: \"result\", resultCause: fallbackResult.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: fallbackResult.cause,\n });\n })();\n };\n\n // step.withResource: Acquire/use/release lifecycle with guaranteed release\n stepFn.withResource = <T, R, AcquireE, UseE>(\n id: string,\n options: {\n acquire: () => AsyncResult<R, AcquireE>;\n use: (resource: R) => AsyncResult<T, UseE>;\n release: (resource: R) => void | Promise<void>;\n }\n ): Promise<T> => {\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.withResource() requires an explicit string ID as the first argument. ' +\n 'Example: step.withResource(\"useDb\", { acquire: () => connect(), use: (db) => query(db), release: (db) => db.close() })'\n );\n }\n\n const stepKey = id;\n const stepName = id;\n const stepId = generateStepId(stepKey);\n const hasEventListeners = onEvent;\n\n return (async () => {\n const startTime = hasEventListeners ? performance.now() : 0;\n\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n });\n }\n\n // Acquire\n let acquireResult: Result<R, AcquireE>;\n try {\n acquireResult = await options.acquire();\n } catch (thrown) {\n if (isEarlyExitE(thrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n throw thrown;\n }\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(thrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: mappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mappedError, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown });\n }\n\n if (!acquireResult.ok) {\n // Acquire failed — no release needed\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(acquireResult.error, {\n origin: \"result\",\n resultCause: acquireResult.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: acquireResult,\n meta: { origin: \"result\", resultCause: acquireResult.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: acquireResult.cause,\n });\n }\n\n const resource = acquireResult.value;\n let useResult: Result<T, UseE> | undefined;\n let useThrown: unknown;\n let useThrewNonResult = false;\n\n // Use\n try {\n useResult = await options.use(resource);\n } catch (thrown) {\n if (isEarlyExitE(thrown)) {\n // Release before propagating\n try {\n await options.release(resource);\n } catch (releaseErr) {\n console.warn(\n `[awaitly] step.withResource(\"${id}\"): release threw after earlyExit:`,\n releaseErr\n );\n }\n throw thrown;\n }\n useThrown = thrown;\n useThrewNonResult = true;\n }\n\n // Release — ALWAYS runs after use (unless acquire failed)\n try {\n await options.release(resource);\n } catch (releaseErr) {\n console.warn(\n `[awaitly] step.withResource(\"${id}\"): release threw:`,\n releaseErr\n );\n }\n\n // Emit events AFTER release completes\n if (useThrewNonResult) {\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(useThrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: mappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mappedError, { cause: useThrown }),\n meta: { origin: \"throw\", thrown: useThrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown: useThrown });\n }\n\n // useResult is defined if useThrewNonResult is false\n const result = useResult!;\n if (result.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result,\n });\n }\n return result.value;\n }\n\n // Use returned an error\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(result.error, {\n origin: \"result\",\n resultCause: result.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result,\n meta: { origin: \"result\", resultCause: result.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n })();\n };\n\n const step = stepFn as RunStep<E | UnexpectedError>;\n const value = await fn({ step });\n\n // Dev-only warning: Detect common mistake of returning ok() or err() from executor\n if (\n process.env.NODE_ENV !== \"production\" &&\n value !== null &&\n typeof value === \"object\" &&\n \"ok\" in value &&\n typeof (value as { ok: unknown }).ok === \"boolean\"\n ) {\n const maybeResult = value as { ok: boolean; value?: unknown; error?: unknown };\n if (\n (maybeResult.ok === true && \"value\" in maybeResult) ||\n (maybeResult.ok === false && \"error\" in maybeResult)\n ) {\n console.warn(\n `awaitly: Workflow executor returned a Result-like object. ` +\n `Return raw values, not ok() or err().\\n\\n` +\n ` Incorrect: return ok({ data });\\n` +\n ` Correct: return { data };\\n\\n` +\n `See: https://jagreehal.github.io/awaitly/guides/troubleshooting/#returning-ok-from-workflow-executor-double-wrapping`\n );\n }\n }\n\n return ok(value);\n } catch (error) {\n // If a catchUnexpected mapper threw, propagate without re-processing\n if (isMapperException(error)) {\n throw error.thrown;\n }\n\n if (isEarlyExitE(error)) {\n // Extract original cause from early exit metadata\n const originalCause = error.meta.origin === \"throw\"\n ? error.meta.thrown\n : error.meta.origin === \"result\"\n ? error.meta.resultCause\n : undefined;\n\n return err(error.error, { cause: originalCause });\n }\n\n const mapped = effectiveCatchUnexpected(error);\n onError?.(mapped as E, \"unexpected\", context);\n return err(mapped, { cause: error });\n }\n}\n\n/**\n * Convenience for run() with catchUnexpected: closed union Result<T, E>.\n * You must provide catchUnexpected to map uncaught exceptions to E.\n */\nrun.strict = <T, E, C = void>(\n fn: (context: { step: RunStep<E> }) => Promise<T> | T,\n options: {\n onError?: (error: E, stepName?: string, ctx?: C) => void;\n /**\n * Listener for workflow events (start, success, error, step events).\n *\n * Note: Context is available both on `event.context` and as the separate `ctx` parameter.\n * The `ctx` parameter is provided for convenience and backward compatibility.\n */\n onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;\n catchUnexpected: (cause: unknown) => E;\n workflowId?: string;\n context?: C;\n /** @internal External signal for workflow-level cancellation. */\n _workflowSignal?: AbortSignal;\n }\n): AsyncResult<T, E, unknown> => {\n return run<T, E, C>(fn, options);\n};\n\n// =============================================================================\n// Unwrap Utilities\n// =============================================================================\n\n/**\n * Error thrown when `unwrap()` is called on an error Result.\n *\n * This error is thrown to prevent silent failures when using `unwrap()`.\n * Prefer using `unwrapOr`, `unwrapOrElse`, or pattern matching with `match` or `isOk`/`isErr`.\n */\nexport class UnwrapError<E = unknown, C = unknown> extends Error {\n constructor(\n public readonly error: E,\n public readonly cause?: C\n ) {\n super(`Unwrap called on an error result: ${String(error)}`);\n this.name = \"UnwrapError\";\n }\n}\n\n/**\n * Unwraps a Result, throwing an error if it's a failure.\n *\n * @remarks When to use: Only at boundaries or tests where a failure should be fatal.\n *\n * ## When to Use\n *\n * Use `unwrap()` when:\n * - You're certain the Result is successful (e.g., after checking with `isOk`)\n * - You're in a context where errors should crash (e.g., tests, initialization)\n * - You need the value immediately and can't handle errors gracefully\n *\n * ## Why Avoid This\n *\n * **Prefer alternatives** in production code:\n * - `unwrapOr(defaultValue)` - Provide a fallback value\n * - `unwrapOrElse(fn)` - Compute fallback from error\n * - `match()` - Handle both cases explicitly\n * - `isOk()` / `isErr()` - Type-safe pattern matching\n *\n * Throwing errors makes error handling harder and can crash your application.\n *\n * @param r - The Result to unwrap\n * @returns The success value if the Result is successful\n * @throws {UnwrapError} If the Result is an error (includes the error and cause)\n *\n * @example\n * ```typescript\n * // Safe usage after checking\n * const result = someOperation();\n * if (isOk(result)) {\n * const value = unwrap(result); // Safe - we know it's ok\n * }\n *\n * // Unsafe usage (not recommended)\n * const value = unwrap(someOperation()); // May throw!\n * ```\n */\nexport const unwrap = <T, E, C>(r: Result<T, E, C>): T => {\n if (r.ok) return r.value;\n throw new UnwrapError<E, C>(r.error, r.cause);\n};\n\n/**\n * Unwraps a Result, returning a default value if it's a failure.\n *\n * @remarks When to use: Provide a safe fallback without branching.\n *\n * ## When to Use\n *\n * Use `unwrapOr()` when:\n * - You have a sensible default value for errors\n * - You want to continue execution even on failure\n * - The default value is cheap to compute (use `unwrapOrElse` if expensive)\n *\n * ## Why Use This\n *\n * - **Safe**: Never throws, always returns a value\n * - **Simple**: One-liner for common error handling\n * - **Type-safe**: TypeScript knows you'll always get a `T`\n *\n * @param r - The Result to unwrap\n * @param defaultValue - The value to return if the Result is an error\n * @returns The success value if successful, otherwise the default value\n *\n * @example\n * ```typescript\n * // Provide default for missing data\n * const user = unwrapOr(fetchUser(id), { id: 'anonymous', name: 'Guest' });\n *\n * // Provide default for numeric operations\n * const count = unwrapOr(parseCount(input), 0);\n *\n * // Provide default for optional features\n * const config = unwrapOr(loadConfig(), getDefaultConfig());\n * ```\n */\nexport const unwrapOr = <T, E, C>(r: Result<T, E, C>, defaultValue: T): T =>\n r.ok ? r.value : defaultValue;\n\n/**\n * Unwraps a Result, computing a default value from the error if it's a failure.\n *\n * @remarks When to use: Compute a fallback from the error (logging, metrics, or derived defaults).\n *\n * ## When to Use\n *\n * Use `unwrapOrElse()` when:\n * - The default value is expensive to compute (lazy evaluation)\n * - You need to log or handle the error before providing a default\n * - The default depends on the error type or cause\n * - You want to transform the error into a success value\n *\n * ## Why Use This Instead of `unwrapOr`\n *\n * - **Lazy**: Default is only computed if needed (better performance)\n * - **Error-aware**: You can inspect the error before providing default\n * - **Flexible**: Default can depend on error type or cause\n *\n * @param r - The Result to unwrap\n * @param fn - Function that receives the error and optional cause, returns the default value\n * @returns The success value if successful, otherwise the result of calling `fn(error, cause)`\n *\n * @example\n * ```typescript\n * // Compute default based on error type\n * const port = unwrapOrElse(parsePort(env.PORT), (error) => {\n * if (error === 'INVALID_FORMAT') return 3000;\n * if (error === 'OUT_OF_RANGE') return 8080;\n * return 4000; // default\n * });\n *\n * // Log error before providing default\n * const data = unwrapOrElse(fetchData(), (error, cause) => {\n * console.error('Failed to fetch:', error, cause);\n * return getCachedData();\n * });\n *\n * // Transform error into success value\n * const result = unwrapOrElse(operation(), (error) => {\n * return { success: false, reason: String(error) };\n * });\n * ```\n */\nexport const unwrapOrElse = <T, E, C>(\n r: Result<T, E, C>,\n fn: (error: E, cause?: C) => T\n): T => (r.ok ? r.value : fn(r.error, r.cause));\n\n/**\n * Alias for `unwrap`. Returns the success value or throws.\n *\n * The Result is already computed; use when you want the value or throw (e.g. at boundaries or in tests).\n *\n * @param r - The Result to unwrap\n * @returns The success value if the Result is successful\n * @throws {UnwrapError} If the Result is an error (includes the error and cause)\n */\nexport const runOrThrow = <T, E, C>(r: Result<T, E, C>): T => unwrap(r);\n\n/**\n * Awaits a Promise of a Result, then returns the success value or rejects.\n *\n * The returned promise **resolves with T** on success and **rejects with UnwrapError** on failure.\n * UnwrapError extends Error and carries the original `error` and `cause` from the Err.\n *\n * @param ar - A Promise or thenable that resolves to a Result\n * @returns A Promise that resolves with the success value or rejects with UnwrapError\n */\nexport const runOrThrowAsync = <T, E, C>(\n ar: PromiseLike<Result<T, E, C>>\n): Promise<T> => Promise.resolve(ar).then(unwrap);\n\n/**\n * Convenience alias for `unwrapOr(r, null)`. Returns the success value or null.\n *\n * @param r - The Result to unwrap\n * @returns The success value if successful, otherwise null\n */\nexport const runOrNull = <T, E, C>(r: Result<T, E, C>): T | null =>\n r.ok ? r.value : null;\n\n/**\n * Convenience alias for `unwrapOr(r, undefined)`. Returns the success value or undefined.\n *\n * @param r - The Result to unwrap\n * @returns The success value if successful, otherwise undefined\n */\nexport const runOrUndefined = <T, E, C>(r: Result<T, E, C>): T | undefined =>\n r.ok ? r.value : undefined;\n\n// =============================================================================\n// Wrapping Functions\n// =============================================================================\n\n/**\n * Wraps a synchronous throwing function in a Result.\n *\n * @remarks When to use: Wrap sync code that might throw so exceptions become Err values.\n *\n * ## When to Use\n *\n * Use `from()` when:\n * - You have a synchronous function that throws exceptions\n * - You want to convert exceptions to typed errors\n * - You're integrating with libraries that throw (e.g., JSON.parse, fs.readFileSync)\n * - You need to handle errors without try/catch blocks\n *\n * ## Why Use This\n *\n * - **Type-safe errors**: Convert thrown exceptions to typed Result errors\n * - **No try/catch**: Cleaner code without nested try/catch blocks\n * - **Composable**: Results can be chained with `andThen`, `map`, etc.\n * - **Explicit errors**: Forces you to handle errors explicitly\n *\n * @param fn - The synchronous function to execute (may throw)\n * @returns A Result with the function's return value or the thrown error\n *\n * @example\n * ```typescript\n * // Wrap JSON.parse\n * const parsed = from(() => JSON.parse('{\"key\": \"value\"}'));\n * // parsed: { ok: true, value: { key: \"value\" } }\n *\n * const error = from(() => JSON.parse('invalid'));\n * // error: { ok: false, error: SyntaxError }\n * ```\n */\nexport function from<T>(fn: () => T): Ok<T> | Err<unknown, unknown>;\n/**\n * Wraps a synchronous throwing function in a Result with custom error mapping.\n *\n * Use this overload when you want to map thrown exceptions to your typed error union.\n *\n * @param fn - The synchronous function to execute (may throw)\n * @param onError - Function to map the thrown exception to a typed error\n * @returns A Result with the function's return value or the mapped error\n *\n * @example\n * ```typescript\n * // Map exceptions to typed errors\n * const parsed = from(\n * () => JSON.parse(input),\n * (cause) => ({ type: 'PARSE_ERROR' as const, cause })\n * );\n * // parsed.error: { type: 'PARSE_ERROR', cause: SyntaxError }\n *\n * // Map to simple error codes\n * const value = from(\n * () => riskyOperation(),\n * () => 'OPERATION_FAILED' as const\n * );\n * ```\n */\nexport function from<T, E>(fn: () => T, onError: (cause: unknown) => E): Ok<T> | Err<E, unknown>;\nexport function from<T, E>(fn: () => T, onError?: (cause: unknown) => E) {\n try {\n return ok(fn());\n } catch (cause) {\n return onError ? err(onError(cause), { cause }) : err(cause);\n }\n}\n\n/**\n * Wraps a Promise in a Result, converting rejections to errors.\n *\n * @remarks When to use: Wrap a Promise and keep the raw rejection as Err; use tryAsync to map errors.\n *\n * ## When to Use\n *\n * Use `fromPromise()` when:\n * - You have an existing Promise that might reject\n * - You want to convert Promise rejections to typed errors\n * - You're working with libraries that return Promises (fetch, database clients)\n * - You need to handle rejections without .catch() chains\n *\n * ## Why Use This\n *\n * - **Type-safe errors**: Convert Promise rejections to typed Result errors\n * - **Composable**: Results can be chained with `andThen`, `map`, etc.\n * - **Explicit handling**: Forces you to handle errors explicitly\n * - **No .catch() chains**: Cleaner than Promise.catch() patterns\n *\n * @param promise - The Promise to await (may reject)\n * @returns A Promise resolving to a Result with the resolved value or rejection reason\n *\n * @example\n * ```typescript\n * // Wrap fetch\n * const result = await fromPromise(\n * fetch('/api').then(r => r.json())\n * );\n * // result.ok: true if fetch succeeded, false if rejected\n * ```\n */\nexport function fromPromise<T>(promise: Promise<T>): Promise<Ok<T> | Err<unknown, unknown>>;\n/**\n * Wraps a Promise in a Result with custom error mapping.\n *\n * Use this overload when you want to map Promise rejections to your typed error union.\n *\n * @param promise - The Promise to await (may reject)\n * @param onError - Function to map the rejection reason to a typed error\n * @returns A Promise resolving to a Result with the resolved value or mapped error\n *\n * @example\n * ```typescript\n * // Map fetch errors to typed errors\n * const result = await fromPromise(\n * fetch('/api').then(r => {\n * if (!r.ok) throw new Error(`HTTP ${r.status}`);\n * return r.json();\n * }),\n * () => 'FETCH_FAILED' as const\n * );\n * // result.error: 'FETCH_FAILED' if fetch failed\n *\n * // Map with error details\n * const data = await fromPromise(\n * db.query(sql),\n * (cause) => ({ type: 'DB_ERROR' as const, message: String(cause) })\n * );\n * ```\n */\nexport function fromPromise<T, E>(\n promise: Promise<T>,\n onError: (cause: unknown) => E\n): Promise<Ok<T> | Err<E, unknown>>;\nexport async function fromPromise<T, E>(\n promise: Promise<T>,\n onError?: (cause: unknown) => E\n): Promise<Ok<T> | Err<E, unknown> | Err<unknown, unknown>> {\n try {\n return ok(await promise);\n } catch (cause) {\n return onError ? err(onError(cause), { cause }) : err(cause);\n }\n}\n\n/**\n * Wraps an async function in a Result, catching both thrown exceptions and Promise rejections.\n *\n * @remarks When to use: Wrap async work and map thrown/rejected values into your typed error union.\n *\n * ## When to Use\n *\n * Use `tryAsync()` when:\n * - You have an async function that might throw or reject\n * - You want to convert both exceptions and rejections to typed errors\n * - You're creating new async functions (use `fromPromise` for existing Promises)\n * - You need to handle errors without try/catch or .catch()\n *\n * ## Why Use This Instead of `fromPromise`\n *\n * - **Function form**: Takes a function, not a Promise (lazy evaluation)\n * - **Catches both**: Handles both thrown exceptions and Promise rejections\n * - **Cleaner syntax**: No need to wrap in Promise manually\n *\n * @param fn - The async function to execute (may throw or reject)\n * @returns A Promise resolving to a Result with the function's return value or error\n *\n * @example\n * ```typescript\n * // Wrap async function\n * const result = await tryAsync(async () => {\n * const data = await fetchData();\n * return processData(data);\n * });\n * ```\n */\nexport function tryAsync<T>(fn: () => Promise<T>): AsyncResult<T, unknown>;\n/**\n * Wraps an async function in a Result with custom error mapping.\n *\n * Use this overload when you want to map errors to your typed error union.\n *\n * @param fn - The async function to execute (may throw or reject)\n * @param onError - Function to map the error (exception or rejection) to a typed error\n * @returns A Promise resolving to a Result with the function's return value or mapped error\n *\n * @example\n * ```typescript\n * // Map errors to typed errors\n * const result = await tryAsync(\n * async () => await fetchData(),\n * () => 'FETCH_ERROR' as const\n * );\n *\n * // Map with error details\n * const data = await tryAsync(\n * async () => await processFile(path),\n * (cause) => ({ type: 'PROCESSING_ERROR' as const, cause })\n * );\n * ```\n */\nexport function tryAsync<T, E>(\n fn: () => Promise<T>,\n onError: (cause: unknown) => E\n): AsyncResult<T, E>;\nexport async function tryAsync<T, E>(\n fn: () => Promise<T>,\n onError?: (cause: unknown) => E\n): AsyncResult<T, E | unknown> {\n try {\n return ok(await fn());\n } catch (cause) {\n return onError ? err(onError(cause), { cause }) : err(cause);\n }\n}\n\n/**\n * Converts a nullable value to a Result.\n *\n * @remarks When to use: Turn null/undefined into a typed error before continuing.\n *\n * ## When to Use\n *\n * Use `fromNullable()` when:\n * - You have a value that might be `null` or `undefined`\n * - You want to treat null/undefined as an error case\n * - You're working with APIs that return nullable values (DOM APIs, optional properties)\n * - You want to avoid null checks scattered throughout your code\n *\n * ## Why Use This\n *\n * - **Type-safe**: Converts nullable types to non-nullable Results\n * - **Explicit errors**: Forces you to handle null/undefined cases\n * - **Composable**: Results can be chained with `andThen`, `map`, etc.\n * - **No null checks**: Eliminates need for `if (value == null)` checks\n *\n * @param value - The value that may be null or undefined\n * @param onNull - Function that returns an error when value is null/undefined\n * @returns A Result with the value if not null/undefined, otherwise the error from `onNull`\n *\n * @example\n * ```typescript\n * // Convert DOM element lookup\n * const element = fromNullable(\n * document.getElementById('app'),\n * () => 'ELEMENT_NOT_FOUND' as const\n * );\n *\n * // Convert optional property\n * const userId = fromNullable(\n * user.id,\n * () => 'USER_ID_MISSING' as const\n * );\n *\n * // Convert database query result\n * const record = fromNullable(\n * await db.find(id),\n * () => ({ type: 'NOT_FOUND' as const, id })\n * );\n * ```\n */\nexport function fromNullable<T, E>(\n value: T | null | undefined,\n onNull: () => E\n): Result<T, E> {\n return value != null ? ok(value) : err(onNull());\n}\n\n// =============================================================================\n// Transformers\n// =============================================================================\n\n/**\n * Transforms the success value of a Result.\n *\n * @remarks When to use: Transform only the Ok value while leaving Err untouched.\n *\n * ## When to Use\n *\n * Use `map()` when:\n * - You need to transform a success value to another type\n * - You want to apply a pure function to the value\n * - You're building a pipeline of transformations\n * - The transformation cannot fail (use `andThen` if it can fail)\n *\n * ## Why Use This\n *\n * - **Functional style**: Composable, chainable transformations\n * - **Error-preserving**: Errors pass through unchanged\n * - **Type-safe**: TypeScript tracks the transformation\n * - **No unwrapping**: Avoids manual `if (r.ok)` checks\n *\n * @param r - The Result to transform\n * @param fn - Pure function that transforms the success value (must not throw)\n * @returns A new Result with the transformed value, or the original error if `r` was an error\n *\n * @example\n * ```typescript\n * // Transform numeric value\n * const doubled = map(ok(21), n => n * 2);\n * // doubled: { ok: true, value: 42 }\n *\n * // Transform object property\n * const name = map(fetchUser(id), user => user.name);\n *\n * // Chain transformations\n * const formatted = map(\n * map(parseNumber(input), n => n * 2),\n * n => `Result: ${n}`\n * );\n * ```\n */\nexport function map<T, U>(r: Ok<T>, fn: (value: T) => U): Ok<U>;\nexport function map<T, U, E, C>(r: Err<E, C>, fn: (value: T) => U): Err<E, C>;\nexport function map<T, U, E, C>(r: Result<T, E, C>, fn: (value: T) => U): Result<U, E, C>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function map(r: any, fn: any): any {\n return r.ok ? ok(fn(r.value)) : r;\n}\n\n/**\n * Transforms the error value of a Result.\n *\n * @remarks When to use: Retype or normalize errors while leaving Ok values unchanged.\n *\n * ## When to Use\n *\n * Use `mapError()` when:\n * - You need to normalize or transform error types\n * - You want to convert errors to a different error type\n * - You're building error handling pipelines\n * - You need to format error messages or codes\n *\n * ## Why Use This\n *\n * - **Error normalization**: Convert errors to a common format\n * - **Type transformation**: Change error type while preserving value type\n * - **Composable**: Can be chained with other transformers\n * - **Success-preserving**: Success values pass through unchanged\n *\n * @param r - The Result to transform\n * @param fn - Function that transforms the error value (must not throw)\n * @returns A new Result with the original value, or the transformed error if `r` was an error\n *\n * @example\n * ```typescript\n * // Normalize error codes\n * const normalized = mapError(err('not_found'), e => e.toUpperCase());\n * // normalized: { ok: false, error: 'NOT_FOUND' }\n *\n * // Convert error types\n * const typed = mapError(\n * err('404'),\n * code => ({ type: 'HTTP_ERROR' as const, status: parseInt(code) })\n * );\n *\n * // Format error messages\n * const formatted = mapError(\n * err('PARSE_ERROR'),\n * code => `Failed to parse: ${code}`\n * );\n * ```\n */\nexport function mapError<T, E, F, C>(\n r: Result<T, E, C>,\n fn: (error: E) => F\n): Result<T, F, C> {\n return r.ok ? r : err(fn(r.error), { cause: r.cause });\n}\n\n/**\n * Pattern matches on a Result, calling the appropriate handler.\n *\n * @remarks When to use: Handle both Ok and Err in a single expression that returns a value.\n *\n * ## When to Use\n *\n * Use `match()` when:\n * - You need to handle both success and error cases\n * - You want to transform a Result to a different type\n * - You need exhaustive handling (both cases must be handled)\n * - You're building user-facing messages or responses\n *\n * ## Why Use This\n *\n * - **Exhaustive**: Forces you to handle both success and error cases\n * - **Type-safe**: TypeScript ensures both handlers are provided\n * - **Functional**: Pattern matching style, similar to Rust's `match` or Haskell's `case`\n * - **Single expression**: Can be used in expressions, not just statements\n *\n * @param r - The Result to match\n * @param handlers - Object with `ok` and `err` handler functions\n * @param handlers.ok - Function called with the success value\n * @param handlers.err - Function called with the error and optional cause\n * @returns The return value of the appropriate handler (both must return the same type `R`)\n *\n * @example\n * ```typescript\n * // Build user-facing messages\n * const message = match(result, {\n * ok: (user) => `Hello ${user.name}`,\n * err: (error) => `Error: ${error}`,\n * });\n *\n * // Transform to API response\n * const response = match(operation(), {\n * ok: (data) => ({ status: 200, body: data }),\n * err: (error) => ({ status: 400, error: String(error) }),\n * });\n *\n * // Handle with cause\n * const response = match(result, {\n * ok: (value) => ({ status: 'success', data: value }),\n * err: (error, cause) => ({ status: 'error', error, cause }),\n * });\n * ```\n */\nexport function match<T, E, C, R>(r: Ok<T>, handlers: { ok: (value: T) => R; err: (error: E, cause?: C) => R }): R;\nexport function match<T, E, C, R>(r: Err<E, C>, handlers: { ok: (value: T) => R; err: (error: E, cause?: C) => R }): R;\nexport function match<T, E, C, R>(r: Result<T, E, C>, handlers: { ok: (value: T) => R; err: (error: E, cause?: C) => R }): R;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function match(r: any, handlers: any): any {\n return r.ok ? handlers.ok(r.value) : handlers.err(r.error, r.cause);\n}\n\n/**\n * Chains Results together (flatMap/monadic bind).\n *\n * @remarks When to use: Chain dependent operations that return Result without nested branching.\n *\n * ## When to Use\n *\n * Use `andThen()` when:\n * - You need to chain operations that can fail\n * - The next operation depends on the previous success value\n * - You're building a pipeline of dependent operations\n * - You want to avoid nested `if (r.ok)` checks\n *\n * ## Why Use This Instead of `map`\n *\n * - **Can fail**: The chained function returns a Result (can fail)\n * - **Short-circuits**: If first Result fails, second operation never runs\n * - **Error accumulation**: Errors from both operations are in the union\n * - **Composable**: Can chain multiple operations together\n *\n * ## Common Pattern\n *\n * This is the fundamental building block for Result pipelines:\n * ```typescript\n * andThen(operation1(), value1 =>\n * andThen(operation2(value1), value2 =>\n * ok({ value1, value2 })\n * )\n * )\n * ```\n *\n * @param r - The first Result\n * @param fn - Function that takes the success value and returns a new Result (may fail)\n * @returns The Result from `fn` if `r` was successful, otherwise the original error\n *\n * @example\n * ```typescript\n * // Chain dependent operations\n * const userPosts = andThen(\n * fetchUser('1'),\n * user => fetchPosts(user.id)\n * );\n *\n * // Build complex pipelines\n * const result = andThen(parseInput(input), parsed =>\n * andThen(validate(parsed), validated =>\n * process(validated)\n * )\n * );\n *\n * // Chain with different error types\n * const data = andThen(\n * fetchUser(id), // Returns Result<User, 'FETCH_ERROR'>\n * user => fetchPosts(user.id) // Returns Result<Post[], 'NOT_FOUND'>\n * );\n * // data.error: 'FETCH_ERROR' | 'NOT_FOUND'\n * ```\n */\nexport function andThen<T, U>(r: Ok<T>, fn: (value: T) => Ok<U>): Ok<U>;\nexport function andThen<T, F, C2>(r: Ok<T>, fn: (value: T) => Err<F, C2>): Err<F, C2>;\nexport function andThen<T, U, F, C2>(r: Ok<T>, fn: (value: T) => Result<U, F, C2>): Result<U, F, C2>;\nexport function andThen<T, U, E, F, C1, C2>(r: Err<E, C1>, fn: (value: T) => Result<U, F, C2>): Err<E, C1>;\nexport 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>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function andThen(r: any, fn: any): any {\n return r.ok ? fn(r.value) : r;\n}\n\n/**\n * Executes a side effect on a successful Result without changing it.\n *\n * @remarks When to use: Add side effects (logging, metrics) on Ok without changing the Result.\n *\n * ## When to Use\n *\n * Use `tap()` when:\n * - You need to log, debug, or observe success values\n * - You want to perform side effects in a pipeline\n * - You need to mutate external state based on success\n * - You're debugging and want to inspect values without breaking the chain\n *\n * ## Why Use This\n *\n * - **Non-breaking**: Doesn't change the Result, just performs side effect\n * - **Composable**: Can be inserted anywhere in a pipeline\n * - **Type-preserving**: Returns the same Result type\n * - **Lazy**: Side effect only runs if Result is successful\n *\n * @param r - The Result to tap\n * @param fn - Side effect function called with the success value (return value ignored)\n * @returns The original Result unchanged (for chaining)\n *\n * @example\n * ```typescript\n * // Log success values\n * const logged = tap(result, user => console.log('Got user:', user.name));\n * // logged === result, but console.log was called\n *\n * // Debug in pipeline\n * const debugged = pipe(\n * fetchUser(id),\n * r => tap(r, user => console.log('Fetched:', user)),\n * r => map(r, user => user.name)\n * );\n *\n * // Mutate external state\n * const tracked = tap(result, data => {\n * analytics.track('operation_success', data);\n * });\n * ```\n */\nexport function tap<T, E, C>(\n r: Result<T, E, C>,\n fn: (value: T) => void\n): Result<T, E, C> {\n if (r.ok) fn(r.value);\n return r;\n}\n\n/**\n * Executes a side effect on an error Result without changing it.\n *\n * @remarks When to use: Add side effects (logging, metrics) on Err without changing the Result.\n *\n * ## When to Use\n *\n * Use `tapError()` when:\n * - You need to log, debug, or observe error values\n * - You want to perform side effects on errors in a pipeline\n * - You need to report errors to external systems (logging, monitoring)\n * - You're debugging and want to inspect errors without breaking the chain\n *\n * ## Why Use This\n *\n * - **Non-breaking**: Doesn't change the Result, just performs side effect\n * - **Composable**: Can be inserted anywhere in a pipeline\n * - **Type-preserving**: Returns the same Result type\n * - **Lazy**: Side effect only runs if Result is an error\n *\n * @param r - The Result to tap\n * @param fn - Side effect function called with the error and optional cause (return value ignored)\n * @returns The original Result unchanged (for chaining)\n *\n * @example\n * ```typescript\n * // Log errors\n * const logged = tapError(result, (error, cause) => {\n * console.error('Error:', error, cause);\n * });\n *\n * // Report to error tracking\n * const tracked = tapError(result, (error, cause) => {\n * errorTracker.report(error, cause);\n * });\n *\n * // Debug in pipeline\n * const debugged = pipe(\n * operation(),\n * r => tapError(r, (err, cause) => console.error('Failed:', err)),\n * r => mapError(r, err => 'FORMATTED_ERROR')\n * );\n * ```\n */\nexport function tapError<T, E, C>(\n r: Result<T, E, C>,\n fn: (error: E, cause?: C) => void\n): Result<T, E, C> {\n if (!r.ok) fn(r.error, r.cause);\n return r;\n}\n\n/**\n * Transforms the success value of a Result, catching any errors thrown by the transform.\n *\n * @remarks When to use: Transform Ok values with a function that might throw and capture the failure.\n *\n * ## When to Use\n *\n * Use `mapTry()` when:\n * - Your transform function might throw exceptions\n * - You want to convert transform errors to typed errors\n * - You're working with libraries that throw (e.g., JSON.parse, Date parsing)\n * - You need to handle both Result errors and transform exceptions\n *\n * ## Why Use This Instead of `map`\n *\n * - **Exception-safe**: Catches exceptions from the transform function\n * - **Error mapping**: Converts thrown exceptions to typed errors\n * - **Dual error handling**: Handles both Result errors and transform exceptions\n *\n * @param result - The Result to transform\n * @param transform - Function to transform the success value (may throw exceptions)\n * @param onError - Function to map thrown exceptions to a typed error\n * @returns A Result with:\n * - Transformed value if both Result and transform succeed\n * - Original error if Result was an error\n * - Transform error if transform threw an exception\n *\n * @example\n * ```typescript\n * // Safe JSON parsing\n * const parsed = mapTry(\n * ok('{\"key\": \"value\"}'),\n * JSON.parse,\n * () => 'PARSE_ERROR' as const\n * );\n *\n * // Safe date parsing\n * const date = mapTry(\n * ok('2024-01-01'),\n * str => new Date(str),\n * () => 'INVALID_DATE' as const\n * );\n *\n * // Transform with error details\n * const processed = mapTry(\n * result,\n * value => riskyTransform(value),\n * (cause) => ({ type: 'TRANSFORM_ERROR' as const, cause })\n * );\n * ```\n */\nexport function mapTry<T, U, E, F, C>(\n result: Result<T, E, C>,\n transform: (value: T) => U,\n onError: (cause: unknown) => F\n): Result<U, E | F, C | unknown> {\n if (!result.ok) return result;\n try {\n return ok(transform(result.value));\n } catch (error) {\n return err(onError(error), { cause: error });\n }\n}\n\n/**\n * Transforms the error value of a Result, catching any errors thrown by the transform.\n *\n * @remarks When to use: Transform errors when the mapping might throw and you want that captured.\n *\n * ## When to Use\n *\n * Use `mapErrorTry()` when:\n * - Your error transform function might throw exceptions\n * - You're doing complex error transformations (e.g., string formatting, object construction)\n * - You want to handle both Result errors and transform exceptions\n * - You need to safely normalize error types\n *\n * ## Why Use This Instead of `mapError`\n *\n * - **Exception-safe**: Catches exceptions from the error transform function\n * - **Error mapping**: Converts thrown exceptions to typed errors\n * - **Dual error handling**: Handles both Result errors and transform exceptions\n *\n * @param result - The Result to transform\n * @param transform - Function to transform the error value (may throw exceptions)\n * @param onError - Function to map thrown exceptions to a typed error\n * @returns A Result with:\n * - Original value if Result was successful\n * - Transformed error if both Result was error and transform succeeded\n * - Transform error if transform threw an exception\n *\n * @example\n * ```typescript\n * // Safe error formatting\n * const formatted = mapErrorTry(\n * err('not_found'),\n * e => e.toUpperCase(), // Might throw if e is not a string\n * () => 'FORMAT_ERROR' as const\n * );\n *\n * // Complex error transformation\n * const normalized = mapErrorTry(\n * result,\n * error => ({ type: 'NORMALIZED', message: String(error) }),\n * () => 'TRANSFORM_ERROR' as const\n * );\n * ```\n */\nexport function mapErrorTry<T, E, F, G, C>(\n result: Result<T, E, C>,\n transform: (error: E) => F,\n onError: (cause: unknown) => G\n): Result<T, F | G, C | unknown> {\n if (result.ok) return result;\n try {\n return err(transform(result.error), { cause: result.cause });\n } catch (error) {\n return err(onError(error), { cause: error });\n }\n}\n\n/**\n * Transforms both the success value and error value of a Result simultaneously.\n *\n * ## When to Use\n *\n * Use `bimap()` when:\n * - You need to transform both success and error in one operation\n * - You're normalizing Results to a common format\n * - You want symmetric transformation of both cases\n * - You're building adapters between different Result types\n *\n * ## Why Use This Instead of `map` + `mapError`\n *\n * - **Single operation**: Transforms both cases in one call\n * - **Clearer intent**: Shows you're handling both cases symmetrically\n * - **Less code**: Avoids chaining map and mapError\n *\n * @param r - The Result to transform\n * @param onOk - Function that transforms the success value\n * @param onErr - Function that transforms the error value\n * @returns A new Result with transformed value or transformed error\n *\n * @example\n * ```typescript\n * // Normalize to API response format\n * const response = bimap(\n * fetchUser(id),\n * user => ({ status: 'success', data: user }),\n * error => ({ status: 'error', code: error })\n * );\n *\n * // Transform types\n * const stringified = bimap(\n * parseNumber(input),\n * n => `Value: ${n}`,\n * e => `Error: ${e}`\n * );\n *\n * // Adapt between error types\n * const adapted = bimap(\n * externalResult,\n * value => internalValue(value),\n * error => internalError(error)\n * );\n * ```\n */\nexport function bimap<T, U, E, F, C>(\n r: Result<T, E, C>,\n onOk: (value: T) => U,\n onErr: (error: E) => F\n): Result<U, F, C> {\n return r.ok ? ok(onOk(r.value)) : err(onErr(r.error), { cause: r.cause });\n}\n\n/**\n * Recovers from an error by returning a new Result.\n * Similar to neverthrow's `.orElse()`.\n *\n * @remarks When to use: Recover from Err by returning a fallback Result or retyping the error.\n *\n * ## When to Use\n *\n * Use `orElse()` when:\n * - You want to recover from errors with fallback operations\n * - The recovery might also fail (returns a Result)\n * - You need to chain fallback strategies\n * - You're implementing retry or fallback patterns\n *\n * ## Why Use This\n *\n * - **Fallback chains**: Try alternative operations on failure\n * - **Error recovery**: Convert errors to success with fallback values\n * - **Composable**: Can chain multiple orElse calls for cascading fallbacks\n * - **Type-safe**: TypeScript tracks the error union through recovery\n *\n * @param r - The Result to potentially recover from\n * @param fn - Function that takes the error and returns a new Result (may succeed or fail)\n * @returns The original Result if successful, or the result of the recovery function\n *\n * @example\n * ```typescript\n * // Fallback to default user\n * const user = orElse(\n * fetchUser(id),\n * error => error === 'NOT_FOUND' ? ok(defaultUser) : err(error)\n * );\n *\n * // Try cache, then database, then fail\n * const data = orElse(\n * orElse(\n * fetchFromCache(key),\n * () => fetchFromDatabase(key)\n * ),\n * () => err('DATA_UNAVAILABLE' as const)\n * );\n *\n * // Convert specific errors to success\n * const result = orElse(\n * riskyOperation(),\n * error => error.code === 'RETRY' ? ok(defaultValue) : err(error)\n * );\n * ```\n */\nexport function orElse<T, E, E2, C, C2>(\n r: Result<T, E, C>,\n fn: (error: E, cause?: C) => Result<T, E2, C2>\n): Result<T, E2, C2> {\n return r.ok ? r : fn(r.error, r.cause);\n}\n\n/**\n * Async version of orElse for recovering from errors with async operations.\n *\n * @param r - The Result or AsyncResult to potentially recover from\n * @param fn - Async function that takes the error and returns a new Result\n * @returns Promise of the original Result if successful, or the result of the recovery function\n *\n * @example\n * ```typescript\n * // Try primary API, fall back to secondary\n * const data = await orElseAsync(\n * await fetchFromPrimaryApi(),\n * async (error) => {\n * if (error === 'UNAVAILABLE') {\n * return await fetchFromSecondaryApi();\n * }\n * return err(error);\n * }\n * );\n * ```\n */\nexport async function orElseAsync<T, E, E2, C, C2>(\n r: Result<T, E, C> | Promise<Result<T, E, C>>,\n fn: (error: E, cause?: C) => Result<T, E2, C2> | Promise<Result<T, E2, C2>>\n): Promise<Result<T, E2, C2>> {\n const resolved = await r;\n return resolved.ok ? resolved : fn(resolved.error, resolved.cause);\n}\n\n/**\n * Recovers from an error by returning a plain value (not a Result).\n * Useful when you want to provide a default value on error.\n *\n * ## When to Use\n *\n * Use `recover()` when:\n * - You want to provide a fallback value on error\n * - Recovery cannot fail (unlike orElse which returns a Result)\n * - You're implementing default value patterns\n * - You want to guarantee a successful Result\n *\n * ## Why Use This Instead of `orElse`\n *\n * - **Simpler**: Recovery function returns plain value, not Result\n * - **Guaranteed success**: Always returns ok() after recovery\n * - **Clearer intent**: Shows recovery cannot fail\n *\n * @param r - The Result to potentially recover from\n * @param fn - Function that takes the error and returns a recovery value\n * @returns The original Result if successful, or ok(recoveryValue) if error\n *\n * @example\n * ```typescript\n * // Provide default user on NOT_FOUND\n * const user = recover(\n * fetchUser(id),\n * error => error === 'NOT_FOUND' ? defaultUser : guestUser\n * );\n *\n * // Convert all errors to default\n * const config = recover(\n * loadConfig(),\n * () => defaultConfig\n * );\n *\n * // Recover with error-based defaults\n * const value = recover(\n * parseNumber(input),\n * error => error === 'EMPTY' ? 0 : -1\n * );\n * ```\n */\nexport function recover<T, E, C>(\n r: Result<T, E, C>,\n fn: (error: E, cause?: C) => T\n): Ok<T> {\n return r.ok ? ok(r.value) : ok(fn(r.error, r.cause));\n}\n\n/**\n * Async version of recover for recovering with async operations.\n *\n * @param r - The Result or AsyncResult to potentially recover from\n * @param fn - Async function that takes the error and returns a recovery value\n * @returns Promise of ok(value) - either original or recovered\n *\n * @example\n * ```typescript\n * // Recover by fetching default from API\n * const user = await recoverAsync(\n * await fetchUser(id),\n * async (error) => await fetchDefaultUser()\n * );\n * ```\n */\nexport async function recoverAsync<T, E, C>(\n r: Result<T, E, C> | Promise<Result<T, E, C>>,\n fn: (error: E, cause?: C) => T | Promise<T>\n): Promise<Ok<T>> {\n const resolved = await r;\n if (resolved.ok) return ok(resolved.value);\n return ok(await fn(resolved.error, resolved.cause));\n}\n\n// =============================================================================\n// Result Hydration (Serialization)\n// =============================================================================\n\n/**\n * Validates and type-narrows a value to a Result.\n *\n * Since this library uses plain objects for Results, serialization is trivial -\n * the serialized form IS the Result. This function validates the structure and\n * provides type-safe narrowing.\n *\n * ## When to Use\n *\n * Use `hydrate()` when:\n * - Receiving Results over RPC/network\n * - Deserializing Results from storage\n * - Validating untrusted data as Results\n *\n * @param value - The unknown value to validate as a Result\n * @returns The value as a typed Result, or null if invalid\n *\n * @example\n * ```typescript\n * // Deserialize from JSON\n * const parsed = JSON.parse(jsonString);\n * const result = hydrate<User, ApiError>(parsed);\n * if (result) {\n * // result is Result<User, ApiError>\n * }\n *\n * // Validate RPC response\n * const rpcResponse = await fetchFromService();\n * const result = hydrate<Data, ServiceError>(rpcResponse);\n * ```\n */\nexport function hydrate<T, E, C = unknown>(value: unknown): Result<T, E, C> | null {\n if (\n value !== null &&\n typeof value === \"object\" &&\n \"ok\" in value &&\n typeof value.ok === \"boolean\"\n ) {\n if (value.ok === true && \"value\" in value) {\n return value as Result<T, E, C>;\n }\n if (value.ok === false && \"error\" in value) {\n return value as Result<T, E, C>;\n }\n }\n return null;\n}\n\n/**\n * Type guard to check if a value is a valid serialized Result.\n *\n * @param value - The value to check\n * @returns True if the value is a valid Result structure\n *\n * @example\n * ```typescript\n * if (isSerializedResult(data)) {\n * // data is Result<unknown, unknown, unknown>\n * if (data.ok) {\n * console.log(data.value);\n * }\n * }\n * ```\n */\nexport function isSerializedResult(\n value: unknown\n): value is Result<unknown, unknown, unknown> {\n return hydrate(value) !== null;\n}\n\n// =============================================================================\n// Batch Operations\n// =============================================================================\n\ntype AllValues<T extends readonly Result<unknown, unknown, unknown>[]> = {\n [K in keyof T]: T[K] extends Ok<infer V>\n ? V\n : T[K] extends Err<unknown, unknown>\n ? never\n : T[K] extends Result<infer V, unknown, unknown>\n ? V\n : never;\n};\ntype AllErrors<T extends readonly Result<unknown, unknown, unknown>[]> = {\n [K in keyof T]: T[K] extends Ok<unknown>\n ? never\n : T[K] extends Err<infer E, unknown>\n ? E\n : T[K] extends Result<unknown, infer E, unknown>\n ? E\n : never;\n}[number];\ntype AllCauses<T extends readonly Result<unknown, unknown, unknown>[]> = {\n [K in keyof T]: T[K] extends Ok<unknown>\n ? never\n : T[K] extends Err<unknown, infer C>\n ? C\n : T[K] extends Result<unknown, unknown, infer C>\n ? C\n : never;\n}[number];\n\n// Conditional type: returns Ok<...> when there are no errors, Result<...> otherwise\n// Note: We only check AllErrors, not AllCauses - causes only matter when there are errors\ntype AllResult<T extends readonly Result<unknown, unknown, unknown>[]> =\n [AllErrors<T>] extends [never]\n ? Ok<AllValues<T>>\n : Result<AllValues<T>, AllErrors<T>, AllCauses<T>>;\n\n/**\n * Combines multiple Results into one, requiring all to succeed.\n *\n * ## When to Use\n *\n * Use `all()` when:\n * - You have multiple independent operations that all must succeed\n * - You want to short-circuit on the first error (fail-fast)\n * - You need all values together (e.g., combining API responses)\n * - Performance matters (stops on first error, doesn't wait for all)\n *\n * ## Why Use This\n *\n * - **Fail-fast**: Stops immediately on first error (better performance)\n * - **Type-safe**: TypeScript infers the array type from input\n * - **Short-circuit**: Doesn't evaluate remaining Results after error\n * - **Composable**: Can be chained with other operations\n *\n * ## Important\n *\n * - **Short-circuits**: Returns first error immediately, doesn't wait for all Results\n * - **All must succeed**: If any Result fails, the entire operation fails\n * - **Use `allSettled`**: If you need to collect all errors (e.g., form validation)\n *\n * @param results - Array of Results to combine (all must succeed)\n * @returns A Result with an array of all success values, or the first error encountered\n *\n * @example\n * ```typescript\n * // Combine multiple successful Results\n * const combined = all([Awaitly.ok(1), Awaitly.ok(2), Awaitly.ok(3)]);\n * // combined: { ok: true, value: [1, 2, 3] }\n *\n * // Short-circuits on first error\n * const error = all([Awaitly.ok(1), Awaitly.err('ERROR'), Awaitly.ok(3)]);\n * // error: { ok: false, error: 'ERROR' }\n * // Note: Awaitly.ok(3) is never evaluated\n *\n * // Combine API responses\n * const data = all([\n * fetchUser(id),\n * fetchPosts(id),\n * fetchComments(id)\n * ]);\n * // data.value: [user, posts, comments] if all succeed\n * ```\n */\nexport function all<const T extends readonly Result<unknown, unknown, unknown>[]>(\n results: T\n): AllResult<T> {\n const values: unknown[] = [];\n for (const result of results) {\n if (!result.ok) {\n return result as unknown as AllResult<T>;\n }\n values.push(result.value);\n }\n return ok(values) as AllResult<T>;\n}\n\n/**\n * Combines multiple Results or Promises of Results into one (async version of `all`).\n *\n * ## When to Use\n *\n * Use `allAsync()` when:\n * - You have multiple async operations that all must succeed\n * - You want to run operations in parallel (better performance)\n * - You want to short-circuit on the first error (fail-fast)\n * - You need all values together from parallel operations\n *\n * ## Why Use This Instead of `all`\n *\n * - **Parallel execution**: All Promises start immediately (faster)\n * - **Async support**: Works with Promises and AsyncResults\n * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`\n *\n * ## Important\n *\n * - **Short-circuits**: Returns first error immediately, cancels remaining operations\n * - **Parallel**: All operations start simultaneously (unlike sequential `andThen`)\n * - **Use `allSettledAsync`**: If you need to collect all errors\n *\n * @param results - Array of Results or Promises of Results to combine (all must succeed)\n * @returns A Promise resolving to a Result with an array of all success values, or the first error\n *\n * @example\n * ```typescript\n * // Parallel API calls\n * const combined = await allAsync([\n * fetchUser('1'),\n * fetchPosts('1'),\n * fetchComments('1')\n * ]);\n * // All three calls start simultaneously\n * // combined: { ok: true, value: [user, posts, comments] } if all succeed\n *\n * // Mix Results and Promises\n * const data = await allAsync([\n * ok(cachedUser), // Already resolved\n * fetchPosts(userId), // Promise\n * ]);\n * ```\n */\nexport async function allAsync<\n const T extends readonly (Result<unknown, unknown, unknown> | Promise<Result<unknown, unknown, unknown>>)[]\n>(\n results: T\n): Promise<\n Result<\n { [K in keyof T]: T[K] extends Result<infer V, unknown, unknown> | Promise<Result<infer V, unknown, unknown>> ? V : never },\n { [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> | Promise<Result<unknown, infer E, unknown>> ? E : never }[number] | PromiseRejectedError,\n { [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> | Promise<Result<unknown, unknown, infer C>> ? C : never }[number] | PromiseRejectionCause\n >\n> {\n type Values = { [K in keyof T]: T[K] extends Result<infer V, unknown, unknown> | Promise<Result<infer V, unknown, unknown>> ? V : never };\n type Errors = { [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> | Promise<Result<unknown, infer E, unknown>> ? E : never }[number] | PromiseRejectedError;\n type Causes = { [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> | Promise<Result<unknown, unknown, infer C>> ? C : never }[number] | PromiseRejectionCause;\n\n if (results.length === 0) {\n return ok([]) as Result<Values, Errors, Causes>;\n }\n\n return new Promise((resolve) => {\n let settled = false;\n let pendingCount = results.length;\n const values: unknown[] = new Array(results.length);\n\n for (let i = 0; i < results.length; i++) {\n const index = i;\n Promise.resolve(results[index])\n .catch((reason) => err(\n { type: \"PROMISE_REJECTED\" as const, cause: reason },\n { cause: { type: \"PROMISE_REJECTION\" as const, reason } as PromiseRejectionCause }\n ))\n .then((result) => {\n if (settled) return;\n\n if (!result.ok) {\n settled = true;\n resolve(result as Result<Values, Errors, Causes>);\n return;\n }\n\n values[index] = result.value;\n pendingCount--;\n\n if (pendingCount === 0) {\n resolve(ok(values) as Result<Values, Errors, Causes>);\n }\n });\n }\n });\n}\n\nexport type SettledError<E, C = unknown> = { error: E; cause?: C };\n\n// Conditional type: returns Ok<...> when there are no errors, Result<...> otherwise\ntype AllSettledResult<T extends readonly Result<unknown, unknown, unknown>[]> =\n [AllErrors<T>] extends [never]\n ? Ok<AllValues<T>>\n : Result<AllValues<T>, SettledError<AllErrors<T>, AllCauses<T>>[]>;\n\n/**\n * Combines multiple Results, collecting all errors instead of short-circuiting.\n *\n * ## When to Use\n *\n * Use `allSettled()` when:\n * - You need to see ALL errors, not just the first one\n * - You're doing form validation (show all field errors)\n * - You want to collect partial results (some succeed, some fail)\n * - You need to process all Results regardless of failures\n *\n * ## Why Use This Instead of `all`\n *\n * - **Collects all errors**: Returns array of all errors, not just first\n * - **No short-circuit**: Evaluates all Results even if some fail\n * - **Partial success**: Can see which operations succeeded and which failed\n * - **Better UX**: Show users all validation errors at once\n *\n * ## Important\n *\n * - **No short-circuit**: All Results are evaluated (slower if many fail early)\n * - **Error array**: Returns array of `{ error, cause }` objects, not single error\n * - **Use `all`**: If you want fail-fast behavior (better performance)\n *\n * @param results - Array of Results to combine (all are evaluated)\n * @returns A Result with:\n * - Array of all success values if all succeed\n * - Array of `{ error, cause }` objects if any fail\n *\n * @example\n * ```typescript\n * // Form validation - show all errors\n * const validated = allSettled([\n * validateEmail(email),\n * validatePassword(password),\n * validateAge(age),\n * ]);\n * // If email and password fail:\n * // { ok: false, error: [\n * // { error: 'INVALID_EMAIL' },\n * // { error: 'WEAK_PASSWORD' }\n * // ]}\n *\n * // Collect partial results\n * const results = allSettled([\n * fetchUser('1'), // succeeds\n * fetchUser('2'), // fails\n * fetchUser('3'), // succeeds\n * ]);\n * // Can see which succeeded and which failed\n * ```\n */\nexport function allSettled<const T extends readonly Result<unknown, unknown, unknown>[]>(\n results: T\n): AllSettledResult<T> {\n const values: unknown[] = [];\n const errors: SettledError<unknown>[] = [];\n\n for (const result of results) {\n if (result.ok) {\n values.push(result.value);\n } else {\n errors.push({ error: result.error, cause: result.cause });\n }\n }\n\n if (errors.length > 0) {\n return err(errors) as unknown as AllSettledResult<T>;\n }\n\n return ok(values) as unknown as AllSettledResult<T>;\n}\n\n/**\n * Splits an array of Results into separate arrays of success values and errors.\n *\n * ## When to Use\n *\n * Use `partition()` when:\n * - You have an array of Results and need to separate successes from failures\n * - You want to process successes and errors separately\n * - You're collecting results from multiple operations (some may fail)\n * - You need to handle partial success scenarios\n *\n * ## Why Use This\n *\n * - **Simple separation**: One call splits successes and errors\n * - **Type-safe**: TypeScript knows `values` is `T[]` and `errors` is `E[]`\n * - **No unwrapping**: Doesn't require manual `if (r.ok)` checks\n * - **Preserves order**: Maintains original array order in both arrays\n *\n * ## Common Pattern\n *\n * Often used after `Promise.all()` with Results:\n * ```typescript\n * const results = await Promise.all(ids.map(id => fetchUser(id)));\n * const { values: users, errors } = partition(results);\n * // Process successful users, handle errors separately\n * ```\n *\n * @param results - Array of Results to partition\n * @returns An object with:\n * - `values`: Array of all success values (type `T[]`)\n * - `errors`: Array of all error values (type `E[]`)\n *\n * @example\n * ```typescript\n * // Split successes and errors\n * const results = [ok(1), err('ERROR_1'), ok(3), err('ERROR_2')];\n * const { values, errors } = partition(results);\n * // values: [1, 3]\n * // errors: ['ERROR_1', 'ERROR_2']\n *\n * // Process batch operations\n * const userResults = await Promise.all(userIds.map(id => fetchUser(id)));\n * const { values: users, errors: fetchErrors } = partition(userResults);\n *\n * // Process successful users\n * users.forEach(user => processUser(user));\n *\n * // Handle errors\n * fetchErrors.forEach(error => logError(error));\n * ```\n */\nexport function partition<T, E, C>(\n results: readonly Result<T, E, C>[]\n): { values: T[]; errors: E[] } {\n const values: T[] = [];\n const errors: E[] = [];\n\n for (const result of results) {\n if (result.ok) {\n values.push(result.value);\n } else {\n errors.push(result.error);\n }\n }\n\n return { values, errors };\n}\n\ntype AnyValue<T extends readonly Result<unknown, unknown, unknown>[]> =\n T[number] extends Result<infer U, unknown, unknown> ? U : never;\ntype AnyErrors<T extends readonly Result<unknown, unknown, unknown>[]> = {\n -readonly [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> ? E : never;\n}[number];\ntype AnyCauses<T extends readonly Result<unknown, unknown, unknown>[]> = {\n -readonly [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> ? C : never;\n}[number];\n\n/**\n * Returns the first successful Result from an array (succeeds fast).\n *\n * ## When to Use\n *\n * Use `any()` when:\n * - You have multiple fallback options and need the first that succeeds\n * - You're trying multiple strategies (e.g., cache → DB → API)\n * - You want fail-fast success (stops on first success)\n * - You have redundant data sources and any one will do\n *\n * ## Why Use This\n *\n * - **Succeeds fast**: Returns immediately on first success (better performance)\n * - **Fallback pattern**: Perfect for trying multiple options\n * - **Short-circuits**: Stops evaluating after first success\n * - **Type-safe**: TypeScript infers the success type\n *\n * ## Important\n *\n * - **First success wins**: Returns first successful Result, ignores rest\n * - **All errors**: If all fail, returns first error (not all errors)\n * - **Empty array**: Returns `EmptyInputError` if array is empty\n * - **Use `all`**: If you need ALL to succeed\n *\n * @param results - Array of Results to check (evaluated in order)\n * @returns The first successful Result, or first error if all fail, or `EmptyInputError` if empty\n *\n * @example\n * ```typescript\n * // Try multiple fallback strategies\n * const data = any([\n * fetchFromCache(id),\n * fetchFromDB(id),\n * fetchFromAPI(id)\n * ]);\n * // Returns first that succeeds\n *\n * // Try multiple formats\n * const parsed = any([\n * parseJSON(input),\n * parseXML(input),\n * parseYAML(input)\n * ]);\n *\n * // All errors case\n * const allErrors = any([err('A'), err('B'), err('C')]);\n * // allErrors: { ok: false, error: 'A' } (first error)\n * ```\n */\nexport function any<const T extends readonly Result<unknown, unknown, unknown>[]>(\n results: T\n): Result<AnyValue<T>, AnyErrors<T> | EmptyInputError, AnyCauses<T>> {\n type ReturnErr = Result<never, AnyErrors<T> | EmptyInputError, AnyCauses<T>>;\n type ReturnOk = Result<AnyValue<T>, never, AnyCauses<T>>;\n\n if (results.length === 0) {\n return err({\n type: \"EMPTY_INPUT\",\n message: \"any() requires at least one Result\",\n }) as ReturnErr;\n }\n let firstError: Result<never, unknown, unknown> | null = null;\n for (const result of results) {\n if (result.ok) return result as ReturnOk;\n if (!firstError) firstError = result;\n }\n return firstError as ReturnErr;\n}\n\ntype AnyAsyncValue<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> =\n Awaited<T[number]> extends Result<infer U, unknown, unknown> ? U : never;\ntype AnyAsyncErrors<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n -readonly [K in keyof T]: Awaited<T[K]> extends Result<unknown, infer E, unknown>\n ? E\n : never;\n}[number];\ntype AnyAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n -readonly [K in keyof T]: Awaited<T[K]> extends Result<unknown, unknown, infer C>\n ? C\n : never;\n}[number];\n\n/**\n * Returns the first successful Result from an array of Results or Promises (async version of `any`).\n *\n * ## When to Use\n *\n * Use `anyAsync()` when:\n * - You have multiple async fallback options and need the first that succeeds\n * - You're trying multiple async strategies in parallel (cache → DB → API)\n * - You want fail-fast success from parallel operations\n * - You have redundant async data sources and any one will do\n *\n * ## Why Use This Instead of `any`\n *\n * - **Parallel execution**: All Promises start immediately (faster)\n * - **Async support**: Works with Promises and AsyncResults\n * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`\n *\n * ## Important\n *\n * - **First success wins**: Returns first successful Result (from any Promise)\n * - **Parallel**: All operations run simultaneously\n * - **All errors**: If all fail, returns first error encountered\n *\n * @param results - Array of Results or Promises of Results to check (all start in parallel)\n * @returns A Promise resolving to the first successful Result, or first error if all fail\n *\n * @example\n * ```typescript\n * // Try multiple async fallbacks in parallel\n * const data = await anyAsync([\n * fetchFromCache(id), // Fastest wins\n * fetchFromDB(id),\n * fetchFromAPI(id)\n * ]);\n *\n * // Try multiple API endpoints\n * const response = await anyAsync([\n * fetch('/api/v1/data'),\n * fetch('/api/v2/data'),\n * fetch('/backup-api/data')\n * ]);\n * ```\n */\nexport async function anyAsync<\n const T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[],\n>(\n results: T\n): Promise<\n Result<AnyAsyncValue<T>, AnyAsyncErrors<T> | EmptyInputError | PromiseRejectedError, AnyAsyncCauses<T> | PromiseRejectionCause>\n> {\n type ReturnErr = Result<\n never,\n AnyAsyncErrors<T> | EmptyInputError | PromiseRejectedError,\n AnyAsyncCauses<T> | PromiseRejectionCause\n >;\n type ReturnOk = Result<AnyAsyncValue<T>, never, AnyAsyncCauses<T>>;\n\n if (results.length === 0) {\n return err({\n type: \"EMPTY_INPUT\",\n message: \"anyAsync() requires at least one Result\",\n }) as ReturnErr;\n }\n\n return new Promise((resolve) => {\n let settled = false;\n let pendingCount = results.length;\n let firstError: Result<never, unknown, unknown> | null = null;\n\n for (const item of results) {\n Promise.resolve(item)\n .catch((reason) =>\n err(\n { type: \"PROMISE_REJECTED\" as const, cause: reason },\n { cause: { type: \"PROMISE_REJECTION\" as const, reason } as PromiseRejectionCause }\n )\n )\n .then((result) => {\n if (settled) return;\n\n if (result.ok) {\n settled = true;\n resolve(result as ReturnOk);\n return;\n }\n\n if (!firstError) firstError = result;\n pendingCount--;\n\n if (pendingCount === 0) {\n resolve(firstError as ReturnErr);\n }\n });\n }\n });\n}\n\ntype AllAsyncValues<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n [K in keyof T]: Awaited<T[K]> extends Result<infer V, unknown, unknown> ? V : never;\n};\ntype AllAsyncErrors<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n [K in keyof T]: Awaited<T[K]> extends Result<unknown, infer E, unknown> ? E : never;\n}[number];\ntype AllAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n [K in keyof T]: Awaited<T[K]> extends Result<unknown, unknown, infer C> ? C : never;\n}[number];\n\n/**\n * Combines multiple Results or Promises of Results, collecting all errors (async version of `allSettled`).\n *\n * ## When to Use\n *\n * Use `allSettledAsync()` when:\n * - You have multiple async operations and need ALL errors reported\n * - You're doing async form validation (show all field errors at once)\n * - You want to run operations in parallel and collect all results\n *\n * ## Behavior\n *\n * **Note:** Unlike `Promise.allSettled()`, this returns a Result:\n * - `ok(values[])` if ALL succeed\n * - `err(SettledError[])` if ANY fail (with all collected errors)\n *\n * This is consistent with awaitly's philosophy - all functions return Results.\n * `Promise.allSettled()` always succeeds with per-item status objects; this function\n * returns a single Result indicating overall success or failure.\n *\n * ## Why Use This Instead of `allSettled`\n *\n * - **Parallel execution**: All Promises start immediately (faster)\n * - **Async support**: Works with Promises and AsyncResults\n * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`\n *\n * ## Important\n *\n * - **No short-circuit**: All operations complete (even if some fail)\n * - **Parallel**: All operations run simultaneously\n * - **Error array**: Returns array of `SettledError` objects (`{ error, cause? }`)\n *\n * @param results - Array of Results or Promises of Results to combine (all are evaluated)\n * @returns A Promise resolving to a Result with:\n * - `ok(values[])` - Array of all success values if ALL succeed\n * - `err(errors[])` - Array of `SettledError` objects if ANY fail\n *\n * @example\n * ```typescript\n * // Async form validation - see all errors at once\n * const validated = await allSettledAsync([\n * validateEmailAsync(email),\n * validatePasswordAsync(password),\n * checkUsernameAvailableAsync(username),\n * ]);\n *\n * if (!validated.ok) {\n * // validated.error is array of all validation failures\n * console.log('Errors:', validated.error.map(e => e.error));\n * }\n *\n * // Parallel API calls with error collection\n * const results = await allSettledAsync([\n * fetchUser('1'),\n * fetchUser('2'),\n * fetchUser('3'),\n * ]);\n * ```\n */\nexport async function allSettledAsync<\n const T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[],\n>(\n results: T\n): Promise<Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>> {\n const settled = await Promise.all(\n results.map((item) =>\n Promise.resolve(item)\n .then((result) => ({ status: \"result\" as const, result }))\n .catch((reason) => ({\n status: \"rejected\" as const,\n error: { type: \"PROMISE_REJECTED\" as const, cause: reason } as PromiseRejectedError,\n cause: { type: \"PROMISE_REJECTION\" as const, reason } as PromiseRejectionCause,\n }))\n )\n );\n\n const values: unknown[] = [];\n const errors: SettledError<unknown, unknown>[] = [];\n\n for (const item of settled) {\n if (item.status === \"rejected\") {\n errors.push({ error: item.error, cause: item.cause });\n } else if (item.result.ok) {\n values.push(item.result.value);\n } else {\n errors.push({ error: item.result.error, cause: item.result.cause });\n }\n }\n\n if (errors.length > 0) {\n return err(errors) as unknown as Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>;\n }\n return ok(values) as unknown as Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>;\n}\n\n/**\n * Combines two Results into a tuple Result.\n *\n * ## When to Use\n *\n * Use `zip()` when:\n * - You have two independent Results and need both values together\n * - You want to combine validation results before processing\n * - You need a pair/tuple from two separate operations\n *\n * ## Why Use This Instead of `all()`\n *\n * - **Simpler types**: Returns `[A, B]` instead of array inference\n * - **Two-argument**: Cleaner API for common case of combining two Results\n * - **Compose with andThen**: Chain multiple zips for complex combinations\n *\n * ## Important\n *\n * - **Short-circuits**: Returns first error if either fails\n * - **Order matters**: If both fail, returns error from first argument\n * - **Use `all()`**: For more than 2 Results\n *\n * @param a - First Result\n * @param b - Second Result\n * @returns A Result containing a tuple `[A, B]` if both succeed, or the first error\n *\n * @example\n * ```typescript\n * // Combine two Results\n * const userResult = await fetchUser('1');\n * const postsResult = await fetchPosts('1');\n * const combined = zip(userResult, postsResult);\n * // combined: Result<[User, Post[]], UserError | PostsError>\n *\n * // Use with andThen for chaining\n * const result = andThen(\n * zip(fetchUser('1'), fetchPosts('1')),\n * ([user, posts]) => createDashboard(user, posts)\n * );\n *\n * // Validation combination\n * const validated = zip(\n * validateEmail(email),\n * validatePassword(password)\n * );\n * if (validated.ok) {\n * const [email, password] = validated.value;\n * createAccount(email, password);\n * }\n * ```\n */\nexport function zip<A, EA, CA, B, EB, CB>(\n a: Result<A, EA, CA>,\n b: Result<B, EB, CB>\n): Result<[A, B], EA | EB, CA | CB> {\n if (!a.ok) return a as Result<never, EA, CA>;\n if (!b.ok) return b as Result<never, EB, CB>;\n return ok([a.value, b.value]) as Result<[A, B], never, never>;\n}\n\n/**\n * Async version of `zip()` - combines two Results or Promises of Results into a tuple.\n *\n * ## When to Use\n *\n * Use `zipAsync()` when:\n * - You have two async operations and need both results together\n * - You want to run two fetches in parallel and combine results\n * - You need to combine Promises of Results into a single Result\n *\n * ## Why Use This Instead of `allAsync()`\n *\n * - **Simpler types**: Returns `[A, B]` instead of array inference\n * - **Two-argument**: Cleaner API for common case of combining two async Results\n * - **Parallel execution**: Both Promises start immediately\n *\n * ## Important\n *\n * - **Parallel**: Both operations run simultaneously (faster than sequential)\n * - **Short-circuits result**: Returns first argument's error if it fails, else second's\n * - **Waits for both**: Both Promises complete before returning (unlike `allAsync` fail-fast)\n * - **Rejection handling**: Promise rejections are wrapped as `PromiseRejectedError`\n * - **Use `allAsync()`**: For more than 2 Results\n *\n * @param a - First Result or Promise of Result\n * @param b - Second Result or Promise of Result\n * @returns A Promise of Result containing a tuple `[A, B]` if both succeed\n *\n * @example\n * ```typescript\n * // Parallel async operations\n * const result = await zipAsync(\n * fetchUser('1'),\n * fetchPosts('1')\n * );\n * // Both fetches run in parallel\n * // result: Result<[User, Post[]], UserError | PostsError>\n *\n * // Mix sync and async\n * const combined = await zipAsync(\n * ok({ cached: true }), // Already resolved\n * fetchFromAPI(id), // Async fetch\n * );\n *\n * // With chaining\n * const dashboard = await zipAsync(fetchUser('1'), fetchPosts('1'))\n * .then(result => andThen(result, ([user, posts]) => createDashboard(user, posts)));\n * ```\n */\nexport async function zipAsync<A, EA, CA, B, EB, CB>(\n a: Result<A, EA, CA> | Promise<Result<A, EA, CA>>,\n b: Result<B, EB, CB> | Promise<Result<B, EB, CB>>\n): AsyncResult<[A, B], EA | EB | PromiseRejectedError, CA | CB | PromiseRejectionCause> {\n // Wrap rejections into PromiseRejectedError (consistent with allAsync)\n const wrapRejection = <T, E, C>(\n p: Result<T, E, C> | Promise<Result<T, E, C>>\n ): Promise<Result<T, E | PromiseRejectedError, C | PromiseRejectionCause>> =>\n Promise.resolve(p).catch((reason) =>\n err(\n { type: \"PROMISE_REJECTED\" as const, cause: reason } as PromiseRejectedError,\n { cause: { type: \"PROMISE_REJECTION\" as const, reason } as PromiseRejectionCause }\n )\n );\n\n const [ra, rb] = await Promise.all([wrapRejection(a), wrapRejection(b)]);\n return zip(ra, rb);\n}\n","/**\n * awaitly/adapters\n *\n * Convenience adapters to wrap common non-Promise async patterns into Results.\n *\n * @example\n * ```typescript\n * import { fromCallback, fromEvent } from 'awaitly/adapters';\n *\n * // Node.js callback style\n * const data = await fromCallback<string>(\n * (cb) => fs.readFile('file.txt', 'utf8', cb)\n * );\n *\n * // One-shot event emitter\n * const response = await fromEvent<Response>(\n * request,\n * { success: 'response', error: 'error' }\n * );\n * ```\n */\n\nimport { ok, err, type AsyncResult } from \"./core\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Standard Node.js error-first callback signature.\n */\nexport type NodeCallback<T> = (error: Error | null | undefined, result: T) => void;\n\n/**\n * Event listener configuration for fromEvent.\n */\nexport type EventConfig = {\n /** Event name that signals success (value is passed to resolve) */\n success: string;\n /** Event name that signals error (value is passed to reject). Optional. */\n error?: string;\n /** Timeout in milliseconds. If exceeded, returns timeout error. Optional. */\n timeout?: number;\n};\n\n/**\n * EventEmitter-like interface (supports Node.js and DOM events).\n */\nexport type EventEmitterLike =\n | { on(event: string, listener: (...args: unknown[]) => void): unknown; off(event: string, listener: (...args: unknown[]) => void): unknown }\n | { addEventListener(event: string, listener: (...args: unknown[]) => void): unknown; removeEventListener(event: string, listener: (...args: unknown[]) => void): unknown };\n\n/**\n * Timeout error returned when fromEvent times out.\n */\nexport type EventTimeoutError = {\n type: \"EVENT_TIMEOUT\";\n event: string;\n timeoutMs: number;\n};\n\n/**\n * Type guard for EventTimeoutError.\n */\nexport function isEventTimeoutError(error: unknown): error is EventTimeoutError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as EventTimeoutError).type === \"EVENT_TIMEOUT\"\n );\n}\n\n/**\n * Error returned when the emitter doesn't have valid event subscription methods.\n */\nexport type InvalidEmitterError = {\n type: \"INVALID_EMITTER\";\n message: string;\n};\n\n/**\n * Type guard for InvalidEmitterError.\n */\nexport function isInvalidEmitterError(error: unknown): error is InvalidEmitterError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as InvalidEmitterError).type === \"INVALID_EMITTER\"\n );\n}\n\n// =============================================================================\n// fromCallback\n// =============================================================================\n\n/**\n * Convert a Node.js callback-style function to AsyncResult.\n *\n * Handles the standard Node.js error-first callback pattern:\n * `(error: Error | null, result: T) => void`\n *\n * @param executor - Function that receives the callback and calls it\n * @param options - Optional error mapping\n * @returns AsyncResult with the callback's result\n *\n * @example\n * ```typescript\n * import { fromCallback } from 'awaitly/adapters';\n * import { readFile } from 'fs';\n *\n * // Basic usage\n * const result = await fromCallback<string>(\n * (cb) => readFile('file.txt', 'utf8', cb)\n * );\n *\n * if (result.ok) {\n * console.log(result.value);\n * } else {\n * console.error(result.error); // Error\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With typed error mapping\n * type FileError = { type: 'FILE_ERROR'; path: string; cause: Error };\n *\n * const result = await fromCallback<string, FileError>(\n * (cb) => readFile('config.json', 'utf8', cb),\n * { onError: (e) => ({ type: 'FILE_ERROR', path: 'config.json', cause: e }) }\n * );\n * ```\n */\nexport function fromCallback<T, E = Error>(\n executor: (callback: NodeCallback<T>) => void,\n options?: {\n /** Map callback error to typed error */\n onError?: (error: Error) => E;\n }\n): AsyncResult<T, E> {\n return new Promise((resolve) => {\n try {\n executor((error, result) => {\n if (error) {\n const mappedError = options?.onError\n ? options.onError(error)\n : (error as unknown as E);\n resolve(err(mappedError, { cause: error }));\n } else {\n resolve(ok(result));\n }\n });\n } catch (thrown) {\n // Handle synchronous throws in executor\n const error = thrown instanceof Error ? thrown : new Error(String(thrown));\n const mappedError = options?.onError\n ? options.onError(error)\n : (error as unknown as E);\n resolve(err(mappedError, { cause: thrown }));\n }\n });\n}\n\n// =============================================================================\n// fromEvent\n// =============================================================================\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFunction = (...args: any[]) => any;\n\n/**\n * Type guard for EventEmitter-like objects with on/off methods.\n */\nfunction hasOnOff(obj: unknown): obj is { on: AnyFunction; off: AnyFunction } {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"on\" in obj &&\n \"off\" in obj &&\n typeof (obj as { on: unknown }).on === \"function\" &&\n typeof (obj as { off: unknown }).off === \"function\"\n );\n}\n\n/**\n * Type guard for EventEmitter-like objects with addEventListener/removeEventListener.\n */\nfunction hasAddRemove(obj: unknown): obj is { addEventListener: AnyFunction; removeEventListener: AnyFunction } {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"addEventListener\" in obj &&\n \"removeEventListener\" in obj &&\n typeof (obj as { addEventListener: unknown }).addEventListener === \"function\" &&\n typeof (obj as { removeEventListener: unknown }).removeEventListener === \"function\"\n );\n}\n\n/**\n * Convert a one-shot event emitter pattern to AsyncResult.\n * Automatically removes listeners after resolution.\n *\n * Supports both Node.js EventEmitter (on/off) and DOM EventTarget\n * (addEventListener/removeEventListener) interfaces.\n *\n * @param emitter - Object with event subscription methods\n * @param config - Event names and optional timeout\n * @param options - Optional error mapping\n * @returns AsyncResult with the event payload\n *\n * @example\n * ```typescript\n * import { fromEvent } from 'awaitly/adapters';\n * import { createReadStream } from 'fs';\n *\n * // Node.js stream - wait for first data chunk\n * const stream = createReadStream('data.txt');\n * const result = await fromEvent<Buffer>(stream, {\n * success: 'data',\n * error: 'error',\n * });\n *\n * if (result.ok) {\n * console.log('First chunk:', result.value);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With timeout\n * const result = await fromEvent<Response>(request, {\n * success: 'response',\n * error: 'error',\n * timeout: 5000,\n * });\n *\n * if (!result.ok && isEventTimeoutError(result.error)) {\n * console.log('Request timed out');\n * }\n * ```\n *\n * @example\n * ```typescript\n * // DOM events\n * const result = await fromEvent<Event>(button, {\n * success: 'click',\n * timeout: 10000,\n * });\n * ```\n */\nexport function fromEvent<T, E = Error | EventTimeoutError | InvalidEmitterError>(\n emitter: EventEmitterLike,\n config: EventConfig,\n options?: {\n /** Map event error to typed error */\n onError?: (error: unknown) => E;\n }\n): AsyncResult<T, E> {\n return new Promise((resolve) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let resolved = false;\n\n // Normalize emitter API\n const addListener = hasOnOff(emitter)\n ? (e: string, l: (...args: unknown[]) => void) => emitter.on(e, l)\n : hasAddRemove(emitter)\n ? (e: string, l: (...args: unknown[]) => void) => emitter.addEventListener(e, l)\n : null;\n\n const removeListener = hasOnOff(emitter)\n ? (e: string, l: (...args: unknown[]) => void) => emitter.off(e, l)\n : hasAddRemove(emitter)\n ? (e: string, l: (...args: unknown[]) => void) => emitter.removeEventListener(e, l)\n : null;\n\n if (!addListener || !removeListener) {\n const invalidError: InvalidEmitterError = {\n type: \"INVALID_EMITTER\",\n message: \"Object does not have on/off or addEventListener/removeEventListener\",\n };\n resolve(err(invalidError as E));\n return;\n }\n\n const successHandler = (...args: unknown[]) => {\n if (resolved) return;\n resolved = true;\n cleanup();\n // First argument is the event value\n resolve(ok(args[0] as T));\n };\n\n const errorHandler = (...args: unknown[]) => {\n if (resolved) return;\n resolved = true;\n cleanup();\n const error = args[0];\n const mappedError = options?.onError\n ? options.onError(error)\n : (error as E);\n resolve(err(mappedError, { cause: error }));\n };\n\n const cleanup = () => {\n if (timeoutId) clearTimeout(timeoutId);\n removeListener(config.success, successHandler);\n if (config.error) removeListener(config.error, errorHandler);\n };\n\n addListener(config.success, successHandler);\n if (config.error) addListener(config.error, errorHandler);\n\n if (config.timeout) {\n timeoutId = setTimeout(() => {\n if (resolved) return;\n resolved = true;\n cleanup();\n const timeoutError: EventTimeoutError = {\n type: \"EVENT_TIMEOUT\",\n event: config.success,\n timeoutMs: config.timeout!,\n };\n resolve(err(timeoutError as unknown as E));\n }, config.timeout);\n }\n });\n}\n\n/**\n * Type guard to check if an object is EventEmitter-like.\n */\nexport function isEventEmitterLike(obj: unknown): obj is EventEmitterLike {\n return hasOnOff(obj) || hasAddRemove(obj);\n}\n"],"mappings":"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","names":["adapters_entry_exports","__export","fromCallback","fromEvent","isEventEmitterLike","isEventTimeoutError","isInvalidEmitterError","__toCommonJS","parseDurationString","input","match","value","unit","UNEXPECTED_ERROR","defaultCatchUnexpected","_cause","UNEXPECTED_ERROR","ok","value","err","error","options","cause","STEP_TIMEOUT_MARKER","isStepTimeoutError","e","getStepTimeoutMeta","err","EARLY_EXIT_SYMBOL","createEarlyExit","error","meta","isEarlyExit","MAPPER_EXCEPTION_SYMBOL","createMapperException","thrown","isMapperException","calculateRetryDelay","attempt","options","backoff","initialDelay","maxDelay","jitter","delay","jitterAmount","sleep","ms","resolve","TIMEOUT_SYMBOL","TIMEOUT_OPTION_SYMBOL","isTimeoutOptionMarker","value","executeWithTimeout","operation","options","stepInfo","externalSignal","controller","behavior","createTimeoutError","timeoutId","externalAbortHandler","timeoutPromise","_","reject","operationPromise","error","errorToThrow","meta","STEP_TIMEOUT_MARKER","DEFAULT_RETRY_CONFIG","run","fn","onError","onEvent","catchUnexpected","providedWorkflowId","workflowName","context","_workflowSignal","workflowId","effectiveCatchUnexpected","defaultCatchUnexpected","activeScopeStack","stepIdCounter","generateStepId","stepKey","emitEvent","event","eventWithContext","eventWithName","stepId","i","scope","earlyExit","createEarlyExit","isEarlyExitE","e","isEarlyExit","wrapForStep","_meta","isResultLike","normalizeParallelOperations","rawOperations","out","key","executeParallelArray","name","scopeId","startTime","scopeEnded","emitScopeEnd","idx","s","result","executeParallelNamed","operations","keys","results","resolve","settled","pendingCount","resultArray","index","reason","err","output","stepFn","id","operationOrResult","stepOptions","parsedOptions","stepName","explicitKey","stepDescription","retryConfig","timeoutConfig","hasEventListeners","overallStartTime","effectiveRetry","lastResult","attempt","attemptStartTime","durationMs","delay","calculateRetryDelay","sleep","thrown","timeoutMs","ok","isStepTimeoutError","timeoutMeta","getStepTimeoutMeta","totalDurationMs","mappedError","mapperError","createMapperException","errorResult","wrappedError","opts","mapToError","mapped","onNull","duration","d","parseDurationString","ms","userSignal","state","onAbort","args","second","normalizedOperations","scopeEntry","_id","_conditionLabel","condition","thenFn","elseFn","errors","items","maxIterations","isRunForm","asyncItems","item","handler","_name","getter","handlers","resolved","mapper","concurrency","allAsync","batch","batchResult","batchIndex","primaryResult","fallbackResultFromThrow","fallbackThrown","fallbackMappedError","primaryError","fallbackResult","acquireResult","resource","useResult","useThrown","useThrewNonResult","releaseErr","maybeResult","isMapperException","originalCause","allAsync","results","ok","resolve","settled","pendingCount","values","i","index","reason","err","result","isEventTimeoutError","error","isInvalidEmitterError","fromCallback","executor","options","resolve","result","mappedError","err","ok","thrown","hasOnOff","obj","hasAddRemove","fromEvent","emitter","config","timeoutId","resolved","addListener","e","l","removeListener","successHandler","args","cleanup","errorHandler","timeoutError","isEventEmitterLike"]}
|
|
1
|
+
{"version":3,"sources":["../src/adapters-entry.ts","../src/tagged-error.ts","../src/errors.ts","../src/core/index.ts","../src/adapters.ts"],"sourcesContent":["/**\n * awaitly/adapters\n *\n * Convenience adapters to wrap common non-Promise async patterns into Results.\n *\n * @example\n * ```typescript\n * import { fromCallback, fromEvent } from 'awaitly/adapters';\n *\n * // Node.js callback style\n * const data = await fromCallback<string>(\n * (cb) => fs.readFile('file.txt', 'utf8', cb)\n * );\n *\n * // One-shot event emitter\n * const response = await fromEvent<Response>(\n * request,\n * { success: 'response', error: 'error' }\n * );\n * ```\n */\n\nexport {\n // Functions\n fromCallback,\n fromEvent,\n\n // Type guards\n isEventTimeoutError,\n isInvalidEmitterError,\n isEventEmitterLike,\n\n // Types\n type NodeCallback,\n type EventConfig,\n type EventEmitterLike,\n type EventTimeoutError,\n type InvalidEmitterError,\n} from \"./adapters\";\n","/**\n * awaitly/tagged-error\n *\n * Factory for creating tagged error types with exhaustive pattern matching.\n * Enables TypeScript to enforce that all error variants are handled.\n *\n * @example\n * ```typescript\n * // Define error types (Props via generic)\n * class NotFoundError extends TaggedError(\"NotFoundError\")<{\n * id: string;\n * resource: string;\n * }> {}\n *\n * // Define with type-safe message (Props inferred from callback annotation)\n * class ValidationError extends TaggedError(\"ValidationError\", {\n * message: (p: { field: string; reason: string }) => `Invalid ${p.field}: ${p.reason}`,\n * }) {}\n *\n * // Create instances\n * const error = new NotFoundError({ id: \"123\", resource: \"User\" });\n *\n * // Runtime type check: instanceof TaggedError works!\n * console.log(error instanceof TaggedError); // true\n *\n * // Exhaustive matching\n * type AppError = NotFoundError | ValidationError;\n * const message = TaggedError.match(error as AppError, {\n * NotFoundError: (e) => `Missing: ${e.resource} ${e.id}`,\n * ValidationError: (e) => `Invalid ${e.field}: ${e.reason}`,\n * });\n * ```\n */\n\n/**\n * Options for Error constructor (compatible with ES2022 ErrorOptions).\n */\nexport interface TaggedErrorOptions {\n cause?: unknown;\n}\n\n/**\n * Options for TaggedError factory with type-safe message callback.\n */\nexport interface TaggedErrorCreateOptions<Props extends Record<string, unknown>> {\n /** Custom message generator from props. Annotate parameter for type safety. */\n message: (props: Props) => string;\n}\n\n/**\n * Base interface for all tagged errors.\n */\nexport interface TaggedErrorBase extends Error {\n readonly _tag: string;\n}\n\n/**\n * Internal base class for instanceof checks.\n * All TaggedError-created classes extend this.\n * @internal\n */\nclass InternalTaggedErrorBase extends Error implements TaggedErrorBase {\n readonly _tag!: string;\n}\n\n/**\n * Instance type for factory-created TaggedErrors.\n */\ntype TaggedErrorInstance<Tag extends string, Props> = TaggedErrorBase & {\n readonly _tag: Tag;\n} & Readonly<Props>;\n\n/**\n * Constructor args type - conditionally optional based on whether Props has required fields.\n * - If Props is empty or all properties are optional: props argument is optional\n * - If Props has any required properties: props argument is required\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ntype ConstructorArgs<Props extends Record<string, unknown>> = {} extends Props\n ? [props?: Props | void, options?: TaggedErrorOptions]\n : [props: Props, options?: TaggedErrorOptions];\n\n/**\n * Constructor type returned by TaggedError factory.\n */\nexport interface TaggedErrorConstructor<\n Tag extends string,\n Props extends Record<string, unknown>,\n> {\n new (...args: ConstructorArgs<Props>): TaggedErrorInstance<Tag, Props>;\n readonly prototype: TaggedErrorInstance<Tag, Props>;\n}\n\n/**\n * Generic class factory type that allows `<Props>` parameterization.\n * This enables the Effect.js-style syntax: `class X extends TaggedError(\"X\")<Props> {}`\n * @internal\n */\nexport interface TaggedErrorClassFactory<Tag extends string> {\n new <Props extends Record<string, unknown> = Record<string, never>>(\n ...args: ConstructorArgs<Props>\n ): TaggedErrorInstance<Tag, Props>;\n}\n\n/**\n * Helper type to extract return type from a function type.\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype FnReturnType<T> = T extends (...args: any[]) => infer R ? R : never;\n\n/**\n * Helper type to get union of return types from all handlers.\n * @internal\n */\ntype HandlersReturnType<H> = { [K in keyof H]: FnReturnType<H[K]> }[keyof H];\n\n/**\n * Helper type to extract keys whose values are definitely functions (not undefined).\n * Only excludes a tag from the fallback type if its handler is guaranteed to be\n * a function. Keys where the value type includes undefined are NOT excluded,\n * ensuring type safety with dynamic/conditional handlers.\n * @internal\n */\ntype DefinitelyHandledKeys<H> = {\n [K in keyof H]-?: undefined extends H[K] ? never : K;\n}[keyof H];\n\n/**\n * Factory function to create tagged error classes.\n *\n * Two usage patterns:\n *\n * 1. **Props via generic** (default message is tag name):\n * ```typescript\n * class NotFoundError extends TaggedError(\"NotFoundError\")<{ id: string }> {}\n * ```\n *\n * 2. **Props inferred from message callback** (type-safe message):\n * ```typescript\n * class NotFoundError extends TaggedError(\"NotFoundError\", {\n * message: (p: { id: string }) => `Not found: ${p.id}`,\n * }) {}\n * ```\n *\n * Both support `instanceof TaggedError` checks at runtime.\n *\n * @param tag - The unique tag string for this error type\n * @param options - Optional configuration with message generator (annotate param for type safety)\n * @returns A class constructor that can be extended\n */\n\n// Overload 1: No options - use <Props> generic syntax, default message is tag\nfunction TaggedError<Tag extends string>(\n tag: Tag\n): TaggedErrorClassFactory<Tag>;\n\n// Overload 2: With message option - Props inferred from callback parameter annotation\nfunction TaggedError<Tag extends string, Props extends Record<string, unknown>>(\n tag: Tag,\n options: TaggedErrorCreateOptions<Props>\n): TaggedErrorConstructor<Tag, Props>;\n\n// Implementation\nfunction TaggedError<Tag extends string, Props extends Record<string, unknown>>(\n tag: Tag,\n options?: TaggedErrorCreateOptions<Props>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): any {\n return class extends InternalTaggedErrorBase {\n override readonly _tag: Tag = tag;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n constructor(props?: any, errorOptions?: TaggedErrorOptions) {\n // Generate message: call callback if provided (even for prop-less errors), else use tag\n const message = options?.message ? options.message(props ?? {}) : tag;\n\n super(message);\n this.name = tag;\n\n // Maintains proper prototype chain for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype);\n\n // Assign props to instance, stripping reserved keys:\n // - _tag: discriminant for pattern matching (cannot be forged)\n // - name, message, stack: Error internals (preserve for logging/debugging)\n // Note: 'cause' is allowed as a user prop (common for domain errors)\n if (props && typeof props === \"object\") {\n const {\n _tag: _,\n name: _n,\n message: _m,\n stack: _s,\n ...safeProps\n } = props;\n\n const hasUserCause = Object.prototype.hasOwnProperty.call(\n safeProps,\n \"cause\"\n );\n const userCause = hasUserCause\n ? (safeProps as { cause?: unknown }).cause\n : undefined;\n if (hasUserCause) {\n delete (safeProps as { cause?: unknown }).cause;\n }\n\n const hasOptionsCause = errorOptions?.cause !== undefined;\n if (hasUserCause && hasOptionsCause) {\n throw new TypeError(\n \"TaggedError: cannot provide 'cause' in props when also setting ErrorOptions.cause\"\n );\n }\n\n Object.assign(this, safeProps);\n\n if (hasUserCause) {\n (this as { cause?: unknown }).cause = userCause;\n }\n if (hasOptionsCause) {\n (this as { cause?: unknown }).cause = errorOptions?.cause;\n }\n } else if (errorOptions?.cause !== undefined) {\n (this as { cause?: unknown }).cause = errorOptions.cause;\n }\n }\n };\n}\n\n// Add Symbol.hasInstance so `instanceof TaggedError` works\nObject.defineProperty(TaggedError, Symbol.hasInstance, {\n value: (instance: unknown): boolean => instance instanceof InternalTaggedErrorBase,\n});\n\n/**\n * Namespace for static methods on TaggedError.\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nnamespace TaggedError {\n /**\n * Type guard to check if a value is an Error instance.\n */\n export function isError(value: unknown): value is Error {\n return value instanceof Error;\n }\n\n /**\n * Type guard to check if a value is a TaggedError instance.\n * Uses the same check as `instanceof TaggedError` - only genuine\n * TaggedError instances (created via the factory) pass this guard.\n */\n export function isTaggedError(value: unknown): value is TaggedErrorBase {\n return value instanceof InternalTaggedErrorBase;\n }\n\n /**\n * Exhaustively matches on a tagged error, requiring handlers for all variants.\n *\n * TypeScript will error if any variant in the error union is not handled.\n *\n * @remarks When to use: You want compile-time enforcement that every tagged variant is handled.\n *\n * @param error - The tagged error to match\n * @param handlers - Object mapping _tag values to handler functions\n * @returns The return value of the matched handler\n *\n * @example\n * ```typescript\n * type AppError = NotFoundError | ValidationError;\n *\n * const message = TaggedError.match(error, {\n * NotFoundError: (e) => `Not found: ${e.id}`,\n * ValidationError: (e) => `Invalid: ${e.field}`,\n * });\n * ```\n */\n export function match<\n E extends TaggedErrorBase,\n H extends { [K in E[\"_tag\"]]: (e: Extract<E, { _tag: K }>) => unknown },\n >(error: E, handlers: H): HandlersReturnType<H> {\n const tag = error._tag as E[\"_tag\"];\n const handler = handlers[tag];\n return handler(\n error as Extract<E, { _tag: typeof tag }>\n ) as HandlersReturnType<H>;\n }\n\n /**\n * Partially matches on a tagged error with a fallback for unhandled variants.\n *\n * The fallback receives variants that are NOT definitely handled. A tag is\n * considered \"definitely handled\" only if its handler is a function (not\n * `undefined`). This ensures type safety even with dynamic/conditional handlers:\n *\n * ```typescript\n * const maybeHandle = featureFlag ? (e) => e.id : undefined;\n * TaggedError.matchPartial(\n * error,\n * { NotFoundError: maybeHandle }, // maybeHandle might be undefined\n * (e) => e._tag // e correctly includes NotFoundError\n * );\n * ```\n *\n * @param error - The tagged error to match\n * @param handlers - Partial object mapping _tag values to handler functions\n * @param otherwise - Fallback handler for unmatched variants\n * @returns The return value of the matched handler or fallback\n *\n * @example\n * ```typescript\n * const message = TaggedError.matchPartial(\n * error,\n * { NotFoundError: (e) => `Not found: ${e.id}` },\n * (e) => `Other error: ${e.message}`\n * );\n * ```\n */\n export function matchPartial<\n E extends TaggedErrorBase,\n H extends Partial<{\n [K in E[\"_tag\"]]: (e: Extract<E, { _tag: K }>) => unknown;\n }>,\n T,\n >(\n error: E,\n handlers: H,\n otherwise: (e: Exclude<E, { _tag: DefinitelyHandledKeys<H> }>) => T\n ): HandlersReturnType<H> | T {\n const tag = error._tag as E[\"_tag\"];\n const handler = handlers[tag];\n if (handler) {\n return handler(\n error as Extract<E, { _tag: typeof tag }>\n ) as HandlersReturnType<H>;\n }\n return otherwise(error as Exclude<E, { _tag: DefinitelyHandledKeys<H> }>);\n }\n}\n\nexport { TaggedError };\n\n/**\n * Helper type to extract the _tag literal type from a TaggedError.\n *\n * @example\n * ```typescript\n * class MyError extends TaggedError(\"MyError\")<{ id: string }> {}\n * type Tag = TagOf<MyError>; // \"MyError\"\n * ```\n */\nexport type TagOf<E extends TaggedErrorBase> = E[\"_tag\"];\n\n/**\n * Helper type to extract a specific variant from a TaggedError union by tag.\n *\n * @example\n * ```typescript\n * type AppError = NotFoundError | ValidationError;\n * type NotFound = ErrorByTag<AppError, \"NotFoundError\">; // NotFoundError\n * ```\n */\nexport type ErrorByTag<\n E extends TaggedErrorBase,\n Tag extends E[\"_tag\"],\n> = Extract<E, { _tag: Tag }>;\n\n/**\n * Reserved keys that are stripped from user props at runtime.\n * These keys cannot be used as user-defined properties:\n * - _tag: discriminant for pattern matching\n * - name, message, stack: Error internals (preserved for logging/debugging)\n *\n * Note: 'cause' is NOT reserved - it can be used as a user prop.\n */\ntype ReservedErrorKeys = \"_tag\" | \"name\" | \"message\" | \"stack\";\n\n/**\n * Helper type to extract props from a TaggedError.\n * Excludes reserved keys that are stripped at runtime.\n *\n * @example\n * ```typescript\n * class MyError extends TaggedError(\"MyError\")<{ id: string }> {}\n * type Props = PropsOf<MyError>; // { id: string }\n *\n * // 'cause' is allowed as a user prop\n * class DomainError extends TaggedError(\"DomainError\")<{ cause: { field: string } }> {}\n * type DomainProps = PropsOf<DomainError>; // { cause: { field: string } }\n * ```\n */\nexport type PropsOf<E extends TaggedErrorBase> = Omit<E, ReservedErrorKeys>;\n","/**\n * awaitly/errors\n *\n * Pre-built error types for common failure scenarios.\n * Uses TaggedError for type-safe exhaustive matching.\n *\n * @example\n * ```typescript\n * import { TimeoutError, RetryExhaustedError, RateLimitError, CircuitOpenError } from 'awaitly/errors';\n *\n * // Create errors\n * const timeout = new TimeoutError({ operation: 'fetchUser', ms: 5000 });\n * const retryFailed = new RetryExhaustedError({ operation: 'sendEmail', attempts: 3 });\n *\n * // Pattern match\n * TaggedError.match(error, {\n * TimeoutError: (e) => `${e.operation} timed out after ${e.ms}ms`,\n * RetryExhaustedError: (e) => `${e.operation} failed after ${e.attempts} attempts`,\n * RateLimitError: (e) => `Rate limit exceeded, retry after ${e.retryAfterMs}ms`,\n * CircuitOpenError: (e) => `Circuit ${e.circuitName} is open`,\n * });\n * ```\n */\n\nimport { TaggedError } from \"./tagged-error\";\n\n// =============================================================================\n// Error Factory\n// =============================================================================\n\n/**\n * Factory function to create tagged error classes with default values.\n *\n * This is a convenience wrapper around TaggedError that allows specifying\n * default property values for error types.\n *\n * @example\n * ```typescript\n * // Define custom error with defaults\n * const NetworkError = makeError('NetworkError', {\n * defaults: { retryable: true },\n * message: (p) => `Network error: ${p.reason}`,\n * });\n *\n * class MyNetworkError extends NetworkError<{ reason: string; code?: number }> {}\n *\n * const error = new MyNetworkError({ reason: 'Connection refused' });\n * // error.retryable === true (from defaults)\n * ```\n */\nexport function makeError<Tag extends string>(\n tag: Tag,\n options?: {\n message?: (props: Record<string, unknown>) => string;\n defaults?: Record<string, unknown>;\n }\n) {\n const messageGenerator = options?.message ?? (() => tag);\n const defaults = options?.defaults ?? {};\n\n // Create base class using TaggedError\n const BaseClass = TaggedError(tag, {\n message: (props: Record<string, unknown>) =>\n messageGenerator({ ...defaults, ...props }),\n });\n\n // Return a factory that applies defaults\n return class extends BaseClass {\n constructor(props?: Record<string, unknown>) {\n super({ ...defaults, ...props } as Record<string, unknown>);\n // Apply defaults to instance\n Object.assign(this, { ...defaults, ...props });\n }\n };\n}\n\n// =============================================================================\n// Pre-built Error Types\n// =============================================================================\n\n/**\n * Error thrown when an operation times out.\n *\n * @example\n * ```typescript\n * const error = new TimeoutError({\n * operation: 'fetchUser',\n * ms: 5000,\n * });\n * console.log(error.message); // \"TimeoutError: fetchUser timed out after 5000ms\"\n * ```\n */\nexport class TimeoutError extends TaggedError(\"TimeoutError\", {\n message: (p: {\n /** Name of the operation that timed out */\n operation?: string;\n /** Timeout duration in milliseconds */\n ms: number;\n }) =>\n p.operation\n ? `TimeoutError: ${p.operation} timed out after ${p.ms}ms`\n : `TimeoutError: Operation timed out after ${p.ms}ms`,\n}) {}\n\n/**\n * Error thrown when all retry attempts are exhausted.\n *\n * @example\n * ```typescript\n * const error = new RetryExhaustedError({\n * operation: 'sendEmail',\n * attempts: 3,\n * lastError: originalError,\n * });\n * console.log(error.message); // \"RetryExhaustedError: sendEmail failed after 3 attempts\"\n * ```\n */\nexport class RetryExhaustedError extends TaggedError(\"RetryExhaustedError\", {\n message: (p: {\n /** Name of the operation that failed */\n operation?: string;\n /** Total number of retry attempts made */\n attempts: number;\n /** The last error encountered before giving up */\n lastError?: unknown;\n }) =>\n p.operation\n ? `RetryExhaustedError: ${p.operation} failed after ${p.attempts} attempts`\n : `RetryExhaustedError: Operation failed after ${p.attempts} attempts`,\n}) {}\n\n/**\n * Error thrown when a rate limit is exceeded.\n *\n * @example\n * ```typescript\n * const error = new RateLimitError({\n * limiterName: 'api-calls',\n * retryAfterMs: 1000,\n * });\n * console.log(error.message); // \"RateLimitError: Rate limit exceeded for api-calls\"\n * ```\n */\nexport class RateLimitError extends TaggedError(\"RateLimitError\", {\n message: (p: {\n /** Name of the rate limiter that was exceeded */\n limiterName?: string;\n /** Time in milliseconds until the rate limit resets */\n retryAfterMs?: number;\n }) =>\n p.limiterName\n ? `RateLimitError: Rate limit exceeded for ${p.limiterName}${p.retryAfterMs ? `, retry after ${p.retryAfterMs}ms` : \"\"}`\n : `RateLimitError: Rate limit exceeded${p.retryAfterMs ? `, retry after ${p.retryAfterMs}ms` : \"\"}`,\n}) {}\n\n/**\n * Error thrown when a circuit breaker is open.\n *\n * @example\n * ```typescript\n * const error = new CircuitBreakerOpenError({\n * circuitName: 'payment-api',\n * state: 'OPEN',\n * retryAfterMs: 30000,\n * });\n * console.log(error.message); // \"CircuitBreakerOpenError: Circuit payment-api is OPEN\"\n * ```\n */\nexport class CircuitBreakerOpenError extends TaggedError(\n \"CircuitBreakerOpenError\",\n {\n message: (p: {\n /** Name of the circuit breaker */\n circuitName: string;\n /** Current state of the circuit */\n state?: \"OPEN\" | \"HALF_OPEN\";\n /** Time in milliseconds until the circuit may close */\n retryAfterMs?: number;\n }) =>\n `CircuitBreakerOpenError: Circuit ${p.circuitName} is ${p.state ?? \"OPEN\"}${p.retryAfterMs ? `, retry after ${Math.ceil(p.retryAfterMs / 1000)}s` : \"\"}`,\n }\n) {}\n\n/**\n * Error thrown when validation fails.\n *\n * @example\n * ```typescript\n * const error = new ValidationError({\n * field: 'email',\n * reason: 'Invalid email format',\n * });\n * console.log(error.message); // \"ValidationError: Invalid email - Invalid email format\"\n * ```\n */\nexport class ValidationError extends TaggedError(\"ValidationError\", {\n message: (p: {\n /** Field that failed validation */\n field: string;\n /** Reason for validation failure */\n reason: string;\n /** Raw value that failed validation */\n value?: unknown;\n }) => `ValidationError: Invalid ${p.field} - ${p.reason}`,\n}) {}\n\n/**\n * Error thrown when a resource is not found.\n *\n * @example\n * ```typescript\n * const error = new NotFoundError({\n * resource: 'User',\n * id: '123',\n * });\n * console.log(error.message); // \"NotFoundError: User with id 123 not found\"\n * ```\n */\nexport class NotFoundError extends TaggedError(\"NotFoundError\", {\n message: (p: {\n /** Type of resource that was not found */\n resource: string;\n /** Identifier of the missing resource */\n id?: string;\n }) =>\n p.id\n ? `NotFoundError: ${p.resource} with id ${p.id} not found`\n : `NotFoundError: ${p.resource} not found`,\n}) {}\n\n/**\n * Error thrown when access is denied.\n *\n * @example\n * ```typescript\n * const error = new UnauthorizedError({\n * action: 'delete',\n * resource: 'User',\n * });\n * console.log(error.message); // \"UnauthorizedError: Not authorized to delete User\"\n * ```\n */\nexport class UnauthorizedError extends TaggedError(\"UnauthorizedError\", {\n message: (p: {\n /** Action that was attempted */\n action?: string;\n /** Resource that was being accessed */\n resource?: string;\n /** Reason for denial */\n reason?: string;\n }) =>\n p.reason\n ? `UnauthorizedError: ${p.reason}`\n : p.action && p.resource\n ? `UnauthorizedError: Not authorized to ${p.action} ${p.resource}`\n : \"UnauthorizedError: Access denied\",\n}) {}\n\n/**\n * Error thrown for network-related failures.\n *\n * @example\n * ```typescript\n * const error = new NetworkError({\n * url: 'https://api.example.com/users',\n * reason: 'Connection refused',\n * retryable: true,\n * });\n * ```\n */\nexport class NetworkError extends TaggedError(\"NetworkError\", {\n message: (p: {\n /** URL that was being accessed */\n url?: string;\n /** Reason for the network failure */\n reason: string;\n /** Whether this error is retryable */\n retryable?: boolean;\n /** HTTP status code if applicable */\n statusCode?: number;\n }) =>\n p.url\n ? `NetworkError: ${p.reason} (${p.url})`\n : `NetworkError: ${p.reason}`,\n}) {}\n\n/**\n * Error thrown when a saga compensation fails.\n *\n * @example\n * ```typescript\n * const error = new CompensationError({\n * step: 'chargeCard',\n * originalError: paymentError,\n * compensationError: refundError,\n * });\n * ```\n */\nexport class CompensationError extends TaggedError(\"CompensationError\", {\n message: (p: {\n /** Step that triggered compensation */\n step: string;\n /** The original error that caused compensation */\n originalError?: unknown;\n /** Error that occurred during compensation */\n compensationError?: unknown;\n }) => `CompensationError: Failed to compensate step ${p.step}`,\n}) {}\n\n// =============================================================================\n// Unexpected Error\n// =============================================================================\n\n/**\n * Default error type for uncaught exceptions and cancellation in workflows.\n * This is the default `U` type when `catchUnexpected` is not provided.\n *\n * @example\n * ```typescript\n * // Automatically used as the default — no need to pass catchUnexpected:\n * const workflow = createWorkflow(\"checkout\", { chargeCard, sendEmail });\n *\n * // Equivalent to:\n * const workflow = createWorkflow(\"checkout\", { chargeCard, sendEmail }, {\n * catchUnexpected: (cause) => new UnexpectedError({ cause }),\n * });\n * ```\n */\nexport class UnexpectedError extends TaggedError(\"UnexpectedError\", {\n message: (p: {\n /** The original thrown value or cancellation error */\n cause?: unknown;\n }) => `UnexpectedError: ${p.cause instanceof Error ? p.cause.message : String(p.cause ?? \"unknown\")}`,\n}) {}\n\n\n// =============================================================================\n// Union Type for Common Errors\n// =============================================================================\n\n/**\n * Union of all pre-built error types.\n * Useful for exhaustive pattern matching.\n *\n * @example\n * ```typescript\n * function handleError(error: AwaitlyError): string {\n * return TaggedError.match(error, {\n * TimeoutError: (e) => `Timeout: ${e.ms}ms`,\n * RetryExhaustedError: (e) => `Retries: ${e.attempts}`,\n * RateLimitError: (e) => `Rate limited`,\n * CircuitBreakerOpenError: (e) => `Circuit open: ${e.circuitName}`,\n * ValidationError: (e) => `Invalid: ${e.field}`,\n * NotFoundError: (e) => `Not found: ${e.resource}`,\n * UnauthorizedError: (e) => `Unauthorized`,\n * NetworkError: (e) => `Network: ${e.reason}`,\n * CompensationError: (e) => `Compensation failed: ${e.step}`,\n * });\n * }\n * ```\n */\nexport type AwaitlyError =\n | TimeoutError\n | RetryExhaustedError\n | RateLimitError\n | CircuitBreakerOpenError\n | ValidationError\n | NotFoundError\n | UnauthorizedError\n | NetworkError\n | CompensationError;\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Check if an error is a TimeoutError.\n */\nexport function isTimeoutError(error: unknown): error is TimeoutError {\n return TaggedError.isTaggedError(error) && error._tag === \"TimeoutError\";\n}\n\n/**\n * Check if an error is a RetryExhaustedError.\n */\nexport function isRetryExhaustedError(\n error: unknown\n): error is RetryExhaustedError {\n return (\n TaggedError.isTaggedError(error) && error._tag === \"RetryExhaustedError\"\n );\n}\n\n/**\n * Check if an error is a RateLimitError.\n */\nexport function isRateLimitError(error: unknown): error is RateLimitError {\n return TaggedError.isTaggedError(error) && error._tag === \"RateLimitError\";\n}\n\n/**\n * Check if an error is a CircuitBreakerOpenError.\n */\nexport function isCircuitBreakerOpenError(\n error: unknown\n): error is CircuitBreakerOpenError {\n return (\n TaggedError.isTaggedError(error) && error._tag === \"CircuitBreakerOpenError\"\n );\n}\n\n/**\n * Check if an error is a ValidationError.\n */\nexport function isValidationError(error: unknown): error is ValidationError {\n return TaggedError.isTaggedError(error) && error._tag === \"ValidationError\";\n}\n\n/**\n * Check if an error is a NotFoundError.\n */\nexport function isNotFoundError(error: unknown): error is NotFoundError {\n return TaggedError.isTaggedError(error) && error._tag === \"NotFoundError\";\n}\n\n/**\n * Check if an error is an UnauthorizedError.\n */\nexport function isUnauthorizedError(\n error: unknown\n): error is UnauthorizedError {\n return TaggedError.isTaggedError(error) && error._tag === \"UnauthorizedError\";\n}\n\n/**\n * Check if an error is a NetworkError.\n */\nexport function isNetworkError(error: unknown): error is NetworkError {\n return TaggedError.isTaggedError(error) && error._tag === \"NetworkError\";\n}\n\n/**\n * Check if an error is a CompensationError.\n */\nexport function isCompensationError(\n error: unknown\n): error is CompensationError {\n return TaggedError.isTaggedError(error) && error._tag === \"CompensationError\";\n}\n\n/**\n * Check if an error is any AwaitlyError.\n */\nexport function isAwaitlyError(error: unknown): error is AwaitlyError {\n if (!TaggedError.isTaggedError(error)) return false;\n const tag = error._tag;\n return [\n \"TimeoutError\",\n \"RetryExhaustedError\",\n \"RateLimitError\",\n \"CircuitBreakerOpenError\",\n \"ValidationError\",\n \"NotFoundError\",\n \"UnauthorizedError\",\n \"NetworkError\",\n \"CompensationError\",\n ].includes(tag);\n}\n","/**\n * awaitly/core\n *\n * Core Result primitives and run() function.\n * Use this module for minimal bundle size when you don't need the full workflow capabilities\n * (like retries, timeout, or state persistence) provided by `createWorkflow`.\n *\n * This module provides:\n * 1. `Result` types for error handling without try/catch\n * 2. `run()` function for executing steps with standardized error management\n * 3. Utilities for transforming and combining Results\n */\n\n// Inline duration type and parser to avoid importing the full duration module\n// This keeps the core bundle minimal (~1KB saved)\n\n/** Duration object with tagged type for type safety */\ntype DurationObject = { readonly _tag: \"Duration\"; readonly millis: number };\n\n/** Duration input: either a string (\"5s\", \"100ms\") or a Duration object */\ntype DurationInput = string | DurationObject;\n\n/** Parse a duration string like \"100ms\", \"5s\", \"2m\", \"1h\", \"1d\" */\nfunction parseDurationString(input: string): DurationObject | undefined {\n const match = input.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d)$/i);\n if (!match) return undefined;\n const value = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n const multipliers: Record<string, number> = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };\n return { _tag: \"Duration\", millis: value * (multipliers[unit] ?? 1) };\n}\n\n// =============================================================================\n// Core Result Types\n// =============================================================================\n\n/**\n * Represents a successful result.\n * Use `ok(value)` to create instances.\n *\n * @template T - The type of the success value\n *\n * @example\n * ```typescript\n * const success = Awaitly.ok(42);\n * // Type shown: Ok<number>\n * ```\n */\nexport type Ok<T> = {\n ok: true;\n value: T;\n};\n\n/**\n * Represents a failed result.\n * Use `err(error)` to create instances.\n *\n * @template E - The type of the error value\n * @template C - The type of the cause (defaults to unknown)\n * @template T - Phantom type for the success value (preserved after narrowing)\n *\n * @example\n * ```typescript\n * const failure = Awaitly.err({ type: \"NOT_FOUND\", message: \"User not found\" });\n * // Type shown: Err<{ type: string; message: string }>\n * ```\n */\nexport type Err<E, C = unknown> = {\n ok: false;\n error: E;\n cause?: C;\n};\n\n/**\n * Represents a successful computation or a failed one.\n * Use this type to represent the outcome of an operation that might fail,\n * instead of throwing exceptions.\n *\n * @template T - The type of the success value\n * @template E - The type of the error value (defaults to unknown)\n * @template C - The type of the cause (defaults to unknown)\n */\nexport type Result<T, E = unknown, C = unknown> = Ok<T> | Err<E, C>;\n\n/**\n * A Promise that resolves to a Result.\n * Use this for asynchronous operations that might fail.\n */\nexport type AsyncResult<T, E = unknown, C = unknown> = Promise<Result<T, E, C>>;\n\n/** Discriminant for PromiseRejectedError type - use in switch statements */\nexport const PROMISE_REJECTED = \"PROMISE_REJECTED\" as const;\n\n// =============================================================================\n// Named Error Constants (for static analysis)\n// =============================================================================\n\n/**\n * Named error constant for unexpected/unhandled errors.\n * Used by the analyzer when a step doesn't declare errors.\n */\nexport const AWAITLY_UNEXPECTED = \"AWAITLY_UNEXPECTED\" as const;\n\n/**\n * Named error constant for cancelled operations.\n */\nexport const AWAITLY_CANCELLED = \"AWAITLY_CANCELLED\" as const;\n\n/**\n * Named error constant for timed-out operations.\n */\nexport const AWAITLY_TIMEOUT = \"AWAITLY_TIMEOUT\" as const;\n\n// =============================================================================\n// Static Analysis Helpers\n// =============================================================================\n\n/**\n * Helper to create a tuple of string literal tags with preserved literal types.\n * Use this when you need to store error tags in a variable while keeping\n * TypeScript's literal type inference (avoiding widening to string[]).\n *\n * @param t - The string literal tags\n * @returns The same array with preserved literal types\n *\n * @example\n * ```typescript\n * // Without tags() - type widens to string[]\n * const errs = ['CART_NOT_FOUND', 'CART_EMPTY']; // string[]\n *\n * // With tags() - literal types preserved\n * const errs = tags('CART_NOT_FOUND', 'CART_EMPTY'); // ['CART_NOT_FOUND', 'CART_EMPTY']\n *\n * await step('getCart', () => getCart(id), {\n * errors: errs, // Analyzer can extract literal types\n * out: 'cart',\n * });\n * ```\n */\nexport const tags = <const T extends readonly string[]>(...t: T): T => t;\n\nimport { UnexpectedError } from \"../errors\";\nexport { UnexpectedError };\n\n/**\n * Default mapper for unexpected causes (uncaught exceptions, cancellation, etc.).\n * Returns an UnexpectedError TaggedError instance.\n * Used when run() is called without catchUnexpected.\n *\n * @param cause - The thrown value\n * @returns An UnexpectedError instance\n */\nexport function defaultCatchUnexpected(cause: unknown): UnexpectedError {\n return new UnexpectedError({ cause });\n}\n\nexport type PromiseRejectedError = { type: typeof PROMISE_REJECTED; cause: unknown };\n/** Cause type for promise rejections in async batch helpers */\nexport type PromiseRejectionCause = { type: \"PROMISE_REJECTION\"; reason: unknown };\nexport type EmptyInputError = { type: \"EMPTY_INPUT\"; message: string };\nexport type MaybeAsyncResult<T, E, C = unknown> = Result<T, E, C> | Promise<Result<T, E, C>>;\n\n// =============================================================================\n// Result Constructors\n// =============================================================================\n\n/**\n * Creates a successful Result.\n * Use this when an operation completes successfully.\n *\n * @remarks When to use: Wrap a successful value in a Result for consistent return types.\n *\n * @param value - The success value to wrap\n * @returns An Ok object with `{ ok: true, value }`\n *\n * @example\n * ```typescript\n * const success = Awaitly.ok(42);\n * // Type: Ok<number>\n *\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) return Awaitly.err(\"Division by zero\");\n * return Awaitly.ok(a / b);\n * }\n * ```\n */\nexport function ok<T>(value: T): Ok<T> {\n return { ok: true as const, value };\n}\n\n/**\n * Creates a failed Result.\n * Use this when an operation fails.\n *\n * @remarks When to use: Return a typed failure without throwing so callers can handle it explicitly.\n *\n * @param error - The error value describing what went wrong (e.g., error code, object)\n * @returns An Err object with `{ ok: false, error }`\n *\n * @example\n * ```typescript\n * // Simple error\n * const r1 = Awaitly.err(\"NOT_FOUND\");\n * // Type: Err<\"NOT_FOUND\">\n *\n * // Error with context (include in error object)\n * const r2 = Awaitly.err({ type: \"PROCESSING_FAILED\", cause: originalError });\n * // Type: Err<{ type: string; cause: Error }>\n * ```\n */\nexport function err<E, C = unknown>(error: E, options?: { cause?: C }): Err<E, C> {\n const cause = options?.cause;\n return { ok: false as const, error, ...(cause !== undefined ? { cause } : {}) } as Err<E, C>;\n}\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Checks if a Result is successful.\n * Use this to narrow the type of a Result to the success case.\n *\n * @remarks When to use: Prefer functional-style checks or array filtering over `result.ok`.\n *\n * @param r - The Result to check\n * @returns `true` if successful, allowing access to `r.value`\n *\n * @example\n * ```typescript\n * const r = someOperation();\n * if (isOk(r)) {\n * // Use r.value (Type is T)\n * processValue(r.value);\n * } else {\n * // Handle r.error (Type is E)\n * handleError(r.error);\n * }\n * ```\n */\nexport const isOk = <T, E, C>(r: Result<T, E, C>): r is Ok<T> => r.ok;\n\n/**\n * Checks if a Result is a failure.\n * Use this to narrow the type of a Result to the error case.\n *\n * @remarks When to use: Prefer functional-style checks or array filtering over `result.ok`.\n *\n * @param r - The Result to check\n * @returns `true` if failed, allowing access to `r.error` and `r.cause`\n *\n * @example\n * ```typescript\n * if (isErr(r)) {\n * // Handle error case early\n * return;\n * }\n * // Proceed with success case\n * ```\n */\nexport const isErr = <T, E, C>(r: Result<T, E, C>): r is Err<E, C> => !r.ok;\n\n/**\n * Checks if an error is an UnexpectedError.\n * Used internally by the framework but exported for advanced custom handling.\n * Indicates an error that wasn't typed/expected in the `run` signature.\n *\n * @remarks When to use: Distinguish unexpected failures from your typed error union.\n */\nexport const isUnexpectedError = (e: unknown): e is UnexpectedError =>\n e instanceof UnexpectedError ||\n (typeof e === \"object\" &&\n e !== null &&\n \"_tag\" in e &&\n (e as { _tag: string })._tag === \"UnexpectedError\");\n\n/**\n * Checks if an error is a PromiseRejectedError.\n * Occurs when a Promise rejects in batch operations (allAsync, anyAsync, zipAsync).\n *\n * @example\n * ```typescript\n * onError: (error): FetchError => {\n * if (isPromiseRejectedError(error)) return 'FETCH_FAILED';\n * return error; // TypeScript narrows to FetchError\n * }\n * ```\n */\nexport const isPromiseRejectedError = (e: unknown): e is PromiseRejectedError =>\n typeof e === \"object\" &&\n e !== null &&\n (e as PromiseRejectedError).type === PROMISE_REJECTED;\n\n// =============================================================================\n// Error Matching\n// =============================================================================\n\n/**\n * Type for exhaustive error handlers mapping string literal errors and UnexpectedError.\n * Each key in E gets a handler, plus UnexpectedError is required.\n */\nexport type MatchErrorHandlers<E extends string, R> = {\n [K in Exclude<E, \"UnexpectedError\">]: (error: K) => R;\n} & {\n UnexpectedError: (error: UnexpectedError) => R;\n};\n\n/**\n * Exhaustive pattern matching for error types.\n * Handles both string literal errors and UnexpectedError, ensuring all cases are covered.\n *\n * @param error - The error to match (string literal or UnexpectedError)\n * @param handlers - Object with a handler for each error case plus UnexpectedError\n * @returns The result of the matched handler\n *\n * @example\n * ```typescript\n * type FetchError = \"NOT_FOUND\" | \"FETCH_ERROR\";\n * const result: Result<User, FetchError | UnexpectedError> = await fetchUser();\n *\n * if (!result.ok) {\n * return matchError(result.error, {\n * NOT_FOUND: () => 404,\n * FETCH_ERROR: () => 500,\n * UnexpectedError: (e) => { throw e.cause; }\n * });\n * }\n * ```\n */\nexport function matchError<E extends string, R>(\n error: E | UnexpectedError,\n handlers: MatchErrorHandlers<E, R>\n): R {\n // Handle UnexpectedError instances\n if (isUnexpectedError(error)) {\n return handlers.UnexpectedError(error as UnexpectedError);\n }\n // Handle string literal errors\n type StringErrors = Exclude<E, \"UnexpectedError\">;\n return handlers[error as StringErrors](error as StringErrors);\n}\n\n// =============================================================================\n// Type Utilities\n// =============================================================================\n\ntype AnyFunction = (...args: never[]) => unknown;\n\n/**\n * Helper to extract the error type from Result or AsyncResult return values.\n * Works even when a function is declared to return a union of both forms.\n */\ntype ErrorOfReturn<R> = Extract<Awaited<R>, { ok: false }> extends { error: infer E }\n ? E\n : never;\n\n/**\n * Extract error type from a single function's return type\n */\nexport type ErrorOf<T extends AnyFunction> = ErrorOfReturn<ReturnType<T>>;\n\n/**\n * Extract union of error types from multiple functions\n */\nexport type Errors<T extends AnyFunction[]> = {\n [K in keyof T]: ErrorOf<T[K]>;\n}[number];\n\n/**\n * Extract value type from Result\n */\nexport type ExtractValue<T> = T extends { ok: true; value: infer U }\n ? U\n : never;\n\n/**\n * Extract error type from Result\n */\nexport type ExtractError<T> = T extends { ok: false; error: infer E }\n ? E\n : never;\n\n/**\n * Extract cause type from Result\n */\nexport type ExtractCause<T> = T extends { ok: false; cause?: infer C }\n ? C\n : never;\n\n/**\n * Helper to extract the cause type from Result or AsyncResult return values.\n * Works even when a function is declared to return a union of both forms.\n */\ntype CauseOfReturn<R> = Extract<Awaited<R>, { ok: false }> extends { cause?: infer C }\n ? C\n : never;\n\n/**\n * Extract cause type from a function's return type\n */\nexport type CauseOf<T extends AnyFunction> = CauseOfReturn<ReturnType<T>>;\n\n// =============================================================================\n// Step Options\n// =============================================================================\n\n/**\n * Options for configuring a step within a workflow.\n * Use these to enable tracing, caching, state persistence, and static analysis.\n */\nexport type StepOptions<\n Errs extends readonly string[] = readonly string[],\n Out extends string | undefined = undefined,\n> = {\n /**\n * Stable identity key for the step.\n * REQUIRED for:\n * 1. Caching: Used as the cache key.\n * 2. Resuming: Used to identify which steps have already completed.\n *\n * Must be unique within the workflow.\n */\n key?: string;\n\n /**\n * Short description for labels/tooltips.\n * Used by static analysis visualization tools.\n */\n description?: string;\n\n /**\n * Full markdown documentation for the step.\n * Used by static analysis visualization tools.\n */\n markdown?: string;\n\n /**\n * Retry configuration for transient failures.\n * When specified, the step will retry on errors according to this config.\n */\n retry?: RetryOptions;\n\n /**\n * Timeout configuration for the operation.\n * When specified, each attempt will be aborted after the timeout duration.\n */\n timeout?: TimeoutOptions;\n\n /**\n * Time-to-live for this step's cache entry in milliseconds.\n * Overrides any global cache TTL. Requires `key` for caching.\n */\n ttl?: number;\n\n // ==========================================================================\n // Static Analysis Options\n // ==========================================================================\n\n /**\n * Declared tagged errors this step may return.\n * Used by the static analyzer to build error flow graphs.\n *\n * Use `tags()` helper when storing in a variable:\n * @example\n * ```typescript\n * const cartErrors = tags('CART_NOT_FOUND', 'CART_EMPTY');\n * await step('getCart', () => getCart(id), { errors: cartErrors });\n *\n * // Or inline (no helper needed)\n * await step('getCart', () => getCart(id), {\n * errors: ['CART_NOT_FOUND', 'CART_EMPTY'],\n * });\n * ```\n */\n errors?: Errs;\n\n /**\n * Write the step's return value to this context key.\n * Replaces manual `ctx.set()` calls for the happy path.\n *\n * @example\n * ```typescript\n * await step('getCart', () => getCart(id), { out: 'cart' });\n * // Now ctx.cart contains the result\n * ```\n */\n out?: Out;\n\n /**\n * Override auto-detected reads from context.\n * Use when the analyzer can't trace complex data dependencies.\n *\n * @example\n * ```typescript\n * await step('charge', () => chargeCard(getCartTotal()), {\n * reads: ['cart'], // Explicitly declare dependency\n * });\n * ```\n */\n reads?: readonly string[];\n\n /**\n * Hint for dependency source tracking.\n * Use when the callback is complex and the analyzer can't detect\n * which dependency function is being called.\n *\n * @example\n * ```typescript\n * await step('getCart', () => {\n * const id = transform(ctx.input.cartId);\n * return deps.getCart(id);\n * }, {\n * dep: 'getCart', // Hint for analyzer\n * });\n * ```\n */\n dep?: string;\n\n // ==========================================================================\n // Agent Metadata — Architecture & Intent\n // ==========================================================================\n\n /**\n * Why this step exists in the business flow.\n * Unlike `description` (which says *what* the step does), `intent` explains\n * the business reason it exists in the workflow.\n *\n * @example\n * ```typescript\n * await step('validateCart', () => validate(cart), {\n * description: 'Validates cart contents and pricing',\n * intent: 'Prevent charging customers for out-of-stock items',\n * });\n * ```\n */\n intent?: string;\n\n /**\n * Business domain this step belongs to.\n * Used by the static analyzer to group steps by bounded context.\n *\n * @example\n * ```typescript\n * await step('chargeCard', () => charge(card, amount), {\n * domain: 'payments',\n * });\n * ```\n */\n domain?: string;\n\n /**\n * Team, service, or bounded-context that owns this step.\n *\n * @example\n * ```typescript\n * await step('shipOrder', () => ship(order), {\n * owner: 'fulfillment-team',\n * });\n * ```\n */\n owner?: string;\n\n /**\n * Classification tags for this step.\n *\n * Recommended vocabulary:\n * `'side-effect'`, `'external-api'`, `'idempotent'`, `'read-only'`,\n * `'cacheable'`, `'pii'`, `'pci'`, `'compensatable'`\n *\n * @example\n * ```typescript\n * await step('chargeCard', () => charge(card, amount), {\n * tags: ['side-effect', 'external-api', 'pci'],\n * });\n * ```\n */\n tags?: readonly string[];\n\n // ==========================================================================\n // Agent Metadata — Effects & Dependencies\n // ==========================================================================\n\n /**\n * Human-oriented descriptions of state mutations this step performs.\n * These are free-text labels for documentation and visualization — they are\n * not machine-parsed at runtime.\n *\n * A future `stateEffects` field will provide structured effect declarations.\n *\n * @example\n * ```typescript\n * await step('placeOrder', () => place(cart), {\n * stateChanges: ['order.status → PLACED', 'inventory.reserved += qty'],\n * });\n * ```\n */\n stateChanges?: readonly string[];\n\n /**\n * Domain events this step produces.\n * Used by the static analyzer to build event flow graphs.\n *\n * @example\n * ```typescript\n * await step('placeOrder', () => place(cart), {\n * emits: ['OrderPlaced', 'InventoryReserved'],\n * });\n * ```\n */\n emits?: readonly string[];\n\n /**\n * External systems or services this step calls.\n * Used by the static analyzer to map external dependencies.\n *\n * @example\n * ```typescript\n * await step('chargeCard', () => charge(card, amount), {\n * calls: ['stripe-api', 'fraud-detection-service'],\n * });\n * ```\n */\n calls?: readonly string[];\n\n // ==========================================================================\n // Agent Metadata — Error Classification\n // ==========================================================================\n\n /**\n * Structured metadata for each error this step may produce.\n * Keys should match entries in the `errors` array.\n *\n * Note: `retryable` classifies the error's nature (whether it CAN be retried),\n * separate from whether this step actually retries it (that's `retry.retryOn`).\n * Both dimensions are useful — \"this error IS retryable\" vs \"this step DOES retry it\".\n * Defaults to `undefined` (unknown), not `true`.\n *\n * @example\n * ```typescript\n * await step('chargeCard', () => charge(card, amount), {\n * errors: ['CARD_DECLINED', 'GATEWAY_TIMEOUT'],\n * errorMeta: {\n * CARD_DECLINED: {\n * retryable: false,\n * severity: 'business',\n * description: 'Card was declined by issuer',\n * },\n * GATEWAY_TIMEOUT: {\n * retryable: true,\n * severity: 'infrastructure',\n * description: 'Payment gateway did not respond in time',\n * },\n * },\n * });\n * ```\n */\n errorMeta?: Record<string, ErrorClassification>;\n};\n\n/** Shared error classification — used in StepOptions.errorMeta, diagnostics, and wide events. */\nexport interface ErrorClassification {\n retryable?: boolean;\n severity?: 'business' | 'infrastructure' | 'validation';\n description?: string;\n}\n\n/** Runtime-visible business context from StepOptions. Does NOT include errorMeta. */\nexport interface StepMetadata {\n intent?: string;\n domain?: string;\n owner?: string;\n tags?: readonly string[];\n stateChanges?: readonly string[];\n emits?: readonly string[];\n calls?: readonly string[];\n}\n\n/** Runtime error diagnostics. classification is the matched ErrorClassification for this error. */\nexport interface StepErrorDiagnostics {\n tag: string;\n classification?: ErrorClassification;\n attempt?: number; // 1-based\n cumulativeDurationMs?: number; // execution only, excludes backoff\n origin: 'result' | 'throw' | 'timeout';\n}\n\n/** Extract canonical error tag. Priority: _tag > tag > code > Error.name > \"unknown\".\n * Tags are case-sensitive, whitespace-trimmed, otherwise raw.\n * Note: Error.name is fallback-grade (often too coarse like \"Error\", \"TypeError\"). */\nexport function extractErrorTag(error: unknown): string {\n if (error == null) return 'unknown';\n\n if (typeof error === 'string') return error.trim() || 'unknown';\n\n if (typeof error === 'object') {\n // Priority 1: _tag (TaggedError pattern)\n const tagged = error as Record<string, unknown>;\n if (typeof tagged._tag === 'string') {\n const trimmed = tagged._tag.trim();\n if (trimmed) return trimmed;\n }\n // Priority 2: tag\n if (typeof tagged.tag === 'string') {\n const trimmed = tagged.tag.trim();\n if (trimmed) return trimmed;\n }\n // Priority 3: code — string used directly, number stringified, anything else skipped\n if (typeof tagged.code === 'string') {\n const trimmed = tagged.code.trim();\n if (trimmed) return trimmed;\n } else if (typeof tagged.code === 'number') {\n return String(tagged.code);\n }\n // Priority 4: Error.name (fallback-grade)\n if (error instanceof Error && error.name) {\n const trimmed = error.name.trim();\n if (trimmed) return trimmed;\n }\n }\n\n return 'unknown';\n}\n\n/** Look up ErrorClassification from errorMeta for a given tag. */\nexport function lookupErrorClassification(\n tag: string,\n errorMeta?: Record<string, ErrorClassification>,\n): ErrorClassification | undefined {\n if (!errorMeta || !tag) return undefined;\n return errorMeta[tag];\n}\n\n/** Extract StepMetadata from StepOptions (returns undefined when empty). */\nexport function extractStepMetadata(options: StepOptions): StepMetadata | undefined {\n const { intent, domain, owner, tags, stateChanges, emits, calls } = options;\n if (!intent && !domain && !owner && !tags?.length && !stateChanges?.length && !emits?.length && !calls?.length) {\n return undefined;\n }\n const metadata: StepMetadata = {};\n if (intent) metadata.intent = intent;\n if (domain) metadata.domain = domain;\n if (owner) metadata.owner = owner;\n if (tags?.length) metadata.tags = tags;\n if (stateChanges?.length) metadata.stateChanges = stateChanges;\n if (emits?.length) metadata.emits = emits;\n if (calls?.length) metadata.calls = calls;\n return metadata;\n}\n\n/** Build StepErrorDiagnostics from error + errorMeta. */\nfunction buildStepErrorPayload(\n error: unknown,\n errorMeta: StepOptions['errorMeta'],\n origin: StepErrorDiagnostics['origin'],\n attempt?: number,\n cumulativeDurationMs?: number,\n): StepErrorDiagnostics {\n const tag = extractErrorTag(error);\n const classification = lookupErrorClassification(tag, errorMeta);\n const diagnostics: StepErrorDiagnostics = { tag, origin };\n if (classification !== undefined) diagnostics.classification = classification;\n if (attempt !== undefined) diagnostics.attempt = attempt;\n if (cumulativeDurationMs !== undefined) diagnostics.cumulativeDurationMs = cumulativeDurationMs;\n return diagnostics;\n}\n\n// =============================================================================\n// Retry and Timeout Types\n// =============================================================================\n\n/**\n * Backoff strategy for retry operations.\n */\nexport type BackoffStrategy = \"fixed\" | \"linear\" | \"exponential\";\n\n/**\n * Configuration for step retry behavior.\n */\nexport type RetryOptions = {\n /**\n * Total number of attempts (1 = no retry, 3 = initial + 2 retries).\n * Must be >= 1.\n */\n attempts: number;\n\n /**\n * Backoff strategy between retries.\n * - 'fixed': Same delay each time (initialDelay)\n * - 'linear': Delay increases linearly (initialDelay * attempt)\n * - 'exponential': Delay doubles each time (initialDelay * 2^(attempt-1))\n * @default 'exponential'\n */\n backoff?: BackoffStrategy;\n\n /**\n * Initial delay in milliseconds before first retry.\n * @default 100\n */\n initialDelay?: number;\n\n /**\n * Maximum delay cap in milliseconds.\n * Prevents exponential backoff from growing too large.\n * @default 30000 (30 seconds)\n */\n maxDelay?: number;\n\n /**\n * Whether to add random jitter (0-25% of delay).\n * Helps prevent thundering herd when multiple workflows retry simultaneously.\n * @default true\n */\n jitter?: boolean;\n\n /**\n * Predicate to determine if a retry should occur.\n * Receives the error and current attempt number (1-indexed).\n * Return true to retry, false to fail immediately.\n * @default Always retry on any error\n */\n retryOn?: (error: unknown, attempt: number) => boolean;\n\n /**\n * Callback invoked before each retry attempt.\n * Useful for logging, metrics, or side effects.\n */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n};\n\n/**\n * Timeout behavior when the timeout is reached.\n *\n * - 'error' (default): Return an error result with StepTimeoutError\n * - 'option': Return Ok(undefined) instead of an error (useful for optional operations)\n * - 'disconnect': Let the operation complete in background, return timeout error immediately\n * - function: Custom handler to generate the timeout error\n */\nexport type TimeoutBehavior =\n | \"error\"\n | \"option\"\n | \"disconnect\"\n | ((stepInfo: { name?: string; key?: string; ms: number }) => unknown);\n\n/**\n * Configuration for step timeout behavior.\n */\nexport type TimeoutOptions = {\n /**\n * Timeout duration in milliseconds per attempt.\n * When combined with retry, each attempt gets its own timeout.\n */\n ms: number;\n\n /**\n * Custom error to use when timeout occurs.\n * @default StepTimeoutError with step details\n */\n error?: unknown;\n\n /**\n * Whether to pass an AbortSignal to the operation.\n * When true, the operation function receives (signal: AbortSignal) as argument.\n * Useful for fetch() and other APIs that support cancellation.\n * @default false\n */\n signal?: boolean;\n\n /**\n * Behavior when timeout is reached.\n *\n * - 'error' (default): Return StepTimeoutError (or custom error if provided)\n * - 'option': Return Ok(undefined) instead of error (operation treated as optional)\n * - 'disconnect': Let operation complete in background, return error immediately\n * - function: Custom handler `(stepInfo) => customError`\n *\n * @default 'error'\n *\n * @example\n * ```typescript\n * // Default: Return timeout error\n * step.withTimeout(() => slowOp(), { ms: 5000 });\n *\n * // Optional: Return undefined if times out\n * step.withTimeout(() => optionalOp(), { ms: 5000, onTimeout: 'option' });\n *\n * // Disconnect: Don't wait for slow operation\n * step.withTimeout(() => fireAndForget(), { ms: 5000, onTimeout: 'disconnect' });\n *\n * // Custom error\n * step.withTimeout(() => apiCall(), {\n * ms: 5000,\n * onTimeout: ({ name, ms }) => ({ type: 'API_TIMEOUT', name, ms })\n * });\n * ```\n */\n onTimeout?: TimeoutBehavior;\n};\n\n/**\n * Standard timeout error type.\n */\nexport type StepTimeoutError = {\n type: \"STEP_TIMEOUT\";\n stepName?: string;\n stepKey?: string;\n timeoutMs: number;\n attempt?: number;\n};\n\n/**\n * Symbol used to mark any error (including custom errors) as a timeout error.\n * This allows detection of timeout errors even when users provide custom error payloads.\n */\nexport const STEP_TIMEOUT_MARKER: unique symbol = Symbol.for(\"step_timeout_marker\");\n\n/**\n * Metadata attached to timeout-marked errors.\n */\nexport type StepTimeoutMarkerMeta = {\n timeoutMs: number;\n stepName?: string;\n stepKey?: string;\n attempt?: number;\n};\n\n/**\n * Type guard to check if an error is a StepTimeoutError.\n * This checks both the standard type field AND the timeout marker symbol,\n * so custom errors provided via timeout.error are also detected.\n */\nexport function isStepTimeoutError(e: unknown): e is StepTimeoutError {\n if (typeof e !== \"object\" || e === null) {\n return false;\n }\n // Check for standard type field\n if ((e as StepTimeoutError).type === \"STEP_TIMEOUT\") {\n return true;\n }\n // Check for timeout marker (custom errors)\n return STEP_TIMEOUT_MARKER in e;\n}\n\n/**\n * Get timeout metadata from a timeout error (works with both standard and custom errors).\n * Returns undefined if the error is not a timeout error.\n */\nexport function getStepTimeoutMeta(e: unknown): StepTimeoutMarkerMeta | undefined {\n if (typeof e !== \"object\" || e === null) {\n return undefined;\n }\n // Check for standard type field first\n if ((e as StepTimeoutError).type === \"STEP_TIMEOUT\") {\n const err = e as StepTimeoutError;\n return {\n timeoutMs: err.timeoutMs,\n stepName: err.stepName,\n stepKey: err.stepKey,\n attempt: err.attempt,\n };\n }\n // Check for timeout marker (custom errors)\n if (STEP_TIMEOUT_MARKER in e) {\n return (e as Record<symbol, StepTimeoutMarkerMeta>)[STEP_TIMEOUT_MARKER];\n }\n return undefined;\n}\n\n// =============================================================================\n// RunStep Interface\n// =============================================================================\n\n/**\n * The `step` object passed to the function in `run(async ({ step }) => { ... })`.\n * acts as the bridge between your business logic and the workflow engine.\n *\n * It provides methods to:\n * 1. Execute operations that return `Result` types.\n * 2. safely wrap operations that might throw exceptions (using `step.try`).\n * 3. Assign names and keys to operations for tracing and caching.\n *\n * @template E - The union of all known error types expected in this workflow.\n */\nexport interface RunStep<E = unknown> {\n /**\n * Execute a Result-returning operation with explicit step ID.\n *\n * The ID is used for:\n * - Static analysis visualization\n * - Error flow tracking\n * - Step identification in diagrams\n * - Caching and resume (ID is used as the cache key)\n *\n * @param id - Unique step identifier (string literal for static analysis)\n * @param operation - A function that returns a Result or AsyncResult\n * @param options - Step options\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the result is an error (stops execution safely)\n *\n * @example\n * ```typescript\n * const cart = await step('getCart', () => getCart(ctx.input.cartId), {\n * errors: ['CART_NOT_FOUND', 'CART_EMPTY'],\n * out: 'cart',\n * });\n * ```\n */\n <T, StepE extends E, StepC = unknown>(\n id: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n options?: StepOptions\n ): Promise<T>;\n\n /**\n * Execute a standard throwing operation safely.\n * Catches exceptions and maps them to a typed error, or wraps them if no mapper is provided.\n *\n * Use this when integrating with libraries that throw exceptions.\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param operation - A function that returns a value or Promise (may throw)\n * @param options - Configuration including error mapping\n * @returns The success value\n * @throws {EarlyExit} If the operation throws (stops execution safely)\n *\n * @example\n * ```typescript\n * const data = await step.try(\n * \"db-query\",\n * () => db.query(),\n * { onError: (e) => ({ type: \"DB_ERROR\", cause: e }) }\n * );\n * ```\n */\n try: <T, const Err extends E>(\n id: string,\n operation: () => T | Promise<T>,\n options:\n | { error: Err; key?: string; ttl?: number }\n | { onError: (cause: unknown) => Err; key?: string; ttl?: number }\n ) => Promise<T>;\n\n /**\n * Execute a Result-returning function and map its error to a typed error.\n *\n * Use this when calling functions that return Result<T, E> and you want to\n * map their typed errors to your workflow's error type. Unlike step.try(),\n * the error passed to onError is typed (not unknown).\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param operation - A function that returns a Result or AsyncResult\n * @param options - Configuration including error mapping\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the result is an error (stops execution safely)\n *\n * @example\n * ```typescript\n * const response = await step.fromResult(\n * \"call-provider\",\n * () => callProvider(input),\n * {\n * onError: (providerError) => ({\n * type: \"PROVIDER_FAILED\",\n * provider: providerError.provider,\n * cause: providerError\n * })\n * }\n * );\n * ```\n */\n fromResult: <T, ResultE, const Err extends E>(\n id: string,\n operation: () => Result<T, ResultE, unknown> | AsyncResult<T, ResultE, unknown>,\n options:\n | { error: Err; key?: string; ttl?: number }\n | { onError: (resultError: ResultE) => Err; key?: string; ttl?: number }\n ) => Promise<T>;\n\n /**\n * Execute an operation that may return null/undefined and convert to a typed error.\n *\n * Shorthand for wrapping `fromNullable()` in a step — avoids boilerplate when\n * looking up optional values (database finds, map lookups, etc.).\n *\n * @param id - Unique step identifier\n * @param operation - A function that returns `T | null | undefined` (or a Promise thereof)\n * @param onNull - Returns the typed error when operation returns null/undefined\n *\n * @example\n * ```typescript\n * const user = await step.fromNullable(\n * 'getUser',\n * () => db.users.findById(id),\n * () => ({ type: 'NOT_FOUND' as const, id })\n * );\n * ```\n */\n fromNullable: <T, const Err extends E>(\n id: string,\n operation: () => T | null | undefined | Promise<T | null | undefined>,\n onNull: () => Err,\n options?: { key?: string; ttl?: number }\n ) => Promise<T>;\n\n /**\n * Execute parallel operations with scope events for visualization.\n *\n * This wraps the operations with scope_start and scope_end events, enabling\n * visualization of parallel execution branches.\n *\n * @overload Object form - step.parallel(name, { key: () => ... })\n * @overload Array form - step.parallel(name, () => allAsync([...]))\n *\n * @example Object form\n * ```typescript\n * const { user, posts } = await step.parallel('Fetch user data', {\n * user: () => fetchUser(id),\n * posts: () => fetchPosts(id),\n * });\n * ```\n *\n * @example Canonical form (strict mode)\n * ```typescript\n * const { user, posts } = await step.parallel('Fetch user data', {\n * user: { fn: () => fetchUser(id), errors: ['NOT_FOUND'] },\n * posts: { fn: () => fetchPosts(id), errors: ['FETCH_ERROR'] },\n * });\n * ```\n *\n * @example Array form\n * ```typescript\n * const [user, posts] = await step.parallel('Fetch all data', () =>\n * allAsync([fetchUser(id), fetchPosts(id)])\n * );\n * ```\n */\n parallel: {\n // Object form: step.parallel(name, { key: () => ... })\n <\n TOperations extends Record<\n string,\n () => MaybeAsyncResult<unknown, E, unknown>\n >\n >(\n name: string,\n operations: TOperations\n ): Promise<{\n [K in keyof TOperations]: TOperations[K] extends () => MaybeAsyncResult<\n infer V,\n E,\n unknown\n >\n ? V\n : never;\n }>;\n\n // Object form canonical: step.parallel(name, { key: { fn, errors } })\n <\n TOperations extends Record<\n string,\n ParallelOperationDescriptor<unknown, readonly string[]>\n >\n >(\n name: string,\n operations: TOperations\n ): Promise<{\n [K in keyof TOperations]: TOperations[K] extends ParallelOperationDescriptor<\n infer V,\n readonly string[]\n >\n ? V\n : never;\n }>;\n\n // Array form: step.parallel(name, () => allAsync([...]))\n <T, StepE extends E, StepC = unknown>(\n name: string,\n operation: () => Result<T[], StepE, StepC> | AsyncResult<T[], StepE, StepC>\n ): Promise<T[]>;\n };\n\n /**\n * Execute a race operation (anyAsync) with scope events for visualization.\n *\n * This wraps the operation with scope_start and scope_end events, enabling\n * visualization of racing execution branches.\n *\n * @param name - Name for this race block (used in visualization)\n * @param operation - A function that returns a Result from anyAsync\n * @returns The success value (first to succeed)\n *\n * @example\n * ```typescript\n * const data = await step.race('Fastest API', () =>\n * anyAsync([fetchFromPrimary(id), fetchFromFallback(id)])\n * );\n * ```\n */\n race: <T, StepE extends E, StepC = unknown>(\n name: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>\n ) => Promise<T>;\n\n /**\n * Execute an allSettled operation with scope events for visualization.\n *\n * This wraps the operation with scope_start and scope_end events, enabling\n * visualization of allSettled execution branches. Unlike step.parallel,\n * allSettled collects all results even if some fail.\n *\n * @param name - Name for this allSettled block (used in visualization)\n * @param operation - A function that returns a Result from allSettledAsync\n * @returns The success value (unwrapped array)\n *\n * @example\n * ```typescript\n * const [user, posts] = await step.allSettled('Fetch all data', () =>\n * allSettledAsync([fetchUser(id), fetchPosts(id)])\n * );\n * ```\n */\n allSettled: <T, StepE extends E, StepC = unknown>(\n name: string,\n operation: () => Result<T[], StepE, StepC> | AsyncResult<T[], StepE, StepC>\n ) => Promise<T[]>;\n\n /**\n * Execute a primary operation with a fallback if the primary fails.\n *\n * If the primary operation returns an error, the fallback is executed instead.\n * When `on` is specified, the fallback only runs for that specific error;\n * other errors propagate without invoking the fallback.\n *\n * Returns `Promise<T>` — errors escape via earlyExit into the workflow's error channel.\n * The error union `E1 | E2` is the generic constraint propagated to the workflow.\n *\n * @overload Fallback on ANY error from primary\n * @overload Fallback on SPECIFIC error literal only (via `on`)\n *\n * @param id - Unique step identifier (single step ID for events)\n * @param operation - Primary operation that returns AsyncResult\n * @param options - Fallback configuration\n * @returns The success value from primary or fallback\n *\n * @example\n * ```typescript\n * const user = await step.withFallback(\n * 'getUser',\n * () => fetchFromPrimary(id),\n * { fallback: () => fetchFromCache(id) }\n * );\n *\n * // With specific error filter\n * const data = await step.withFallback(\n * 'getData',\n * () => fetchFromApi(id),\n * { on: 'NOT_FOUND', fallback: () => getDefault(id) }\n * );\n * ```\n */\n withFallback: {\n // Overload 1: fallback on ANY error from primary\n <T, E1 extends E, E2 extends E>(\n id: string,\n operation: () => AsyncResult<T, E1>,\n options: { fallback: () => AsyncResult<T, E2>; key?: string }\n ): Promise<T>;\n\n // Overload 2: fallback on SPECIFIC error literal only\n <T, E1 extends E & string, E2 extends E>(\n id: string,\n operation: () => AsyncResult<T, E1>,\n options: { on: E1; fallback: () => AsyncResult<T, E2>; key?: string }\n ): Promise<T>;\n };\n\n /**\n * Execute an operation with automatic resource lifecycle management.\n *\n * Acquires a resource, uses it, and guarantees release regardless of outcome.\n * Release always runs after use completes (even on error or throw).\n * Release errors are logged via console.warn but never override the use result.\n *\n * No caching support — caching resource-using steps is dangerous.\n *\n * @param id - Unique step identifier\n * @param options - Resource lifecycle configuration\n * @returns The success value from the use function\n *\n * @example\n * ```typescript\n * const data = await step.withResource('useDb', {\n * acquire: () => connectToDb(),\n * use: (db) => db.query('SELECT * FROM users'),\n * release: (db) => db.close(),\n * });\n * ```\n */\n withResource: <T, R, AcquireE extends E, UseE extends E>(\n id: string,\n options: {\n acquire: () => AsyncResult<R, AcquireE>;\n use: (resource: R) => AsyncResult<T, UseE>;\n release: (resource: R) => void | Promise<void>;\n }\n ) => Promise<T>;\n\n /**\n * Execute an operation with retry and optional timeout.\n *\n * Use this for operations that may fail transiently (network issues, rate limits)\n * and benefit from automatic retry with backoff.\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param operation - A function that returns a Result or AsyncResult\n * @param options - Retry configuration and optional timeout\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If all retries are exhausted (stops execution safely)\n *\n * @example\n * ```typescript\n * const data = await step.retry(\n * \"fetch-external\",\n * () => fetchFromExternalApi(id),\n * {\n * attempts: 3,\n * backoff: 'exponential',\n * initialDelay: 200,\n * retryOn: (error) => error === 'RATE_LIMITED' || error === 'TRANSIENT',\n * onRetry: (error, attempt, delay) => {\n * console.log(`Retry ${attempt} after ${delay}ms`);\n * },\n * }\n * );\n * ```\n */\n retry: <T, StepE extends E, StepC = unknown>(\n id: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n options: RetryOptions & { key?: string; timeout?: TimeoutOptions }\n ) => Promise<T>;\n\n /**\n * Execute an operation with a timeout.\n *\n * Use this for operations that may hang indefinitely (external APIs, connections)\n * and need to be aborted after a certain duration.\n *\n * When `signal: true` is set, an AbortSignal is passed to your operation,\n * which you can use with APIs like fetch() for proper cancellation.\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param operation - A function that returns a Result (may receive AbortSignal)\n * @param options - Timeout configuration\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the operation times out (stops execution safely)\n *\n * @example\n * ```typescript\n * // Without AbortSignal\n * const data = await step.withTimeout(\n * \"fetch-data\",\n * () => fetchData(id),\n * { ms: 5000 }\n * );\n *\n * // With AbortSignal for fetch()\n * const data = await step.withTimeout(\n * \"fetch-url\",\n * (signal) => fetch(url, { signal }).then(r => ok(r.json())),\n * { ms: 5000, signal: true }\n * );\n * ```\n */\n withTimeout: <T, StepE extends E, StepC = unknown>(\n id: string,\n operation:\n | (() => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>)\n | ((signal: AbortSignal) => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>),\n options: TimeoutOptions & { key?: string }\n ) => Promise<T>;\n\n /**\n * Pause execution for a specified duration.\n *\n * Use this for intentional delays between operations (rate limiting,\n * polling intervals, debouncing). Respects workflow cancellation.\n *\n * @param id - Unique identifier for this step (required for analysis and caching)\n * @param duration - Duration as string (\"5s\", \"100ms\") or Duration object\n * @param options - Optional key for per-iteration identity, ttl, description\n * @returns Promise that resolves after the duration\n * @throws {AbortError} If the workflow is cancelled during sleep\n *\n * @example\n * ```typescript\n * // String duration\n * await step.sleep(\"rate-limit-delay\", \"5s\");\n *\n * // Duration object\n * await step.sleep(\"my-sleep\", seconds(5));\n * ```\n */\n sleep(\n id: string,\n duration: DurationInput,\n options?: { key?: string; ttl?: number; description?: string; signal?: AbortSignal }\n ): Promise<void>;\n\n // ===========================================================================\n // Streaming Methods\n // ===========================================================================\n\n /**\n * Get a writable stream for this workflow.\n *\n * Use this to write values that can be consumed by readers\n * (e.g., HTTP response streaming, AI token streaming).\n *\n * @param options - Stream options (namespace, highWaterMark)\n * @returns StreamWriter for writing values\n *\n * @example\n * ```typescript\n * const writer = step.getWritable<string>({ namespace: 'ai-response' });\n *\n * await step(() => generateAI({\n * prompt: 'Hello',\n * onToken: async (token) => { await writer.write(token); }\n * }), { key: 'generate' });\n *\n * await writer.close();\n * ```\n */\n getWritable: <T>(options?: StreamWritableOptions) => StreamWriterInterface<T>;\n\n /**\n * Get a readable stream for this workflow.\n *\n * Use this to consume values from a stream, with support for\n * resuming from a specific position.\n *\n * @param options - Read options (namespace, startIndex)\n * @returns StreamReader for reading values\n *\n * @example\n * ```typescript\n * const reader = step.getReadable<string>({ namespace: 'ai-response' });\n *\n * let result = await reader.read();\n * while (result.ok) {\n * response.write(result.value);\n * result = await reader.read();\n * }\n * ```\n */\n getReadable: <T>(options?: StreamReadableOptions) => StreamReaderInterface<T>;\n\n /**\n * Process stream items with checkpointing.\n *\n * Combines streaming with batch processing - each item is processed\n * and checkpointed, enabling resume from the last successful item.\n *\n * @param source - StreamReader or AsyncIterable to process\n * @param processor - Function to process each item\n * @param options - Processing options\n * @returns Results from all processed items\n *\n * @example\n * ```typescript\n * const reader = step.getReadable<Message>({ namespace: 'messages' });\n *\n * const result = await step.streamForEach(\n * reader,\n * async (message, index) => {\n * const processed = await processMessage(message);\n * return ok(processed);\n * },\n * { name: 'process-messages', checkpointInterval: 10 }\n * );\n *\n * console.log(`Processed ${result.value.processedCount} messages`);\n * ```\n */\n streamForEach: <T, R, StepE extends E>(\n source: StreamReaderInterface<T> | AsyncIterable<T>,\n processor: (item: T, index: number) => AsyncResult<R, StepE>,\n options?: StreamForEachStepOptions\n ) => Promise<StreamForEachResultType<R>>;\n\n // ===========================================================================\n // Static Analysis Methods\n // ===========================================================================\n\n /**\n * Mark a conditional for static analysis with a stable ID and condition label.\n * Runtime: returns the boolean result of condition().\n * Analysis: emits a DecisionNode with stable id and conditionLabel, and attaches\n * the then/else subgraphs from the if/else branches.\n *\n * @param id - Stable identifier for this decision point (string literal for static analysis)\n * @param conditionLabel - Human-readable label describing the condition\n * @param condition - Function that returns the boolean condition\n * @returns The result of the condition function\n *\n * @example\n * ```typescript\n * if (step.if('payment', 'cart.total > 0', () => ctx.ref('cart').total > 0)) {\n * await step('chargeCard', () => deps.chargeCard(ctx.ref('cart').total), {\n * errors: ['CARD_DECLINED'],\n * });\n * } else {\n * await step('skipPayment', async () => ({ skipped: true }), {\n * errors: [],\n * });\n * }\n * ```\n */\n if: <T extends boolean>(\n id: string,\n conditionLabel: string,\n condition: () => T\n ) => T;\n\n /**\n * Alias for `step.if()`. Mark a conditional for static analysis with a stable ID.\n * Use this to label conditionals in strict mode when they contain step calls.\n *\n * @param id - Stable identifier for this decision point\n * @param conditionLabel - Human-readable label describing the condition\n * @param condition - Function that returns the boolean condition\n * @returns The result of the condition function\n *\n * @example\n * ```typescript\n * if (step.label('email-type', 'user.isPremium', () => user.isPremium)) {\n * await step('premium', () => sendPriorityEmail(user), { errors: ['EMAIL_FAILED'] });\n * } else {\n * await step('free', () => sendRegularEmail(user), { errors: ['EMAIL_FAILED'] });\n * }\n * ```\n */\n label: <T extends boolean>(\n id: string,\n conditionLabel: string,\n condition: () => T\n ) => T;\n\n /**\n * Execute a branch with explicit metadata for static analysis.\n * Use when you want richer analyzer metadata (conditionLabel, per-arm errors).\n * For most cases, use natural if/else with step.label() instead.\n *\n * @param id - Stable identifier for this branch point\n * @param options - Branch configuration with condition, then/else arms, and errors\n * @returns The result from the executed arm\n *\n * @example\n * ```typescript\n * const charge = await step.branch('payment', {\n * conditionLabel: 'cart.total > 0',\n * condition: () => ctx.ref('cart').total > 0,\n * out: 'charge',\n * then: () => chargeCard(ctx.ref('cart').total),\n * thenErrors: ['CARD_DECLINED'],\n * else: () => ok({ skipped: true }),\n * elseErrors: [],\n * });\n * ```\n */\n branch: <\n T,\n const ThenErrs extends readonly string[] = readonly [],\n const ElseErrs extends readonly string[] = readonly [],\n const Out extends string | undefined = undefined,\n >(\n id: string,\n options: BranchOptions<T, ThenErrs, ElseErrs, Out>\n ) => Promise<T>;\n\n /**\n * Create an arm definition for use with step.branch().\n * Runtime: returns the arm definition unchanged.\n * Analyzer: extracts arm metadata for visualization.\n *\n * @param fn - The arm function\n * @param errors - Declared errors for this arm\n * @returns The arm definition\n *\n * @example\n * ```typescript\n * const thenArm = step.arm(() => chargeCard(total), ['CARD_DECLINED']);\n * const elseArm = step.arm(() => ok({ skipped: true }), []);\n * ```\n */\n arm: <T, const Errs extends readonly string[] = readonly []>(\n fn: () => T | Promise<T>,\n errors?: Errs\n ) => ArmDefinition<T, Errs>;\n\n /**\n * Execute a forEach loop with static analysis support.\n * Supports both simple (run) and complex (item) forms.\n *\n * @param id - Stable identifier for this loop\n * @param items - Iterable to loop over\n * @param options - Loop configuration\n * @returns Array of results from each iteration\n *\n * @example Simple form:\n * ```typescript\n * await step.forEach('process-items', items, {\n * maxIterations: 100,\n * stepIdPattern: 'process-{i}',\n * errors: ['PROCESS_ERROR'],\n * run: (item) => processItem(item),\n * });\n * ```\n *\n * @example Complex form with multiple steps:\n * ```typescript\n * await step.forEach('process-items', items, {\n * maxIterations: 100,\n * item: step.item((item, i, innerStep) => {\n * await innerStep('validate', () => validate(item), { errors: ['INVALID'] });\n * await innerStep('process', () => process(item), { errors: ['FAILED'] });\n * }),\n * });\n * ```\n */\n forEach: {\n // Simple form with run callback\n <T, R, const Errs extends readonly string[] = readonly []>(\n id: string,\n items: Iterable<T> | AsyncIterable<T>,\n options: ForEachRunOptions<T, R, Errs>\n ): Promise<R[]>;\n\n // Complex form with item callback\n <T, R>(\n id: string,\n items: Iterable<T> | AsyncIterable<T>,\n options: ForEachItemOptions<T, R>\n ): Promise<R[]>;\n };\n\n /**\n * Create an item handler for use with step.forEach().\n * Runtime: returns the handler unchanged.\n * Analyzer: extracts the inner step structure.\n *\n * @param handler - Function to process each item\n * @returns The item handler\n *\n * @example\n * ```typescript\n * step.item((item, index, innerStep) => {\n * await innerStep('validate', () => validate(item));\n * await innerStep('process', () => process(item));\n * });\n * ```\n */\n item: <T, R>(\n handler: (item: T, index: number, step: RunStep<E>) => R | Promise<R>\n ) => ForEachItemHandler<T, R>;\n\n /**\n * Wrap a dependency function for static analysis tracking.\n * Returns the function unchanged but marks it for the analyzer.\n *\n * @param name - Name of the dependency (for analyzer tracking)\n * @param fn - The dependency function to wrap\n * @returns The same function, unchanged\n *\n * @example\n * ```typescript\n * await step('getCart', step.dep('getCart', () => deps.getCart(ctx.input.cartId)), {\n * errors: ['CART_NOT_FOUND'],\n * out: 'cart',\n * });\n * ```\n */\n dep: <T extends (...args: unknown[]) => unknown>(name: string, fn: T) => T;\n\n // ===========================================================================\n // Effect-Style Ergonomics\n // ===========================================================================\n\n /**\n * Unwrap an AsyncResult directly within a workflow step.\n *\n * Use this when you already have an AsyncResult and want to unwrap it\n * without wrapping it in a function. Automatically exits on error.\n *\n * @param id - Unique step identifier\n * @param result - The AsyncResult to unwrap\n * @param options - Step options\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the result is an error\n *\n * @example\n * ```typescript\n * const userResult = fetchUser(userId); // AsyncResult<User, 'NOT_FOUND'>\n * const user = await step.run('fetchUser', userResult);\n * // Automatically unwraps and exits on error\n * ```\n */\n run: <T, StepE extends E, StepC = unknown>(\n id: string,\n result: AsyncResult<T, StepE, StepC>,\n options?: StepOptions\n ) => Promise<T>;\n\n /**\n * Run a sub-workflow (or any AsyncResult-returning operation) as a step.\n * Use for workflow composition; the getter's error type (SubE) flows into the parent's error union.\n *\n * @param id - Unique step identifier\n * @param getter - Function that returns AsyncResult (e.g. () => subWorkflow.run(fn))\n * @param options - Step options (key, ttl, etc.)\n * @returns The success value (unwrapped)\n * @throws {EarlyExit} If the result is an error\n *\n * @example\n * ```typescript\n * const authResult = await step.workflow(\"authorize\", () => authorizeWorkflow.run(fn));\n * ```\n */\n workflow: <T, SubE extends E, StepC = unknown>(\n id: string,\n getter: () => AsyncResult<T, SubE, StepC>,\n options?: StepOptions\n ) => Promise<T>;\n\n /**\n * Chain AsyncResult operations with step tracking.\n *\n * Use this for composing AsyncResult operations where each step\n * depends on the previous one's success value.\n *\n * @param id - Unique step identifier\n * @param value - The value to pass to the function\n * @param fn - Function that takes the value and returns an AsyncResult\n * @param options - Step options\n * @returns The final success value (unwrapped)\n * @throws {EarlyExit} If the result is an error\n *\n * @example\n * ```typescript\n * const user = await step.run('fetchUser', fetchUser(id));\n * const enriched = await step.andThen('enrich', user, (user) =>\n * enrichUser(user) // Returns AsyncResult<EnrichedUser, E>\n * );\n * ```\n */\n andThen: <T, U, StepE extends E, StepC = unknown>(\n id: string,\n value: T,\n fn: (value: T) => AsyncResult<U, StepE, StepC>,\n options?: StepOptions\n ) => Promise<U>;\n\n /**\n * Pattern match on a Result with step tracking for both branches.\n *\n * Use this for handling Result values where both success and error\n * paths need to be tracked as separate steps.\n *\n * @param id - Unique step identifier\n * @param result - The Result to match on\n * @param handlers - Object with ok and err handler functions\n * @param options - Step options\n * @returns The value returned by the matched handler\n *\n * @example\n * ```typescript\n * const user = await step.run('fetchUser', fetchUser(id));\n *\n * const message = await step.match('handleUser', user, {\n * ok: async (user) => {\n * await step('sendWelcome', () => sendEmail(user.email));\n * return 'Sent welcome email';\n * },\n * err: async (error) => {\n * await step('logError', () => logError(error));\n * return 'Failed to fetch user';\n * }\n * });\n * ```\n */\n match: <T, StepE extends E, U, StepC = unknown>(\n id: string,\n result: Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n handlers: {\n ok: (value: T) => U | Promise<U>;\n err: (error: StepE, cause?: StepC) => U | Promise<U>;\n },\n options?: StepOptions\n ) => Promise<U>;\n\n /**\n * Alias for step.parallel - Effect.all-style API for parallel execution.\n *\n * Executes multiple operations in parallel and returns named results.\n * Identical to step.parallel but with a name more familiar to Effect users.\n *\n * @param name - Name for this parallel block\n * @param operations - Object mapping keys to operations\n * @returns Object with results mapped to the same keys\n *\n * @example\n * ```typescript\n * const { user, posts, comments } = await step.all('fetchAll', {\n * user: () => fetchUser('1'),\n * posts: () => fetchPosts('1'),\n * comments: () => fetchComments('1')\n * });\n * ```\n */\n all: RunStep<E>[\"parallel\"];\n\n /**\n * Map over an array with parallel execution and error tracking.\n *\n * Similar to Effect.forEach - executes mapper function for each item\n * in parallel and collects results.\n *\n * @param id - Unique step identifier\n * @param items - Array of items to process\n * @param mapper - Function to process each item (returns AsyncResult)\n * @param options - Optional concurrency limit and cache key\n * @returns Array of results in original order\n *\n * @example\n * ```typescript\n * const users = await step.map('fetchUsers', userIds, (id) =>\n * fetchUser(id)\n * );\n * // Automatic parallel execution with error union\n * ```\n */\n map: <T, U, StepE extends E, StepC = unknown>(\n id: string,\n items: T[],\n mapper: (item: T, index: number) => AsyncResult<U, StepE, StepC>,\n options?: { concurrency?: number; key?: string }\n ) => Promise<U[]>;\n\n}\n\n// =============================================================================\n// Parallel Types\n// =============================================================================\n\n/**\n * Operation descriptor for canonical parallel form.\n * Use this for analyzable parallel operations with explicit error declarations.\n */\nexport type ParallelOperationDescriptor<\n T,\n Errs extends readonly string[] = readonly [],\n> = {\n /** The operation function */\n fn: () => MaybeAsyncResult<T, unknown, unknown>;\n /** Declared errors for this operation (for static analysis) */\n errors?: Errs;\n};\n\n// =============================================================================\n// Branch and ForEach Types\n// =============================================================================\n\n/**\n * Options for step.branch().\n */\nexport type BranchOptions<\n T,\n ThenErrs extends readonly string[] = readonly [],\n ElseErrs extends readonly string[] = readonly [],\n Out extends string | undefined = undefined,\n> = {\n /** Human-readable label describing the condition */\n conditionLabel: string;\n /** Function that evaluates the condition */\n condition: () => boolean;\n /** Output key for data flow (writes result to ctx[out]) */\n out?: Out;\n /** Function to execute when condition is true */\n then: () => T | Promise<T>;\n /** Declared errors for the then arm */\n thenErrors?: ThenErrs;\n /** Function to execute when condition is false */\n else?: () => T | Promise<T>;\n /** Declared errors for the else arm */\n elseErrors?: ElseErrs;\n};\n\n/**\n * Arm definition for step.branch().\n */\nexport type ArmDefinition<T, Errs extends readonly string[] = readonly []> = {\n fn: () => T | Promise<T>;\n errors?: Errs;\n};\n\n/**\n * Options for step.forEach() with simple run form.\n */\nexport type ForEachRunOptions<T, R, Errs extends readonly string[] = readonly []> = {\n /** Maximum iterations (for bounded analysis) */\n maxIterations?: number;\n /** Step ID pattern for iterations (e.g., 'process-{i}') */\n stepIdPattern?: string;\n /** Declared errors for the loop body */\n errors?: Errs;\n /** Output key for results (requires collect option in strict mode) */\n out?: string;\n /** How to collect results when out is specified */\n collect?: \"array\" | \"last\";\n /** Simple callback for each item */\n run: (item: T, index: number) => R | Promise<R>;\n};\n\n/**\n * Options for step.forEach() with complex item form.\n */\nexport type ForEachItemOptions<T, R> = {\n /** Maximum iterations (for bounded analysis) */\n maxIterations?: number;\n /** Step ID pattern for iterations (e.g., 'process-{i}') */\n stepIdPattern?: string;\n /** Output key for results (requires collect option in strict mode) */\n out?: string;\n /** How to collect results when out is specified */\n collect?: \"array\" | \"last\";\n /** Complex item handler with inner step access */\n item: ForEachItemHandler<T, R>;\n};\n\n/**\n * Item handler for step.forEach() with inner step access.\n */\nexport type ForEachItemHandler<T, R> = {\n __forEachItemHandler: true;\n handler: (item: T, index: number, step: RunStep<unknown>) => R | Promise<R>;\n};\n\n// =============================================================================\n// Streaming Types (minimal interfaces for RunStep)\n// =============================================================================\n\n/**\n * Options for getWritable.\n */\nexport interface StreamWritableOptions {\n /** Named streams (default: 'default') */\n namespace?: string;\n /** Backpressure threshold (default: 16) */\n highWaterMark?: number;\n}\n\n/**\n * Options for getReadable.\n */\nexport interface StreamReadableOptions {\n /** Named streams (default: 'default') */\n namespace?: string;\n /** Resume from position (0-indexed) */\n startIndex?: number;\n /** Poll interval in ms when waiting for new items (default: 10) */\n pollInterval?: number;\n /** Stop polling after this many ms with no new items (default: 30000) */\n pollTimeout?: number;\n}\n\n/**\n * Options for streamForEach.\n */\nexport interface StreamForEachStepOptions {\n /** Checkpoint after every N items (default: 1) */\n checkpointInterval?: number;\n /** Maximum concurrent processors (default: 1 = sequential) */\n concurrency?: number;\n}\n\n/**\n * Result from streamForEach operation.\n */\nexport interface StreamForEachResultType<R> {\n /** Results from each processed item */\n results: R[];\n /** Total items processed */\n processedCount: number;\n /** Position of last processed item */\n lastPosition: number;\n}\n\n/**\n * Writable stream interface used in RunStep.\n * @see StreamWriter in awaitly/streaming for full interface\n */\nexport interface StreamWriterInterface<T> {\n write(value: T): AsyncResult<void, StreamWriteErrorType>;\n close(): AsyncResult<void, StreamCloseErrorType>;\n abort(reason: unknown): void;\n readonly writable: boolean;\n readonly position: number;\n readonly namespace: string;\n}\n\n/**\n * Readable stream interface used in RunStep.\n * @see StreamReader in awaitly/streaming for full interface\n */\nexport interface StreamReaderInterface<T> {\n read(): AsyncResult<T, StreamReadErrorType | StreamEndedMarkerType>;\n close(): void;\n readonly readable: boolean;\n readonly position: number;\n readonly namespace: string;\n}\n\n/**\n * Stream write error type.\n */\nexport interface StreamWriteErrorType {\n type: \"STREAM_WRITE_ERROR\";\n reason: \"closed\" | \"aborted\" | \"store_error\";\n message: string;\n cause?: unknown;\n}\n\n/**\n * Stream read error type.\n */\nexport interface StreamReadErrorType {\n type: \"STREAM_READ_ERROR\";\n reason: \"closed\" | \"store_error\";\n message: string;\n cause?: unknown;\n}\n\n/**\n * Stream close error type.\n */\nexport interface StreamCloseErrorType {\n type: \"STREAM_CLOSE_ERROR\";\n reason: \"already_closed\" | \"store_error\";\n message: string;\n cause?: unknown;\n}\n\n/**\n * Stream ended marker type.\n */\nexport interface StreamEndedMarkerType {\n type: \"STREAM_ENDED\";\n finalPosition: number;\n}\n\n// =============================================================================\n// Event Types (for run() optional event support)\n// =============================================================================\n\n/**\n * Unified event stream for workflow execution.\n *\n * Note: step_complete.result uses Result<unknown, unknown, unknown> because events\n * aggregate results from heterogeneous steps. At runtime, the actual Result object\n * preserves its original types, but the event type cannot statically represent them.\n * Use runtime checks or the meta field to interpret cause values.\n */\n/**\n * Scope types for parallel and race operations.\n */\nexport type ScopeType = \"parallel\" | \"race\" | \"allSettled\";\n\nexport type WorkflowEvent<E, C = unknown> =\n | { type: \"workflow_start\"; workflowId: string; workflowName?: string; ts: number; context?: C }\n | { type: \"workflow_success\"; workflowId: string; workflowName?: string; ts: number; durationMs: number; context?: C }\n | { type: \"workflow_error\"; workflowId: string; workflowName?: string; ts: number; durationMs: number; error: E; context?: C }\n | { type: \"step_start\"; workflowId: string; workflowName?: string; stepId: string; stepKey?: string; name?: string; description?: string; ts: number; metadata?: StepMetadata; context?: C }\n | { type: \"step_success\"; workflowId: string; workflowName?: string; stepId: string; stepKey?: string; name?: string; description?: string; ts: number; durationMs: number; metadata?: StepMetadata; context?: C }\n | { type: \"step_error\"; workflowId: string; workflowName?: string; stepId: string; stepKey?: string; name?: string; description?: string; ts: number; durationMs: number; error: E; metadata?: StepMetadata; diagnostics?: StepErrorDiagnostics; context?: C }\n | { type: \"step_aborted\"; workflowId: string; workflowName?: string; stepId: string; stepKey?: string; name?: string; description?: string; ts: number; durationMs: number; metadata?: StepMetadata; context?: C }\n | { type: \"step_complete\"; workflowId: string; workflowName?: string; stepKey: string; name?: string; description?: string; ts: number; durationMs: number; result: Result<unknown, unknown, unknown>; meta?: StepFailureMeta; metadata?: StepMetadata; context?: C }\n | { type: \"step_cache_hit\"; workflowId: string; workflowName?: string; stepKey: string; name?: string; ts: number; metadata?: StepMetadata; context?: C }\n | { type: \"step_cache_miss\"; workflowId: string; workflowName?: string; stepKey: string; name?: string; ts: number; metadata?: StepMetadata; context?: C }\n | { type: \"step_skipped\"; workflowId: string; workflowName?: string; stepKey?: string; name?: string; reason?: string; decisionId?: string; ts: number; metadata?: StepMetadata; context?: C }\n | { type: \"scope_start\"; workflowId: string; workflowName?: string; scopeId: string; scopeType: ScopeType; name?: string; ts: number; context?: C }\n | { type: \"scope_end\"; workflowId: string; workflowName?: string; scopeId: string; ts: number; durationMs: number; winnerId?: string; context?: C }\n // Retry events\n | {\n type: \"step_retry\";\n workflowId: string;\n workflowName?: string;\n stepId: string;\n stepKey?: string;\n name?: string;\n ts: number;\n attempt: number;\n maxAttempts: number;\n delayMs: number;\n error: E;\n metadata?: StepMetadata;\n diagnostics?: StepErrorDiagnostics;\n context?: C;\n }\n | {\n type: \"step_retries_exhausted\";\n workflowId: string;\n workflowName?: string;\n stepId: string;\n stepKey?: string;\n name?: string;\n ts: number;\n durationMs: number;\n attempts: number;\n lastError: E;\n metadata?: StepMetadata;\n diagnostics?: StepErrorDiagnostics;\n context?: C;\n }\n // Timeout event\n | {\n type: \"step_timeout\";\n workflowId: string;\n workflowName?: string;\n stepId: string;\n stepKey?: string;\n name?: string;\n ts: number;\n timeoutMs: number;\n attempt?: number;\n metadata?: StepMetadata;\n diagnostics?: StepErrorDiagnostics;\n context?: C;\n }\n // Hook events\n | {\n type: \"hook_should_run\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n result: boolean;\n skipped: boolean;\n context?: C;\n }\n | {\n type: \"hook_should_run_error\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n error: E;\n context?: C;\n }\n | {\n type: \"hook_before_start\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n result: boolean;\n skipped: boolean;\n context?: C;\n }\n | {\n type: \"hook_before_start_error\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n error: E;\n context?: C;\n }\n | {\n type: \"hook_after_step\";\n workflowId: string;\n workflowName?: string;\n stepKey: string;\n ts: number;\n durationMs: number;\n context?: C;\n }\n | {\n type: \"hook_after_step_error\";\n workflowId: string;\n workflowName?: string;\n stepKey: string;\n ts: number;\n durationMs: number;\n error: E;\n context?: C;\n }\n // Stream events\n | {\n type: \"stream_created\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_write\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n position: number;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_read\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n position: number;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_close\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n finalPosition: number;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_error\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n error: unknown;\n position: number;\n ts: number;\n context?: C;\n }\n | {\n type: \"stream_backpressure\";\n workflowId: string;\n workflowName?: string;\n namespace: string;\n bufferedCount: number;\n state: \"paused\" | \"flowing\";\n ts: number;\n context?: C;\n }\n // Workflow cancellation event\n | {\n type: \"workflow_cancelled\";\n workflowId: string;\n workflowName?: string;\n ts: number;\n durationMs: number;\n /** Reason from AbortSignal.reason (if provided) */\n reason?: string;\n /** Last successfully completed keyed step before cancellation (for resume purposes) */\n lastStepKey?: string;\n context?: C;\n };\n\n// =============================================================================\n// Run Options\n// =============================================================================\n\nexport type RunOptionsWithCatch<E, C = void> = {\n /**\n * Handler for expected errors.\n * Called when a step fails with a known error type.\n */\n onError?: (error: E, stepName?: string, ctx?: C) => void;\n /**\n * Listener for workflow events (start, success, error, step events).\n * Use this for logging, telemetry, or debugging.\n *\n * Context is automatically included in `event.context` when provided via the `context` option.\n * The separate `ctx` parameter is provided for convenience.\n */\n onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;\n /**\n * Catch-all mapper for unexpected exceptions.\n * Converts unknown exceptions (and cancellation) into your typed error union E.\n */\n catchUnexpected: (cause: unknown) => E;\n /**\n * Unique ID for this workflow execution.\n * Defaults to a random UUID.\n * Useful for correlating logs across distributed systems.\n */\n workflowId?: string;\n /**\n * Human-readable workflow name included on emitted events.\n * Useful for observability and visualization.\n */\n workflowName?: string;\n /**\n * Arbitrary context object passed to onEvent and onError.\n * Useful for passing request IDs, user IDs, or loggers.\n */\n context?: C;\n /**\n * @internal External signal for workflow-level cancellation.\n * Used by createWorkflow() to pass the workflow signal to steps.\n */\n _workflowSignal?: AbortSignal;\n};\n\nexport type RunOptionsWithoutCatch<E, C = void> = {\n /**\n * Handler for expected errors AND unexpected errors.\n * Unexpected errors will be wrapped in `UnexpectedError`.\n */\n onError?: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;\n /**\n * Listener for workflow events (start, success, error, step events).\n *\n * Note: Context is available both on `event.context` and as the separate `ctx` parameter.\n * The `ctx` parameter is provided for convenience and backward compatibility.\n */\n onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;\n catchUnexpected?: undefined;\n workflowId?: string;\n /**\n * Human-readable workflow name included on emitted events.\n * Useful for observability and visualization.\n */\n workflowName?: string;\n context?: C;\n /**\n * @internal External signal for workflow-level cancellation.\n * Used by createWorkflow() to pass the workflow signal to steps.\n */\n _workflowSignal?: AbortSignal;\n};\n\nexport type RunOptions<E, C = void> = RunOptionsWithCatch<E, C> | RunOptionsWithoutCatch<E, C>;\n\n// =============================================================================\n// Early Exit Mechanism (exported for caching layer)\n// =============================================================================\n\n/**\n * Symbol used to identify early exit throws.\n * Exported for the caching layer in workflow.ts.\n * @internal\n */\nexport const EARLY_EXIT_SYMBOL: unique symbol = Symbol(\"early-exit\");\n\n/**\n * Metadata about how a step failed.\n * @internal\n */\nexport type StepFailureMeta =\n | { origin: \"result\"; resultCause?: unknown }\n | { origin: \"throw\"; thrown: unknown }\n | { origin: \"fallback\"; fallbackUsed: true; fallbackReason: string };\n\n/**\n * Early exit object thrown to short-circuit workflow execution.\n * @internal\n */\nexport type EarlyExit<E> = {\n [EARLY_EXIT_SYMBOL]: true;\n error: E;\n meta: StepFailureMeta;\n};\n\n/**\n * Create an early exit throw object.\n * Used by the caching layer to synthesize early exits for cached errors.\n * @internal\n */\nexport function createEarlyExit<E>(error: E, meta: StepFailureMeta): EarlyExit<E> {\n return {\n [EARLY_EXIT_SYMBOL]: true,\n error,\n meta,\n };\n}\n\n/**\n * Type guard for early exit objects.\n * @internal\n */\nexport function isEarlyExit<E>(e: unknown): e is EarlyExit<E> {\n return (\n typeof e === \"object\" &&\n e !== null &&\n (e as Record<PropertyKey, unknown>)[EARLY_EXIT_SYMBOL] === true\n );\n}\n\n/**\n * Symbol to mark exceptions thrown by catchUnexpected mappers.\n * These should propagate without being re-processed.\n * @internal\n */\nconst MAPPER_EXCEPTION_SYMBOL: unique symbol = Symbol(\"mapper-exception\");\n\ntype MapperException = {\n [MAPPER_EXCEPTION_SYMBOL]: true;\n thrown: unknown;\n};\n\nfunction createMapperException(thrown: unknown): MapperException {\n return { [MAPPER_EXCEPTION_SYMBOL]: true, thrown };\n}\n\nfunction isMapperException(e: unknown): e is MapperException {\n return (\n typeof e === \"object\" &&\n e !== null &&\n (e as Record<PropertyKey, unknown>)[MAPPER_EXCEPTION_SYMBOL] === true\n );\n}\n\n// =============================================================================\n// Retry and Timeout Utilities\n// =============================================================================\n\n/**\n * Calculate the delay for a retry attempt based on the backoff strategy.\n * @internal\n */\nfunction calculateRetryDelay(\n attempt: number,\n options: {\n backoff: BackoffStrategy;\n initialDelay: number;\n maxDelay: number;\n jitter: boolean;\n }\n): number {\n const { backoff, initialDelay, maxDelay, jitter } = options;\n\n let delay: number;\n\n switch (backoff) {\n case \"fixed\":\n delay = initialDelay;\n break;\n case \"linear\":\n delay = initialDelay * attempt;\n break;\n case \"exponential\":\n delay = initialDelay * Math.pow(2, attempt - 1);\n break;\n }\n\n // Apply max cap\n delay = Math.min(delay, maxDelay);\n\n // Apply jitter (0-25% of delay)\n if (jitter) {\n const jitterAmount = delay * 0.25 * Math.random();\n delay = delay + jitterAmount;\n }\n\n return Math.floor(delay);\n}\n\n/**\n * Sleep for a specified number of milliseconds.\n * @internal\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nconst DEFAULT_RETRY_ASYNC_CONFIG = {\n backoff: \"exponential\" as BackoffStrategy,\n initialDelay: 100,\n maxDelay: 30000,\n jitter: true,\n retryOn: (_error: unknown, _attempt: number) => true,\n onRetry: (_error: unknown, _attempt: number, _delayMs: number) => {},\n} as const;\n\n/**\n * Run an async function with retry. Reuses the same backoff and retryOn semantics as step.retry.\n * Use this when you want retries without the workflow/step machinery (e.g. in fetch).\n *\n * @param fn - Function that returns a Promise<Result<T, E>>\n * @param options - Retry configuration (attempts, backoff, retryOn, etc.)\n * @returns Promise that resolves to the last Result (ok or err). Rejects only if fn throws and retryOn returns false.\n */\nexport async function retryAsync<T, E>(\n fn: () => Promise<Result<T, E>>,\n options: RetryOptions\n): Promise<Result<T, E>> {\n const attempts = Math.max(1, options.attempts);\n const effective = {\n backoff: options.backoff ?? DEFAULT_RETRY_ASYNC_CONFIG.backoff,\n initialDelay: options.initialDelay ?? DEFAULT_RETRY_ASYNC_CONFIG.initialDelay,\n maxDelay: options.maxDelay ?? DEFAULT_RETRY_ASYNC_CONFIG.maxDelay,\n jitter: options.jitter ?? DEFAULT_RETRY_ASYNC_CONFIG.jitter,\n retryOn: options.retryOn ?? DEFAULT_RETRY_ASYNC_CONFIG.retryOn,\n onRetry: options.onRetry ?? DEFAULT_RETRY_ASYNC_CONFIG.onRetry,\n };\n\n let lastResult: Result<T, E> | undefined;\n for (let attempt = 1; attempt <= attempts; attempt++) {\n try {\n const result = await fn();\n if (result.ok) return result;\n lastResult = result;\n if (attempt < attempts && effective.retryOn(result.error, attempt)) {\n const delay = calculateRetryDelay(attempt, effective);\n effective.onRetry(result.error, attempt, delay);\n await sleep(delay);\n continue;\n }\n return result;\n } catch (thrown) {\n if (attempt < attempts && effective.retryOn(thrown, attempt)) {\n const delay = calculateRetryDelay(attempt, effective);\n effective.onRetry(thrown, attempt, delay);\n await sleep(delay);\n continue;\n }\n throw thrown;\n }\n }\n return lastResult!;\n}\n\n/**\n * Symbol used internally to identify timeout rejection.\n */\nconst TIMEOUT_SYMBOL: unique symbol = Symbol(\"timeout\");\nconst TIMEOUT_OPTION_SYMBOL: unique symbol = Symbol(\"timeout-option\");\n\n/**\n * Check if an error is a timeout option marker (should return undefined instead of error).\n * @internal\n */\nfunction isTimeoutOptionMarker(\n value: unknown\n): value is { [TIMEOUT_OPTION_SYMBOL]: true; ms: number } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as Record<symbol, unknown>)[TIMEOUT_OPTION_SYMBOL] === true\n );\n}\n\n/**\n * Execute an operation with a timeout using Promise.race.\n * @internal\n */\nasync function executeWithTimeout<T>(\n operation: (() => Promise<T>) | ((signal: AbortSignal) => Promise<T>),\n options: TimeoutOptions,\n stepInfo: { name?: string; key?: string; attempt?: number },\n /** External signal (e.g., workflow cancellation) to combine with timeout signal */\n externalSignal?: AbortSignal\n): Promise<T> {\n const controller = new AbortController();\n const behavior = options.onTimeout ?? \"error\";\n\n // Create the timeout error based on behavior\n const createTimeoutError = (): unknown => {\n // For function behavior, call the handler to generate the error\n if (typeof behavior === \"function\") {\n return behavior({\n name: stepInfo.name,\n key: stepInfo.key,\n ms: options.ms,\n });\n }\n\n // For other behaviors, use custom error or default StepTimeoutError\n return (\n (options.error as StepTimeoutError) ?? {\n type: \"STEP_TIMEOUT\",\n stepName: stepInfo.name,\n stepKey: stepInfo.key,\n timeoutMs: options.ms,\n attempt: stepInfo.attempt,\n }\n );\n };\n\n // Track the timeout ID for cleanup\n let timeoutId: ReturnType<typeof setTimeout>;\n\n // If external signal is already aborted, abort immediately\n if (externalSignal?.aborted) {\n controller.abort(externalSignal.reason);\n }\n\n // Forward external signal abort to internal controller\n let externalAbortHandler: (() => void) | undefined;\n if (externalSignal && !externalSignal.aborted) {\n externalAbortHandler = () => controller.abort(externalSignal.reason);\n externalSignal.addEventListener(\"abort\", externalAbortHandler, { once: true });\n }\n\n // Create a timeout promise that rejects after the specified duration\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n // For 'disconnect', don't abort - let operation continue in background\n if (behavior !== \"disconnect\") {\n controller.abort();\n }\n\n // For 'option', throw special marker to return undefined\n if (behavior === \"option\") {\n reject({ [TIMEOUT_OPTION_SYMBOL]: true, ms: options.ms });\n return;\n }\n\n // For all other behaviors, throw the timeout error\n reject({ [TIMEOUT_SYMBOL]: true, error: createTimeoutError() });\n }, options.ms);\n });\n\n // Execute the operation\n let operationPromise: Promise<T>;\n if (options.signal) {\n // Operation expects an AbortSignal\n // Pass the internal controller's signal which is linked to both timeout and external signal\n operationPromise = Promise.resolve(\n (operation as (signal: AbortSignal) => Promise<T>)(controller.signal)\n );\n } else {\n // Standard operation\n operationPromise = Promise.resolve((operation as () => Promise<T>)());\n }\n\n try {\n // Race between operation and timeout\n const result = await Promise.race([operationPromise, timeoutPromise]);\n return result;\n } catch (error) {\n // Check if this was an 'option' timeout - return undefined as success\n if (\n typeof error === \"object\" &&\n error !== null &&\n (error as Record<symbol, unknown>)[TIMEOUT_OPTION_SYMBOL] === true\n ) {\n // Throw special marker that step handler will convert to ok(undefined)\n throw { [TIMEOUT_OPTION_SYMBOL]: true, ms: options.ms };\n }\n\n // Check if this was our timeout\n if (\n typeof error === \"object\" &&\n error !== null &&\n (error as Record<symbol, unknown>)[TIMEOUT_SYMBOL] === true\n ) {\n // For 'disconnect' behavior, the operation continues in the background\n // Attach a catch handler to prevent unhandled rejection if it fails later\n if (behavior === \"disconnect\") {\n operationPromise.catch(() => {\n // Intentionally swallowed - operation was disconnected\n });\n }\n\n const errorToThrow = (error as { error: unknown }).error;\n\n // Mark the error with STEP_TIMEOUT_MARKER if it's a custom error (not already a StepTimeoutError)\n // This allows isStepTimeoutError() and getStepTimeoutMeta() to work with custom errors\n // Note: Always update metadata to reflect the current attempt (same error may be reused across retries)\n if (\n typeof errorToThrow === \"object\" &&\n errorToThrow !== null &&\n (errorToThrow as StepTimeoutError).type !== \"STEP_TIMEOUT\"\n ) {\n const meta: StepTimeoutMarkerMeta = {\n timeoutMs: options.ms,\n stepName: stepInfo.name,\n stepKey: stepInfo.key,\n attempt: stepInfo.attempt,\n };\n\n if (STEP_TIMEOUT_MARKER in errorToThrow) {\n // Update existing marker with current attempt's metadata\n (errorToThrow as Record<symbol, StepTimeoutMarkerMeta>)[STEP_TIMEOUT_MARKER] = meta;\n } else {\n // Define new marker (writable so it can be updated on retry)\n Object.defineProperty(errorToThrow, STEP_TIMEOUT_MARKER, {\n value: meta,\n enumerable: false,\n writable: true,\n configurable: false,\n });\n }\n }\n\n throw errorToThrow;\n }\n // Re-throw other errors\n throw error;\n } finally {\n // Always clear the timeout to prevent leaks\n clearTimeout(timeoutId!);\n // Clean up external signal listener\n if (externalAbortHandler && externalSignal) {\n externalSignal.removeEventListener(\"abort\", externalAbortHandler);\n }\n }\n}\n\n/**\n * Default retry configuration values.\n * @internal\n */\nconst DEFAULT_RETRY_CONFIG = {\n backoff: \"exponential\" as BackoffStrategy,\n initialDelay: 100,\n maxDelay: 30000,\n jitter: true,\n retryOn: () => true,\n onRetry: () => {},\n} as const;\n\n// =============================================================================\n// run() Function\n// =============================================================================\n\n/**\n * Execute a workflow with step-based error handling.\n *\n * ## When to Use run()\n *\n * Use `run()` when:\n * - Dependencies are dynamic (passed at runtime, not known at compile time)\n * - You don't need step caching or resume state\n * - Error types are known upfront and can be specified manually\n * - Building lightweight, one-off workflows\n *\n * For automatic error type inference from static dependencies, use `createWorkflow()`.\n *\n * ## Error union\n *\n * `run()` returns:\n * - **`catchUnexpected`**: Maps uncaught exceptions to your type E → `Result<T, E>`\n * - **No catchUnexpected**: Step errors pass through + `UnexpectedError` for exceptions → `Result<T, E | UnexpectedError>`\n *\n * When `E` is not specified, it defaults to `never`, giving `Result<T, UnexpectedError>`.\n *\n * @see createWorkflow - For static dependencies with auto error inference\n */\n\n/**\n * run() with catchUnexpected: closed union Result<T, E>.\n */\nexport function run<T, E, C = void>(\n fn: (context: { step: RunStep<E> }) => Promise<T> | T,\n options: RunOptionsWithCatch<E, C>\n): AsyncResult<T, E, unknown>;\n\n/**\n * run() without catchUnexpected.\n * Always adds UnexpectedError to the error union so callers know\n * uncaught exceptions are possible. Step errors pass through as-is.\n * When E is never (default), step is RunStep<unknown> so any operation is allowed.\n */\nexport function run<T, E = never, C = void>(\n fn: (context: {\n step: [E] extends [never] ? RunStep<unknown> : RunStep<E>;\n }) => Promise<T> | T,\n options?: {\n onError?: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;\n onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;\n workflowId?: string;\n workflowName?: string;\n context?: C;\n /** @internal External signal for workflow-level cancellation. */\n _workflowSignal?: AbortSignal;\n }\n): AsyncResult<T, E | UnexpectedError, unknown>;\n\n// Implementation\nexport async function run<T, E, C = void>(\n fn: (context: { step: RunStep<E> }) => Promise<T> | T,\n options?: RunOptions<E, C>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): AsyncResult<T, any> {\n const {\n onError,\n onEvent,\n catchUnexpected,\n workflowId: providedWorkflowId,\n workflowName,\n context,\n _workflowSignal,\n } = options && typeof options === \"object\"\n ? (options as RunOptions<E, C>)\n : ({} as RunOptions<E, C>);\n\n const workflowId = providedWorkflowId ?? crypto.randomUUID();\n const effectiveCatchUnexpected = catchUnexpected ?? defaultCatchUnexpected;\n\n // Track active scopes as a stack for proper nesting\n // When a step succeeds, only the innermost race scope gets the winner\n const activeScopeStack: Array<{ scopeId: string; type: ScopeType; winnerId?: string }> = [];\n\n // Counter for generating unique step IDs\n let stepIdCounter = 0;\n\n // Generate a unique step ID\n // Uses stepKey when provided (for cache stability), otherwise generates a unique ID.\n // Note: name is NOT used for stepId because multiple concurrent steps may share a name,\n // which would cause them to collide in activeSteps tracking and race winner detection.\n const generateStepId = (stepKey?: string): string => {\n return stepKey ?? `step_${++stepIdCounter}`;\n };\n\n const emitEvent = (event: WorkflowEvent<E | UnexpectedError, C>) => {\n // Add context to event only if:\n // 1. Event doesn't already have context (preserves replayed events or per-step overrides)\n // 2. Workflow actually has a context (don't add context: undefined property)\n const eventWithContext =\n event.context !== undefined || context === undefined\n ? event\n : ({ ...event, context: context as C } as WorkflowEvent<E | UnexpectedError, C>);\n\n const eventWithName =\n workflowName !== undefined && eventWithContext.workflowName === undefined\n ? ({ ...eventWithContext, workflowName } as WorkflowEvent<E | UnexpectedError, C>)\n : eventWithContext;\n \n // Track first successful step in the innermost race scope for winnerId\n if (eventWithName.type === \"step_success\") {\n // Use the stepId from the event (already generated at step start)\n const stepId = eventWithName.stepId;\n\n // Find innermost race scope (search from end of stack)\n for (let i = activeScopeStack.length - 1; i >= 0; i--) {\n const scope = activeScopeStack[i];\n if (scope.type === \"race\" && !scope.winnerId) {\n scope.winnerId = stepId;\n break; // Only update innermost race scope\n }\n }\n }\n onEvent?.(eventWithName, context as C);\n };\n\n // Use the exported early exit function with proper type parameter\n const earlyExit = createEarlyExit<E>;\n\n // Local type guard that narrows to EarlyExit<E> specifically\n const isEarlyExitE = (e: unknown): e is EarlyExit<E> => isEarlyExit(e);\n\n // Step errors always pass through — they are typed Result errors.\n // Only truly uncaught exceptions get mapped via effectiveCatchUnexpected.\n const wrapForStep = (\n error: unknown,\n _meta?: StepFailureMeta\n ): E => {\n return error as E;\n };\n\n // Helper to check if a value is a Result (has ok property) vs a function\n const isResultLike = (value: unknown): value is Result<unknown, unknown, unknown> | Promise<Result<unknown, unknown, unknown>> => {\n if (typeof value === 'function') return false;\n if (value && typeof value === 'object' && 'ok' in value) return true;\n // Check for Promise<Result> - it will have a then method\n if (value && typeof value === 'object' && 'then' in value && typeof (value as Promise<unknown>).then === 'function') return true;\n return false;\n };\n\n try {\n // Step function: requires step('id', fn, opts) or step('id', result, opts)\n const stepFn = <T, StepE, StepC = unknown>(\n id: string,\n operationOrResult: (() => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>) | Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n stepOptions?: StepOptions\n ): Promise<T> => {\n return (async () => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step() requires an explicit string ID as the first argument. ' +\n 'Example: step(\"fetchUser\", () => fetchUser(id))'\n );\n }\n\n const parsedOptions: StepOptions = stepOptions ?? {};\n const stepMetadata = extractStepMetadata(parsedOptions);\n\n // Name is always derived from ID\n const stepName = id;\n const stepKey = parsedOptions.key ?? id; // For general events (step_start, step_success, etc.)\n const explicitKey = parsedOptions.key ?? id; // For step_complete and caching (ID is used when no key)\n const { description: stepDescription, retry: retryConfig, timeout: timeoutConfig } = parsedOptions;\n const stepId = generateStepId(stepKey);\n const hasEventListeners = onEvent;\n const overallStartTime = hasEventListeners ? performance.now() : 0;\n\n // Determine if this is a direct Result or a function\n const isDirectResult = isResultLike(operationOrResult);\n const operation = isDirectResult\n ? () => operationOrResult as Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>\n : operationOrResult as () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>;\n\n // Build effective retry config with defaults\n // Ensure at least 1 attempt (0 would skip the loop entirely and crash)\n const maxAttempts = Math.max(1, retryConfig?.attempts ?? 1);\n const effectiveRetry = {\n attempts: maxAttempts,\n backoff: retryConfig?.backoff ?? DEFAULT_RETRY_CONFIG.backoff,\n initialDelay: retryConfig?.initialDelay ?? DEFAULT_RETRY_CONFIG.initialDelay,\n maxDelay: retryConfig?.maxDelay ?? DEFAULT_RETRY_CONFIG.maxDelay,\n jitter: retryConfig?.jitter ?? DEFAULT_RETRY_CONFIG.jitter,\n retryOn: retryConfig?.retryOn ?? DEFAULT_RETRY_CONFIG.retryOn,\n onRetry: retryConfig?.onRetry ?? DEFAULT_RETRY_CONFIG.onRetry,\n };\n\n // Emit step_start only once (before first attempt)\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n }\n\n let lastResult: Result<T, StepE, StepC> | undefined;\n\n for (let attempt = 1; attempt <= effectiveRetry.attempts; attempt++) {\n const attemptStartTime = hasEventListeners ? performance.now() : 0;\n\n try {\n // Execute operation with optional timeout\n let result: Result<T, StepE, StepC>;\n\n if (timeoutConfig) {\n // Wrap with timeout, passing workflow signal for { signal: true } steps\n result = await executeWithTimeout(\n operation as () => Promise<Result<T, StepE, StepC>>,\n timeoutConfig,\n { name: stepName, key: stepKey, attempt },\n _workflowSignal\n );\n } else {\n result = await operation();\n }\n\n // Success case\n if (result.ok) {\n const durationMs = performance.now() - overallStartTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs,\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs,\n result,\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n }\n return result.value;\n }\n\n // Result error case - check if we should retry\n lastResult = result;\n\n if (attempt < effectiveRetry.attempts && effectiveRetry.retryOn(result.error, attempt)) {\n const delay = calculateRetryDelay(attempt, effectiveRetry);\n\n // Emit retry event\n emitEvent({\n type: \"step_retry\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n attempt: attempt + 1,\n maxAttempts: effectiveRetry.attempts,\n delayMs: delay,\n error: result.error as unknown as E,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(result.error, parsedOptions.errorMeta, 'result', attempt, performance.now() - overallStartTime),\n });\n\n effectiveRetry.onRetry(result.error, attempt, delay);\n await sleep(delay);\n continue;\n }\n\n // No more retries or retryOn returned false - emit exhausted event if we retried\n if (effectiveRetry.attempts > 1) {\n emitEvent({\n type: \"step_retries_exhausted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n attempts: attempt,\n lastError: result.error as unknown as E,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(result.error, parsedOptions.errorMeta, 'result', attempt, performance.now() - overallStartTime),\n });\n }\n\n // Fall through to final error handling below\n break;\n\n } catch (thrown) {\n const durationMs = performance.now() - attemptStartTime;\n\n // Handle timeout with 'option' behavior - return undefined as success\n if (isTimeoutOptionMarker(thrown)) {\n const timeoutMs = thrown.ms;\n emitEvent({\n type: \"step_timeout\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n timeoutMs,\n attempt,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(thrown, parsedOptions.errorMeta, 'timeout', attempt),\n });\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n result: ok(undefined),\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n }\n // Return undefined as success value (timeout was treated as optional)\n return undefined as T;\n }\n\n // Handle early exit - propagate immediately\n if (isEarlyExitE(thrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs,\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n throw thrown;\n }\n\n // Handle timeout error\n if (isStepTimeoutError(thrown)) {\n // Get timeout metadata from the error (works for both standard and custom errors)\n const timeoutMeta = getStepTimeoutMeta(thrown);\n const timeoutMs = timeoutConfig?.ms ?? timeoutMeta?.timeoutMs ?? 0;\n emitEvent({\n type: \"step_timeout\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n timeoutMs,\n attempt,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(thrown, parsedOptions.errorMeta, 'timeout', attempt),\n });\n\n // Check if we should retry after timeout\n if (attempt < effectiveRetry.attempts && effectiveRetry.retryOn(thrown, attempt)) {\n const delay = calculateRetryDelay(attempt, effectiveRetry);\n\n emitEvent({\n type: \"step_retry\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n attempt: attempt + 1,\n maxAttempts: effectiveRetry.attempts,\n delayMs: delay,\n error: thrown as unknown as E,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(thrown, parsedOptions.errorMeta, 'timeout', attempt, performance.now() - overallStartTime),\n });\n\n effectiveRetry.onRetry(thrown, attempt, delay);\n await sleep(delay);\n continue;\n }\n\n // No more retries - emit exhausted if we retried\n if (effectiveRetry.attempts > 1) {\n emitEvent({\n type: \"step_retries_exhausted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n attempts: attempt,\n lastError: thrown as unknown as E,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(thrown, parsedOptions.errorMeta, 'timeout', attempt, performance.now() - overallStartTime),\n });\n }\n\n // Treat STEP_TIMEOUT as a typed error - exit directly without UnexpectedError wrapper\n // This provides better DX: users get STEP_TIMEOUT directly in result.error\n const totalDurationMs = performance.now() - overallStartTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n error: thrown as unknown as E,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(thrown, parsedOptions.errorMeta, 'timeout', attempt, totalDurationMs),\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n result: err(thrown as unknown as E, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n }\n onError?.(thrown as unknown as E, stepName, context);\n throw earlyExit(thrown as unknown as E, { origin: \"throw\", thrown });\n }\n\n // Handle other thrown errors (continue to error handling below)\n\n // Check if we should retry thrown errors\n if (attempt < effectiveRetry.attempts && effectiveRetry.retryOn(thrown, attempt)) {\n const delay = calculateRetryDelay(attempt, effectiveRetry);\n\n emitEvent({\n type: \"step_retry\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n attempt: attempt + 1,\n maxAttempts: effectiveRetry.attempts,\n delayMs: delay,\n error: thrown as unknown as E,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(thrown, parsedOptions.errorMeta, 'throw', attempt, performance.now() - overallStartTime),\n });\n\n effectiveRetry.onRetry(thrown, attempt, delay);\n await sleep(delay);\n continue;\n }\n\n // No more retries for thrown errors - emit exhausted if we retried\n if (effectiveRetry.attempts > 1 && !isStepTimeoutError(thrown)) {\n emitEvent({\n type: \"step_retries_exhausted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - overallStartTime,\n attempts: attempt,\n lastError: thrown as unknown as E,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(thrown, parsedOptions.errorMeta, 'throw', attempt, performance.now() - overallStartTime),\n });\n }\n\n // Handle the error using effectiveCatchUnexpected\n const totalDurationMs = performance.now() - overallStartTime;\n\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(thrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n error: mappedError,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(thrown, parsedOptions.errorMeta, 'throw', attempt, totalDurationMs),\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n result: err(mappedError, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown });\n }\n }\n\n // All retries exhausted with Result error - handle final error\n // At this point lastResult must be an error result (we only reach here on error)\n const errorResult = lastResult as Err<StepE, StepC>;\n const totalDurationMs = performance.now() - overallStartTime;\n const wrappedError = wrapForStep(errorResult.error, {\n origin: \"result\",\n resultCause: errorResult.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n error: wrappedError,\n ...(stepMetadata && { metadata: stepMetadata }),\n diagnostics: buildStepErrorPayload(errorResult.error, parsedOptions.errorMeta, 'result', effectiveRetry.attempts, totalDurationMs),\n });\n if (explicitKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey: explicitKey,\n name: stepName,\n description: stepDescription,\n ts: Date.now(),\n durationMs: totalDurationMs,\n result: errorResult,\n meta: { origin: \"result\", resultCause: errorResult.cause },\n ...(stepMetadata && { metadata: stepMetadata }),\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: errorResult.cause,\n });\n })();\n };\n\n stepFn.try = <T, Err>(\n id: string,\n operation: () => T | Promise<T>,\n opts:\n | { error: Err; key?: string }\n | { onError: (cause: unknown) => Err; key?: string }\n ): Promise<T> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.try() requires an explicit string ID as the first argument. ' +\n 'Example: step.try(\"parse\", () => JSON.parse(str), { error: \"PARSE_ERROR\" })'\n );\n }\n\n const stepKey = opts.key ?? id; // Use id as key if not provided\n const stepName = id; // Name is always the id\n const stepId = id;\n const mapToError = \"error\" in opts ? () => opts.error : opts.onError;\n const hasEventListeners = onEvent;\n\n return (async () => {\n const startTime = hasEventListeners ? performance.now() : 0;\n\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n });\n }\n\n try {\n const value = await operation();\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n // Emit step_complete for keyed steps (for state persistence)\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: ok(value),\n });\n }\n return value;\n } catch (error) {\n const mapped = mapToError(error);\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(mapped, { origin: \"throw\", thrown: error });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n // Emit step_complete for keyed steps (for state persistence)\n // Note: For step.try errors, we encode the mapped error, not the original thrown\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mapped, { cause: error }),\n meta: { origin: \"throw\", thrown: error },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, { origin: \"throw\", thrown: error });\n }\n })();\n };\n\n // step.fromResult: Execute a Result-returning function and map its typed error\n stepFn.fromResult = <T, ResultE, Err>(\n id: string,\n operation: () => Result<T, ResultE, unknown> | AsyncResult<T, ResultE, unknown>,\n opts:\n | { error: Err; key?: string }\n | { onError: (resultError: ResultE) => Err; key?: string }\n ): Promise<T> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.fromResult() requires an explicit string ID as the first argument. ' +\n 'Example: step.fromResult(\"callProvider\", () => callProvider(input), { onError: (e) => ({ type: \"FAILED\" }) })'\n );\n }\n\n const stepKey = opts.key ?? id; // Use id as key if not provided\n const stepName = id; // Name is always the id\n const stepId = id;\n const mapToError = \"error\" in opts ? () => opts.error : opts.onError;\n const hasEventListeners = onEvent;\n\n return (async () => {\n const startTime = hasEventListeners ? performance.now() : 0;\n\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n });\n }\n\n const result = await operation();\n\n if (result.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n // Emit step_complete for keyed steps (for state persistence)\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: ok(result.value),\n });\n }\n return result.value;\n } else {\n const mapped = mapToError(result.error);\n const durationMs = performance.now() - startTime;\n // For fromResult, the cause is the original result.error (what got mapped)\n // This is analogous to step.try using thrown exception as cause\n const wrappedError = wrapForStep(mapped, {\n origin: \"result\",\n resultCause: result.error,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n // Emit step_complete for keyed steps (for state persistence)\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mapped, { cause: result.error }),\n meta: { origin: \"result\", resultCause: result.error },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: result.error,\n });\n }\n })();\n };\n\n // step.fromNullable: Execute an operation returning T | null/undefined and convert to typed error\n stepFn.fromNullable = <T, Err>(\n id: string,\n operation: () => T | null | undefined | Promise<T | null | undefined>,\n onNull: () => Err,\n options?: { key?: string; ttl?: number }\n ): Promise<T> => {\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.fromNullable() requires an explicit string ID as the first argument. ' +\n 'Example: step.fromNullable(\"getUser\", () => db.find(id), () => ({ type: \"NOT_FOUND\" }))'\n );\n }\n return stepFn(\n id,\n async () => {\n const value = await operation();\n return value != null ? ok(value) : err(onNull());\n },\n options\n );\n };\n\n // step.retry: Execute an operation with retry and optional timeout\n stepFn.retry = <T, StepE, StepC = unknown>(\n id: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n options: RetryOptions & { key?: string; timeout?: TimeoutOptions }\n ): Promise<T> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.retry() requires an explicit string ID as the first argument. ' +\n 'Example: step.retry(\"fetchData\", () => fetchData(), { attempts: 3 })'\n );\n }\n\n // Delegate to stepFn with retry options merged into StepOptions\n // Use key for caching if provided, otherwise use id\n return stepFn(id, operation, {\n key: options.key ?? id,\n retry: {\n attempts: options.attempts,\n backoff: options.backoff,\n initialDelay: options.initialDelay,\n maxDelay: options.maxDelay,\n jitter: options.jitter,\n retryOn: options.retryOn,\n onRetry: options.onRetry,\n },\n timeout: options.timeout,\n });\n };\n\n // step.withTimeout: Execute an operation with a timeout\n stepFn.withTimeout = <T, StepE, StepC = unknown>(\n id: string,\n operation:\n | (() => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>)\n | ((signal: AbortSignal) => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>),\n options: TimeoutOptions & { key?: string }\n ): Promise<T> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.withTimeout() requires an explicit string ID as the first argument. ' +\n 'Example: step.withTimeout(\"slowOp\", () => slowOp(), { ms: 5000 })'\n );\n }\n\n // Delegate to stepFn with timeout options\n // The signal handling happens in executeWithTimeout when timeout.signal is true\n // Use key for caching if provided, otherwise use id\n return stepFn(\n id,\n operation as () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n {\n key: options.key ?? id,\n timeout: options,\n }\n );\n };\n\n // step.sleep: Pause execution for a specified duration\n stepFn.sleep = (\n id: string,\n duration: DurationInput,\n options?: { key?: string; ttl?: number; description?: string; signal?: AbortSignal }\n ): Promise<void> => {\n // Validate required string ID\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.sleep() requires an explicit string ID as the first argument. ' +\n 'Example: step.sleep(\"delay\", \"5s\")'\n );\n }\n\n // Parse duration - inline to avoid importing duration module\n const d = typeof duration === \"string\" ? parseDurationString(duration) : duration;\n if (!d) {\n throw new Error(`step.sleep: invalid duration '${duration}'`);\n }\n const ms = d.millis;\n const userSignal = options?.signal;\n\n // Delegate to stepFn with a cancellation-aware sleep operation\n // Use key for caching if provided, otherwise use id\n return stepFn(\n id,\n async (): AsyncResult<void, never> => {\n // Check if already aborted (workflow or user signal)\n if (_workflowSignal?.aborted || userSignal?.aborted) {\n const e = new Error(\"Sleep aborted\");\n e.name = \"AbortError\";\n throw e;\n }\n\n return new Promise<Result<void, never>>((resolve, reject) => {\n // Using object to avoid prefer-const warning while allowing\n // onAbort to reference the timeout before it's assigned\n const state = { timeoutId: undefined as ReturnType<typeof setTimeout> | undefined };\n\n const onAbort = () => {\n if (state.timeoutId) clearTimeout(state.timeoutId);\n const e = new Error(\"Sleep aborted\");\n e.name = \"AbortError\";\n reject(e);\n };\n\n _workflowSignal?.addEventListener(\"abort\", onAbort, { once: true });\n userSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n state.timeoutId = setTimeout(() => {\n _workflowSignal?.removeEventListener(\"abort\", onAbort);\n userSignal?.removeEventListener(\"abort\", onAbort);\n resolve(ok(undefined));\n }, ms);\n });\n },\n {\n key: options?.key ?? id,\n description: options?.description,\n }\n );\n };\n\n // step.parallel: Execute parallel operations with scope events\n // 1. Object form: step.parallel(name, { key: fn | { fn, errors } })\n // 2. Array form: step.parallel(name, () => allAsync([...]))\n stepFn.parallel = ((...args: unknown[]): Promise<unknown> => {\n if (typeof args[0] !== \"string\") {\n throw new TypeError(\n \"step.parallel(name, ...): first argument must be a string (step name). Example: step.parallel('Fetch data', { user: () => fetchUser(), posts: () => fetchPosts() })\"\n );\n }\n const name = args[0] as string;\n const second = args[1];\n if (typeof second === \"function\") {\n return executeParallelArray(name, second as () => MaybeAsyncResult<unknown[], unknown, unknown>);\n }\n if (second && typeof second === \"object\" && !Array.isArray(second)) {\n const rawOperations = second as Record<string, (() => MaybeAsyncResult<unknown, unknown, unknown>) | ParallelOperationDescriptor<unknown, readonly string[]>>;\n const normalizedOperations = normalizeParallelOperations(rawOperations);\n return executeParallelNamed(normalizedOperations, { name });\n }\n throw new TypeError(\n \"step.parallel(name, ...): second argument must be a function (array form) or an object of operations (object form).\"\n );\n }) as RunStep<E>[\"parallel\"];\n\n function normalizeParallelOperations(\n rawOperations: Record<string, (() => MaybeAsyncResult<unknown, unknown, unknown>) | ParallelOperationDescriptor<unknown, readonly string[]>>\n ): Record<string, () => MaybeAsyncResult<unknown, unknown, unknown>> {\n const out: Record<string, () => MaybeAsyncResult<unknown, unknown, unknown>> = {};\n for (const [key, value] of Object.entries(rawOperations)) {\n if (typeof value === \"function\") {\n out[key] = value;\n } else if (value && typeof value === \"object\" && \"fn\" in value) {\n out[key] = value.fn;\n } else {\n throw new TypeError(`step.parallel: operation \"${key}\" must be a function or { fn, errors? } object`);\n }\n }\n return out;\n }\n\n // Array form implementation\n function executeParallelArray<T>(\n name: string,\n operation: () => MaybeAsyncResult<T[], unknown, unknown>\n ): Promise<T[]> {\n const scopeId = `scope_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n\n return (async () => {\n const startTime = performance.now();\n let scopeEnded = false;\n\n // Push this scope onto the stack for proper nesting tracking\n activeScopeStack.push({ scopeId, type: \"parallel\" });\n\n // Helper to emit scope_end exactly once\n const emitScopeEnd = () => {\n if (scopeEnded) return;\n scopeEnded = true;\n // Pop this scope from the stack\n const idx = activeScopeStack.findIndex(s => s.scopeId === scopeId);\n if (idx !== -1) activeScopeStack.splice(idx, 1);\n emitEvent({\n type: \"scope_end\",\n workflowId,\n scopeId,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n };\n\n // Emit scope_start event\n emitEvent({\n type: \"scope_start\",\n workflowId,\n scopeId,\n scopeType: \"parallel\",\n name,\n ts: Date.now(),\n });\n\n try {\n const result = await operation();\n\n // Emit scope_end before processing result\n emitScopeEnd();\n\n if (!result.ok) {\n onError?.(result.error as unknown as E, name, context);\n throw earlyExit(result.error as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n }\n\n return result.value;\n } catch (error) {\n // Always emit scope_end in finally-like fashion\n emitScopeEnd();\n throw error;\n }\n })();\n }\n\n // Named object form implementation - execute each operation in parallel\n function executeParallelNamed<T extends Record<string, unknown>>(\n operations: Record<string, () => MaybeAsyncResult<unknown, unknown, unknown>>,\n options: { name?: string }\n ): Promise<T> {\n const keys = Object.keys(operations);\n const name = options.name ?? `Parallel(${keys.join(\", \")})`;\n const scopeId = `scope_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n\n return (async () => {\n const startTime = performance.now();\n let scopeEnded = false;\n\n // Push this scope onto the stack for proper nesting tracking\n activeScopeStack.push({ scopeId, type: \"parallel\" });\n\n // Helper to emit scope_end exactly once\n const emitScopeEnd = () => {\n if (scopeEnded) return;\n scopeEnded = true;\n const idx = activeScopeStack.findIndex(s => s.scopeId === scopeId);\n if (idx !== -1) activeScopeStack.splice(idx, 1);\n emitEvent({\n type: \"scope_end\",\n workflowId,\n scopeId,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n };\n\n // Emit scope_start event with operation names in metadata\n emitEvent({\n type: \"scope_start\",\n workflowId,\n scopeId,\n scopeType: \"parallel\",\n name,\n ts: Date.now(),\n });\n\n try {\n // Execute all operations in parallel, fail-fast on first error\n const results = await new Promise<{ key: string; result: Result<unknown, unknown, unknown> }[]>((resolve) => {\n if (keys.length === 0) {\n resolve([]);\n return;\n }\n\n let settled = false;\n let pendingCount = keys.length;\n const resultArray: { key: string; result: Result<unknown, unknown, unknown> }[] = new Array(keys.length);\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const index = i;\n\n Promise.resolve(operations[key]())\n .catch((reason) => err(\n { type: \"PROMISE_REJECTED\" as const, cause: reason },\n { cause: { type: \"PROMISE_REJECTION\" as const, reason } }\n ))\n .then((result) => {\n if (settled) return;\n\n // Fail-fast: if any operation fails, resolve immediately with just the failed entry\n if (!result.ok) {\n settled = true;\n resolve([{ key, result }]);\n return;\n }\n\n resultArray[index] = { key, result };\n pendingCount--;\n\n if (pendingCount === 0) {\n resolve(resultArray);\n }\n });\n }\n });\n\n // Emit scope_end before processing results\n emitScopeEnd();\n\n // Check for errors and build result object\n const output: Record<string, unknown> = {};\n for (const { key, result } of results) {\n if (!result.ok) {\n onError?.(result.error as unknown as E, key, context);\n throw earlyExit(result.error as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n }\n output[key] = result.value;\n }\n\n return output as T;\n } catch (error) {\n // Always emit scope_end in finally-like fashion\n emitScopeEnd();\n throw error;\n }\n })();\n }\n\n // step.race: Execute a race operation with scope events\n stepFn.race = <T, StepE, StepC>(\n name: string,\n operation: () => Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>\n ): Promise<T> => {\n const scopeId = `scope_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n\n return (async () => {\n const startTime = performance.now();\n let scopeEnded = false;\n\n // Push this race scope onto the stack to track the first successful step as winner\n const scopeEntry = { scopeId, type: \"race\" as const, winnerId: undefined as string | undefined };\n activeScopeStack.push(scopeEntry);\n\n // Helper to emit scope_end exactly once, including winnerId\n const emitScopeEnd = () => {\n if (scopeEnded) return;\n scopeEnded = true;\n // Pop this scope from the stack\n const idx = activeScopeStack.findIndex(s => s.scopeId === scopeId);\n if (idx !== -1) activeScopeStack.splice(idx, 1);\n emitEvent({\n type: \"scope_end\",\n workflowId,\n scopeId,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n winnerId: scopeEntry.winnerId,\n });\n };\n\n // Emit scope_start event\n emitEvent({\n type: \"scope_start\",\n workflowId,\n scopeId,\n scopeType: \"race\",\n name,\n ts: Date.now(),\n });\n\n try {\n const result = await operation();\n\n // Emit scope_end before processing result\n emitScopeEnd();\n\n if (!result.ok) {\n onError?.(result.error as unknown as E, name, context);\n throw earlyExit(result.error as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n }\n\n return result.value;\n } catch (error) {\n // Always emit scope_end in finally-like fashion\n emitScopeEnd();\n throw error;\n }\n })();\n };\n\n // step.allSettled: Execute an allSettled operation with scope events\n stepFn.allSettled = <T, StepE, StepC>(\n name: string,\n operation: () => Result<T[], StepE, StepC> | AsyncResult<T[], StepE, StepC>\n ): Promise<T[]> => {\n const scopeId = `scope_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n\n return (async () => {\n const startTime = performance.now();\n let scopeEnded = false;\n\n // Push this scope onto the stack for proper nesting tracking\n activeScopeStack.push({ scopeId, type: \"allSettled\" });\n\n // Helper to emit scope_end exactly once\n const emitScopeEnd = () => {\n if (scopeEnded) return;\n scopeEnded = true;\n // Pop this scope from the stack\n const idx = activeScopeStack.findIndex(s => s.scopeId === scopeId);\n if (idx !== -1) activeScopeStack.splice(idx, 1);\n emitEvent({\n type: \"scope_end\",\n workflowId,\n scopeId,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n };\n\n // Emit scope_start event\n emitEvent({\n type: \"scope_start\",\n workflowId,\n scopeId,\n scopeType: \"allSettled\",\n name,\n ts: Date.now(),\n });\n\n try {\n const result = await operation();\n\n // Emit scope_end before processing result\n emitScopeEnd();\n\n if (!result.ok) {\n onError?.(result.error as unknown as E, name, context);\n throw earlyExit(result.error as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n }\n\n return result.value;\n } catch (error) {\n // Always emit scope_end in finally-like fashion\n emitScopeEnd();\n throw error;\n }\n })();\n };\n\n // step.if: Mark a conditional for static analysis\n // Runtime: just executes the condition and returns the result\n // Analyzer: extracts the id and conditionLabel for DecisionNode\n stepFn.if = <T extends boolean>(\n _id: string,\n _conditionLabel: string,\n condition: () => T\n ): T => {\n return condition();\n };\n\n // step.label: Alias for step.if - mark a conditional for static analysis\n // Use step.label for strict mode when conditionals contain step calls\n stepFn.label = stepFn.if;\n\n // step.branch: Execute a branch with explicit metadata for static analysis\n // Runtime: evaluates condition and executes appropriate arm\n // Analyzer: extracts branch metadata (conditionLabel, per-arm errors, out)\n stepFn.branch = async <\n T,\n const ThenErrs extends readonly string[] = readonly [],\n const ElseErrs extends readonly string[] = readonly [],\n const Out extends string | undefined = undefined,\n >(\n _id: string,\n options: BranchOptions<T, ThenErrs, ElseErrs, Out>\n ): Promise<T> => {\n const { condition, then: thenFn, else: elseFn } = options;\n const conditionResult = condition();\n if (conditionResult) {\n return await thenFn();\n } else if (elseFn) {\n return await elseFn();\n }\n return undefined as T;\n };\n\n // step.arm: Create an arm definition for use with step.branch\n // Runtime: returns the arm definition unchanged\n // Analyzer: extracts arm metadata\n stepFn.arm = <T, const Errs extends readonly string[] = readonly []>(\n fn: () => T | Promise<T>,\n errors?: Errs\n ): ArmDefinition<T, Errs> => {\n return { fn, errors };\n };\n\n // step.forEach: Execute a forEach loop with static analysis support\n // Supports both simple (run) and complex (item) forms\n stepFn.forEach = async <T, R>(\n _id: string,\n items: Iterable<T> | AsyncIterable<T>,\n options: ForEachRunOptions<T, R, readonly string[]> | ForEachItemOptions<T, R>\n ): Promise<R[]> => {\n const results: R[] = [];\n const maxIterations = options.maxIterations;\n let index = 0;\n\n // Check if this is the run form or item form\n const isRunForm = 'run' in options;\n\n // Convert items to async iterable for uniform handling\n const asyncItems = Symbol.asyncIterator in (items as object)\n ? (items as AsyncIterable<T>)\n : (async function* () { yield* items as Iterable<T>; })();\n\n for await (const item of asyncItems) {\n if (maxIterations !== undefined && index >= maxIterations) {\n break;\n }\n\n let result: R;\n if (isRunForm) {\n const runOptions = options as ForEachRunOptions<T, R, readonly string[]>;\n result = await runOptions.run(item, index);\n } else {\n const itemOptions = options as ForEachItemOptions<T, R>;\n result = await itemOptions.item.handler(item, index, stepFn as unknown as RunStep<unknown>);\n }\n\n results.push(result);\n index++;\n }\n\n return results;\n };\n\n // step.item: Create an item handler for use with step.forEach\n // Runtime: returns the handler wrapped in a marker object\n // Analyzer: extracts the inner step structure\n stepFn.item = <T, R>(\n handler: (item: T, index: number, step: RunStep<unknown>) => R | Promise<R>\n ): ForEachItemHandler<T, R> => {\n return {\n __forEachItemHandler: true as const,\n handler,\n };\n };\n\n // step.dep: Wrap a dependency function for static analysis tracking\n // Runtime: returns the function unchanged\n // Analyzer: records the dependency name\n stepFn.dep = <T extends (...args: unknown[]) => unknown>(\n _name: string,\n fn: T\n ): T => {\n return fn;\n };\n\n // ===========================================================================\n // Effect-Style Ergonomics\n // ===========================================================================\n\n // step.run: Unwrap an AsyncResult directly\n stepFn.run = <T, StepE, StepC = unknown>(\n id: string,\n result: AsyncResult<T, StepE, StepC>,\n options?: StepOptions\n ): Promise<T> => {\n return stepFn(id, () => result, options);\n };\n\n // step.workflow: Run sub-workflow (or any AsyncResult getter) as a step; same engine as step(id, getter, opts)\n stepFn.workflow = <T, SubE, StepC = unknown>(\n id: string,\n getter: () => AsyncResult<T, SubE, StepC>,\n options?: StepOptions\n ): Promise<T> => {\n return stepFn(id, getter as () => AsyncResult<T, E, StepC>, options);\n };\n\n // step.andThen: Chain AsyncResult operations\n stepFn.andThen = <T, U, StepE, StepC = unknown>(\n id: string,\n value: T,\n fn: (value: T) => AsyncResult<U, StepE, StepC>,\n options?: StepOptions\n ): Promise<U> => {\n return stepFn(id, () => fn(value), options);\n };\n\n // step.match: Pattern match on Result with step tracking (runs through step engine for lifecycle events)\n stepFn.match = async <T, StepE, U, StepC = unknown>(\n id: string,\n result: Result<T, StepE, StepC> | AsyncResult<T, StepE, StepC>,\n handlers: {\n ok: (value: T) => U | Promise<U>;\n err: (error: StepE, cause?: StepC) => U | Promise<U>;\n },\n options?: StepOptions\n ): Promise<U> => {\n return stepFn(id, async () => {\n const resolved = await result;\n if (resolved.ok) {\n return ok(await handlers.ok(resolved.value));\n } else {\n return ok(await handlers.err(resolved.error, resolved.cause));\n }\n }, options);\n };\n\n // step.all: Alias for step.parallel (Effect.all-style API)\n stepFn.all = stepFn.parallel;\n\n // step.map: Map over array with parallel execution\n stepFn.map = async <T, U, StepE, StepC = unknown>(\n id: string,\n items: T[],\n mapper: (item: T, index: number) => AsyncResult<U, StepE, StepC>,\n options?: { concurrency?: number; key?: string }\n ): Promise<U[]> => {\n const concurrency = options?.concurrency ?? items.length;\n\n // Use allAsync for parallel execution with fail-fast\n return stepFn(\n id,\n () => {\n if (concurrency >= items.length) {\n // Full parallelism - execute all at once\n return allAsync(items.map((item, index) => mapper(item, index)));\n } else {\n // Limited concurrency - batch execution\n return (async () => {\n const results: U[] = [];\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n const batchResult = await allAsync(\n batch.map((item, batchIndex) => mapper(item, i + batchIndex))\n );\n // allAsync returns Result<U[], E, C>, so we need to check if it's ok\n if (!batchResult.ok) {\n return batchResult; // Propagate the error\n }\n results.push(...batchResult.value);\n }\n return ok(results);\n })();\n }\n },\n { key: options?.key }\n );\n };\n\n // step.withFallback: Execute primary with fallback on error\n stepFn.withFallback = <T, E1, E2>(\n id: string,\n operation: () => AsyncResult<T, E1>,\n options: { on?: E1 & string; fallback: () => AsyncResult<T, E2>; key?: string }\n ): Promise<T> => {\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.withFallback() requires an explicit string ID as the first argument. ' +\n 'Example: step.withFallback(\"getUser\", () => fetchUser(id), { fallback: () => fetchFromCache(id) })'\n );\n }\n\n const stepKey = options.key ?? id;\n const stepName = id;\n const stepId = generateStepId(stepKey);\n const hasEventListeners = onEvent;\n\n return (async () => {\n const startTime = hasEventListeners ? performance.now() : 0;\n\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n });\n }\n\n // Try the primary operation\n let primaryResult: Result<T, E1>;\n try {\n primaryResult = await operation();\n } catch (thrown) {\n // If it's an earlyExit from a nested step, propagate\n if (isEarlyExitE(thrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n throw thrown;\n }\n\n // Primary threw — map to UnexpectedError\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(thrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n\n // If `on` is specified, only run fallback if it matches the mapped error\n if (options.on !== undefined && options.on !== mappedError) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: mappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mappedError, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown });\n }\n\n // Run fallback for thrown error\n let fallbackResultFromThrow: Result<T, E2>;\n try {\n fallbackResultFromThrow = await options.fallback();\n } catch (fallbackThrown) {\n if (isEarlyExitE(fallbackThrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n throw fallbackThrown;\n }\n let fallbackMappedError: E | UnexpectedError;\n try {\n fallbackMappedError = effectiveCatchUnexpected(fallbackThrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: fallbackMappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(fallbackMappedError, { cause: fallbackThrown }),\n meta: { origin: \"throw\", thrown: fallbackThrown },\n });\n }\n onError?.(fallbackMappedError as E, stepName, context);\n throw earlyExit(fallbackMappedError as E, { origin: \"throw\", thrown: fallbackThrown });\n }\n\n if (fallbackResultFromThrow.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: fallbackResultFromThrow,\n meta: { origin: \"fallback\" as const, fallbackUsed: true as const, fallbackReason: String(mappedError) },\n });\n }\n return fallbackResultFromThrow.value;\n } else {\n // Fallback also failed\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(fallbackResultFromThrow.error, {\n origin: \"result\",\n resultCause: fallbackResultFromThrow.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: fallbackResultFromThrow,\n meta: { origin: \"result\", resultCause: fallbackResultFromThrow.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: fallbackResultFromThrow.cause,\n });\n }\n }\n\n // Primary returned a result (didn't throw)\n if (primaryResult.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: primaryResult,\n });\n }\n return primaryResult.value;\n }\n\n // Primary returned an error\n const primaryError = primaryResult.error;\n\n // If `on` is specified and doesn't match, earlyExit with primary error (no fallback)\n if (options.on !== undefined && options.on !== primaryError) {\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(primaryError, {\n origin: \"result\",\n resultCause: primaryResult.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: primaryResult,\n meta: { origin: \"result\", resultCause: primaryResult.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: primaryResult.cause,\n });\n }\n\n // Run fallback\n let fallbackResult: Result<T, E2>;\n try {\n fallbackResult = await options.fallback();\n } catch (thrown) {\n if (isEarlyExitE(thrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n throw thrown;\n }\n // Fallback threw — map via effectiveCatchUnexpected\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(thrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: mappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mappedError, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown });\n }\n\n if (fallbackResult.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: fallbackResult,\n meta: { origin: \"fallback\" as const, fallbackUsed: true as const, fallbackReason: String(primaryError) },\n });\n }\n return fallbackResult.value;\n }\n\n // Fallback also returned an error\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(fallbackResult.error, {\n origin: \"result\",\n resultCause: fallbackResult.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: fallbackResult,\n meta: { origin: \"result\", resultCause: fallbackResult.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: fallbackResult.cause,\n });\n })();\n };\n\n // step.withResource: Acquire/use/release lifecycle with guaranteed release\n stepFn.withResource = <T, R, AcquireE, UseE>(\n id: string,\n options: {\n acquire: () => AsyncResult<R, AcquireE>;\n use: (resource: R) => AsyncResult<T, UseE>;\n release: (resource: R) => void | Promise<void>;\n }\n ): Promise<T> => {\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(\n '[awaitly] step.withResource() requires an explicit string ID as the first argument. ' +\n 'Example: step.withResource(\"useDb\", { acquire: () => connect(), use: (db) => query(db), release: (db) => db.close() })'\n );\n }\n\n const stepKey = id;\n const stepName = id;\n const stepId = generateStepId(stepKey);\n const hasEventListeners = onEvent;\n\n return (async () => {\n const startTime = hasEventListeners ? performance.now() : 0;\n\n if (onEvent) {\n emitEvent({\n type: \"step_start\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n });\n }\n\n // Acquire\n let acquireResult: Result<R, AcquireE>;\n try {\n acquireResult = await options.acquire();\n } catch (thrown) {\n if (isEarlyExitE(thrown)) {\n emitEvent({\n type: \"step_aborted\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs: performance.now() - startTime,\n });\n throw thrown;\n }\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(thrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: mappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mappedError, { cause: thrown }),\n meta: { origin: \"throw\", thrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown });\n }\n\n if (!acquireResult.ok) {\n // Acquire failed — no release needed\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(acquireResult.error, {\n origin: \"result\",\n resultCause: acquireResult.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: acquireResult,\n meta: { origin: \"result\", resultCause: acquireResult.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: acquireResult.cause,\n });\n }\n\n const resource = acquireResult.value;\n let useResult: Result<T, UseE> | undefined;\n let useThrown: unknown;\n let useThrewNonResult = false;\n\n // Use\n try {\n useResult = await options.use(resource);\n } catch (thrown) {\n if (isEarlyExitE(thrown)) {\n // Release before propagating\n try {\n await options.release(resource);\n } catch (releaseErr) {\n console.warn(\n `[awaitly] step.withResource(\"${id}\"): release threw after earlyExit:`,\n releaseErr\n );\n }\n throw thrown;\n }\n useThrown = thrown;\n useThrewNonResult = true;\n }\n\n // Release — ALWAYS runs after use (unless acquire failed)\n try {\n await options.release(resource);\n } catch (releaseErr) {\n console.warn(\n `[awaitly] step.withResource(\"${id}\"): release threw:`,\n releaseErr\n );\n }\n\n // Emit events AFTER release completes\n if (useThrewNonResult) {\n let mappedError: E | UnexpectedError;\n try {\n mappedError = effectiveCatchUnexpected(useThrown) as E | UnexpectedError;\n } catch (mapperError) {\n throw createMapperException(mapperError);\n }\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: mappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result: err(mappedError, { cause: useThrown }),\n meta: { origin: \"throw\", thrown: useThrown },\n });\n }\n onError?.(mappedError as E, stepName, context);\n throw earlyExit(mappedError as E, { origin: \"throw\", thrown: useThrown });\n }\n\n // useResult is defined if useThrewNonResult is false\n const result = useResult!;\n if (result.ok) {\n const durationMs = performance.now() - startTime;\n emitEvent({\n type: \"step_success\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result,\n });\n }\n return result.value;\n }\n\n // Use returned an error\n const durationMs = performance.now() - startTime;\n const wrappedError = wrapForStep(result.error, {\n origin: \"result\",\n resultCause: result.cause,\n });\n emitEvent({\n type: \"step_error\",\n workflowId,\n stepId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n error: wrappedError,\n });\n if (stepKey) {\n emitEvent({\n type: \"step_complete\",\n workflowId,\n stepKey,\n name: stepName,\n ts: Date.now(),\n durationMs,\n result,\n meta: { origin: \"result\", resultCause: result.cause },\n });\n }\n onError?.(wrappedError as unknown as E, stepName, context);\n throw earlyExit(wrappedError as unknown as E, {\n origin: \"result\",\n resultCause: result.cause,\n });\n })();\n };\n\n const step = stepFn as RunStep<E | UnexpectedError>;\n const value = await fn({ step });\n\n // Dev-only warning: Detect common mistake of returning ok() or err() from executor\n if (\n process.env.NODE_ENV !== \"production\" &&\n value !== null &&\n typeof value === \"object\" &&\n \"ok\" in value &&\n typeof (value as { ok: unknown }).ok === \"boolean\"\n ) {\n const maybeResult = value as { ok: boolean; value?: unknown; error?: unknown };\n if (\n (maybeResult.ok === true && \"value\" in maybeResult) ||\n (maybeResult.ok === false && \"error\" in maybeResult)\n ) {\n console.warn(\n `awaitly: Workflow executor returned a Result-like object. ` +\n `Return raw values, not ok() or err().\\n\\n` +\n ` Incorrect: return ok({ data });\\n` +\n ` Correct: return { data };\\n\\n` +\n `See: https://jagreehal.github.io/awaitly/guides/troubleshooting/#returning-ok-from-workflow-executor-double-wrapping`\n );\n }\n }\n\n return ok(value);\n } catch (error) {\n // If a catchUnexpected mapper threw, propagate without re-processing\n if (isMapperException(error)) {\n throw error.thrown;\n }\n\n if (isEarlyExitE(error)) {\n // Extract original cause from early exit metadata\n const originalCause = error.meta.origin === \"throw\"\n ? error.meta.thrown\n : error.meta.origin === \"result\"\n ? error.meta.resultCause\n : undefined;\n\n return err(error.error, { cause: originalCause });\n }\n\n const mapped = effectiveCatchUnexpected(error);\n onError?.(mapped as E, \"unexpected\", context);\n return err(mapped, { cause: error });\n }\n}\n\n/**\n * Convenience for run() with catchUnexpected: closed union Result<T, E>.\n * You must provide catchUnexpected to map uncaught exceptions to E.\n */\nrun.strict = <T, E, C = void>(\n fn: (context: { step: RunStep<E> }) => Promise<T> | T,\n options: {\n onError?: (error: E, stepName?: string, ctx?: C) => void;\n /**\n * Listener for workflow events (start, success, error, step events).\n *\n * Note: Context is available both on `event.context` and as the separate `ctx` parameter.\n * The `ctx` parameter is provided for convenience and backward compatibility.\n */\n onEvent?: (event: WorkflowEvent<E | UnexpectedError, C>, ctx: C) => void;\n catchUnexpected: (cause: unknown) => E;\n workflowId?: string;\n context?: C;\n /** @internal External signal for workflow-level cancellation. */\n _workflowSignal?: AbortSignal;\n }\n): AsyncResult<T, E, unknown> => {\n return run<T, E, C>(fn, options);\n};\n\n// =============================================================================\n// Unwrap Utilities\n// =============================================================================\n\n/**\n * Error thrown when `unwrap()` is called on an error Result.\n *\n * This error is thrown to prevent silent failures when using `unwrap()`.\n * Prefer using `unwrapOr`, `unwrapOrElse`, or pattern matching with `match` or `isOk`/`isErr`.\n */\nexport class UnwrapError<E = unknown, C = unknown> extends Error {\n constructor(\n public readonly error: E,\n public readonly cause?: C\n ) {\n super(`Unwrap called on an error result: ${String(error)}`);\n this.name = \"UnwrapError\";\n }\n}\n\n/**\n * Unwraps a Result, throwing an error if it's a failure.\n *\n * @remarks When to use: Only at boundaries or tests where a failure should be fatal.\n *\n * ## When to Use\n *\n * Use `unwrap()` when:\n * - You're certain the Result is successful (e.g., after checking with `isOk`)\n * - You're in a context where errors should crash (e.g., tests, initialization)\n * - You need the value immediately and can't handle errors gracefully\n *\n * ## Why Avoid This\n *\n * **Prefer alternatives** in production code:\n * - `unwrapOr(defaultValue)` - Provide a fallback value\n * - `unwrapOrElse(fn)` - Compute fallback from error\n * - `match()` - Handle both cases explicitly\n * - `isOk()` / `isErr()` - Type-safe pattern matching\n *\n * Throwing errors makes error handling harder and can crash your application.\n *\n * @param r - The Result to unwrap\n * @returns The success value if the Result is successful\n * @throws {UnwrapError} If the Result is an error (includes the error and cause)\n *\n * @example\n * ```typescript\n * // Safe usage after checking\n * const result = someOperation();\n * if (isOk(result)) {\n * const value = unwrap(result); // Safe - we know it's ok\n * }\n *\n * // Unsafe usage (not recommended)\n * const value = unwrap(someOperation()); // May throw!\n * ```\n */\nexport const unwrap = <T, E, C>(r: Result<T, E, C>): T => {\n if (r.ok) return r.value;\n throw new UnwrapError<E, C>(r.error, r.cause);\n};\n\n/**\n * Unwraps a Result, returning a default value if it's a failure.\n *\n * @remarks When to use: Provide a safe fallback without branching.\n *\n * ## When to Use\n *\n * Use `unwrapOr()` when:\n * - You have a sensible default value for errors\n * - You want to continue execution even on failure\n * - The default value is cheap to compute (use `unwrapOrElse` if expensive)\n *\n * ## Why Use This\n *\n * - **Safe**: Never throws, always returns a value\n * - **Simple**: One-liner for common error handling\n * - **Type-safe**: TypeScript knows you'll always get a `T`\n *\n * @param r - The Result to unwrap\n * @param defaultValue - The value to return if the Result is an error\n * @returns The success value if successful, otherwise the default value\n *\n * @example\n * ```typescript\n * // Provide default for missing data\n * const user = unwrapOr(fetchUser(id), { id: 'anonymous', name: 'Guest' });\n *\n * // Provide default for numeric operations\n * const count = unwrapOr(parseCount(input), 0);\n *\n * // Provide default for optional features\n * const config = unwrapOr(loadConfig(), getDefaultConfig());\n * ```\n */\nexport const unwrapOr = <T, E, C>(r: Result<T, E, C>, defaultValue: T): T =>\n r.ok ? r.value : defaultValue;\n\n/**\n * Unwraps a Result, computing a default value from the error if it's a failure.\n *\n * @remarks When to use: Compute a fallback from the error (logging, metrics, or derived defaults).\n *\n * ## When to Use\n *\n * Use `unwrapOrElse()` when:\n * - The default value is expensive to compute (lazy evaluation)\n * - You need to log or handle the error before providing a default\n * - The default depends on the error type or cause\n * - You want to transform the error into a success value\n *\n * ## Why Use This Instead of `unwrapOr`\n *\n * - **Lazy**: Default is only computed if needed (better performance)\n * - **Error-aware**: You can inspect the error before providing default\n * - **Flexible**: Default can depend on error type or cause\n *\n * @param r - The Result to unwrap\n * @param fn - Function that receives the error and optional cause, returns the default value\n * @returns The success value if successful, otherwise the result of calling `fn(error, cause)`\n *\n * @example\n * ```typescript\n * // Compute default based on error type\n * const port = unwrapOrElse(parsePort(env.PORT), (error) => {\n * if (error === 'INVALID_FORMAT') return 3000;\n * if (error === 'OUT_OF_RANGE') return 8080;\n * return 4000; // default\n * });\n *\n * // Log error before providing default\n * const data = unwrapOrElse(fetchData(), (error, cause) => {\n * console.error('Failed to fetch:', error, cause);\n * return getCachedData();\n * });\n *\n * // Transform error into success value\n * const result = unwrapOrElse(operation(), (error) => {\n * return { success: false, reason: String(error) };\n * });\n * ```\n */\nexport const unwrapOrElse = <T, E, C>(\n r: Result<T, E, C>,\n fn: (error: E, cause?: C) => T\n): T => (r.ok ? r.value : fn(r.error, r.cause));\n\n/**\n * Alias for `unwrap`. Returns the success value or throws.\n *\n * The Result is already computed; use when you want the value or throw (e.g. at boundaries or in tests).\n *\n * @param r - The Result to unwrap\n * @returns The success value if the Result is successful\n * @throws {UnwrapError} If the Result is an error (includes the error and cause)\n */\nexport const runOrThrow = <T, E, C>(r: Result<T, E, C>): T => unwrap(r);\n\n/**\n * Awaits a Promise of a Result, then returns the success value or rejects.\n *\n * The returned promise **resolves with T** on success and **rejects with UnwrapError** on failure.\n * UnwrapError extends Error and carries the original `error` and `cause` from the Err.\n *\n * @param ar - A Promise or thenable that resolves to a Result\n * @returns A Promise that resolves with the success value or rejects with UnwrapError\n */\nexport const runOrThrowAsync = <T, E, C>(\n ar: PromiseLike<Result<T, E, C>>\n): Promise<T> => Promise.resolve(ar).then(unwrap);\n\n/**\n * Convenience alias for `unwrapOr(r, null)`. Returns the success value or null.\n *\n * @param r - The Result to unwrap\n * @returns The success value if successful, otherwise null\n */\nexport const runOrNull = <T, E, C>(r: Result<T, E, C>): T | null =>\n r.ok ? r.value : null;\n\n/**\n * Convenience alias for `unwrapOr(r, undefined)`. Returns the success value or undefined.\n *\n * @param r - The Result to unwrap\n * @returns The success value if successful, otherwise undefined\n */\nexport const runOrUndefined = <T, E, C>(r: Result<T, E, C>): T | undefined =>\n r.ok ? r.value : undefined;\n\n// =============================================================================\n// Wrapping Functions\n// =============================================================================\n\n/**\n * Wraps a synchronous throwing function in a Result.\n *\n * @remarks When to use: Wrap sync code that might throw so exceptions become Err values.\n *\n * ## When to Use\n *\n * Use `from()` when:\n * - You have a synchronous function that throws exceptions\n * - You want to convert exceptions to typed errors\n * - You're integrating with libraries that throw (e.g., JSON.parse, fs.readFileSync)\n * - You need to handle errors without try/catch blocks\n *\n * ## Why Use This\n *\n * - **Type-safe errors**: Convert thrown exceptions to typed Result errors\n * - **No try/catch**: Cleaner code without nested try/catch blocks\n * - **Composable**: Results can be chained with `andThen`, `map`, etc.\n * - **Explicit errors**: Forces you to handle errors explicitly\n *\n * @param fn - The synchronous function to execute (may throw)\n * @returns A Result with the function's return value or the thrown error\n *\n * @example\n * ```typescript\n * // Wrap JSON.parse\n * const parsed = from(() => JSON.parse('{\"key\": \"value\"}'));\n * // parsed: { ok: true, value: { key: \"value\" } }\n *\n * const error = from(() => JSON.parse('invalid'));\n * // error: { ok: false, error: SyntaxError }\n * ```\n */\nexport function from<T>(fn: () => T): Ok<T> | Err<unknown, unknown>;\n/**\n * Wraps a synchronous throwing function in a Result with custom error mapping.\n *\n * Use this overload when you want to map thrown exceptions to your typed error union.\n *\n * @param fn - The synchronous function to execute (may throw)\n * @param onError - Function to map the thrown exception to a typed error\n * @returns A Result with the function's return value or the mapped error\n *\n * @example\n * ```typescript\n * // Map exceptions to typed errors\n * const parsed = from(\n * () => JSON.parse(input),\n * (cause) => ({ type: 'PARSE_ERROR' as const, cause })\n * );\n * // parsed.error: { type: 'PARSE_ERROR', cause: SyntaxError }\n *\n * // Map to simple error codes\n * const value = from(\n * () => riskyOperation(),\n * () => 'OPERATION_FAILED' as const\n * );\n * ```\n */\nexport function from<T, E>(fn: () => T, onError: (cause: unknown) => E): Ok<T> | Err<E, unknown>;\nexport function from<T, E>(fn: () => T, onError?: (cause: unknown) => E) {\n try {\n return ok(fn());\n } catch (cause) {\n return onError ? err(onError(cause), { cause }) : err(cause);\n }\n}\n\n/**\n * Wraps a Promise in a Result, converting rejections to errors.\n *\n * @remarks When to use: Wrap a Promise and keep the raw rejection as Err; use tryAsync to map errors.\n *\n * ## When to Use\n *\n * Use `fromPromise()` when:\n * - You have an existing Promise that might reject\n * - You want to convert Promise rejections to typed errors\n * - You're working with libraries that return Promises (fetch, database clients)\n * - You need to handle rejections without .catch() chains\n *\n * ## Why Use This\n *\n * - **Type-safe errors**: Convert Promise rejections to typed Result errors\n * - **Composable**: Results can be chained with `andThen`, `map`, etc.\n * - **Explicit handling**: Forces you to handle errors explicitly\n * - **No .catch() chains**: Cleaner than Promise.catch() patterns\n *\n * @param promise - The Promise to await (may reject)\n * @returns A Promise resolving to a Result with the resolved value or rejection reason\n *\n * @example\n * ```typescript\n * // Wrap fetch\n * const result = await fromPromise(\n * fetch('/api').then(r => r.json())\n * );\n * // result.ok: true if fetch succeeded, false if rejected\n * ```\n */\nexport function fromPromise<T>(promise: Promise<T>): Promise<Ok<T> | Err<unknown, unknown>>;\n/**\n * Wraps a Promise in a Result with custom error mapping.\n *\n * Use this overload when you want to map Promise rejections to your typed error union.\n *\n * @param promise - The Promise to await (may reject)\n * @param onError - Function to map the rejection reason to a typed error\n * @returns A Promise resolving to a Result with the resolved value or mapped error\n *\n * @example\n * ```typescript\n * // Map fetch errors to typed errors\n * const result = await fromPromise(\n * fetch('/api').then(r => {\n * if (!r.ok) throw new Error(`HTTP ${r.status}`);\n * return r.json();\n * }),\n * () => 'FETCH_FAILED' as const\n * );\n * // result.error: 'FETCH_FAILED' if fetch failed\n *\n * // Map with error details\n * const data = await fromPromise(\n * db.query(sql),\n * (cause) => ({ type: 'DB_ERROR' as const, message: String(cause) })\n * );\n * ```\n */\nexport function fromPromise<T, E>(\n promise: Promise<T>,\n onError: (cause: unknown) => E\n): Promise<Ok<T> | Err<E, unknown>>;\nexport async function fromPromise<T, E>(\n promise: Promise<T>,\n onError?: (cause: unknown) => E\n): Promise<Ok<T> | Err<E, unknown> | Err<unknown, unknown>> {\n try {\n return ok(await promise);\n } catch (cause) {\n return onError ? err(onError(cause), { cause }) : err(cause);\n }\n}\n\n/**\n * Wraps an async function in a Result, catching both thrown exceptions and Promise rejections.\n *\n * @remarks When to use: Wrap async work and map thrown/rejected values into your typed error union.\n *\n * ## When to Use\n *\n * Use `tryAsync()` when:\n * - You have an async function that might throw or reject\n * - You want to convert both exceptions and rejections to typed errors\n * - You're creating new async functions (use `fromPromise` for existing Promises)\n * - You need to handle errors without try/catch or .catch()\n *\n * ## Why Use This Instead of `fromPromise`\n *\n * - **Function form**: Takes a function, not a Promise (lazy evaluation)\n * - **Catches both**: Handles both thrown exceptions and Promise rejections\n * - **Cleaner syntax**: No need to wrap in Promise manually\n *\n * @param fn - The async function to execute (may throw or reject)\n * @returns A Promise resolving to a Result with the function's return value or error\n *\n * @example\n * ```typescript\n * // Wrap async function\n * const result = await tryAsync(async () => {\n * const data = await fetchData();\n * return processData(data);\n * });\n * ```\n */\nexport function tryAsync<T>(fn: () => Promise<T>): AsyncResult<T, unknown>;\n/**\n * Wraps an async function in a Result with custom error mapping.\n *\n * Use this overload when you want to map errors to your typed error union.\n *\n * @param fn - The async function to execute (may throw or reject)\n * @param onError - Function to map the error (exception or rejection) to a typed error\n * @returns A Promise resolving to a Result with the function's return value or mapped error\n *\n * @example\n * ```typescript\n * // Map errors to typed errors\n * const result = await tryAsync(\n * async () => await fetchData(),\n * () => 'FETCH_ERROR' as const\n * );\n *\n * // Map with error details\n * const data = await tryAsync(\n * async () => await processFile(path),\n * (cause) => ({ type: 'PROCESSING_ERROR' as const, cause })\n * );\n * ```\n */\nexport function tryAsync<T, E>(\n fn: () => Promise<T>,\n onError: (cause: unknown) => E\n): AsyncResult<T, E>;\nexport async function tryAsync<T, E>(\n fn: () => Promise<T>,\n onError?: (cause: unknown) => E\n): AsyncResult<T, E | unknown> {\n try {\n return ok(await fn());\n } catch (cause) {\n return onError ? err(onError(cause), { cause }) : err(cause);\n }\n}\n\n/**\n * Converts a nullable value to a Result.\n *\n * @remarks When to use: Turn null/undefined into a typed error before continuing.\n *\n * ## When to Use\n *\n * Use `fromNullable()` when:\n * - You have a value that might be `null` or `undefined`\n * - You want to treat null/undefined as an error case\n * - You're working with APIs that return nullable values (DOM APIs, optional properties)\n * - You want to avoid null checks scattered throughout your code\n *\n * ## Why Use This\n *\n * - **Type-safe**: Converts nullable types to non-nullable Results\n * - **Explicit errors**: Forces you to handle null/undefined cases\n * - **Composable**: Results can be chained with `andThen`, `map`, etc.\n * - **No null checks**: Eliminates need for `if (value == null)` checks\n *\n * @param value - The value that may be null or undefined\n * @param onNull - Function that returns an error when value is null/undefined\n * @returns A Result with the value if not null/undefined, otherwise the error from `onNull`\n *\n * @example\n * ```typescript\n * // Convert DOM element lookup\n * const element = fromNullable(\n * document.getElementById('app'),\n * () => 'ELEMENT_NOT_FOUND' as const\n * );\n *\n * // Convert optional property\n * const userId = fromNullable(\n * user.id,\n * () => 'USER_ID_MISSING' as const\n * );\n *\n * // Convert database query result\n * const record = fromNullable(\n * await db.find(id),\n * () => ({ type: 'NOT_FOUND' as const, id })\n * );\n * ```\n */\nexport function fromNullable<T, E>(\n value: T | null | undefined,\n onNull: () => E\n): Result<T, E> {\n return value != null ? ok(value) : err(onNull());\n}\n\n// =============================================================================\n// Transformers\n// =============================================================================\n\n/**\n * Transforms the success value of a Result.\n *\n * @remarks When to use: Transform only the Ok value while leaving Err untouched.\n *\n * ## When to Use\n *\n * Use `map()` when:\n * - You need to transform a success value to another type\n * - You want to apply a pure function to the value\n * - You're building a pipeline of transformations\n * - The transformation cannot fail (use `andThen` if it can fail)\n *\n * ## Why Use This\n *\n * - **Functional style**: Composable, chainable transformations\n * - **Error-preserving**: Errors pass through unchanged\n * - **Type-safe**: TypeScript tracks the transformation\n * - **No unwrapping**: Avoids manual `if (r.ok)` checks\n *\n * @param r - The Result to transform\n * @param fn - Pure function that transforms the success value (must not throw)\n * @returns A new Result with the transformed value, or the original error if `r` was an error\n *\n * @example\n * ```typescript\n * // Transform numeric value\n * const doubled = map(ok(21), n => n * 2);\n * // doubled: { ok: true, value: 42 }\n *\n * // Transform object property\n * const name = map(fetchUser(id), user => user.name);\n *\n * // Chain transformations\n * const formatted = map(\n * map(parseNumber(input), n => n * 2),\n * n => `Result: ${n}`\n * );\n * ```\n */\nexport function map<T, U>(r: Ok<T>, fn: (value: T) => U): Ok<U>;\nexport function map<T, U, E, C>(r: Err<E, C>, fn: (value: T) => U): Err<E, C>;\nexport function map<T, U, E, C>(r: Result<T, E, C>, fn: (value: T) => U): Result<U, E, C>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function map(r: any, fn: any): any {\n return r.ok ? ok(fn(r.value)) : r;\n}\n\n/**\n * Transforms the error value of a Result.\n *\n * @remarks When to use: Retype or normalize errors while leaving Ok values unchanged.\n *\n * ## When to Use\n *\n * Use `mapError()` when:\n * - You need to normalize or transform error types\n * - You want to convert errors to a different error type\n * - You're building error handling pipelines\n * - You need to format error messages or codes\n *\n * ## Why Use This\n *\n * - **Error normalization**: Convert errors to a common format\n * - **Type transformation**: Change error type while preserving value type\n * - **Composable**: Can be chained with other transformers\n * - **Success-preserving**: Success values pass through unchanged\n *\n * @param r - The Result to transform\n * @param fn - Function that transforms the error value (must not throw)\n * @returns A new Result with the original value, or the transformed error if `r` was an error\n *\n * @example\n * ```typescript\n * // Normalize error codes\n * const normalized = mapError(err('not_found'), e => e.toUpperCase());\n * // normalized: { ok: false, error: 'NOT_FOUND' }\n *\n * // Convert error types\n * const typed = mapError(\n * err('404'),\n * code => ({ type: 'HTTP_ERROR' as const, status: parseInt(code) })\n * );\n *\n * // Format error messages\n * const formatted = mapError(\n * err('PARSE_ERROR'),\n * code => `Failed to parse: ${code}`\n * );\n * ```\n */\nexport function mapError<T, E, F, C>(\n r: Result<T, E, C>,\n fn: (error: E) => F\n): Result<T, F, C> {\n return r.ok ? r : err(fn(r.error), { cause: r.cause });\n}\n\n/**\n * Pattern matches on a Result, calling the appropriate handler.\n *\n * @remarks When to use: Handle both Ok and Err in a single expression that returns a value.\n *\n * ## When to Use\n *\n * Use `match()` when:\n * - You need to handle both success and error cases\n * - You want to transform a Result to a different type\n * - You need exhaustive handling (both cases must be handled)\n * - You're building user-facing messages or responses\n *\n * ## Why Use This\n *\n * - **Exhaustive**: Forces you to handle both success and error cases\n * - **Type-safe**: TypeScript ensures both handlers are provided\n * - **Functional**: Pattern matching style, similar to Rust's `match` or Haskell's `case`\n * - **Single expression**: Can be used in expressions, not just statements\n *\n * @param r - The Result to match\n * @param handlers - Object with `ok` and `err` handler functions\n * @param handlers.ok - Function called with the success value\n * @param handlers.err - Function called with the error and optional cause\n * @returns The return value of the appropriate handler (both must return the same type `R`)\n *\n * @example\n * ```typescript\n * // Build user-facing messages\n * const message = match(result, {\n * ok: (user) => `Hello ${user.name}`,\n * err: (error) => `Error: ${error}`,\n * });\n *\n * // Transform to API response\n * const response = match(operation(), {\n * ok: (data) => ({ status: 200, body: data }),\n * err: (error) => ({ status: 400, error: String(error) }),\n * });\n *\n * // Handle with cause\n * const response = match(result, {\n * ok: (value) => ({ status: 'success', data: value }),\n * err: (error, cause) => ({ status: 'error', error, cause }),\n * });\n * ```\n */\nexport function match<T, E, C, R>(r: Ok<T>, handlers: { ok: (value: T) => R; err: (error: E, cause?: C) => R }): R;\nexport function match<T, E, C, R>(r: Err<E, C>, handlers: { ok: (value: T) => R; err: (error: E, cause?: C) => R }): R;\nexport function match<T, E, C, R>(r: Result<T, E, C>, handlers: { ok: (value: T) => R; err: (error: E, cause?: C) => R }): R;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function match(r: any, handlers: any): any {\n return r.ok ? handlers.ok(r.value) : handlers.err(r.error, r.cause);\n}\n\n/**\n * Chains Results together (flatMap/monadic bind).\n *\n * @remarks When to use: Chain dependent operations that return Result without nested branching.\n *\n * ## When to Use\n *\n * Use `andThen()` when:\n * - You need to chain operations that can fail\n * - The next operation depends on the previous success value\n * - You're building a pipeline of dependent operations\n * - You want to avoid nested `if (r.ok)` checks\n *\n * ## Why Use This Instead of `map`\n *\n * - **Can fail**: The chained function returns a Result (can fail)\n * - **Short-circuits**: If first Result fails, second operation never runs\n * - **Error accumulation**: Errors from both operations are in the union\n * - **Composable**: Can chain multiple operations together\n *\n * ## Common Pattern\n *\n * This is the fundamental building block for Result pipelines:\n * ```typescript\n * andThen(operation1(), value1 =>\n * andThen(operation2(value1), value2 =>\n * ok({ value1, value2 })\n * )\n * )\n * ```\n *\n * @param r - The first Result\n * @param fn - Function that takes the success value and returns a new Result (may fail)\n * @returns The Result from `fn` if `r` was successful, otherwise the original error\n *\n * @example\n * ```typescript\n * // Chain dependent operations\n * const userPosts = andThen(\n * fetchUser('1'),\n * user => fetchPosts(user.id)\n * );\n *\n * // Build complex pipelines\n * const result = andThen(parseInput(input), parsed =>\n * andThen(validate(parsed), validated =>\n * process(validated)\n * )\n * );\n *\n * // Chain with different error types\n * const data = andThen(\n * fetchUser(id), // Returns Result<User, 'FETCH_ERROR'>\n * user => fetchPosts(user.id) // Returns Result<Post[], 'NOT_FOUND'>\n * );\n * // data.error: 'FETCH_ERROR' | 'NOT_FOUND'\n * ```\n */\nexport function andThen<T, U>(r: Ok<T>, fn: (value: T) => Ok<U>): Ok<U>;\nexport function andThen<T, F, C2>(r: Ok<T>, fn: (value: T) => Err<F, C2>): Err<F, C2>;\nexport function andThen<T, U, F, C2>(r: Ok<T>, fn: (value: T) => Result<U, F, C2>): Result<U, F, C2>;\nexport function andThen<T, U, E, F, C1, C2>(r: Err<E, C1>, fn: (value: T) => Result<U, F, C2>): Err<E, C1>;\nexport 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>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function andThen(r: any, fn: any): any {\n return r.ok ? fn(r.value) : r;\n}\n\n/**\n * Executes a side effect on a successful Result without changing it.\n *\n * @remarks When to use: Add side effects (logging, metrics) on Ok without changing the Result.\n *\n * ## When to Use\n *\n * Use `tap()` when:\n * - You need to log, debug, or observe success values\n * - You want to perform side effects in a pipeline\n * - You need to mutate external state based on success\n * - You're debugging and want to inspect values without breaking the chain\n *\n * ## Why Use This\n *\n * - **Non-breaking**: Doesn't change the Result, just performs side effect\n * - **Composable**: Can be inserted anywhere in a pipeline\n * - **Type-preserving**: Returns the same Result type\n * - **Lazy**: Side effect only runs if Result is successful\n *\n * @param r - The Result to tap\n * @param fn - Side effect function called with the success value (return value ignored)\n * @returns The original Result unchanged (for chaining)\n *\n * @example\n * ```typescript\n * // Log success values\n * const logged = tap(result, user => console.log('Got user:', user.name));\n * // logged === result, but console.log was called\n *\n * // Debug in pipeline\n * const debugged = pipe(\n * fetchUser(id),\n * r => tap(r, user => console.log('Fetched:', user)),\n * r => map(r, user => user.name)\n * );\n *\n * // Mutate external state\n * const tracked = tap(result, data => {\n * analytics.track('operation_success', data);\n * });\n * ```\n */\nexport function tap<T, E, C>(\n r: Result<T, E, C>,\n fn: (value: T) => void\n): Result<T, E, C> {\n if (r.ok) fn(r.value);\n return r;\n}\n\n/**\n * Executes a side effect on an error Result without changing it.\n *\n * @remarks When to use: Add side effects (logging, metrics) on Err without changing the Result.\n *\n * ## When to Use\n *\n * Use `tapError()` when:\n * - You need to log, debug, or observe error values\n * - You want to perform side effects on errors in a pipeline\n * - You need to report errors to external systems (logging, monitoring)\n * - You're debugging and want to inspect errors without breaking the chain\n *\n * ## Why Use This\n *\n * - **Non-breaking**: Doesn't change the Result, just performs side effect\n * - **Composable**: Can be inserted anywhere in a pipeline\n * - **Type-preserving**: Returns the same Result type\n * - **Lazy**: Side effect only runs if Result is an error\n *\n * @param r - The Result to tap\n * @param fn - Side effect function called with the error and optional cause (return value ignored)\n * @returns The original Result unchanged (for chaining)\n *\n * @example\n * ```typescript\n * // Log errors\n * const logged = tapError(result, (error, cause) => {\n * console.error('Error:', error, cause);\n * });\n *\n * // Report to error tracking\n * const tracked = tapError(result, (error, cause) => {\n * errorTracker.report(error, cause);\n * });\n *\n * // Debug in pipeline\n * const debugged = pipe(\n * operation(),\n * r => tapError(r, (err, cause) => console.error('Failed:', err)),\n * r => mapError(r, err => 'FORMATTED_ERROR')\n * );\n * ```\n */\nexport function tapError<T, E, C>(\n r: Result<T, E, C>,\n fn: (error: E, cause?: C) => void\n): Result<T, E, C> {\n if (!r.ok) fn(r.error, r.cause);\n return r;\n}\n\n/**\n * Transforms the success value of a Result, catching any errors thrown by the transform.\n *\n * @remarks When to use: Transform Ok values with a function that might throw and capture the failure.\n *\n * ## When to Use\n *\n * Use `mapTry()` when:\n * - Your transform function might throw exceptions\n * - You want to convert transform errors to typed errors\n * - You're working with libraries that throw (e.g., JSON.parse, Date parsing)\n * - You need to handle both Result errors and transform exceptions\n *\n * ## Why Use This Instead of `map`\n *\n * - **Exception-safe**: Catches exceptions from the transform function\n * - **Error mapping**: Converts thrown exceptions to typed errors\n * - **Dual error handling**: Handles both Result errors and transform exceptions\n *\n * @param result - The Result to transform\n * @param transform - Function to transform the success value (may throw exceptions)\n * @param onError - Function to map thrown exceptions to a typed error\n * @returns A Result with:\n * - Transformed value if both Result and transform succeed\n * - Original error if Result was an error\n * - Transform error if transform threw an exception\n *\n * @example\n * ```typescript\n * // Safe JSON parsing\n * const parsed = mapTry(\n * ok('{\"key\": \"value\"}'),\n * JSON.parse,\n * () => 'PARSE_ERROR' as const\n * );\n *\n * // Safe date parsing\n * const date = mapTry(\n * ok('2024-01-01'),\n * str => new Date(str),\n * () => 'INVALID_DATE' as const\n * );\n *\n * // Transform with error details\n * const processed = mapTry(\n * result,\n * value => riskyTransform(value),\n * (cause) => ({ type: 'TRANSFORM_ERROR' as const, cause })\n * );\n * ```\n */\nexport function mapTry<T, U, E, F, C>(\n result: Result<T, E, C>,\n transform: (value: T) => U,\n onError: (cause: unknown) => F\n): Result<U, E | F, C | unknown> {\n if (!result.ok) return result;\n try {\n return ok(transform(result.value));\n } catch (error) {\n return err(onError(error), { cause: error });\n }\n}\n\n/**\n * Transforms the error value of a Result, catching any errors thrown by the transform.\n *\n * @remarks When to use: Transform errors when the mapping might throw and you want that captured.\n *\n * ## When to Use\n *\n * Use `mapErrorTry()` when:\n * - Your error transform function might throw exceptions\n * - You're doing complex error transformations (e.g., string formatting, object construction)\n * - You want to handle both Result errors and transform exceptions\n * - You need to safely normalize error types\n *\n * ## Why Use This Instead of `mapError`\n *\n * - **Exception-safe**: Catches exceptions from the error transform function\n * - **Error mapping**: Converts thrown exceptions to typed errors\n * - **Dual error handling**: Handles both Result errors and transform exceptions\n *\n * @param result - The Result to transform\n * @param transform - Function to transform the error value (may throw exceptions)\n * @param onError - Function to map thrown exceptions to a typed error\n * @returns A Result with:\n * - Original value if Result was successful\n * - Transformed error if both Result was error and transform succeeded\n * - Transform error if transform threw an exception\n *\n * @example\n * ```typescript\n * // Safe error formatting\n * const formatted = mapErrorTry(\n * err('not_found'),\n * e => e.toUpperCase(), // Might throw if e is not a string\n * () => 'FORMAT_ERROR' as const\n * );\n *\n * // Complex error transformation\n * const normalized = mapErrorTry(\n * result,\n * error => ({ type: 'NORMALIZED', message: String(error) }),\n * () => 'TRANSFORM_ERROR' as const\n * );\n * ```\n */\nexport function mapErrorTry<T, E, F, G, C>(\n result: Result<T, E, C>,\n transform: (error: E) => F,\n onError: (cause: unknown) => G\n): Result<T, F | G, C | unknown> {\n if (result.ok) return result;\n try {\n return err(transform(result.error), { cause: result.cause });\n } catch (error) {\n return err(onError(error), { cause: error });\n }\n}\n\n/**\n * Transforms both the success value and error value of a Result simultaneously.\n *\n * ## When to Use\n *\n * Use `bimap()` when:\n * - You need to transform both success and error in one operation\n * - You're normalizing Results to a common format\n * - You want symmetric transformation of both cases\n * - You're building adapters between different Result types\n *\n * ## Why Use This Instead of `map` + `mapError`\n *\n * - **Single operation**: Transforms both cases in one call\n * - **Clearer intent**: Shows you're handling both cases symmetrically\n * - **Less code**: Avoids chaining map and mapError\n *\n * @param r - The Result to transform\n * @param onOk - Function that transforms the success value\n * @param onErr - Function that transforms the error value\n * @returns A new Result with transformed value or transformed error\n *\n * @example\n * ```typescript\n * // Normalize to API response format\n * const response = bimap(\n * fetchUser(id),\n * user => ({ status: 'success', data: user }),\n * error => ({ status: 'error', code: error })\n * );\n *\n * // Transform types\n * const stringified = bimap(\n * parseNumber(input),\n * n => `Value: ${n}`,\n * e => `Error: ${e}`\n * );\n *\n * // Adapt between error types\n * const adapted = bimap(\n * externalResult,\n * value => internalValue(value),\n * error => internalError(error)\n * );\n * ```\n */\nexport function bimap<T, U, E, F, C>(\n r: Result<T, E, C>,\n onOk: (value: T) => U,\n onErr: (error: E) => F\n): Result<U, F, C> {\n return r.ok ? ok(onOk(r.value)) : err(onErr(r.error), { cause: r.cause });\n}\n\n/**\n * Recovers from an error by returning a new Result.\n * Similar to neverthrow's `.orElse()`.\n *\n * @remarks When to use: Recover from Err by returning a fallback Result or retyping the error.\n *\n * ## When to Use\n *\n * Use `orElse()` when:\n * - You want to recover from errors with fallback operations\n * - The recovery might also fail (returns a Result)\n * - You need to chain fallback strategies\n * - You're implementing retry or fallback patterns\n *\n * ## Why Use This\n *\n * - **Fallback chains**: Try alternative operations on failure\n * - **Error recovery**: Convert errors to success with fallback values\n * - **Composable**: Can chain multiple orElse calls for cascading fallbacks\n * - **Type-safe**: TypeScript tracks the error union through recovery\n *\n * @param r - The Result to potentially recover from\n * @param fn - Function that takes the error and returns a new Result (may succeed or fail)\n * @returns The original Result if successful, or the result of the recovery function\n *\n * @example\n * ```typescript\n * // Fallback to default user\n * const user = orElse(\n * fetchUser(id),\n * error => error === 'NOT_FOUND' ? ok(defaultUser) : err(error)\n * );\n *\n * // Try cache, then database, then fail\n * const data = orElse(\n * orElse(\n * fetchFromCache(key),\n * () => fetchFromDatabase(key)\n * ),\n * () => err('DATA_UNAVAILABLE' as const)\n * );\n *\n * // Convert specific errors to success\n * const result = orElse(\n * riskyOperation(),\n * error => error.code === 'RETRY' ? ok(defaultValue) : err(error)\n * );\n * ```\n */\nexport function orElse<T, E, E2, C, C2>(\n r: Result<T, E, C>,\n fn: (error: E, cause?: C) => Result<T, E2, C2>\n): Result<T, E2, C2> {\n return r.ok ? r : fn(r.error, r.cause);\n}\n\n/**\n * Async version of orElse for recovering from errors with async operations.\n *\n * @param r - The Result or AsyncResult to potentially recover from\n * @param fn - Async function that takes the error and returns a new Result\n * @returns Promise of the original Result if successful, or the result of the recovery function\n *\n * @example\n * ```typescript\n * // Try primary API, fall back to secondary\n * const data = await orElseAsync(\n * await fetchFromPrimaryApi(),\n * async (error) => {\n * if (error === 'UNAVAILABLE') {\n * return await fetchFromSecondaryApi();\n * }\n * return err(error);\n * }\n * );\n * ```\n */\nexport async function orElseAsync<T, E, E2, C, C2>(\n r: Result<T, E, C> | Promise<Result<T, E, C>>,\n fn: (error: E, cause?: C) => Result<T, E2, C2> | Promise<Result<T, E2, C2>>\n): Promise<Result<T, E2, C2>> {\n const resolved = await r;\n return resolved.ok ? resolved : fn(resolved.error, resolved.cause);\n}\n\n/**\n * Recovers from an error by returning a plain value (not a Result).\n * Useful when you want to provide a default value on error.\n *\n * ## When to Use\n *\n * Use `recover()` when:\n * - You want to provide a fallback value on error\n * - Recovery cannot fail (unlike orElse which returns a Result)\n * - You're implementing default value patterns\n * - You want to guarantee a successful Result\n *\n * ## Why Use This Instead of `orElse`\n *\n * - **Simpler**: Recovery function returns plain value, not Result\n * - **Guaranteed success**: Always returns ok() after recovery\n * - **Clearer intent**: Shows recovery cannot fail\n *\n * @param r - The Result to potentially recover from\n * @param fn - Function that takes the error and returns a recovery value\n * @returns The original Result if successful, or ok(recoveryValue) if error\n *\n * @example\n * ```typescript\n * // Provide default user on NOT_FOUND\n * const user = recover(\n * fetchUser(id),\n * error => error === 'NOT_FOUND' ? defaultUser : guestUser\n * );\n *\n * // Convert all errors to default\n * const config = recover(\n * loadConfig(),\n * () => defaultConfig\n * );\n *\n * // Recover with error-based defaults\n * const value = recover(\n * parseNumber(input),\n * error => error === 'EMPTY' ? 0 : -1\n * );\n * ```\n */\nexport function recover<T, E, C>(\n r: Result<T, E, C>,\n fn: (error: E, cause?: C) => T\n): Ok<T> {\n return r.ok ? ok(r.value) : ok(fn(r.error, r.cause));\n}\n\n/**\n * Async version of recover for recovering with async operations.\n *\n * @param r - The Result or AsyncResult to potentially recover from\n * @param fn - Async function that takes the error and returns a recovery value\n * @returns Promise of ok(value) - either original or recovered\n *\n * @example\n * ```typescript\n * // Recover by fetching default from API\n * const user = await recoverAsync(\n * await fetchUser(id),\n * async (error) => await fetchDefaultUser()\n * );\n * ```\n */\nexport async function recoverAsync<T, E, C>(\n r: Result<T, E, C> | Promise<Result<T, E, C>>,\n fn: (error: E, cause?: C) => T | Promise<T>\n): Promise<Ok<T>> {\n const resolved = await r;\n if (resolved.ok) return ok(resolved.value);\n return ok(await fn(resolved.error, resolved.cause));\n}\n\n// =============================================================================\n// Result Hydration (Serialization)\n// =============================================================================\n\n/**\n * Validates and type-narrows a value to a Result.\n *\n * Since this library uses plain objects for Results, serialization is trivial -\n * the serialized form IS the Result. This function validates the structure and\n * provides type-safe narrowing.\n *\n * ## When to Use\n *\n * Use `hydrate()` when:\n * - Receiving Results over RPC/network\n * - Deserializing Results from storage\n * - Validating untrusted data as Results\n *\n * @param value - The unknown value to validate as a Result\n * @returns The value as a typed Result, or null if invalid\n *\n * @example\n * ```typescript\n * // Deserialize from JSON\n * const parsed = JSON.parse(jsonString);\n * const result = hydrate<User, ApiError>(parsed);\n * if (result) {\n * // result is Result<User, ApiError>\n * }\n *\n * // Validate RPC response\n * const rpcResponse = await fetchFromService();\n * const result = hydrate<Data, ServiceError>(rpcResponse);\n * ```\n */\nexport function hydrate<T, E, C = unknown>(value: unknown): Result<T, E, C> | null {\n if (\n value !== null &&\n typeof value === \"object\" &&\n \"ok\" in value &&\n typeof value.ok === \"boolean\"\n ) {\n if (value.ok === true && \"value\" in value) {\n return value as Result<T, E, C>;\n }\n if (value.ok === false && \"error\" in value) {\n return value as Result<T, E, C>;\n }\n }\n return null;\n}\n\n/**\n * Type guard to check if a value is a valid serialized Result.\n *\n * @param value - The value to check\n * @returns True if the value is a valid Result structure\n *\n * @example\n * ```typescript\n * if (isSerializedResult(data)) {\n * // data is Result<unknown, unknown, unknown>\n * if (data.ok) {\n * console.log(data.value);\n * }\n * }\n * ```\n */\nexport function isSerializedResult(\n value: unknown\n): value is Result<unknown, unknown, unknown> {\n return hydrate(value) !== null;\n}\n\n// =============================================================================\n// Batch Operations\n// =============================================================================\n\ntype AllValues<T extends readonly Result<unknown, unknown, unknown>[]> = {\n [K in keyof T]: T[K] extends Ok<infer V>\n ? V\n : T[K] extends Err<unknown, unknown>\n ? never\n : T[K] extends Result<infer V, unknown, unknown>\n ? V\n : never;\n};\ntype AllErrors<T extends readonly Result<unknown, unknown, unknown>[]> = {\n [K in keyof T]: T[K] extends Ok<unknown>\n ? never\n : T[K] extends Err<infer E, unknown>\n ? E\n : T[K] extends Result<unknown, infer E, unknown>\n ? E\n : never;\n}[number];\ntype AllCauses<T extends readonly Result<unknown, unknown, unknown>[]> = {\n [K in keyof T]: T[K] extends Ok<unknown>\n ? never\n : T[K] extends Err<unknown, infer C>\n ? C\n : T[K] extends Result<unknown, unknown, infer C>\n ? C\n : never;\n}[number];\n\n// Conditional type: returns Ok<...> when there are no errors, Result<...> otherwise\n// Note: We only check AllErrors, not AllCauses - causes only matter when there are errors\ntype AllResult<T extends readonly Result<unknown, unknown, unknown>[]> =\n [AllErrors<T>] extends [never]\n ? Ok<AllValues<T>>\n : Result<AllValues<T>, AllErrors<T>, AllCauses<T>>;\n\n/**\n * Combines multiple Results into one, requiring all to succeed.\n *\n * ## When to Use\n *\n * Use `all()` when:\n * - You have multiple independent operations that all must succeed\n * - You want to short-circuit on the first error (fail-fast)\n * - You need all values together (e.g., combining API responses)\n * - Performance matters (stops on first error, doesn't wait for all)\n *\n * ## Why Use This\n *\n * - **Fail-fast**: Stops immediately on first error (better performance)\n * - **Type-safe**: TypeScript infers the array type from input\n * - **Short-circuit**: Doesn't evaluate remaining Results after error\n * - **Composable**: Can be chained with other operations\n *\n * ## Important\n *\n * - **Short-circuits**: Returns first error immediately, doesn't wait for all Results\n * - **All must succeed**: If any Result fails, the entire operation fails\n * - **Use `allSettled`**: If you need to collect all errors (e.g., form validation)\n *\n * @param results - Array of Results to combine (all must succeed)\n * @returns A Result with an array of all success values, or the first error encountered\n *\n * @example\n * ```typescript\n * // Combine multiple successful Results\n * const combined = all([Awaitly.ok(1), Awaitly.ok(2), Awaitly.ok(3)]);\n * // combined: { ok: true, value: [1, 2, 3] }\n *\n * // Short-circuits on first error\n * const error = all([Awaitly.ok(1), Awaitly.err('ERROR'), Awaitly.ok(3)]);\n * // error: { ok: false, error: 'ERROR' }\n * // Note: Awaitly.ok(3) is never evaluated\n *\n * // Combine API responses\n * const data = all([\n * fetchUser(id),\n * fetchPosts(id),\n * fetchComments(id)\n * ]);\n * // data.value: [user, posts, comments] if all succeed\n * ```\n */\nexport function all<const T extends readonly Result<unknown, unknown, unknown>[]>(\n results: T\n): AllResult<T> {\n const values: unknown[] = [];\n for (const result of results) {\n if (!result.ok) {\n return result as unknown as AllResult<T>;\n }\n values.push(result.value);\n }\n return ok(values) as AllResult<T>;\n}\n\n/**\n * Combines multiple Results or Promises of Results into one (async version of `all`).\n *\n * ## When to Use\n *\n * Use `allAsync()` when:\n * - You have multiple async operations that all must succeed\n * - You want to run operations in parallel (better performance)\n * - You want to short-circuit on the first error (fail-fast)\n * - You need all values together from parallel operations\n *\n * ## Why Use This Instead of `all`\n *\n * - **Parallel execution**: All Promises start immediately (faster)\n * - **Async support**: Works with Promises and AsyncResults\n * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`\n *\n * ## Important\n *\n * - **Short-circuits**: Returns first error immediately, cancels remaining operations\n * - **Parallel**: All operations start simultaneously (unlike sequential `andThen`)\n * - **Use `allSettledAsync`**: If you need to collect all errors\n *\n * @param results - Array of Results or Promises of Results to combine (all must succeed)\n * @returns A Promise resolving to a Result with an array of all success values, or the first error\n *\n * @example\n * ```typescript\n * // Parallel API calls\n * const combined = await allAsync([\n * fetchUser('1'),\n * fetchPosts('1'),\n * fetchComments('1')\n * ]);\n * // All three calls start simultaneously\n * // combined: { ok: true, value: [user, posts, comments] } if all succeed\n *\n * // Mix Results and Promises\n * const data = await allAsync([\n * ok(cachedUser), // Already resolved\n * fetchPosts(userId), // Promise\n * ]);\n * ```\n */\nexport async function allAsync<\n const T extends readonly (Result<unknown, unknown, unknown> | Promise<Result<unknown, unknown, unknown>>)[]\n>(\n results: T\n): Promise<\n Result<\n { [K in keyof T]: T[K] extends Result<infer V, unknown, unknown> | Promise<Result<infer V, unknown, unknown>> ? V : never },\n { [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> | Promise<Result<unknown, infer E, unknown>> ? E : never }[number] | PromiseRejectedError,\n { [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> | Promise<Result<unknown, unknown, infer C>> ? C : never }[number] | PromiseRejectionCause\n >\n> {\n type Values = { [K in keyof T]: T[K] extends Result<infer V, unknown, unknown> | Promise<Result<infer V, unknown, unknown>> ? V : never };\n type Errors = { [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> | Promise<Result<unknown, infer E, unknown>> ? E : never }[number] | PromiseRejectedError;\n type Causes = { [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> | Promise<Result<unknown, unknown, infer C>> ? C : never }[number] | PromiseRejectionCause;\n\n if (results.length === 0) {\n return ok([]) as Result<Values, Errors, Causes>;\n }\n\n return new Promise((resolve) => {\n let settled = false;\n let pendingCount = results.length;\n const values: unknown[] = new Array(results.length);\n\n for (let i = 0; i < results.length; i++) {\n const index = i;\n Promise.resolve(results[index])\n .catch((reason) => err(\n { type: \"PROMISE_REJECTED\" as const, cause: reason },\n { cause: { type: \"PROMISE_REJECTION\" as const, reason } as PromiseRejectionCause }\n ))\n .then((result) => {\n if (settled) return;\n\n if (!result.ok) {\n settled = true;\n resolve(result as Result<Values, Errors, Causes>);\n return;\n }\n\n values[index] = result.value;\n pendingCount--;\n\n if (pendingCount === 0) {\n resolve(ok(values) as Result<Values, Errors, Causes>);\n }\n });\n }\n });\n}\n\nexport type SettledError<E, C = unknown> = { error: E; cause?: C };\n\n// Conditional type: returns Ok<...> when there are no errors, Result<...> otherwise\ntype AllSettledResult<T extends readonly Result<unknown, unknown, unknown>[]> =\n [AllErrors<T>] extends [never]\n ? Ok<AllValues<T>>\n : Result<AllValues<T>, SettledError<AllErrors<T>, AllCauses<T>>[]>;\n\n/**\n * Combines multiple Results, collecting all errors instead of short-circuiting.\n *\n * ## When to Use\n *\n * Use `allSettled()` when:\n * - You need to see ALL errors, not just the first one\n * - You're doing form validation (show all field errors)\n * - You want to collect partial results (some succeed, some fail)\n * - You need to process all Results regardless of failures\n *\n * ## Why Use This Instead of `all`\n *\n * - **Collects all errors**: Returns array of all errors, not just first\n * - **No short-circuit**: Evaluates all Results even if some fail\n * - **Partial success**: Can see which operations succeeded and which failed\n * - **Better UX**: Show users all validation errors at once\n *\n * ## Important\n *\n * - **No short-circuit**: All Results are evaluated (slower if many fail early)\n * - **Error array**: Returns array of `{ error, cause }` objects, not single error\n * - **Use `all`**: If you want fail-fast behavior (better performance)\n *\n * @param results - Array of Results to combine (all are evaluated)\n * @returns A Result with:\n * - Array of all success values if all succeed\n * - Array of `{ error, cause }` objects if any fail\n *\n * @example\n * ```typescript\n * // Form validation - show all errors\n * const validated = allSettled([\n * validateEmail(email),\n * validatePassword(password),\n * validateAge(age),\n * ]);\n * // If email and password fail:\n * // { ok: false, error: [\n * // { error: 'INVALID_EMAIL' },\n * // { error: 'WEAK_PASSWORD' }\n * // ]}\n *\n * // Collect partial results\n * const results = allSettled([\n * fetchUser('1'), // succeeds\n * fetchUser('2'), // fails\n * fetchUser('3'), // succeeds\n * ]);\n * // Can see which succeeded and which failed\n * ```\n */\nexport function allSettled<const T extends readonly Result<unknown, unknown, unknown>[]>(\n results: T\n): AllSettledResult<T> {\n const values: unknown[] = [];\n const errors: SettledError<unknown>[] = [];\n\n for (const result of results) {\n if (result.ok) {\n values.push(result.value);\n } else {\n errors.push({ error: result.error, cause: result.cause });\n }\n }\n\n if (errors.length > 0) {\n return err(errors) as unknown as AllSettledResult<T>;\n }\n\n return ok(values) as unknown as AllSettledResult<T>;\n}\n\n/**\n * Splits an array of Results into separate arrays of success values and errors.\n *\n * ## When to Use\n *\n * Use `partition()` when:\n * - You have an array of Results and need to separate successes from failures\n * - You want to process successes and errors separately\n * - You're collecting results from multiple operations (some may fail)\n * - You need to handle partial success scenarios\n *\n * ## Why Use This\n *\n * - **Simple separation**: One call splits successes and errors\n * - **Type-safe**: TypeScript knows `values` is `T[]` and `errors` is `E[]`\n * - **No unwrapping**: Doesn't require manual `if (r.ok)` checks\n * - **Preserves order**: Maintains original array order in both arrays\n *\n * ## Common Pattern\n *\n * Often used after `Promise.all()` with Results:\n * ```typescript\n * const results = await Promise.all(ids.map(id => fetchUser(id)));\n * const { values: users, errors } = partition(results);\n * // Process successful users, handle errors separately\n * ```\n *\n * @param results - Array of Results to partition\n * @returns An object with:\n * - `values`: Array of all success values (type `T[]`)\n * - `errors`: Array of all error values (type `E[]`)\n *\n * @example\n * ```typescript\n * // Split successes and errors\n * const results = [ok(1), err('ERROR_1'), ok(3), err('ERROR_2')];\n * const { values, errors } = partition(results);\n * // values: [1, 3]\n * // errors: ['ERROR_1', 'ERROR_2']\n *\n * // Process batch operations\n * const userResults = await Promise.all(userIds.map(id => fetchUser(id)));\n * const { values: users, errors: fetchErrors } = partition(userResults);\n *\n * // Process successful users\n * users.forEach(user => processUser(user));\n *\n * // Handle errors\n * fetchErrors.forEach(error => logError(error));\n * ```\n */\nexport function partition<T, E, C>(\n results: readonly Result<T, E, C>[]\n): { values: T[]; errors: E[] } {\n const values: T[] = [];\n const errors: E[] = [];\n\n for (const result of results) {\n if (result.ok) {\n values.push(result.value);\n } else {\n errors.push(result.error);\n }\n }\n\n return { values, errors };\n}\n\ntype AnyValue<T extends readonly Result<unknown, unknown, unknown>[]> =\n T[number] extends Result<infer U, unknown, unknown> ? U : never;\ntype AnyErrors<T extends readonly Result<unknown, unknown, unknown>[]> = {\n -readonly [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> ? E : never;\n}[number];\ntype AnyCauses<T extends readonly Result<unknown, unknown, unknown>[]> = {\n -readonly [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> ? C : never;\n}[number];\n\n/**\n * Returns the first successful Result from an array (succeeds fast).\n *\n * ## When to Use\n *\n * Use `any()` when:\n * - You have multiple fallback options and need the first that succeeds\n * - You're trying multiple strategies (e.g., cache → DB → API)\n * - You want fail-fast success (stops on first success)\n * - You have redundant data sources and any one will do\n *\n * ## Why Use This\n *\n * - **Succeeds fast**: Returns immediately on first success (better performance)\n * - **Fallback pattern**: Perfect for trying multiple options\n * - **Short-circuits**: Stops evaluating after first success\n * - **Type-safe**: TypeScript infers the success type\n *\n * ## Important\n *\n * - **First success wins**: Returns first successful Result, ignores rest\n * - **All errors**: If all fail, returns first error (not all errors)\n * - **Empty array**: Returns `EmptyInputError` if array is empty\n * - **Use `all`**: If you need ALL to succeed\n *\n * @param results - Array of Results to check (evaluated in order)\n * @returns The first successful Result, or first error if all fail, or `EmptyInputError` if empty\n *\n * @example\n * ```typescript\n * // Try multiple fallback strategies\n * const data = any([\n * fetchFromCache(id),\n * fetchFromDB(id),\n * fetchFromAPI(id)\n * ]);\n * // Returns first that succeeds\n *\n * // Try multiple formats\n * const parsed = any([\n * parseJSON(input),\n * parseXML(input),\n * parseYAML(input)\n * ]);\n *\n * // All errors case\n * const allErrors = any([err('A'), err('B'), err('C')]);\n * // allErrors: { ok: false, error: 'A' } (first error)\n * ```\n */\nexport function any<const T extends readonly Result<unknown, unknown, unknown>[]>(\n results: T\n): Result<AnyValue<T>, AnyErrors<T> | EmptyInputError, AnyCauses<T>> {\n type ReturnErr = Result<never, AnyErrors<T> | EmptyInputError, AnyCauses<T>>;\n type ReturnOk = Result<AnyValue<T>, never, AnyCauses<T>>;\n\n if (results.length === 0) {\n return err({\n type: \"EMPTY_INPUT\",\n message: \"any() requires at least one Result\",\n }) as ReturnErr;\n }\n let firstError: Result<never, unknown, unknown> | null = null;\n for (const result of results) {\n if (result.ok) return result as ReturnOk;\n if (!firstError) firstError = result;\n }\n return firstError as ReturnErr;\n}\n\ntype AnyAsyncValue<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> =\n Awaited<T[number]> extends Result<infer U, unknown, unknown> ? U : never;\ntype AnyAsyncErrors<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n -readonly [K in keyof T]: Awaited<T[K]> extends Result<unknown, infer E, unknown>\n ? E\n : never;\n}[number];\ntype AnyAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n -readonly [K in keyof T]: Awaited<T[K]> extends Result<unknown, unknown, infer C>\n ? C\n : never;\n}[number];\n\n/**\n * Returns the first successful Result from an array of Results or Promises (async version of `any`).\n *\n * ## When to Use\n *\n * Use `anyAsync()` when:\n * - You have multiple async fallback options and need the first that succeeds\n * - You're trying multiple async strategies in parallel (cache → DB → API)\n * - You want fail-fast success from parallel operations\n * - You have redundant async data sources and any one will do\n *\n * ## Why Use This Instead of `any`\n *\n * - **Parallel execution**: All Promises start immediately (faster)\n * - **Async support**: Works with Promises and AsyncResults\n * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`\n *\n * ## Important\n *\n * - **First success wins**: Returns first successful Result (from any Promise)\n * - **Parallel**: All operations run simultaneously\n * - **All errors**: If all fail, returns first error encountered\n *\n * @param results - Array of Results or Promises of Results to check (all start in parallel)\n * @returns A Promise resolving to the first successful Result, or first error if all fail\n *\n * @example\n * ```typescript\n * // Try multiple async fallbacks in parallel\n * const data = await anyAsync([\n * fetchFromCache(id), // Fastest wins\n * fetchFromDB(id),\n * fetchFromAPI(id)\n * ]);\n *\n * // Try multiple API endpoints\n * const response = await anyAsync([\n * fetch('/api/v1/data'),\n * fetch('/api/v2/data'),\n * fetch('/backup-api/data')\n * ]);\n * ```\n */\nexport async function anyAsync<\n const T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[],\n>(\n results: T\n): Promise<\n Result<AnyAsyncValue<T>, AnyAsyncErrors<T> | EmptyInputError | PromiseRejectedError, AnyAsyncCauses<T> | PromiseRejectionCause>\n> {\n type ReturnErr = Result<\n never,\n AnyAsyncErrors<T> | EmptyInputError | PromiseRejectedError,\n AnyAsyncCauses<T> | PromiseRejectionCause\n >;\n type ReturnOk = Result<AnyAsyncValue<T>, never, AnyAsyncCauses<T>>;\n\n if (results.length === 0) {\n return err({\n type: \"EMPTY_INPUT\",\n message: \"anyAsync() requires at least one Result\",\n }) as ReturnErr;\n }\n\n return new Promise((resolve) => {\n let settled = false;\n let pendingCount = results.length;\n let firstError: Result<never, unknown, unknown> | null = null;\n\n for (const item of results) {\n Promise.resolve(item)\n .catch((reason) =>\n err(\n { type: \"PROMISE_REJECTED\" as const, cause: reason },\n { cause: { type: \"PROMISE_REJECTION\" as const, reason } as PromiseRejectionCause }\n )\n )\n .then((result) => {\n if (settled) return;\n\n if (result.ok) {\n settled = true;\n resolve(result as ReturnOk);\n return;\n }\n\n if (!firstError) firstError = result;\n pendingCount--;\n\n if (pendingCount === 0) {\n resolve(firstError as ReturnErr);\n }\n });\n }\n });\n}\n\ntype AllAsyncValues<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n [K in keyof T]: Awaited<T[K]> extends Result<infer V, unknown, unknown> ? V : never;\n};\ntype AllAsyncErrors<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n [K in keyof T]: Awaited<T[K]> extends Result<unknown, infer E, unknown> ? E : never;\n}[number];\ntype AllAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {\n [K in keyof T]: Awaited<T[K]> extends Result<unknown, unknown, infer C> ? C : never;\n}[number];\n\n/**\n * Combines multiple Results or Promises of Results, collecting all errors (async version of `allSettled`).\n *\n * ## When to Use\n *\n * Use `allSettledAsync()` when:\n * - You have multiple async operations and need ALL errors reported\n * - You're doing async form validation (show all field errors at once)\n * - You want to run operations in parallel and collect all results\n *\n * ## Behavior\n *\n * **Note:** Unlike `Promise.allSettled()`, this returns a Result:\n * - `ok(values[])` if ALL succeed\n * - `err(SettledError[])` if ANY fail (with all collected errors)\n *\n * This is consistent with awaitly's philosophy - all functions return Results.\n * `Promise.allSettled()` always succeeds with per-item status objects; this function\n * returns a single Result indicating overall success or failure.\n *\n * ## Why Use This Instead of `allSettled`\n *\n * - **Parallel execution**: All Promises start immediately (faster)\n * - **Async support**: Works with Promises and AsyncResults\n * - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`\n *\n * ## Important\n *\n * - **No short-circuit**: All operations complete (even if some fail)\n * - **Parallel**: All operations run simultaneously\n * - **Error array**: Returns array of `SettledError` objects (`{ error, cause? }`)\n *\n * @param results - Array of Results or Promises of Results to combine (all are evaluated)\n * @returns A Promise resolving to a Result with:\n * - `ok(values[])` - Array of all success values if ALL succeed\n * - `err(errors[])` - Array of `SettledError` objects if ANY fail\n *\n * @example\n * ```typescript\n * // Async form validation - see all errors at once\n * const validated = await allSettledAsync([\n * validateEmailAsync(email),\n * validatePasswordAsync(password),\n * checkUsernameAvailableAsync(username),\n * ]);\n *\n * if (!validated.ok) {\n * // validated.error is array of all validation failures\n * console.log('Errors:', validated.error.map(e => e.error));\n * }\n *\n * // Parallel API calls with error collection\n * const results = await allSettledAsync([\n * fetchUser('1'),\n * fetchUser('2'),\n * fetchUser('3'),\n * ]);\n * ```\n */\nexport async function allSettledAsync<\n const T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[],\n>(\n results: T\n): Promise<Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>> {\n const settled = await Promise.all(\n results.map((item) =>\n Promise.resolve(item)\n .then((result) => ({ status: \"result\" as const, result }))\n .catch((reason) => ({\n status: \"rejected\" as const,\n error: { type: \"PROMISE_REJECTED\" as const, cause: reason } as PromiseRejectedError,\n cause: { type: \"PROMISE_REJECTION\" as const, reason } as PromiseRejectionCause,\n }))\n )\n );\n\n const values: unknown[] = [];\n const errors: SettledError<unknown, unknown>[] = [];\n\n for (const item of settled) {\n if (item.status === \"rejected\") {\n errors.push({ error: item.error, cause: item.cause });\n } else if (item.result.ok) {\n values.push(item.result.value);\n } else {\n errors.push({ error: item.result.error, cause: item.result.cause });\n }\n }\n\n if (errors.length > 0) {\n return err(errors) as unknown as Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>;\n }\n return ok(values) as unknown as Result<AllAsyncValues<T>, SettledError<AllAsyncErrors<T> | PromiseRejectedError, AllAsyncCauses<T> | PromiseRejectionCause>[]>;\n}\n\n/**\n * Combines two Results into a tuple Result.\n *\n * ## When to Use\n *\n * Use `zip()` when:\n * - You have two independent Results and need both values together\n * - You want to combine validation results before processing\n * - You need a pair/tuple from two separate operations\n *\n * ## Why Use This Instead of `all()`\n *\n * - **Simpler types**: Returns `[A, B]` instead of array inference\n * - **Two-argument**: Cleaner API for common case of combining two Results\n * - **Compose with andThen**: Chain multiple zips for complex combinations\n *\n * ## Important\n *\n * - **Short-circuits**: Returns first error if either fails\n * - **Order matters**: If both fail, returns error from first argument\n * - **Use `all()`**: For more than 2 Results\n *\n * @param a - First Result\n * @param b - Second Result\n * @returns A Result containing a tuple `[A, B]` if both succeed, or the first error\n *\n * @example\n * ```typescript\n * // Combine two Results\n * const userResult = await fetchUser('1');\n * const postsResult = await fetchPosts('1');\n * const combined = zip(userResult, postsResult);\n * // combined: Result<[User, Post[]], UserError | PostsError>\n *\n * // Use with andThen for chaining\n * const result = andThen(\n * zip(fetchUser('1'), fetchPosts('1')),\n * ([user, posts]) => createDashboard(user, posts)\n * );\n *\n * // Validation combination\n * const validated = zip(\n * validateEmail(email),\n * validatePassword(password)\n * );\n * if (validated.ok) {\n * const [email, password] = validated.value;\n * createAccount(email, password);\n * }\n * ```\n */\nexport function zip<A, EA, CA, B, EB, CB>(\n a: Result<A, EA, CA>,\n b: Result<B, EB, CB>\n): Result<[A, B], EA | EB, CA | CB> {\n if (!a.ok) return a as Result<never, EA, CA>;\n if (!b.ok) return b as Result<never, EB, CB>;\n return ok([a.value, b.value]) as Result<[A, B], never, never>;\n}\n\n/**\n * Async version of `zip()` - combines two Results or Promises of Results into a tuple.\n *\n * ## When to Use\n *\n * Use `zipAsync()` when:\n * - You have two async operations and need both results together\n * - You want to run two fetches in parallel and combine results\n * - You need to combine Promises of Results into a single Result\n *\n * ## Why Use This Instead of `allAsync()`\n *\n * - **Simpler types**: Returns `[A, B]` instead of array inference\n * - **Two-argument**: Cleaner API for common case of combining two async Results\n * - **Parallel execution**: Both Promises start immediately\n *\n * ## Important\n *\n * - **Parallel**: Both operations run simultaneously (faster than sequential)\n * - **Short-circuits result**: Returns first argument's error if it fails, else second's\n * - **Waits for both**: Both Promises complete before returning (unlike `allAsync` fail-fast)\n * - **Rejection handling**: Promise rejections are wrapped as `PromiseRejectedError`\n * - **Use `allAsync()`**: For more than 2 Results\n *\n * @param a - First Result or Promise of Result\n * @param b - Second Result or Promise of Result\n * @returns A Promise of Result containing a tuple `[A, B]` if both succeed\n *\n * @example\n * ```typescript\n * // Parallel async operations\n * const result = await zipAsync(\n * fetchUser('1'),\n * fetchPosts('1')\n * );\n * // Both fetches run in parallel\n * // result: Result<[User, Post[]], UserError | PostsError>\n *\n * // Mix sync and async\n * const combined = await zipAsync(\n * ok({ cached: true }), // Already resolved\n * fetchFromAPI(id), // Async fetch\n * );\n *\n * // With chaining\n * const dashboard = await zipAsync(fetchUser('1'), fetchPosts('1'))\n * .then(result => andThen(result, ([user, posts]) => createDashboard(user, posts)));\n * ```\n */\nexport async function zipAsync<A, EA, CA, B, EB, CB>(\n a: Result<A, EA, CA> | Promise<Result<A, EA, CA>>,\n b: Result<B, EB, CB> | Promise<Result<B, EB, CB>>\n): AsyncResult<[A, B], EA | EB | PromiseRejectedError, CA | CB | PromiseRejectionCause> {\n // Wrap rejections into PromiseRejectedError (consistent with allAsync)\n const wrapRejection = <T, E, C>(\n p: Result<T, E, C> | Promise<Result<T, E, C>>\n ): Promise<Result<T, E | PromiseRejectedError, C | PromiseRejectionCause>> =>\n Promise.resolve(p).catch((reason) =>\n err(\n { type: \"PROMISE_REJECTED\" as const, cause: reason } as PromiseRejectedError,\n { cause: { type: \"PROMISE_REJECTION\" as const, reason } as PromiseRejectionCause }\n )\n );\n\n const [ra, rb] = await Promise.all([wrapRejection(a), wrapRejection(b)]);\n return zip(ra, rb);\n}\n","/**\n * awaitly/adapters\n *\n * Convenience adapters to wrap common non-Promise async patterns into Results.\n *\n * @example\n * ```typescript\n * import { fromCallback, fromEvent } from 'awaitly/adapters';\n *\n * // Node.js callback style\n * const data = await fromCallback<string>(\n * (cb) => fs.readFile('file.txt', 'utf8', cb)\n * );\n *\n * // One-shot event emitter\n * const response = await fromEvent<Response>(\n * request,\n * { success: 'response', error: 'error' }\n * );\n * ```\n */\n\nimport { ok, err, type AsyncResult } from \"./core\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Standard Node.js error-first callback signature.\n */\nexport type NodeCallback<T> = (error: Error | null | undefined, result: T) => void;\n\n/**\n * Event listener configuration for fromEvent.\n */\nexport type EventConfig = {\n /** Event name that signals success (value is passed to resolve) */\n success: string;\n /** Event name that signals error (value is passed to reject). Optional. */\n error?: string;\n /** Timeout in milliseconds. If exceeded, returns timeout error. Optional. */\n timeout?: number;\n};\n\n/**\n * EventEmitter-like interface (supports Node.js and DOM events).\n */\nexport type EventEmitterLike =\n | { on(event: string, listener: (...args: unknown[]) => void): unknown; off(event: string, listener: (...args: unknown[]) => void): unknown }\n | { addEventListener(event: string, listener: (...args: unknown[]) => void): unknown; removeEventListener(event: string, listener: (...args: unknown[]) => void): unknown };\n\n/**\n * Timeout error returned when fromEvent times out.\n */\nexport type EventTimeoutError = {\n type: \"EVENT_TIMEOUT\";\n event: string;\n timeoutMs: number;\n};\n\n/**\n * Type guard for EventTimeoutError.\n */\nexport function isEventTimeoutError(error: unknown): error is EventTimeoutError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as EventTimeoutError).type === \"EVENT_TIMEOUT\"\n );\n}\n\n/**\n * Error returned when the emitter doesn't have valid event subscription methods.\n */\nexport type InvalidEmitterError = {\n type: \"INVALID_EMITTER\";\n message: string;\n};\n\n/**\n * Type guard for InvalidEmitterError.\n */\nexport function isInvalidEmitterError(error: unknown): error is InvalidEmitterError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as InvalidEmitterError).type === \"INVALID_EMITTER\"\n );\n}\n\n// =============================================================================\n// fromCallback\n// =============================================================================\n\n/**\n * Convert a Node.js callback-style function to AsyncResult.\n *\n * Handles the standard Node.js error-first callback pattern:\n * `(error: Error | null, result: T) => void`\n *\n * @param executor - Function that receives the callback and calls it\n * @param options - Optional error mapping\n * @returns AsyncResult with the callback's result\n *\n * @example\n * ```typescript\n * import { fromCallback } from 'awaitly/adapters';\n * import { readFile } from 'fs';\n *\n * // Basic usage\n * const result = await fromCallback<string>(\n * (cb) => readFile('file.txt', 'utf8', cb)\n * );\n *\n * if (result.ok) {\n * console.log(result.value);\n * } else {\n * console.error(result.error); // Error\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With typed error mapping\n * type FileError = { type: 'FILE_ERROR'; path: string; cause: Error };\n *\n * const result = await fromCallback<string, FileError>(\n * (cb) => readFile('config.json', 'utf8', cb),\n * { onError: (e) => ({ type: 'FILE_ERROR', path: 'config.json', cause: e }) }\n * );\n * ```\n */\nexport function fromCallback<T, E = Error>(\n executor: (callback: NodeCallback<T>) => void,\n options?: {\n /** Map callback error to typed error */\n onError?: (error: Error) => E;\n }\n): AsyncResult<T, E> {\n return new Promise((resolve) => {\n try {\n executor((error, result) => {\n if (error) {\n const mappedError = options?.onError\n ? options.onError(error)\n : (error as unknown as E);\n resolve(err(mappedError, { cause: error }));\n } else {\n resolve(ok(result));\n }\n });\n } catch (thrown) {\n // Handle synchronous throws in executor\n const error = thrown instanceof Error ? thrown : new Error(String(thrown));\n const mappedError = options?.onError\n ? options.onError(error)\n : (error as unknown as E);\n resolve(err(mappedError, { cause: thrown }));\n }\n });\n}\n\n// =============================================================================\n// fromEvent\n// =============================================================================\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFunction = (...args: any[]) => any;\n\n/**\n * Type guard for EventEmitter-like objects with on/off methods.\n */\nfunction hasOnOff(obj: unknown): obj is { on: AnyFunction; off: AnyFunction } {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"on\" in obj &&\n \"off\" in obj &&\n typeof (obj as { on: unknown }).on === \"function\" &&\n typeof (obj as { off: unknown }).off === \"function\"\n );\n}\n\n/**\n * Type guard for EventEmitter-like objects with addEventListener/removeEventListener.\n */\nfunction hasAddRemove(obj: unknown): obj is { addEventListener: AnyFunction; removeEventListener: AnyFunction } {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"addEventListener\" in obj &&\n \"removeEventListener\" in obj &&\n typeof (obj as { addEventListener: unknown }).addEventListener === \"function\" &&\n typeof (obj as { removeEventListener: unknown }).removeEventListener === \"function\"\n );\n}\n\n/**\n * Convert a one-shot event emitter pattern to AsyncResult.\n * Automatically removes listeners after resolution.\n *\n * Supports both Node.js EventEmitter (on/off) and DOM EventTarget\n * (addEventListener/removeEventListener) interfaces.\n *\n * @param emitter - Object with event subscription methods\n * @param config - Event names and optional timeout\n * @param options - Optional error mapping\n * @returns AsyncResult with the event payload\n *\n * @example\n * ```typescript\n * import { fromEvent } from 'awaitly/adapters';\n * import { createReadStream } from 'fs';\n *\n * // Node.js stream - wait for first data chunk\n * const stream = createReadStream('data.txt');\n * const result = await fromEvent<Buffer>(stream, {\n * success: 'data',\n * error: 'error',\n * });\n *\n * if (result.ok) {\n * console.log('First chunk:', result.value);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With timeout\n * const result = await fromEvent<Response>(request, {\n * success: 'response',\n * error: 'error',\n * timeout: 5000,\n * });\n *\n * if (!result.ok && isEventTimeoutError(result.error)) {\n * console.log('Request timed out');\n * }\n * ```\n *\n * @example\n * ```typescript\n * // DOM events\n * const result = await fromEvent<Event>(button, {\n * success: 'click',\n * timeout: 10000,\n * });\n * ```\n */\nexport function fromEvent<T, E = Error | EventTimeoutError | InvalidEmitterError>(\n emitter: EventEmitterLike,\n config: EventConfig,\n options?: {\n /** Map event error to typed error */\n onError?: (error: unknown) => E;\n }\n): AsyncResult<T, E> {\n return new Promise((resolve) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let resolved = false;\n\n // Normalize emitter API\n const addListener = hasOnOff(emitter)\n ? (e: string, l: (...args: unknown[]) => void) => emitter.on(e, l)\n : hasAddRemove(emitter)\n ? (e: string, l: (...args: unknown[]) => void) => emitter.addEventListener(e, l)\n : null;\n\n const removeListener = hasOnOff(emitter)\n ? (e: string, l: (...args: unknown[]) => void) => emitter.off(e, l)\n : hasAddRemove(emitter)\n ? (e: string, l: (...args: unknown[]) => void) => emitter.removeEventListener(e, l)\n : null;\n\n if (!addListener || !removeListener) {\n const invalidError: InvalidEmitterError = {\n type: \"INVALID_EMITTER\",\n message: \"Object does not have on/off or addEventListener/removeEventListener\",\n };\n resolve(err(invalidError as E));\n return;\n }\n\n const successHandler = (...args: unknown[]) => {\n if (resolved) return;\n resolved = true;\n cleanup();\n // First argument is the event value\n resolve(ok(args[0] as T));\n };\n\n const errorHandler = (...args: unknown[]) => {\n if (resolved) return;\n resolved = true;\n cleanup();\n const error = args[0];\n const mappedError = options?.onError\n ? options.onError(error)\n : (error as E);\n resolve(err(mappedError, { cause: error }));\n };\n\n const cleanup = () => {\n if (timeoutId) clearTimeout(timeoutId);\n removeListener(config.success, successHandler);\n if (config.error) removeListener(config.error, errorHandler);\n };\n\n addListener(config.success, successHandler);\n if (config.error) addListener(config.error, errorHandler);\n\n if (config.timeout) {\n timeoutId = setTimeout(() => {\n if (resolved) return;\n resolved = true;\n cleanup();\n const timeoutError: EventTimeoutError = {\n type: \"EVENT_TIMEOUT\",\n event: config.success,\n timeoutMs: config.timeout!,\n };\n resolve(err(timeoutError as unknown as E));\n }, config.timeout);\n }\n });\n}\n\n/**\n * Type guard to check if an object is EventEmitter-like.\n */\nexport function isEventEmitterLike(obj: unknown): obj is EventEmitterLike {\n return hasOnOff(obj) || hasAddRemove(obj);\n}\n"],"mappings":"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","names":["adapters_entry_exports","__export","fromCallback","fromEvent","isEventEmitterLike","isEventTimeoutError","isInvalidEmitterError","__toCommonJS","InternalTaggedErrorBase","TaggedError","tag","options","props","errorOptions","message","_","_n","_m","_s","safeProps","hasUserCause","userCause","hasOptionsCause","instance","isError","value","isTaggedError","match","error","handlers","handler","matchPartial","otherwise","TimeoutError","TaggedError","p","RetryExhaustedError","RateLimitError","CircuitBreakerOpenError","ValidationError","NotFoundError","UnauthorizedError","NetworkError","CompensationError","UnexpectedError","parseDurationString","input","match","value","unit","defaultCatchUnexpected","cause","UnexpectedError","ok","value","err","error","options","extractErrorTag","error","tagged","trimmed","lookupErrorClassification","tag","errorMeta","extractStepMetadata","options","intent","domain","owner","tags","stateChanges","emits","calls","metadata","buildStepErrorPayload","origin","attempt","cumulativeDurationMs","classification","diagnostics","STEP_TIMEOUT_MARKER","isStepTimeoutError","getStepTimeoutMeta","err","EARLY_EXIT_SYMBOL","createEarlyExit","meta","isEarlyExit","MAPPER_EXCEPTION_SYMBOL","createMapperException","thrown","isMapperException","calculateRetryDelay","backoff","initialDelay","maxDelay","jitter","delay","jitterAmount","sleep","ms","resolve","TIMEOUT_SYMBOL","TIMEOUT_OPTION_SYMBOL","isTimeoutOptionMarker","value","executeWithTimeout","operation","options","stepInfo","externalSignal","controller","behavior","createTimeoutError","timeoutId","externalAbortHandler","timeoutPromise","_","reject","operationPromise","error","errorToThrow","meta","STEP_TIMEOUT_MARKER","DEFAULT_RETRY_CONFIG","run","fn","onError","onEvent","catchUnexpected","providedWorkflowId","workflowName","context","_workflowSignal","workflowId","effectiveCatchUnexpected","defaultCatchUnexpected","activeScopeStack","stepIdCounter","generateStepId","stepKey","emitEvent","event","eventWithContext","eventWithName","stepId","i","scope","earlyExit","createEarlyExit","isEarlyExitE","e","isEarlyExit","wrapForStep","_meta","isResultLike","normalizeParallelOperations","rawOperations","out","key","executeParallelArray","name","scopeId","startTime","scopeEnded","emitScopeEnd","idx","s","result","executeParallelNamed","operations","keys","results","resolve","settled","pendingCount","resultArray","index","reason","err","output","stepFn","id","operationOrResult","stepOptions","parsedOptions","stepMetadata","extractStepMetadata","stepName","explicitKey","stepDescription","retryConfig","timeoutConfig","hasEventListeners","overallStartTime","effectiveRetry","lastResult","attempt","attemptStartTime","durationMs","delay","calculateRetryDelay","buildStepErrorPayload","sleep","thrown","timeoutMs","ok","isStepTimeoutError","timeoutMeta","getStepTimeoutMeta","totalDurationMs","mappedError","mapperError","createMapperException","errorResult","wrappedError","opts","mapToError","mapped","onNull","duration","d","parseDurationString","ms","userSignal","state","onAbort","args","second","normalizedOperations","scopeEntry","_id","_conditionLabel","condition","thenFn","elseFn","errors","items","maxIterations","isRunForm","asyncItems","item","handler","_name","getter","handlers","resolved","mapper","concurrency","allAsync","batch","batchResult","batchIndex","primaryResult","fallbackResultFromThrow","fallbackThrown","fallbackMappedError","primaryError","fallbackResult","acquireResult","resource","useResult","useThrown","useThrewNonResult","releaseErr","maybeResult","isMapperException","originalCause","allAsync","results","ok","resolve","settled","pendingCount","values","i","index","reason","err","result","isEventTimeoutError","error","isInvalidEmitterError","fromCallback","executor","options","resolve","result","mappedError","err","ok","thrown","hasOnOff","obj","hasAddRemove","fromEvent","emitter","config","timeoutId","resolved","addListener","e","l","removeListener","successHandler","args","cleanup","errorHandler","timeoutError","isEventEmitterLike"]}
|