import { EventObject, StateValue, StateNode, TransitionDefinition, Snapshot, MachineContext, ActorLogic, MachineSnapshot, ParameterizedObject, StateNodeConfig, TODO, TransitionConfig } from 'xstate'; export type AnyStateNode = StateNode; export interface TransitionMap { state: StateValue | undefined; } export type JSONSerializable = T & { toJSON: () => U; }; export type DirectedGraphLabel = JSONSerializable<{ text: string; }, { text: string; }>; export type DirectedGraphEdge = JSONSerializable<{ id: string; source: AnyStateNode; target: AnyStateNode; label: DirectedGraphLabel; transition: TransitionDefinition; }, { source: string; target: string; label: ReturnType; }>; export type DirectedGraphNode = JSONSerializable<{ id: string; stateNode: StateNode; children: DirectedGraphNode[]; /** The edges representing all transitions from this `stateNode`. */ edges: DirectedGraphEdge[]; }, { id: string; children: DirectedGraphNode[]; }>; export interface ValueAdjacencyMap { [stateId: SerializedSnapshot]: Record; } export interface StatePlan, TEvent extends EventObject> { /** The target state. */ state: TSnapshot; /** The paths that reach the target state. */ paths: Array>; } export interface StatePath, TEvent extends EventObject> { /** The ending state of the path. */ state: TSnapshot; /** * The ordered array of state-event pairs (steps) which reach the ending * `state`. */ steps: Steps; /** The combined weight of all steps in the path. */ weight: number; } export interface StatePlanMap, TEvent extends EventObject> { [key: string]: StatePlan; } export interface Step, TEvent extends EventObject> { /** The event that resulted in the current state */ event: TEvent; /** The current state after taking the event. */ state: TSnapshot; } export type Steps, TEvent extends EventObject> = Array>; export type ExtractEvent = TEvent extends { type: TType; } ? TEvent : never; export interface ValueAdjacencyMapOptions { events?: { [K in TEvent['type']]?: Array> | ((state: TState) => Array>); }; filter?: (state: TState) => boolean; serializeState?: (state: TState) => string; serializeEvent?: (event: TEvent) => string; } export interface VisitedContext { vertices: Set; edges: Set; a?: TState | TEvent; } export interface SerializationConfig, TEvent extends EventObject> { serializeState: (state: TSnapshot, event: TEvent | undefined, prevState?: TSnapshot) => string; serializeEvent: (event: TEvent) => string; } export type SerializationOptions, TEvent extends EventObject> = Partial, 'serializeState' | 'serializeEvent'>>; export type TraversalOptions, TEvent extends EventObject, TInput> = { input?: TInput; } & SerializationOptions & Partial, 'events' | 'limit' | 'fromState' | 'stopWhen' | 'toState'>>; export interface TraversalConfig, TEvent extends EventObject> extends SerializationConfig { events: readonly TEvent[] | ((state: TSnapshot) => readonly TEvent[]); /** * The maximum number of traversals to perform when calculating the state * transition adjacency map. * * @default `Infinity` */ limit: number; fromState: TSnapshot | undefined; /** When true, traversal of the adjacency map will stop for that current state. */ stopWhen: ((state: TSnapshot) => boolean) | undefined; toState: ((state: TSnapshot) => boolean) | undefined; } type Brand = T & { __tag: Tag; }; export type SerializedSnapshot = Brand; export type SerializedEvent = Brand; export type GetPathsOptions, TEvent extends EventObject, TInput> = Partial & { pathGenerator?: PathGenerator; }>; export interface TestStateNodeConfig extends Pick, 'type' | 'history' | 'on' | 'onDone' | 'entry' | 'exit' | 'meta' | 'always' | 'output' | 'id' | 'tags' | 'description'> { initial?: string; states?: Record>; } export interface TestMeta { test?: (testContext: T, state: MachineSnapshot) => Promise | void; description?: string | ((state: MachineSnapshot) => string); skip?: boolean; } interface TestStateResult { error: null | Error; } export interface TestStepResult { step: Step; state: TestStateResult; event: { error: null | Error; }; } export interface TestParam, TEvent extends EventObject> { states?: { [key: string]: (state: TSnapshot) => void | Promise; }; events?: { [TEventType in TEvent['type']]?: EventExecutor['type']; }>; }; } export interface TestPath, TEvent extends EventObject> extends StatePath { description: string; /** * Tests and executes each step in `steps` sequentially, and then tests the * postcondition that the `state` is reached. */ test: (params: TestParam) => Promise; } export interface TestPathResult { steps: TestStepResult[]; state: TestStateResult; } export type StatePredicate = (state: TState) => boolean; /** * Executes an effect using the `testContext` and `event` that triggers the * represented `event`. */ export type EventExecutor, TEvent extends EventObject> = (step: Step) => Promise | void; export interface TestModelOptions, TEvent extends EventObject, TInput> extends TraversalOptions { stateMatcher: (state: TSnapshot, stateKey: string) => boolean; logger: { log: (msg: string) => void; error: (msg: string) => void; }; serializeTransition: (state: TSnapshot, event: TEvent | undefined, prevState?: TSnapshot) => string; } export interface TestTransitionConfig extends TransitionConfig { test?: (state: MachineSnapshot, testContext: TTestContext) => void; } export type TestTransitionsConfig = { [K in TEvent['type'] | '' | '*']?: K extends '' | '*' ? TestTransitionConfig | string : TestTransitionConfig, TTestContext> | string; }; export type PathGenerator, TEvent extends EventObject, TInput> = (behavior: ActorLogic, options: TraversalOptions) => Array>; export {};