import { BUILTIN } from "./brand.js"; import type { MachineContext, NonReducibleUnknown, SingleOrArray } from "./common.js"; import type { EventObject } from "./events.js"; /** The argument object passed to every action, guard, delay and output function. */ export interface ActionArgs { context: TContext; event: TExpressionEvent; } /** * A custom action: inline in the config (`TParams` = `undefined`) or referenced * by name through `implementations.actions` (`TParams` is whatever the * `{ type, params }` reference resolved to). */ export type ActionFunction = (args: ActionArgs, params: TParams) => void; /** * Call signature carried by every builtin action / guard object. Builtins are * declarative: calling one throws. The signature exists for type inference * only, in two ways (both borrowed from XState): * * - TypeScript defers inference of a nested generic call (`assign(...)` * inside `createMachine({...})`) only when the callee returns a function * type; with a plain-object return `TContext` / `TEvent` would be fixed to * their defaults before the outer call is inferred. * - An inline arrow next to a builtin in a union slot is contextually typed * only when every callable member of the union has an identical parameter * list, so `TParams` must match the slot (`undefined` in configs, `never` * in implementation tables) — it is inferred from the slot, never written. */ export interface BuiltinCallable { (args: ActionArgs, params: TParams): never; } /** Static params or a function computing them from `{ context, event }`. */ export type DynamicParams = TParams | ((args: ActionArgs) => TParams); /** `{ type: "name", params?: ... }` reference to an action of the implementation table. */ export interface ActionObject { type: string; params?: DynamicParams; } export type Assigner = (args: ActionArgs, params: TParams) => Partial; export type PropertyAssigner = { [K in keyof TContext]?: TContext[K] | ((args: ActionArgs, params: TParams) => TContext[K]); }; /** Produced by `assign()`. Applied by the interpreter core (shallow merge, XState semantics). */ export interface AssignAction extends BuiltinCallable { readonly [BUILTIN]: "assign"; readonly type: "xstate.assign"; readonly assignment: Assigner | PropertyAssigner; } export type SendExpr = (args: ActionArgs, params: TParams) => TSentEvent; export type DelayExpr = (args: ActionArgs, params: TParams) => number; export interface RaiseActionOptions { /** Identifier for `cancel(id)`. Defaults to an internal unique id. */ id?: string; /** Milliseconds, a named delay from `implementations.delays`, or a function computing milliseconds. */ delay?: number | string | DelayExpr; } /** * Produced by `raise()`. Without `delay` the event goes to the internal queue * of the running macrostep; with `delay` it is scheduled through the executor. */ export interface RaiseAction extends BuiltinCallable { readonly [BUILTIN]: "raise"; readonly type: "xstate.raise"; readonly event: TEvent | SendExpr; readonly id: string | undefined; readonly delay: number | string | DelayExpr | undefined; } /** Produced by `cancel()`. Drops a pending delayed `raise` / `after` timer by id. */ export interface CancelAction extends BuiltinCallable { readonly [BUILTIN]: "cancel"; readonly type: "xstate.cancel"; readonly sendId: string | ((args: ActionArgs, params: TParams) => string); } export type LogExpr = (args: ActionArgs, params: TParams) => unknown; /** Produced by `log()`. Delegated to the executor's `log` (default `console.log`). */ export interface LogAction extends BuiltinCallable { readonly [BUILTIN]: "log"; readonly type: "xstate.log"; readonly value: NonReducibleUnknown | LogExpr; readonly label: string | undefined; } /** * Recipe of `mutate()`: `context` arrives as an Immer draft, the return * value is ignored. Declared with method syntax so that the arguments are * bivariant: an implementation may type `event` narrower than the machine's * event union (generated code narrows it to the events whose transitions * reference the action; the config, not TypeScript, guarantees the fit). */ export type MutateRecipe = { bivarianceHack(args: ActionArgs, params: TParams): void; }["bivarianceHack"]; /** * Produced by `mutate()`. Applied by the interpreter core: the next context is * `produce(context, recipe)` — structurally shared with the previous one, * which is never mutated. Not an XState builtin (`type` says so). */ export interface MutateAction extends BuiltinCallable { readonly [BUILTIN]: "mutate"; readonly type: "rx-toolkit.mutate"; readonly recipe: MutateRecipe; } export type BuiltinAction = AssignAction | MutateAction | RaiseAction | CancelAction | LogAction; /** * Everything accepted in `entry`, `exit` and transition `actions`: * a name, a `{ type, params }` reference, an inline function or a builtin. */ export type Action = string | ActionObject | ActionFunction | BuiltinAction; export type Actions = SingleOrArray>;