/** * Runtime context passed to each saga step's run and compensate functions. */ export interface SagaContext { /** Name of the saga currently executing. */ sagaName: string; /** * Accumulated results from prior steps, keyed by step name. * Later steps may read outputs produced by earlier steps. */ results: Record; } /** * Run function for a step. Receives the saga input and context; * returns the step's output (which is stored in `ctx.results`). */ export type StepRunFn = (input: TInput, ctx: SagaContext) => TOutput | Promise; /** * Compensation function for a step. Invoked in reverse order on * saga failure. Receives the step's own output (what `run` returned). */ export type StepCompensateFn = (output: TOutput, ctx: SagaContext) => void | Promise; /** * Internal step definition accumulated by the {@link sagaStep} builder. */ export interface SagaStepDefinition { name: string; runFn?: StepRunFn; compensateFn?: StepCompensateFn; } /** * Fluent builder for a saga step. Chain `.run()` and optionally `.compensate()`. */ export interface SagaStepBuilder { run(fn: StepRunFn): SagaStepBuilder; /** Sets the step's compensation (rollback) function. */ compensate(fn: StepCompensateFn): SagaStepBuilder; /** Internal definition. Do not mutate. */ readonly definition: SagaStepDefinition; } /** * Create a step builder. Name must be unique within a saga. * * ```ts * sagaStep("reserve-inventory") * .run(async (input, ctx) => { ... }) * .compensate(async (output, ctx) => { ... }) * ``` */ export declare function sagaStep(name: string): SagaStepBuilder; /** * Options passed to {@link SagaDefinition.run}. */ export interface SagaRunOptions { /** Initial input passed to every step's run function. */ input?: unknown; /** * Pre-seeded `ctx.results` entries — used by resume runs to expose * prior step outputs (from a parent run) without re-executing the * step. Steps whose name appears in `seedResults` are skipped at * the executor level: their entry is copied into ctx.results and * `runFn` is not invoked. Compensation for skipped steps is also * suppressed (the parent run's output remains canonical). * * Pairs with {@link skipUntil} — typically you set both to the * same set so callers don't need to coordinate. When `skipUntil` * is set, every step before that name MUST appear in `seedResults` * so dependent steps see the values they expect. */ seedResults?: Record; /** * Resume sentinel — when set, the executor skips steps until it * reaches this name (then runs normally from there onward). Steps * before the sentinel are still added to ctx.results from * {@link seedResults}. Throws if the named step doesn't exist in * the saga. */ skipUntil?: string; } /** * Result of a successful saga execution. */ export interface SagaResult { /** Step outputs keyed by step name. */ results: Record; } /** * In-process domain saga returned by {@link createSaga}. */ export interface SagaDefinition { /** Saga name. */ readonly name: string; /** Ordered list of step builders. */ readonly steps: ReadonlyArray; /** Execute the saga. Throws on failure after running compensations. */ run(options?: SagaRunOptions): Promise; } /** * Thrown when a saga is misconfigured, for example when a run function is * missing or step names are duplicated. */ export declare class SagaError extends Error { constructor(message: string); } /** * Create an in-process saga from a sequence of compensating steps. * * Semantics: * - Steps run sequentially in array order. * - Each step's output is stored in `ctx.results[stepName]`. * - If any step's run function throws, previously-completed steps' * compensation functions run in reverse order, then the error re-throws. * - Compensation errors are caught and logged; they do not mask the * original failure. * This is not a durable job runner: execution lives entirely within one * process. Use a job when work must survive process failure or run later. */ export declare function createSaga(name: string, steps: ReadonlyArray): SagaDefinition;