/** * @file Generator-based state machine composition utilities. * @description * This module provides a generator-based approach to composing state machine transitions. * Instead of chaining method calls or using composition functions, you can write * imperative-style code using generators that feels like sequential, synchronous code * while maintaining the immutability and type safety of the state machine model. * * This pattern is particularly useful for: * - Multi-step workflows where each step depends on the previous * - Complex transition logic that would be unwieldy with chaining * - When you want imperative control flow (if/else, loops) with immutable state * - Testing scenarios where you want to control the flow step-by-step * * @example * ```typescript * const result = run(function* (machine) { * // Each yield passes control back and receives the next state * let m = yield* step(machine.increment()); * m = yield* step(m.add(5)); * if (m.context.count > 10) { * m = yield* step(m.reset()); * } * return m.context.count; * }, initialMachine); * ``` */ /** * Runs a generator-based state machine flow to completion. * * This function executes a generator that yields machine states and returns a final value. * Each yield passes the current machine state back to the generator, allowing you to * write imperative-style code while maintaining immutability. * * **How it works:** * 1. The generator function receives the initial machine * 2. Each `yield` expression produces a new machine state * 3. That state is sent back into the generator via `next()` * 4. The generator can use the received state for the next operation * 5. When the generator returns, that value is returned from `run()` * * **Key insight:** The generator doesn't mutate state—it yields new immutable states * at each step, creating a clear audit trail of state transitions. * * @template C - The context object type for the machine. * @template T - The return type of the generator (can be any type). * * @param flow - A generator function that receives a machine and yields machines, * eventually returning a value of type T. * @param initial - The initial machine state to start the flow. * * @returns The final value returned by the generator. * * @example Basic usage with counter * ```typescript * const counter = createMachine({ count: 0 }, { * increment: function() { * return createMachine({ count: this.context.count + 1 }, this); * }, * add: function(n: number) { * return createMachine({ count: this.context.count + n }, this); * } * }); * * const finalCount = run(function* (m) { * m = yield* step(m.increment()); // count: 1 * m = yield* step(m.add(5)); // count: 6 * m = yield* step(m.increment()); // count: 7 * return m.context.count; * }, counter); * * console.log(finalCount); // 7 * ``` * * @example Conditional logic * ```typescript * const result = run(function* (m) { * m = yield* step(m.increment()); * * if (m.context.count > 5) { * m = yield* step(m.reset()); * } else { * m = yield* step(m.add(10)); * } * * return m; * }, counter); * ``` * * @example Loops and accumulation * ```typescript * const sum = run(function* (m) { * let total = 0; * * for (let i = 0; i < 5; i++) { * m = yield* step(m.increment()); * total += m.context.count; * } * * return total; * }, counter); * ``` * * @example Error handling * ```typescript * const result = run(function* (m) { * try { * m = yield* step(m.riskyOperation()); * m = yield* step(m.processResult()); * } catch (error) { * m = yield* step(m.handleError(error)); * } * return m; * }, machine); * ``` */ export declare function run = { context: C; }, T = any>(flow: (m: M) => Generator, initial: M): T; /** * A helper function to yield a machine state and receive the next state back. * * This function creates a mini-generator that yields the provided machine and * returns whatever value the outer runner sends back. It's designed to be used * with `yield*` (yield delegation) inside your main generator. * * **Why use this helper?** * - Makes the intent clear: "step to this state" * - Provides a consistent API for state transitions * - Enables type inference for the received state * - Works seamlessly with the `run()` function * * **What `yield*` does:** * `yield*` delegates to another generator. When you write `yield* step(m)`, * control passes to the `step` generator, which yields `m`, then returns the * value sent back by the runner. * * @template C - The context object type for the machine. * * @param m - The machine state to yield. * * @returns A generator that yields the machine and returns the received state. * * @example Basic stepping * ```typescript * run(function* (machine) { * // Yield this state and receive the next one * const next = yield* step(machine.increment()); * console.log(next.context.count); * return next; * }, counter); * ``` * * @example Without step (more verbose) * ```typescript * run(function* (machine) { * // This is what step() does internally * const next = yield machine.increment(); * return next; * }, counter); * ``` * * @example Chaining with step * ```typescript * run(function* (m) { * m = yield* step(m.action1()); * m = yield* step(m.action2()); * m = yield* step(m.action3()); * return m; * }, machine); * ``` */ export declare function step = { context: C; }>(m: M): Generator; /** * Alternative to `step` that doesn't require `yield*`. * This is semantically identical but uses direct yielding. * * Use this if you prefer the simpler syntax without delegation. * * @template C - The context object type. * @param m - The machine to yield. * @returns The same machine (passed through). * * @example * ```typescript * run(function* (m) { * m = yield m.increment(); // No yield* needed * m = yield m.add(5); * return m; * }, counter); * ``` */ export declare function yieldMachine = { context: C; }>(m: M): M; /** * Runs multiple generator flows in sequence, passing the result of each to the next. * * This is useful for composing multiple generator-based workflows into a pipeline. * * @template C - The context object type. * @param initial - The initial machine state. * @param flows - An array of generator functions to run in sequence. * @returns The final machine state after all flows complete. * * @example * ```typescript * const flow1 = function* (m: Machine<{ count: number }>) { * m = yield* step(m.increment()); * return m; * }; * * const flow2 = function* (m: Machine<{ count: number }>) { * m = yield* step(m.add(5)); * return m; * }; * * const result = runSequence(counter, [flow1, flow2]); * console.log(result.context.count); // 6 * ``` */ export declare function runSequence = { context: C; }>(initial: M, flows: Array<(m: M) => Generator>): M; /** * Creates a reusable generator flow that can be composed into other flows. * * This allows you to define common state machine patterns as reusable building blocks. * * @template C - The context object type. * @param flow - A generator function representing a reusable flow. * @returns A function that can be used with `yield*` in other generators. * * @example * ```typescript * // Define a reusable flow * const incrementThrice = createFlow(function* (m: Machine<{ count: number }>) { * m = yield* step(m.increment()); * m = yield* step(m.increment()); * m = yield* step(m.increment()); * return m; * }); * * // Use it in another flow * const result = run(function* (m) { * m = yield* incrementThrice(m); * m = yield* step(m.add(10)); * return m; * }, counter); * ``` */ export declare function createFlow = { context: C; }>(flow: (m: M) => Generator): (m: M) => Generator; /** * Runs a generator flow with debugging output at each step. * * This is useful for understanding the state transitions in your flow. * * @template C - The context object type. * @template T - The return type. * @param flow - The generator function to run. * @param initial - The initial machine state. * @param logger - Optional custom logger function. * @returns The final value from the generator. * * @example * ```typescript * const result = runWithDebug(function* (m) { * m = yield* step(m.increment()); * m = yield* step(m.add(5)); * return m.context.count; * }, counter); * * // Output: * // Step 0: { count: 0 } * // Step 1: { count: 1 } * // Step 2: { count: 6 } * // Final: 6 * ``` */ export declare function runWithDebug = { context: C; }, T = any>(flow: (m: M) => Generator, initial: M, logger?: (step: number, machine: M) => void): T; /** * Async version of `run` for async state machines. * * This allows you to use async/await inside your generator flows while maintaining * the same compositional benefits. * * @template C - The context object type. * @template T - The return type. * @param flow - An async generator function. * @param initial - The initial machine state. * @returns A promise that resolves to the final value. * * @example * ```typescript * const result = await runAsync(async function* (m) { * m = yield* stepAsync(await m.fetchData()); * m = yield* stepAsync(await m.processData()); * return m.context; * }, asyncMachine); * ``` */ export declare function runAsync = { context: C; }, T = any>(flow: (m: M) => AsyncGenerator, initial: M): Promise; /** * Async version of `step` for async generators. * * @template C - The context object type. * @param m - The machine to yield. * @returns An async generator. * * @example * ```typescript * await runAsync(async function* (m) { * m = yield* stepAsync(await m.asyncOperation()); * return m; * }, machine); * ``` */ export declare function stepAsync = { context: C; }>(m: M): AsyncGenerator; //# sourceMappingURL=generators.d.ts.map