UNPKG

@hyrfilm/workhorse

Version:

Transactional task queue for the browser with support for OPFS, localStorage, sessionStorage, in-memory

955 lines (947 loc) 72.2 kB
type InspectionEvent = InspectedSnapshotEvent | InspectedEventEvent | InspectedActorEvent | InspectedMicrostepEvent | InspectedActionEvent; interface BaseInspectionEventProperties { rootId: string; /** * The relevant actorRef for the inspection event. * * - For snapshot events, this is the `actorRef` of the snapshot. * - For event events, this is the target `actorRef` (recipient of event). * - For actor events, this is the `actorRef` of the registered actor. */ actorRef: ActorRefLike; } interface InspectedSnapshotEvent extends BaseInspectionEventProperties { type: '@xstate.snapshot'; event: AnyEventObject; snapshot: Snapshot<unknown>; } interface InspectedMicrostepEvent extends BaseInspectionEventProperties { type: '@xstate.microstep'; event: AnyEventObject; snapshot: Snapshot<unknown>; _transitions: AnyTransitionDefinition[]; } interface InspectedActionEvent extends BaseInspectionEventProperties { type: '@xstate.action'; action: { type: string; params: unknown; }; } interface InspectedEventEvent extends BaseInspectionEventProperties { type: '@xstate.event'; sourceRef: ActorRefLike | undefined; event: AnyEventObject; } interface InspectedActorEvent extends BaseInspectionEventProperties { type: '@xstate.actor'; } interface ScheduledEvent { id: string; event: EventObject; startedAt: number; delay: number; source: AnyActorRef; target: AnyActorRef; } interface Clock { setTimeout(fn: (...args: any[]) => void, timeout: number): any; clearTimeout(id: any): void; } interface Scheduler { schedule(source: AnyActorRef, target: AnyActorRef, event: EventObject, delay: number, id: string | undefined): void; cancel(source: AnyActorRef, id: string): void; cancelAll(actorRef: AnyActorRef): void; } interface ActorSystem<T extends ActorSystemInfo> { get: <K extends keyof T['actors']>(key: K) => T['actors'][K] | undefined; inspect: (observer: Observer<InspectionEvent> | ((inspectionEvent: InspectionEvent) => void)) => Subscription; scheduler: Scheduler; getSnapshot: () => { _scheduledEvents: Record<string, ScheduledEvent>; }; start: () => void; _clock: Clock; _logger: (...args: any[]) => void; } type AnyActorSystem = ActorSystem<any>; declare class StateMachine<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TStateValue extends StateValue, TTag extends string, TInput, TOutput, TEmitted extends EventObject, TMeta extends MetaObject, TConfig extends StateSchema> implements ActorLogic<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, TEvent, TInput, AnyActorSystem, TEmitted> { /** The raw config used to create the machine. */ config: MachineConfig<TContext, TEvent, any, any, any, any, any, any, TOutput, any, // TEmitted any> & { schemas?: unknown; }; /** The machine's own version. */ version?: string; schemas: unknown; implementations: MachineImplementationsSimplified<TContext, TEvent>; root: StateNode<TContext, TEvent>; id: string; states: StateNode<TContext, TEvent>['states']; events: Array<EventDescriptor<TEvent>>; constructor( /** The raw config used to create the machine. */ config: MachineConfig<TContext, TEvent, any, any, any, any, any, any, TOutput, any, // TEmitted any> & { schemas?: unknown; }, implementations?: MachineImplementationsSimplified<TContext, TEvent>); /** * Clones this state machine with the provided implementations and merges the * `context` (if provided). * * @param implementations Options (`actions`, `guards`, `actors`, `delays`, * `context`) to recursively merge with the existing options. * @returns A new `StateMachine` instance with the provided implementations. */ provide(implementations: InternalMachineImplementations<ResolvedStateMachineTypes<TContext, DoNotInfer<TEvent>, TActor, TAction, TGuard, TDelay, TTag, TEmitted>>): StateMachine<TContext, TEvent, TChildren, TActor, TAction, TGuard, TDelay, TStateValue, TTag, TInput, TOutput, TEmitted, TMeta, TConfig>; resolveState(config: { value: StateValue; context?: TContext; historyValue?: HistoryValue<TContext, TEvent>; status?: SnapshotStatus; output?: TOutput; error?: unknown; } & (Equals<TContext, MachineContext> extends false ? { context: unknown; } : {})): MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>; /** * Determines the next snapshot given the current `snapshot` and received * `event`. Calculates a full macrostep from all microsteps. * * @param snapshot The current snapshot * @param event The received event */ transition(snapshot: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, event: TEvent, actorScope: ActorScope<typeof snapshot, TEvent, AnyActorSystem, TEmitted>): MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>; /** * Determines the next state given the current `state` and `event`. Calculates * a microstep. * * @param state The current state * @param event The received event */ microstep(snapshot: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, event: TEvent, actorScope: AnyActorScope): Array<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>>; getTransitionData(snapshot: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, event: TEvent): Array<TransitionDefinition<TContext, TEvent>>; /** * The initial state _before_ evaluating any microsteps. This "pre-initial" * state is provided to initial actions executed in the initial state. */ private getPreInitialState; /** * Returns the initial `State` instance, with reference to `self` as an * `ActorRef`. */ getInitialSnapshot(actorScope: ActorScope<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, TEvent, AnyActorSystem, TEmitted>, input?: TInput): MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>; start(snapshot: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>): void; getStateNodeById(stateId: string): StateNode<TContext, TEvent>; get definition(): StateMachineDefinition<TContext, TEvent>; toJSON(): StateMachineDefinition<TContext, TEvent>; getPersistedSnapshot(snapshot: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, options?: unknown): Snapshot<unknown>; restoreSnapshot(snapshot: Snapshot<unknown>, _actorScope: ActorScope<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, TEvent, AnyActorSystem, TEmitted>): MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>; } interface StateNodeOptions<TContext extends MachineContext, TEvent extends EventObject> { _key: string; _parent?: StateNode<TContext, TEvent>; _machine: AnyStateMachine; } declare class StateNode<TContext extends MachineContext = MachineContext, TEvent extends EventObject = EventObject> { /** The raw config used to create the machine. */ config: StateNodeConfig<TContext, TEvent, TODO, // actors TODO, // actions TODO, // guards TODO, // delays TODO, // tags TODO, // output TODO, // emitted TODO>; /** * The relative key of the state node, which represents its location in the * overall state value. */ key: string; /** The unique ID of the state node. */ id: string; /** * The type of this state node: * * - `'atomic'` - no child state nodes * - `'compound'` - nested child state nodes (XOR) * - `'parallel'` - orthogonal nested child state nodes (AND) * - `'history'` - history state node * - `'final'` - final state node */ type: 'atomic' | 'compound' | 'parallel' | 'final' | 'history'; /** The string path from the root machine node to this node. */ path: string[]; /** The child state nodes. */ states: StateNodesConfig<TContext, TEvent>; /** * The type of history on this state node. Can be: * * - `'shallow'` - recalls only top-level historical state value * - `'deep'` - recalls historical state value at all levels */ history: false | 'shallow' | 'deep'; /** The action(s) to be executed upon entering the state node. */ entry: UnknownAction[]; /** The action(s) to be executed upon exiting the state node. */ exit: UnknownAction[]; /** The parent state node. */ parent?: StateNode<TContext, TEvent>; /** The root machine node. */ machine: StateMachine<TContext, TEvent, any, // children any, // actor any, // action any, // guard any, // delay any, // state value any, // tag any, // input any, // output any, // emitted any, // meta any>; /** * The meta data associated with this state node, which will be returned in * State instances. */ meta?: any; /** * The output data sent with the "xstate.done.state._id_" event if this is a * final state node. */ output?: Mapper<MachineContext, EventObject, unknown, EventObject> | NonReducibleUnknown; /** * The order this state node appears. Corresponds to the implicit document * order. */ order: number; description?: string; tags: string[]; transitions: Map<string, TransitionDefinition<TContext, TEvent>[]>; always?: Array<TransitionDefinition<TContext, TEvent>>; constructor( /** The raw config used to create the machine. */ config: StateNodeConfig<TContext, TEvent, TODO, // actors TODO, // actions TODO, // guards TODO, // delays TODO, // tags TODO, // output TODO, // emitted TODO>, options: StateNodeOptions<TContext, TEvent>); /** The well-structured state node definition. */ get definition(): StateNodeDefinition<TContext, TEvent>; /** The logic invoked as actors by this state node. */ get invoke(): Array<InvokeDefinition<TContext, TEvent, ProvidedActor, ParameterizedObject, ParameterizedObject, string, TODO, // TEmitted TODO>>; /** The mapping of events to transitions. */ get on(): TransitionDefinitionMap<TContext, TEvent>; get after(): Array<DelayedTransitionDefinition<TContext, TEvent>>; get initial(): InitialTransitionDefinition<TContext, TEvent>; /** All the event types accepted by this state node and its descendants. */ get events(): Array<EventDescriptor<TEvent>>; /** * All the events that have transitions directly from this state node. * * Excludes any inert events. */ get ownEvents(): Array<EventDescriptor<TEvent>>; } type ToTestStateValue<TStateValue extends StateValue> = TStateValue extends string ? TStateValue : IsNever<keyof TStateValue> extends true ? never : keyof TStateValue | { [K in keyof TStateValue]?: ToTestStateValue<NonNullable<TStateValue[K]>>; }; interface MachineSnapshotBase<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TOutput, TMeta, TStateSchema extends StateSchema = StateSchema> { /** The state machine that produced this state snapshot. */ machine: StateMachine<TContext, TEvent, TChildren, ProvidedActor, ParameterizedObject, ParameterizedObject, string, TStateValue, TTag, unknown, TOutput, EventObject, // TEmitted any, // TMeta TStateSchema>; /** The tags of the active state nodes that represent the current state value. */ tags: Set<string>; /** * The current state value. * * This represents the active state nodes in the state machine. * * - For atomic state nodes, it is a string. * - For compound parent state nodes, it is an object where: * * - The key is the parent state node's key * - The value is the current state value of the active child state node(s) * * @example * * ```ts * // single-level state node * snapshot.value; // => 'yellow' * * // nested state nodes * snapshot.value; // => { red: 'wait' } * ``` */ value: TStateValue; /** The current status of this snapshot. */ status: SnapshotStatus; error: unknown; context: TContext; historyValue: Readonly<HistoryValue<TContext, TEvent>>; /** The enabled state nodes representative of the state value. */ _nodes: Array<StateNode<TContext, TEvent>>; /** An object mapping actor names to spawned/invoked actors. */ children: TChildren; /** * Whether the current state value is a subset of the given partial state * value. * * @param partialStateValue */ matches: (partialStateValue: ToTestStateValue<TStateValue>) => boolean; /** * Whether the current state nodes has a state node with the specified `tag`. * * @param tag */ hasTag: (tag: TTag) => boolean; /** * Determines whether sending the `event` will cause a non-forbidden * transition to be selected, even if the transitions have no actions nor * change the state value. * * @param event The event to test * @returns Whether the event will cause a transition */ can: (event: TEvent) => boolean; getMeta: () => Record<StateId<TStateSchema> & string, TMeta | undefined>; toJSON: () => unknown; } interface ActiveMachineSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TOutput, TMeta extends MetaObject, TConfig extends StateSchema> extends MachineSnapshotBase<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig> { status: 'active'; output: undefined; error: undefined; } interface DoneMachineSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TOutput, TMeta extends MetaObject, TConfig extends StateSchema> extends MachineSnapshotBase<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig> { status: 'done'; output: TOutput; error: undefined; } interface ErrorMachineSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TOutput, TMeta extends MetaObject, TConfig extends StateSchema> extends MachineSnapshotBase<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig> { status: 'error'; output: undefined; error: unknown; } interface StoppedMachineSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TOutput, TMeta extends MetaObject, TConfig extends StateSchema> extends MachineSnapshotBase<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig> { status: 'stopped'; output: undefined; error: undefined; } type MachineSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TOutput, TMeta extends MetaObject, TConfig extends StateSchema> = ActiveMachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig> | DoneMachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig> | ErrorMachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig> | StoppedMachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>; declare const symbolObservable: typeof Symbol.observable; /** * An Actor is a running process that can receive events, send events and change * its behavior based on the events it receives, which can cause effects outside * of the actor. When you run a state machine, it becomes an actor. */ declare class Actor<TLogic extends AnyActorLogic> implements ActorRef<SnapshotFrom<TLogic>, EventFromLogic<TLogic>, EmittedFrom<TLogic>> { logic: TLogic; /** The current internal state of the actor. */ private _snapshot; /** * The clock that is responsible for setting and clearing timeouts, such as * delayed events and transitions. */ clock: Clock; options: Readonly<ActorOptions<TLogic>>; /** The unique identifier for this actor relative to its parent. */ id: string; private mailbox; private observers; private eventListeners; private logger; _parent?: AnyActorRef; ref: ActorRef<SnapshotFrom<TLogic>, EventFromLogic<TLogic>, EmittedFrom<TLogic>>; private _actorScope; private _systemId; /** The globally unique process ID for this invocation. */ sessionId: string; /** The system to which this actor belongs. */ system: AnyActorSystem; private _doneEvent?; src: string | AnyActorLogic; /** * Creates a new actor instance for the given logic with the provided options, * if any. * * @param logic The logic to create an actor from * @param options Actor options */ constructor(logic: TLogic, options?: ActorOptions<TLogic>); private _initState; private _deferred; private update; /** * Subscribe an observer to an actor’s snapshot values. * * @remarks * The observer will receive the actor’s snapshot value when it is emitted. * The observer can be: * * - A plain function that receives the latest snapshot, or * - An observer object whose `.next(snapshot)` method receives the latest * snapshot * * @example * * ```ts * // Observer as a plain function * const subscription = actor.subscribe((snapshot) => { * console.log(snapshot); * }); * ``` * * @example * * ```ts * // Observer as an object * const subscription = actor.subscribe({ * next(snapshot) { * console.log(snapshot); * }, * error(err) { * // ... * }, * complete() { * // ... * } * }); * ``` * * The return value of `actor.subscribe(observer)` is a subscription object * that has an `.unsubscribe()` method. You can call * `subscription.unsubscribe()` to unsubscribe the observer: * * @example * * ```ts * const subscription = actor.subscribe((snapshot) => { * // ... * }); * * // Unsubscribe the observer * subscription.unsubscribe(); * ``` * * When the actor is stopped, all of its observers will automatically be * unsubscribed. * * @param observer - Either a plain function that receives the latest * snapshot, or an observer object whose `.next(snapshot)` method receives * the latest snapshot */ subscribe(observer: Observer<SnapshotFrom<TLogic>>): Subscription; subscribe(nextListener?: (snapshot: SnapshotFrom<TLogic>) => void, errorListener?: (error: any) => void, completeListener?: () => void): Subscription; on<TType extends EmittedFrom<TLogic>['type'] | '*'>(type: TType, handler: (emitted: EmittedFrom<TLogic> & (TType extends '*' ? unknown : { type: TType; })) => void): Subscription; /** Starts the Actor from the initial state */ start(): this; private _process; private _stop; /** Stops the Actor and unsubscribe all listeners. */ stop(): this; private _complete; private _reportError; private _error; private _stopProcedure; /** * Sends an event to the running Actor to trigger a transition. * * @param event The event to send */ send(event: EventFromLogic<TLogic>): void; private attachDevTools; toJSON(): { xstate$$type: number; id: string; }; /** * Obtain the internal state of the actor, which can be persisted. * * @remarks * The internal state can be persisted from any actor, not only machines. * * Note that the persisted state is not the same as the snapshot from * {@link Actor.getSnapshot}. Persisted state represents the internal state of * the actor, while snapshots represent the actor's last emitted value. * * Can be restored with {@link ActorOptions.state} * @see https://stately.ai/docs/persistence */ getPersistedSnapshot(): Snapshot<unknown>; [symbolObservable](): InteropSubscribable<SnapshotFrom<TLogic>>; /** * Read an actor’s snapshot synchronously. * * @remarks * The snapshot represent an actor's last emitted value. * * When an actor receives an event, its internal state may change. An actor * may emit a snapshot when a state transition occurs. * * Note that some actors, such as callback actors generated with * `fromCallback`, will not emit snapshots. * @see {@link Actor.subscribe} to subscribe to an actor’s snapshot values. * @see {@link Actor.getPersistedSnapshot} to persist the internal state of an actor (which is more than just a snapshot). */ getSnapshot(): SnapshotFrom<TLogic>; } type GuardPredicate<TContext extends MachineContext, TExpressionEvent extends EventObject, TParams extends ParameterizedObject['params'] | undefined, TGuard extends ParameterizedObject> = { (args: GuardArgs<TContext, TExpressionEvent>, params: TParams): boolean; _out_TGuard?: TGuard; }; interface GuardArgs<TContext extends MachineContext, TExpressionEvent extends EventObject> { context: TContext; event: TExpressionEvent; } type Guard<TContext extends MachineContext, TExpressionEvent extends EventObject, TParams extends ParameterizedObject['params'] | undefined, TGuard extends ParameterizedObject> = NoRequiredParams<TGuard> | WithDynamicParams<TContext, TExpressionEvent, TGuard> | GuardPredicate<TContext, TExpressionEvent, TParams, TGuard>; type UnknownGuard = UnknownReferencedGuard | UnknownInlineGuard; type UnknownReferencedGuard = Guard<MachineContext, EventObject, ParameterizedObject['params'], ParameterizedObject>; type UnknownInlineGuard = Guard<MachineContext, EventObject, undefined, ParameterizedObject>; type GetParameterizedParams<T extends ParameterizedObject | undefined> = T extends any ? ('params' extends keyof T ? T['params'] : undefined) : never; /** * @remarks * `T | unknown` reduces to `unknown` and that can be problematic when it comes * to contextual typing. It especially is a problem when the union has a * function member, like here: * * ```ts * declare function test( * cbOrVal: ((arg: number) => unknown) | unknown * ): void; * test((arg) => {}); // oops, implicit any * ``` * * This type can be used to avoid this problem. This union represents the same * value space as `unknown`. */ type NonReducibleUnknown = {} | null | undefined; type AnyFunction = (...args: any[]) => any; type ReturnTypeOrValue<T> = T extends AnyFunction ? ReturnType<T> : T; type IsNever<T> = [T] extends [never] ? true : false; type IsNotNever<T> = [T] extends [never] ? false : true; type Compute<A> = { [K in keyof A]: A[K]; } & unknown; type Values<T> = T[keyof T]; type Equals<A1, A2> = (<A>() => A extends A2 ? true : false) extends <A>() => A extends A1 ? true : false ? true : false; type DoNotInfer<T> = [T][T extends any ? 0 : any]; type LowInfer<T> = T & NonNullable<unknown>; type MetaObject = Record<string, any>; /** The full definition of an event, with a string `type`. */ type EventObject = { /** The type of event that is sent. */ type: string; }; interface AnyEventObject extends EventObject { [key: string]: any; } interface ParameterizedObject { type: string; params?: NonReducibleUnknown; } interface UnifiedArg<TContext extends MachineContext, TExpressionEvent extends EventObject, TEvent extends EventObject> { context: TContext; event: TExpressionEvent; self: ActorRef<MachineSnapshot<TContext, TEvent, Record<string, AnyActorRef | undefined>, // TODO: this should be replaced with `TChildren` StateValue, string, unknown, TODO, // TMeta TODO>, TEvent, AnyEventObject>; system: AnyActorSystem; } type MachineContext = Record<string, any>; interface ActionArgs<TContext extends MachineContext, TExpressionEvent extends EventObject, TEvent extends EventObject> extends UnifiedArg<TContext, TExpressionEvent, TEvent> { } type InputFrom<T> = T extends StateMachine<infer _TContext, infer _TEvent, infer _TChildren, infer _TActor, infer _TAction, infer _TGuard, infer _TDelay, infer _TStateValue, infer _TTag, infer TInput, infer _TOutput, infer _TEmitted, infer _TMeta, infer _TStateSchema> ? TInput : T extends ActorLogic<infer _TSnapshot, infer _TEvent, infer TInput, infer _TSystem, infer _TEmitted> ? TInput : never; type OutputFrom<T> = T extends ActorLogic<infer TSnapshot, infer _TEvent, infer _TInput, infer _TSystem, infer _TEmitted> ? (TSnapshot & { status: 'done'; })['output'] : T extends ActorRef<infer TSnapshot, infer _TEvent, infer _TEmitted> ? (TSnapshot & { status: 'done'; })['output'] : never; type ActionFunction<TContext extends MachineContext, TExpressionEvent extends EventObject, TEvent extends EventObject, TParams extends ParameterizedObject['params'] | undefined, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject> = { (args: ActionArgs<TContext, TExpressionEvent, TEvent>, params: TParams): void; _out_TEvent?: TEvent; _out_TActor?: TActor; _out_TAction?: TAction; _out_TGuard?: TGuard; _out_TDelay?: TDelay; _out_TEmitted?: TEmitted; }; type NoRequiredParams<T extends ParameterizedObject> = T extends any ? undefined extends T['params'] ? T['type'] : never : never; type ConditionalRequired<T, Condition extends boolean> = Condition extends true ? Required<T> : T; type WithDynamicParams<TContext extends MachineContext, TExpressionEvent extends EventObject, T extends ParameterizedObject> = T extends any ? ConditionalRequired<{ type: T['type']; params?: T['params'] | (({ context, event }: { context: TContext; event: TExpressionEvent; }) => T['params']); }, undefined extends T['params'] ? false : true> : never; type Action<TContext extends MachineContext, TExpressionEvent extends EventObject, TEvent extends EventObject, TParams extends ParameterizedObject['params'] | undefined, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject> = NoRequiredParams<TAction> | WithDynamicParams<TContext, TExpressionEvent, TAction> | ActionFunction<TContext, TExpressionEvent, TEvent, TParams, TActor, TAction, TGuard, TDelay, TEmitted>; type UnknownAction = Action<MachineContext, EventObject, EventObject, ParameterizedObject['params'] | undefined, ProvidedActor, ParameterizedObject, ParameterizedObject, string, EventObject>; type Actions<TContext extends MachineContext, TExpressionEvent extends EventObject, TEvent extends EventObject, TParams extends ParameterizedObject['params'] | undefined, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject> = SingleOrArray<Action<TContext, TExpressionEvent, TEvent, TParams, TActor, TAction, TGuard, TDelay, TEmitted>>; interface StateValueMap { [key: string]: StateValue | undefined; } /** * The string or object representing the state value relative to the parent * state node. * * @remarks * - For a child atomic state node, this is a string, e.g., `"pending"`. * - For complex state nodes, this is an object, e.g., `{ success: * "someChildState" }`. */ type StateValue = string | StateValueMap; type TransitionTarget = SingleOrArray<string>; interface TransitionConfig<TContext extends MachineContext, TExpressionEvent extends EventObject, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject = EventObject, TMeta extends MetaObject = MetaObject> { guard?: Guard<TContext, TExpressionEvent, undefined, TGuard>; actions?: Actions<TContext, TExpressionEvent, TEvent, undefined, TActor, TAction, TGuard, TDelay, TEmitted>; reenter?: boolean; target?: TransitionTarget | undefined; meta?: TMeta; description?: string; } interface InitialTransitionConfig<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string> extends TransitionConfig<TContext, TEvent, TEvent, TActor, TAction, TGuard, TDelay, TODO, // TEmitted TODO> { target: string; } interface InvokeDefinition<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject, TMeta extends MetaObject> { id: string; systemId: string | undefined; /** The source of the actor logic to be invoked */ src: AnyActorLogic | string; input?: Mapper<TContext, TEvent, NonReducibleUnknown, TEvent> | NonReducibleUnknown; /** * The transition to take upon the invoked child machine reaching its final * top-level state. */ onDone?: string | SingleOrArray<TransitionConfig<TContext, DoneActorEvent<unknown>, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; /** * The transition to take upon the invoked child machine sending an error * event. */ onError?: string | SingleOrArray<TransitionConfig<TContext, ErrorActorEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; onSnapshot?: string | SingleOrArray<TransitionConfig<TContext, SnapshotEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; toJSON: () => Omit<InvokeDefinition<TContext, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>, 'onDone' | 'onError' | 'toJSON'>; } type Delay<TDelay extends string> = TDelay | number; type DelayedTransitions<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string> = { [K in Delay<TDelay>]?: string | SingleOrArray<TransitionConfig<TContext, TEvent, TEvent, TActor, TAction, TGuard, TDelay, TODO, // TEmitted TODO>>; }; type SingleOrArray<T> = readonly T[] | T; type StateNodesConfig<TContext extends MachineContext, TEvent extends EventObject> = { [K in string]: StateNode<TContext, TEvent>; }; type StatesConfig<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TTag extends string, TOutput, TEmitted extends EventObject, TMeta extends MetaObject> = { [K in string]: StateNodeConfig<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag, TOutput, TEmitted, TMeta>; }; type StatesDefinition<TContext extends MachineContext, TEvent extends EventObject> = { [K in string]: StateNodeDefinition<TContext, TEvent>; }; type TransitionConfigTarget = string | undefined; type TransitionConfigOrTarget<TContext extends MachineContext, TExpressionEvent extends EventObject, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject, TMeta extends MetaObject> = SingleOrArray<TransitionConfigTarget | TransitionConfig<TContext, TExpressionEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; type TransitionsConfig<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject, TMeta extends MetaObject> = { [K in EventDescriptor<TEvent>]?: TransitionConfigOrTarget<TContext, ExtractEvent<TEvent, K>, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>; }; type PartialEventDescriptor<TEventType extends string> = TEventType extends `${infer TLeading}.${infer TTail}` ? `${TLeading}.*` | `${TLeading}.${PartialEventDescriptor<TTail>}` : never; type EventDescriptor<TEvent extends EventObject> = TEvent['type'] | PartialEventDescriptor<TEvent['type']> | '*'; type NormalizeDescriptor<TDescriptor extends string> = TDescriptor extends '*' ? string : TDescriptor extends `${infer TLeading}.*` ? `${TLeading}.${string}` : TDescriptor; type IsLiteralString<T extends string> = string extends T ? false : true; type DistributeActors<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject, TMeta extends MetaObject, TSpecificActor extends ProvidedActor> = TSpecificActor extends { src: infer TSrc; } ? Compute<{ systemId?: string; /** The source of the machine to be invoked, or the machine itself. */ src: TSrc; /** * The unique identifier for the invoked machine. If not specified, * this will be the machine's own `id`, or the URL (from `src`). */ id?: TSpecificActor['id']; input?: Mapper<TContext, TEvent, InputFrom<TSpecificActor['logic']>, TEvent> | InputFrom<TSpecificActor['logic']>; /** * The transition to take upon the invoked child machine reaching * its final top-level state. */ onDone?: string | SingleOrArray<TransitionConfigOrTarget<TContext, DoneActorEvent<OutputFrom<TSpecificActor['logic']>>, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; /** * The transition to take upon the invoked child machine sending an * error event. */ onError?: string | SingleOrArray<TransitionConfigOrTarget<TContext, ErrorActorEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; onSnapshot?: string | SingleOrArray<TransitionConfigOrTarget<TContext, SnapshotEvent<SnapshotFrom<TSpecificActor['logic']>>, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; } & { [K in RequiredActorOptions<TSpecificActor>]: unknown; }> | { id?: never; systemId?: string; src: AnyActorLogic; input?: Mapper<TContext, TEvent, NonReducibleUnknown, TEvent> | NonReducibleUnknown; onDone?: string | SingleOrArray<TransitionConfigOrTarget<TContext, DoneActorEvent<unknown>, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; onError?: string | SingleOrArray<TransitionConfigOrTarget<TContext, ErrorActorEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; onSnapshot?: string | SingleOrArray<TransitionConfigOrTarget<TContext, SnapshotEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; } : never; type InvokeConfig<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TEmitted extends EventObject, TMeta extends MetaObject> = IsLiteralString<TActor['src']> extends true ? DistributeActors<TContext, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta, TActor> : { /** * The unique identifier for the invoked machine. If not specified, this * will be the machine's own `id`, or the URL (from `src`). */ id?: string; systemId?: string; /** The source of the machine to be invoked, or the machine itself. */ src: AnyActorLogic | string; input?: Mapper<TContext, TEvent, NonReducibleUnknown, TEvent> | NonReducibleUnknown; /** * The transition to take upon the invoked child machine reaching its * final top-level state. */ onDone?: string | SingleOrArray<TransitionConfigOrTarget<TContext, DoneActorEvent<any>, // TODO: consider replacing with `unknown` TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; /** * The transition to take upon the invoked child machine sending an * error event. */ onError?: string | SingleOrArray<TransitionConfigOrTarget<TContext, ErrorActorEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; onSnapshot?: string | SingleOrArray<TransitionConfigOrTarget<TContext, SnapshotEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; }; interface StateNodeConfig<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TTag extends string, _TOutput, TEmitted extends EventObject, TMeta extends MetaObject> { /** The initial state transition. */ initial?: InitialTransitionConfig<TContext, TEvent, TActor, TAction, TGuard, TDelay> | string | undefined; /** * The type of this state node: * * - `'atomic'` - no child state nodes * - `'compound'` - nested child state nodes (XOR) * - `'parallel'` - orthogonal nested child state nodes (AND) * - `'history'` - history state node * - `'final'` - final state node */ type?: 'atomic' | 'compound' | 'parallel' | 'final' | 'history'; /** * Indicates whether the state node is a history state node, and what type of * history: shallow, deep, true (shallow), false (none), undefined (none) */ history?: 'shallow' | 'deep' | boolean | undefined; /** * The mapping of state node keys to their state node configurations * (recursive). */ states?: StatesConfig<TContext, TEvent, TActor, TAction, TGuard, TDelay, TTag, NonReducibleUnknown, TEmitted, TMeta> | undefined; /** * The services to invoke upon entering this state node. These services will * be stopped upon exiting this state node. */ invoke?: SingleOrArray<InvokeConfig<TContext, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>>; /** The mapping of event types to their potential transition(s). */ on?: TransitionsConfig<TContext, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>; /** The action(s) to be executed upon entering the state node. */ entry?: Actions<TContext, TEvent, TEvent, undefined, TActor, TAction, TGuard, TDelay, TEmitted>; /** The action(s) to be executed upon exiting the state node. */ exit?: Actions<TContext, TEvent, TEvent, undefined, TActor, TAction, TGuard, TDelay, TEmitted>; /** * The potential transition(s) to be taken upon reaching a final child state * node. * * This is equivalent to defining a `[done(id)]` transition on this state * node's `on` property. */ onDone?: string | SingleOrArray<TransitionConfig<TContext, DoneStateEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>> | undefined; /** * The mapping (or array) of delays (in milliseconds) to their potential * transition(s). The delayed transitions are taken after the specified delay * in an interpreter. */ after?: DelayedTransitions<TContext, TEvent, TActor, TAction, TGuard, TDelay>; /** * An eventless transition that is always taken when this state node is * active. */ always?: TransitionConfigOrTarget<TContext, TEvent, TEvent, TActor, TAction, TGuard, TDelay, TEmitted, TMeta>; parent?: StateNode<TContext, TEvent>; /** * The meta data associated with this state node, which will be returned in * State instances. */ meta?: TMeta; /** * The output data sent with the "xstate.done.state._id_" event if this is a * final state node. * * The output data will be evaluated with the current `context` and placed on * the `.data` property of the event. */ output?: Mapper<TContext, TEvent, unknown, TEvent> | NonReducibleUnknown; /** * The unique ID of the state node, which can be referenced as a transition * target via the `#id` syntax. */ id?: string | undefined; /** * The order this state node appears. Corresponds to the implicit document * order. */ order?: number; /** * The tags for this state node, which are accumulated into the `state.tags` * property. */ tags?: SingleOrArray<TTag>; /** A text description of the state node */ description?: string; /** A default target for a history state */ target?: string | undefined; } interface StateNodeDefinition<TContext extends MachineContext, TEvent extends EventObject> { id: string; version?: string | undefined; key: string; type: 'atomic' | 'compound' | 'parallel' | 'final' | 'history'; initial: InitialTransitionDefinition<TContext, TEvent> | undefined; history: boolean | 'shallow' | 'deep' | undefined; states: StatesDefinition<TContext, TEvent>; on: TransitionDefinitionMap<TContext, TEvent>; transitions: Array<TransitionDefinition<TContext, TEvent>>; entry: UnknownAction[]; exit: UnknownAction[]; meta: any; order: number; output?: StateNodeConfig<TContext, TEvent, ProvidedActor, ParameterizedObject, ParameterizedObject, string, string, unknown, EventObject, // TEmitted any>['output']; invoke: Array<InvokeDefinition<TContext, TEvent, TODO, TODO, TODO, TODO, TODO, // TEmitted TODO>>; description?: string; tags: string[]; } interface StateMachineDefinition<TContext extends MachineContext, TEvent extends EventObject> extends StateNodeDefinition<TContext, TEvent> { } type AnyStateMachine = StateMachine<any, // context any, // event any, // children any, // actor any, // action any, // guard any, // delay any, // state value any, // tag any, // input any, // output any, // emitted any, // TMeta any>; type ActionFunctionMap<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor, TAction extends ParameterizedObject = ParameterizedObject, TGuard extends ParameterizedObject = ParameterizedObject, TDelay extends string = string, TEmitted extends EventObject = EventObject> = { [K in TAction['type']]?: ActionFunction<TContext, TEvent, TEvent, GetParameterizedParams<TAction extends { type: K; } ? TAction : never>, TActor, TAction, TGuard, TDelay, TEmitted>; }; type GuardMap<TContext extends MachineContext, TEvent extends EventObject, TGuard extends ParameterizedObject> = { [K in TGuard['type']]?: GuardPredicate<TContext, TEvent, GetParameterizedParams<TGuard extends { type: K; } ? TGuard : never>, TGuard>; }; type DelayFunctionMap<TContext extends MachineContext, TEvent extends EventObject, TAction extends ParameterizedObject> = Record<string, DelayConfig<TContext, TEvent, TAction['params'], TEvent>>; type DelayConfig<TContext extends MachineContext, TExpressionEvent extends EventObject, TParams extends ParameterizedObject['params'] | undefined, TEvent extends EventObject> = number | DelayExpr<TContext, TExpressionEvent, TParams, TEvent>; /** @ignore */ interface MachineImplementationsSimplified<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor = ProvidedActor, TAction extends ParameterizedObject = ParameterizedObject, TGuard extends ParameterizedObject = ParameterizedObject> { guards: GuardMap<TContext, TEvent, TGuard>; actions: ActionFunctionMap<TContext, TEvent, TActor, TAction>; actors: Record<string, AnyActorLogic | { src: AnyActorLogic; input: Mapper<TContext, TEvent, unknown, TEvent> | NonReducibleUnknown; }>; delays: DelayFunctionMap<TContext, TEvent, TAction>; } type MachineImplementationsActions<TTypes extends StateMachineTypes> = { [K in TTypes['actions']['type']]?: ActionFunction<TTypes['context'], TTypes['events'], TTypes['events'], GetConcreteByKey<TTypes['actions'], 'type', K>['params'], TTypes['actors'], TTypes['actions'], TTypes['guards'], TTypes['delays'], TTypes['emitted']>; }; type MachineImplementationsActors<TTypes extends StateMachineTypes> = { [K in TTypes['actors']['src']]?: GetConcreteByKey<TTypes['actors'], 'src', K>['logic']; }; type MachineImplementationsDelays<TTypes extends StateMachineTypes> = { [K in TTypes['delays']]?: DelayConfig<TTypes['context'], TTypes['events'], undefined, TTypes['events']>; }; type MachineImplementationsGuards<TTypes extends StateMachineTypes> = { [K in TTypes['guards']['type']]?: Guard<TTypes['context'], TTypes['events'], GetConcreteByKey<TTypes['guards'], 'type', K>['params'], TTypes['guards']>; }; type InternalMachineImplementations<TTypes extends StateMachineTypes> = { actions?: MachineImplementationsActions<TTypes>; actors?: MachineImplementationsActors<TTypes>; delays?: MachineImplementationsDelays<TTypes>; guards?: MachineImplementationsGuards<TTypes>; }; type InitialContext<TContext extends MachineContext, TActor extends ProvidedActor, TInput, TEvent extends EventObject> = TContext | ContextFactory<TContext, TActor, TInput, TEvent>; type ContextFactory<TContext extends MachineContext, TActor extends ProvidedActor, TInput, TEvent extends EventObject = EventObject> = ({ spawn, input, self }: { spawn: Spawner<TActor>; input: TInput; self: ActorRef<MachineSnapshot<TContext, TEvent, Record<string, AnyActorRef | undefined>, // TODO: this should be replaced with `TChildren` StateValue, string, unknown, TODO, // TMeta TODO>, TEvent, AnyEventObject>; }) => TContext; type MachineConfig<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor = ProvidedActor, TAction extends ParameterizedObject = ParameterizedObject, TGuard extends ParameterizedObject = ParameterizedObject, TDelay extends string = string, TTag extends string = string, TInput = any, TOutput = unknown, TEmitted extends EventObject = EventObject, TMeta extends MetaObject = MetaObject> = (Omit<StateNodeConfig<DoNotInfer<TContext>, DoNotInfer<TEvent>, DoNotInfer<TActor>, DoNotInfer<TAction>, DoNotInfer<TGuard>, DoNotInfer<TDelay>, DoNotInfer<TTag>, DoNotInfer<TOutput>, DoNotInfer<TEmitted>, DoNotInfer<TMeta>>, 'output'> & { /** The initial context (extended state) */ /** The machine's own version. */ version?: string; output?: Mapper<TContext, DoneStateEvent, TOutput, TEvent> | TOutput; }) & (MachineContext extends TContext ? { context?: InitialContext<LowInfer<TContext>, TActor, TInput, TEvent>; } : { context: InitialContext<LowInfer<TContext>, TActor, TInput, TEvent>; }); interface ProvidedActor { src: string; logic: UnknownActorLogic; id?: string | undefined; } type HistoryValue<TContext extends MachineContext, TEvent extends EventObject> = Record<string, Array<StateNode<TContext, TEvent>>>; interface DoneActorEvent<TOutput = unknown, TId extends string = string> extends EventObject { type: `xstate.done.actor.${TId}`; output: TOutput; actorId: TId; } interface ErrorActorEvent<TErrorData = unknown, TId extends string = string> extends EventObject { type: `xstate.error.actor.${TId}`; error: TErrorData; actorId: TId; } interface SnapshotEvent<TSnapshot extends Snapshot<unknown> = Snapshot<unknown>> extends EventObject { type: `xstate.snapshot.${string}`; snapshot: TSnapshot; } interface DoneStateEvent<TOutput = unknown> extends EventObject { type: `xstate.done.state.${string}`; output: TOutput; } type DelayExpr<TContext extends MachineContext, TExpressionEvent extends EventObject, TParams extends ParameterizedObject['params'] | undefined, TEvent extends EventObject> = (args: ActionArgs<TContext, TExpressionEvent, TEvent>, params: TParams) => number; type Mapper<TContext extends MachineContext, TExpressionEvent extends EventObject, TResult, TEvent extends EventObject> = (args: { context: TContext; event: TExpressionEvent; self: ActorRef<MachineSnapshot<TContext, TEvent, Record<string, AnyActorRef>, // TODO: this should be replaced with `TChildren` StateValue, string, unknown, TODO, // TMeta TODO>, TEvent, AnyEventObject>; }) => TResult; interface TransitionDefinition<TContext extends MachineContext, TEvent extends EventObject> extends Omit<TransitionConfig<TContext, TEvent, TEvent, TODO, TODO, TODO, TODO, TODO, // TEmitted TODO>, 'target' | 'guard'> { target: ReadonlyArray<StateNode<TContext, TEvent>> | undefined; source: StateNode<TContext, TEvent>; actions: readonly UnknownAction[]; reenter: boolean; guard?: UnknownGuard; eventType: EventDescriptor<TEvent>; toJSON: () => { target: string[] | undefined; source: string; actions: readonly UnknownAction[]; guard?: UnknownGuard; eventType: EventDescriptor<TEvent>; meta?: Record<string, any>; }; } type AnyTransitionDefinition = TransitionDefinition<any, any>; interface InitialTransitionDefinition<TContext extends MachineContext, TEvent extends EventObject> extends TransitionDefinition<TContext, TEvent> { tar