xstate 6.0.0-alpha.11 → 6.0.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/{StateMachine-0aa98f54.development.esm.js → StateMachine-193c2d4d.development.esm.js} +43 -2
  2. package/dist/{StateMachine-aef700df.cjs.js → StateMachine-1b26c5de.cjs.js} +43 -2
  3. package/dist/{StateMachine-da872dde.development.cjs.js → StateMachine-3120a7ff.development.cjs.js} +43 -2
  4. package/dist/{StateMachine-d4931336.esm.js → StateMachine-614c0f36.esm.js} +43 -2
  5. package/dist/declarations/src/StateMachine.d.ts +1 -0
  6. package/dist/declarations/src/actors/promise.d.ts +4 -2
  7. package/dist/declarations/src/createActor.d.ts +2 -8
  8. package/dist/declarations/src/createMachineFromConfig.d.ts +56 -25
  9. package/dist/declarations/src/fsm.d.ts +74 -0
  10. package/dist/declarations/src/index.d.ts +2 -1
  11. package/dist/declarations/src/serialize.d.ts +8 -22
  12. package/dist/declarations/src/setup.d.ts +54 -23
  13. package/dist/declarations/src/stateUtils.d.ts +3 -1
  14. package/dist/declarations/src/transitionActions.d.ts +1 -1
  15. package/dist/declarations/src/types.d.ts +17 -7
  16. package/dist/declarations/src/types.v6.d.ts +25 -6
  17. package/dist/{index-219cb621.development.cjs.js → index-08d86676.development.cjs.js} +48 -27
  18. package/dist/{index-559ceab3.cjs.js → index-32631949.cjs.js} +48 -27
  19. package/dist/{index-8828376f.esm.js → index-603c1cda.esm.js} +45 -28
  20. package/dist/{index-2f2fbd9b.development.esm.js → index-7081e0c9.development.esm.js} +45 -28
  21. package/dist/xstate-actors.cjs.js +1 -1
  22. package/dist/xstate-actors.development.cjs.js +1 -1
  23. package/dist/xstate-actors.development.esm.js +1 -1
  24. package/dist/xstate-actors.esm.js +1 -1
  25. package/dist/xstate-actors.umd.min.js.map +1 -1
  26. package/dist/xstate-graph.cjs.js +2 -2
  27. package/dist/xstate-graph.development.cjs.js +2 -2
  28. package/dist/xstate-graph.development.esm.js +2 -2
  29. package/dist/xstate-graph.esm.js +2 -2
  30. package/dist/xstate-graph.umd.min.js +1 -1
  31. package/dist/xstate-graph.umd.min.js.map +1 -1
  32. package/dist/xstate.cjs.js +835 -144
  33. package/dist/xstate.cjs.mjs +1 -0
  34. package/dist/xstate.development.cjs.js +835 -144
  35. package/dist/xstate.development.cjs.mjs +1 -0
  36. package/dist/xstate.development.esm.js +838 -148
  37. package/dist/xstate.esm.js +838 -148
  38. package/dist/xstate.umd.min.js +1 -1
  39. package/dist/xstate.umd.min.js.map +1 -1
  40. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { P as ProcessingStatus, C as resolveReferencedActor, c as createActor, S as STATE_DELIMITER, D as mapValues, t as toArray, E as createInvokeId, F as getDelayedTransitions, G as evaluateCandidate, H as formatTransition, N as NULL_EVENT, I as toTransitionConfigArray, J as createInvokeTimeoutEvent, K as getCandidates, L as formatRouteTransitions, M as resolveStateValue, O as getAllStateNodes, f as getStateNodes, Q as createMachineSnapshot, R as isInFinalState, a as macrostep, U as transitionNode, m as matchesEventDescriptor, V as resolveActionsWithContext, b as createInitEvent, d as initialMicrostep, W as toStatePath, X as isStateId, Y as getStateNodeByPath, Z as getPersistedSnapshot, $ as $$ACTOR_TYPE } from './index-2f2fbd9b.development.esm.js';
1
+ import { P as ProcessingStatus, G as resolveReferencedActor, d as createActor, S as STATE_DELIMITER, H as mapValues, t as toArray, I as createInvokeId, J as getDelayedTransitions, K as evaluateCandidate, L as formatTransition, N as NULL_EVENT, M as toTransitionConfigArray, O as createInvokeTimeoutEvent, Q as getCandidates, R as formatRouteTransitions, U as resolveStateValue, V as getAllStateNodes, k as getStateNodes, W as createMachineSnapshot, Y as isInFinalState, e as macrostep, Z as cloneMachineSnapshot, _ as transitionNode, m as matchesEventDescriptor, r as resolveActionsWithContext, f as createInitEvent, g as initialMicrostep, $ as toStatePath, a0 as isStateId, a1 as getStateNodeByPath, a2 as getPersistedSnapshot, a3 as $$ACTOR_TYPE } from './index-7081e0c9.development.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  machine,
@@ -264,7 +264,7 @@ function formatChoiceTransitions(stateNode) {
264
264
  if (!result || result.target === undefined) {
265
265
  throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
266
266
  }
267
- for (const key of ['actions', 'to', 'context']) {
267
+ for (const key of ['actions', 'to']) {
268
268
  if (result[key] !== undefined) {
269
269
  throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
270
270
  }
@@ -526,12 +526,53 @@ class StateMachine {
526
526
  * @param event The received event
527
527
  */
528
528
  transition(snapshot, event, actorScope) {
529
+ const fastSnapshot = this._transitionFast(snapshot, event, actorScope);
530
+ if (fastSnapshot) {
531
+ return [fastSnapshot, []];
532
+ }
529
533
  const {
530
534
  snapshot: nextSnapshot,
531
535
  microsteps
532
536
  } = macrostep(snapshot, event, actorScope, []);
533
537
  return [nextSnapshot, microsteps.flatMap(([, actions]) => actions)];
534
538
  }
539
+ _transitionFast(snapshot, event, actorScope) {
540
+ if (snapshot.status !== 'active' || typeof snapshot.value !== 'string' || this.root.always?.length) {
541
+ return undefined;
542
+ }
543
+ const sourceNode = this.root.states[snapshot.value];
544
+ if (!sourceNode || sourceNode.type !== 'atomic' || sourceNode.exit || sourceNode.invoke.length || sourceNode.always?.length || sourceNode.after?.length) {
545
+ return undefined;
546
+ }
547
+ const transitions = sourceNode.transitions.get(event.type);
548
+ if (transitions?.length !== 1) {
549
+ return undefined;
550
+ }
551
+ const selected = transitions[0];
552
+ if (selected.guard || selected.actions || selected.to || selected.reenter || selected.input || typeof selected.context === 'function' || selected.target && selected.target.length !== 1) {
553
+ return undefined;
554
+ }
555
+ const targetNode = selected.target?.[0] ?? sourceNode;
556
+ const stateChanged = targetNode !== sourceNode;
557
+ if (targetNode.parent !== this.root || targetNode.type !== 'atomic' || stateChanged && (targetNode.entry || targetNode.invoke.length || targetNode.always?.length || targetNode.after?.length)) {
558
+ return undefined;
559
+ }
560
+ const context = selected.context !== undefined ? {
561
+ ...snapshot.context,
562
+ ...selected.context
563
+ } : snapshot.context;
564
+ const collectedMicrosteps = actorScope.self._collectedMicrosteps || [];
565
+ collectedMicrosteps.push(selected);
566
+ actorScope.self._collectedMicrosteps = collectedMicrosteps;
567
+ return cloneMachineSnapshot(snapshot, {
568
+ ...(context !== snapshot.context ? {
569
+ context
570
+ } : {}),
571
+ ...(stateChanged ? {
572
+ _nodes: [this.root, targetNode]
573
+ } : {})
574
+ });
575
+ }
535
576
 
536
577
  /**
537
578
  * Determines the next state given the current `state` and `event`. Calculates
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var dist_xstateActors = require('./index-559ceab3.cjs.js');
3
+ var dist_xstateActors = require('./index-32631949.cjs.js');
4
4
 
5
5
  function createSpawner(actorScope, {
6
6
  machine,
@@ -266,7 +266,7 @@ function formatChoiceTransitions(stateNode) {
266
266
  if (!result || result.target === undefined) {
267
267
  throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
268
268
  }
269
- for (const key of ['actions', 'to', 'context']) {
269
+ for (const key of ['actions', 'to']) {
270
270
  if (result[key] !== undefined) {
271
271
  throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
272
272
  }
@@ -514,12 +514,53 @@ class StateMachine {
514
514
  * @param event The received event
515
515
  */
516
516
  transition(snapshot, event, actorScope) {
517
+ const fastSnapshot = this._transitionFast(snapshot, event, actorScope);
518
+ if (fastSnapshot) {
519
+ return [fastSnapshot, []];
520
+ }
517
521
  const {
518
522
  snapshot: nextSnapshot,
519
523
  microsteps
520
524
  } = dist_xstateActors.macrostep(snapshot, event, actorScope, []);
521
525
  return [nextSnapshot, microsteps.flatMap(([, actions]) => actions)];
522
526
  }
527
+ _transitionFast(snapshot, event, actorScope) {
528
+ if (snapshot.status !== 'active' || typeof snapshot.value !== 'string' || this.root.always?.length) {
529
+ return undefined;
530
+ }
531
+ const sourceNode = this.root.states[snapshot.value];
532
+ if (!sourceNode || sourceNode.type !== 'atomic' || sourceNode.exit || sourceNode.invoke.length || sourceNode.always?.length || sourceNode.after?.length) {
533
+ return undefined;
534
+ }
535
+ const transitions = sourceNode.transitions.get(event.type);
536
+ if (transitions?.length !== 1) {
537
+ return undefined;
538
+ }
539
+ const selected = transitions[0];
540
+ if (selected.guard || selected.actions || selected.to || selected.reenter || selected.input || typeof selected.context === 'function' || selected.target && selected.target.length !== 1) {
541
+ return undefined;
542
+ }
543
+ const targetNode = selected.target?.[0] ?? sourceNode;
544
+ const stateChanged = targetNode !== sourceNode;
545
+ if (targetNode.parent !== this.root || targetNode.type !== 'atomic' || stateChanged && (targetNode.entry || targetNode.invoke.length || targetNode.always?.length || targetNode.after?.length)) {
546
+ return undefined;
547
+ }
548
+ const context = selected.context !== undefined ? {
549
+ ...snapshot.context,
550
+ ...selected.context
551
+ } : snapshot.context;
552
+ const collectedMicrosteps = actorScope.self._collectedMicrosteps || [];
553
+ collectedMicrosteps.push(selected);
554
+ actorScope.self._collectedMicrosteps = collectedMicrosteps;
555
+ return dist_xstateActors.cloneMachineSnapshot(snapshot, {
556
+ ...(context !== snapshot.context ? {
557
+ context
558
+ } : {}),
559
+ ...(stateChanged ? {
560
+ _nodes: [this.root, targetNode]
561
+ } : {})
562
+ });
563
+ }
523
564
 
524
565
  /**
525
566
  * Determines the next state given the current `state` and `event`. Calculates
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var dist_xstateActors = require('./index-219cb621.development.cjs.js');
3
+ var dist_xstateActors = require('./index-08d86676.development.cjs.js');
4
4
 
5
5
  function createSpawner(actorScope, {
6
6
  machine,
@@ -266,7 +266,7 @@ function formatChoiceTransitions(stateNode) {
266
266
  if (!result || result.target === undefined) {
267
267
  throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
268
268
  }
269
- for (const key of ['actions', 'to', 'context']) {
269
+ for (const key of ['actions', 'to']) {
270
270
  if (result[key] !== undefined) {
271
271
  throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
272
272
  }
@@ -528,12 +528,53 @@ class StateMachine {
528
528
  * @param event The received event
529
529
  */
530
530
  transition(snapshot, event, actorScope) {
531
+ const fastSnapshot = this._transitionFast(snapshot, event, actorScope);
532
+ if (fastSnapshot) {
533
+ return [fastSnapshot, []];
534
+ }
531
535
  const {
532
536
  snapshot: nextSnapshot,
533
537
  microsteps
534
538
  } = dist_xstateActors.macrostep(snapshot, event, actorScope, []);
535
539
  return [nextSnapshot, microsteps.flatMap(([, actions]) => actions)];
536
540
  }
541
+ _transitionFast(snapshot, event, actorScope) {
542
+ if (snapshot.status !== 'active' || typeof snapshot.value !== 'string' || this.root.always?.length) {
543
+ return undefined;
544
+ }
545
+ const sourceNode = this.root.states[snapshot.value];
546
+ if (!sourceNode || sourceNode.type !== 'atomic' || sourceNode.exit || sourceNode.invoke.length || sourceNode.always?.length || sourceNode.after?.length) {
547
+ return undefined;
548
+ }
549
+ const transitions = sourceNode.transitions.get(event.type);
550
+ if (transitions?.length !== 1) {
551
+ return undefined;
552
+ }
553
+ const selected = transitions[0];
554
+ if (selected.guard || selected.actions || selected.to || selected.reenter || selected.input || typeof selected.context === 'function' || selected.target && selected.target.length !== 1) {
555
+ return undefined;
556
+ }
557
+ const targetNode = selected.target?.[0] ?? sourceNode;
558
+ const stateChanged = targetNode !== sourceNode;
559
+ if (targetNode.parent !== this.root || targetNode.type !== 'atomic' || stateChanged && (targetNode.entry || targetNode.invoke.length || targetNode.always?.length || targetNode.after?.length)) {
560
+ return undefined;
561
+ }
562
+ const context = selected.context !== undefined ? {
563
+ ...snapshot.context,
564
+ ...selected.context
565
+ } : snapshot.context;
566
+ const collectedMicrosteps = actorScope.self._collectedMicrosteps || [];
567
+ collectedMicrosteps.push(selected);
568
+ actorScope.self._collectedMicrosteps = collectedMicrosteps;
569
+ return dist_xstateActors.cloneMachineSnapshot(snapshot, {
570
+ ...(context !== snapshot.context ? {
571
+ context
572
+ } : {}),
573
+ ...(stateChanged ? {
574
+ _nodes: [this.root, targetNode]
575
+ } : {})
576
+ });
577
+ }
537
578
 
538
579
  /**
539
580
  * Determines the next state given the current `state` and `event`. Calculates
@@ -1,4 +1,4 @@
1
- import { P as ProcessingStatus, C as resolveReferencedActor, c as createActor, S as STATE_DELIMITER, D as mapValues, t as toArray, E as createInvokeId, F as getDelayedTransitions, G as evaluateCandidate, H as formatTransition, N as NULL_EVENT, I as toTransitionConfigArray, J as createInvokeTimeoutEvent, K as getCandidates, L as formatRouteTransitions, M as resolveStateValue, O as getAllStateNodes, f as getStateNodes, Q as createMachineSnapshot, R as isInFinalState, a as macrostep, U as transitionNode, m as matchesEventDescriptor, V as resolveActionsWithContext, b as createInitEvent, d as initialMicrostep, W as toStatePath, X as isStateId, Y as getStateNodeByPath, Z as getPersistedSnapshot, $ as $$ACTOR_TYPE } from './index-8828376f.esm.js';
1
+ import { P as ProcessingStatus, G as resolveReferencedActor, d as createActor, S as STATE_DELIMITER, H as mapValues, t as toArray, I as createInvokeId, J as getDelayedTransitions, K as evaluateCandidate, L as formatTransition, N as NULL_EVENT, M as toTransitionConfigArray, O as createInvokeTimeoutEvent, Q as getCandidates, R as formatRouteTransitions, U as resolveStateValue, V as getAllStateNodes, k as getStateNodes, W as createMachineSnapshot, Y as isInFinalState, e as macrostep, Z as cloneMachineSnapshot, _ as transitionNode, m as matchesEventDescriptor, r as resolveActionsWithContext, f as createInitEvent, g as initialMicrostep, $ as toStatePath, a0 as isStateId, a1 as getStateNodeByPath, a2 as getPersistedSnapshot, a3 as $$ACTOR_TYPE } from './index-603c1cda.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  machine,
@@ -264,7 +264,7 @@ function formatChoiceTransitions(stateNode) {
264
264
  if (!result || result.target === undefined) {
265
265
  throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
266
266
  }
267
- for (const key of ['actions', 'to', 'context']) {
267
+ for (const key of ['actions', 'to']) {
268
268
  if (result[key] !== undefined) {
269
269
  throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
270
270
  }
@@ -512,12 +512,53 @@ class StateMachine {
512
512
  * @param event The received event
513
513
  */
514
514
  transition(snapshot, event, actorScope) {
515
+ const fastSnapshot = this._transitionFast(snapshot, event, actorScope);
516
+ if (fastSnapshot) {
517
+ return [fastSnapshot, []];
518
+ }
515
519
  const {
516
520
  snapshot: nextSnapshot,
517
521
  microsteps
518
522
  } = macrostep(snapshot, event, actorScope, []);
519
523
  return [nextSnapshot, microsteps.flatMap(([, actions]) => actions)];
520
524
  }
525
+ _transitionFast(snapshot, event, actorScope) {
526
+ if (snapshot.status !== 'active' || typeof snapshot.value !== 'string' || this.root.always?.length) {
527
+ return undefined;
528
+ }
529
+ const sourceNode = this.root.states[snapshot.value];
530
+ if (!sourceNode || sourceNode.type !== 'atomic' || sourceNode.exit || sourceNode.invoke.length || sourceNode.always?.length || sourceNode.after?.length) {
531
+ return undefined;
532
+ }
533
+ const transitions = sourceNode.transitions.get(event.type);
534
+ if (transitions?.length !== 1) {
535
+ return undefined;
536
+ }
537
+ const selected = transitions[0];
538
+ if (selected.guard || selected.actions || selected.to || selected.reenter || selected.input || typeof selected.context === 'function' || selected.target && selected.target.length !== 1) {
539
+ return undefined;
540
+ }
541
+ const targetNode = selected.target?.[0] ?? sourceNode;
542
+ const stateChanged = targetNode !== sourceNode;
543
+ if (targetNode.parent !== this.root || targetNode.type !== 'atomic' || stateChanged && (targetNode.entry || targetNode.invoke.length || targetNode.always?.length || targetNode.after?.length)) {
544
+ return undefined;
545
+ }
546
+ const context = selected.context !== undefined ? {
547
+ ...snapshot.context,
548
+ ...selected.context
549
+ } : snapshot.context;
550
+ const collectedMicrosteps = actorScope.self._collectedMicrosteps || [];
551
+ collectedMicrosteps.push(selected);
552
+ actorScope.self._collectedMicrosteps = collectedMicrosteps;
553
+ return cloneMachineSnapshot(snapshot, {
554
+ ...(context !== snapshot.context ? {
555
+ context
556
+ } : {}),
557
+ ...(stateChanged ? {
558
+ _nodes: [this.root, targetNode]
559
+ } : {})
560
+ });
561
+ }
521
562
 
522
563
  /**
523
564
  * Determines the next state given the current `state` and `event`. Calculates
@@ -63,6 +63,7 @@ export declare class StateMachine<TContext extends MachineContext, TEvent extend
63
63
  * @param event The received event
64
64
  */
65
65
  transition(snapshot: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, event: TEvent, actorScope: ActorScope<typeof snapshot, TEvent, AnyActorSystem, TEmitted>): ActorLogicTransitionResult<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, ExecutableActionObjectFromLogic<this>>;
66
+ private _transitionFast;
66
67
  /**
67
68
  * Determines the next state given the current `state` and `event`. Calculates
68
69
  * a microstep.
@@ -41,6 +41,7 @@ export interface LogicEnqueue<TEmitted extends EventObject> {
41
41
  step: <TStepOutput>(key: string, exec: () => TStepOutput | PromiseLike<TStepOutput>) => Promise<TStepOutput>;
42
42
  }
43
43
  export type LogicFunction<TOutput, TInput = NonReducibleUnknown, TEmitted extends EventObject = EventObject> = (args: LogicArgs<TOutput, TInput>, enq: LogicEnqueue<TEmitted>) => PromiseLike<TOutput>;
44
+ type AsyncLogicFunctionOutput<TLogicFunction extends (...args: any[]) => PromiseLike<any>> = Awaited<ReturnType<TLogicFunction>>;
44
45
  export interface LogicConfig<TOutput, TInput = NonReducibleUnknown, TEmitted extends EventObject = EventObject, TInputSchema extends StandardSchemaV1 = StandardSchemaV1, TOutputSchema extends StandardSchemaV1 = StandardSchemaV1> {
45
46
  /**
46
47
  * Stable identifier for this async logic. This identifies the logic, not a
@@ -165,12 +166,13 @@ export declare function createAsyncLogic<const TInputSchema extends StandardSche
165
166
  }): AsyncActorLogic<StandardSchemaV1.InferOutput<TOutputSchema>, StandardSchemaV1.InferOutput<TInputSchema>, TEmitted> & {
166
167
  id?: string;
167
168
  };
168
- export declare function createAsyncLogic<TOutput, const TInputSchema extends StandardSchemaV1, TEmitted extends EventObject = EventObject>(asyncLogic: LogicConfig<TOutput, StandardSchemaV1.InferOutput<TInputSchema>, TEmitted, TInputSchema> & {
169
+ export declare function createAsyncLogic<const TInputSchema extends StandardSchemaV1, TEmitted extends EventObject = EventObject, TLogicFunction extends LogicFunction<any, StandardSchemaV1.InferOutput<TInputSchema>, TEmitted> = LogicFunction<any, StandardSchemaV1.InferOutput<TInputSchema>, TEmitted>>(asyncLogic: Omit<LogicConfig<never, StandardSchemaV1.InferOutput<TInputSchema>, TEmitted, TInputSchema>, 'run' | 'schemas'> & {
169
170
  schemas: {
170
171
  input: TInputSchema;
171
172
  output?: never;
172
173
  };
173
- }): AsyncActorLogic<TOutput, StandardSchemaV1.InferOutput<TInputSchema>, TEmitted> & {
174
+ run: TLogicFunction;
175
+ }): AsyncActorLogic<AsyncLogicFunctionOutput<TLogicFunction>, StandardSchemaV1.InferOutput<TInputSchema>, TEmitted> & {
174
176
  id?: string;
175
177
  };
176
178
  export declare function createAsyncLogic<const TOutputSchema extends StandardSchemaV1, TInput = NonReducibleUnknown, TEmitted extends EventObject = EventObject>(asyncLogic: LogicConfig<StandardSchemaV1.InferOutput<TOutputSchema>, TInput, TEmitted, StandardSchemaV1, TOutputSchema> & {
@@ -1,6 +1,6 @@
1
1
  import { symbolObservable } from "./symbolObservable.js";
2
2
  import { AnyActorSystem, Clock } from "./system.js";
3
- import type { AnyActor, AnyActorLogic, EmittedFrom, EventFromLogic, SendableEventFromLogic, InputFrom, Snapshot, SnapshotFrom, Readable } from "./types.js";
3
+ import type { ActorTrigger, AnyActor, AnyActorLogic, EmittedFrom, EventFromLogic, SendableEventFromLogic, InputFrom, Snapshot, SnapshotFrom, Readable } from "./types.js";
4
4
  import { ActorOptions, ActorInstance, ActorRef, InteropSubscribable, Observer, Subscription } from "./types.js";
5
5
  export declare const $$ACTOR_TYPE = 1;
6
6
  export declare enum ProcessingStatus {
@@ -45,13 +45,7 @@ export declare class Actor<TLogic extends AnyActorLogic> implements ActorInstanc
45
45
  sessionId: string;
46
46
  /** The system to which this actor belongs. */
47
47
  system: AnyActorSystem;
48
- trigger: {
49
- [K in SendableEventFromLogic<TLogic>['type']]: {} extends Omit<Extract<SendableEventFromLogic<TLogic>, {
50
- type: K;
51
- }>, 'type'> ? () => void : (payload: Omit<Extract<SendableEventFromLogic<TLogic>, {
52
- type: K;
53
- }>, 'type'>) => void;
54
- };
48
+ trigger: ActorTrigger<SendableEventFromLogic<TLogic>>;
55
49
  src: string | AnyActorLogic;
56
50
  /**
57
51
  * Creates a new actor instance for the given logic with the provided options,
@@ -90,44 +90,64 @@ interface ScxmlIfJSON {
90
90
  }
91
91
  interface CustomActionJSON {
92
92
  type: string;
93
- params?: Record<string, unknown>;
93
+ params?: unknown;
94
94
  }
95
- export type ActionJSON = CustomActionJSON | RaiseJSON | CancelJSON | LogJSON | EmitJSON | AssignJSON | ScxmlAssignJSON | ScxmlRaiseJSON | ScxmlScriptJSON | ScxmlIfJSON | ScxmlForeachJSON | ScxmlCancelJSON | ScxmlBlockJSON;
95
+ export type ActionJSON = CustomActionJSON | RaiseJSON | CancelJSON | LogJSON | EmitJSON | AssignJSON | ScxmlAssignJSON | ScxmlRaiseJSON | ScxmlScriptJSON | ScxmlIfJSON | ScxmlForeachJSON | ScxmlCancelJSON | ScxmlBlockJSON | ExpressionJSON | CodeJSON;
96
96
  export interface GuardJSON {
97
97
  type: string;
98
- params?: Record<string, unknown>;
98
+ params?: unknown;
99
+ }
100
+ interface ExpressionJSON {
101
+ '@expr': string;
102
+ '@lang'?: string;
103
+ }
104
+ interface CodeJSON {
105
+ '@code': string;
106
+ '@lang'?: string;
107
+ }
108
+ type ResolvableJSON = ExpressionJSON | CodeJSON;
109
+ type ConditionJSON = GuardJSON | ResolvableJSON;
110
+ interface ChoiceBranchJSON {
111
+ when?: ConditionJSON;
112
+ target: string | string[];
113
+ context?: MachineContext;
114
+ input?: unknown;
115
+ description?: string;
116
+ reenter?: boolean;
117
+ meta?: MetaObject;
99
118
  }
100
119
  export interface InvokeJSON {
101
120
  id?: string;
102
121
  registryKey?: string;
103
- src: string | UnserializableMarker;
122
+ src: string;
104
123
  input?: unknown;
105
- onDone?: TransitionJSON | TransitionJSON[];
106
- onError?: TransitionJSON | TransitionJSON[];
107
- onSnapshot?: TransitionJSON | TransitionJSON[];
108
- timeout?: number | string;
109
- onTimeout?: TransitionJSON | TransitionJSON[];
124
+ onDone?: TransitionConfigJSON | TransitionConfigJSON[];
125
+ onError?: TransitionConfigJSON | TransitionConfigJSON[];
126
+ onSnapshot?: TransitionConfigJSON | TransitionConfigJSON[];
127
+ timeout?: number | string | ResolvableJSON;
128
+ onTimeout?: TransitionConfigJSON | TransitionConfigJSON[];
110
129
  }
111
130
  export interface TransitionJSON {
112
131
  target?: string | string[];
113
132
  context?: MachineContext;
114
133
  actions?: ActionJSON[];
115
- guard?: GuardJSON;
134
+ guard?: ConditionJSON;
116
135
  description?: string;
117
136
  reenter?: boolean;
118
137
  meta?: MetaObject;
119
138
  input?: unknown;
120
139
  }
140
+ type TransitionConfigJSON = TransitionJSON | ResolvableJSON;
121
141
  export interface StateNodeJSON {
122
142
  id?: string;
123
143
  key?: string;
124
144
  type?: 'atomic' | 'compound' | 'parallel' | 'final' | 'history' | 'choice';
125
145
  initial?: string;
126
146
  states?: Record<string, StateNodeJSON>;
127
- on?: Record<string, TransitionJSON | TransitionJSON[]>;
128
- after?: Record<string, TransitionJSON | TransitionJSON[]>;
129
- always?: TransitionJSON | TransitionJSON[];
130
- choice?: TransitionJSON;
147
+ on?: Record<string, TransitionConfigJSON | TransitionConfigJSON[]>;
148
+ after?: Record<string, TransitionConfigJSON | TransitionConfigJSON[]>;
149
+ always?: TransitionConfigJSON | TransitionConfigJSON[];
150
+ choice?: ChoiceBranchJSON[] | ResolvableJSON;
131
151
  /**
132
152
  * JSON route config. Unlike the authoring API (a function), the JSON layer
133
153
  * allows an object form whose `guard` may be a named guard reference (string)
@@ -139,16 +159,16 @@ export interface StateNodeJSON {
139
159
  meta?: MetaObject;
140
160
  guard?: string;
141
161
  input?: Record<string, unknown>;
142
- };
162
+ } | ResolvableJSON;
143
163
  invoke?: InvokeJSON | InvokeJSON[];
144
- entry?: ActionJSON[];
145
- exit?: ActionJSON[];
164
+ entry?: ActionJSON | ActionJSON[];
165
+ exit?: ActionJSON | ActionJSON[];
146
166
  meta?: MetaObject;
147
167
  description?: string;
148
168
  tags?: string[];
149
169
  input?: unknown;
150
- timeout?: number | string;
151
- onTimeout?: TransitionJSON | TransitionJSON[];
170
+ timeout?: number | string | ResolvableJSON;
171
+ onTimeout?: TransitionConfigJSON | TransitionConfigJSON[];
152
172
  history?: 'shallow' | 'deep';
153
173
  target?: string;
154
174
  output?: unknown;
@@ -156,22 +176,33 @@ export interface StateNodeJSON {
156
176
  _scxmlDonedata?: ScxmlDonedataJSON;
157
177
  }
158
178
  export interface MachineJSON extends StateNodeJSON {
179
+ '@exprLang'?: string;
159
180
  version?: string;
160
- actions?: Record<string, unknown>;
161
- guards?: Record<string, unknown>;
181
+ actions?: Record<string, ActionJSON | ActionJSON[]>;
182
+ guards?: Record<string, {
183
+ when: ConditionJSON;
184
+ }>;
162
185
  actorSources?: Record<string, unknown>;
163
- delays?: Record<string, unknown>;
186
+ delays?: Record<string, number | string | {
187
+ duration: number | string | ResolvableJSON;
188
+ }>;
164
189
  schemas?: Record<string, unknown>;
165
190
  }
166
- interface UnserializableMarker {
167
- $unserializable: 'function' | 'actor' | 'schema' | 'value';
168
- id?: string;
191
+ type EvaluatorSlot = 'context' | 'guard' | 'choice' | 'action' | 'actionParams' | 'transition' | 'input' | 'output' | 'delay' | 'transitionContext' | 'unknown';
192
+ type EvaluatorKind = 'expr' | 'code';
193
+ interface EvaluatorArgs {
194
+ source: string;
195
+ kind: EvaluatorKind;
196
+ slot: EvaluatorSlot;
197
+ scope: Record<string, unknown>;
198
+ path: string;
169
199
  }
170
200
  interface MachineImplementations {
171
201
  actions?: Record<string, (...args: any[]) => unknown>;
172
202
  guards?: Record<string, (...args: any[]) => boolean>;
173
203
  actorSources?: Record<string, AnyActorLogic>;
174
204
  delays?: Record<string, number | ((...args: any[]) => number)>;
205
+ evaluators?: Record<string, (args: EvaluatorArgs) => unknown>;
175
206
  }
176
207
  export declare function createMachineFromConfig(json: MachineJSON, implementations?: MachineImplementations): AnyStateMachine;
177
208
  export {};
@@ -0,0 +1,74 @@
1
+ import { createTransitionEnqueue } from "./transitionActions.js";
2
+ import type { ActorLogic, EventObject, MachineContext, NonReducibleUnknown, Snapshot } from "./types.js";
3
+ export type FSMSnapshot<TContext extends MachineContext, TState extends string, TInput = unknown> = Snapshot<undefined> & {
4
+ value: TState;
5
+ context: TContext;
6
+ input: TInput | undefined;
7
+ children: {};
8
+ _stateInput: Record<string, unknown> | undefined;
9
+ machine: {
10
+ id: string;
11
+ implementations: {
12
+ actions: {};
13
+ actorSources: {};
14
+ guards: {};
15
+ delays: {};
16
+ };
17
+ };
18
+ };
19
+ type FSMArgs<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = {
20
+ context: TContext;
21
+ event: TEvent;
22
+ input: TInput | undefined;
23
+ value: TState;
24
+ self: any;
25
+ system: any;
26
+ parent: any;
27
+ children: {};
28
+ };
29
+ type FSMAction<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = (args: FSMArgs<TContext, TEvent, TState, TInput> & {
30
+ input: Record<string, unknown> | undefined;
31
+ }, enq: ReturnType<typeof createTransitionEnqueue>) => void | {
32
+ context?: FSMContextPatch<TContext>;
33
+ };
34
+ type FSMGuard<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = (args: FSMArgs<TContext, TEvent, TState, TInput>) => boolean;
35
+ type FSMContextPatch<TContext extends MachineContext> = Partial<TContext> & {
36
+ call?: never;
37
+ apply?: never;
38
+ bind?: never;
39
+ };
40
+ type FSMContextMapper<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = (args: FSMArgs<TContext, TEvent, TState, TInput>) => FSMContextPatch<TContext>;
41
+ type FSMTarget<TContext extends MachineContext> = {
42
+ target?: string;
43
+ context?: FSMContextPatch<TContext>;
44
+ input?: Record<string, unknown> | ((args: {
45
+ context: TContext;
46
+ event: EventObject;
47
+ }) => Record<string, unknown>);
48
+ };
49
+ type FSMObjectTarget<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = Omit<FSMTarget<TContext>, 'context'> & {
50
+ context?: FSMContextPatch<TContext> | FSMContextMapper<TContext, TEvent, TState, TInput>;
51
+ };
52
+ type FSMTransitionFunction<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = (args: FSMArgs<TContext, TEvent, TState, TInput>, enq: ReturnType<typeof createTransitionEnqueue>) => void | false | FSMTarget<TContext>;
53
+ type FSMTransition<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = FSMObjectTarget<TContext, TEvent, TState, TInput> | (FSMObjectTarget<TContext, TEvent, TState, TInput> & {
54
+ guard?: FSMGuard<TContext, TEvent, TState, TInput>;
55
+ actions?: FSMAction<TContext, TEvent, TState, TInput> | Array<FSMAction<TContext, TEvent, TState, TInput>>;
56
+ }) | FSMTransitionFunction<TContext, TEvent, TState, TInput>;
57
+ type FSMStateConfig<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = {
58
+ entry?: FSMAction<TContext, TEvent, TState, TInput> | Array<FSMAction<TContext, TEvent, TState, TInput>>;
59
+ exit?: FSMAction<TContext, TEvent, TState, TInput> | Array<FSMAction<TContext, TEvent, TState, TInput>>;
60
+ on?: Record<string, FSMTransition<TContext, TEvent, TState, TInput> | Array<FSMTransition<TContext, TEvent, TState, TInput>>>;
61
+ };
62
+ export type FSMConfig<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput = NonReducibleUnknown> = {
63
+ id?: string;
64
+ initial: TState;
65
+ context?: TContext | ((args: {
66
+ input: TInput;
67
+ }) => TContext);
68
+ states: Record<TState, FSMStateConfig<TContext, TEvent, TState, TInput>>;
69
+ };
70
+ export type FSMActorLogic<TContext extends MachineContext, TEvent extends EventObject, TState extends string, TInput> = ActorLogic<FSMSnapshot<TContext, TState, TInput>, TEvent, TInput, any, EventObject> & {
71
+ id?: string;
72
+ };
73
+ export declare function createFSM<TContext extends MachineContext, TEvent extends EventObject, TInput = NonReducibleUnknown>(config: FSMConfig<TContext, TEvent, string, TInput>): FSMActorLogic<TContext, TEvent, string, TInput>;
74
+ export {};
@@ -2,9 +2,10 @@ export * from "./actors/index.js";
2
2
  export { assertEvent } from "./assert.js";
3
3
  export { Actor, createActor, type RequiredActorOptionsKeys as RequiredActorOptionsKeys } from "./createActor.js";
4
4
  export { createMachine, createStateConfig } from "./createMachine.js";
5
+ export { createFSM, type FSMActorLogic, type FSMConfig, type FSMSnapshot } from "./fsm.js";
5
6
  export { createMachineFromConfig } from "./createMachineFromConfig.js";
6
7
  export type { ActionJSON, GuardJSON, InvokeJSON, MachineJSON, StateNodeJSON, TransitionJSON } from "./createMachineFromConfig.js";
7
- export { machineConfigToJSON, serializeMachine, type CodeExpression, type UnserializableMarker } from "./serialize.js";
8
+ export { machineConfigToJSON, serializeMachine, type CodeExpression } from "./serialize.js";
8
9
  export { mapState } from "./mapState.js";
9
10
  export { types, isTypeSchema, type StandardSchemaV1, type TypeSchema } from "./schema.types.js";
10
11
  export { createSystem, setup } from "./setup.js";
@@ -4,34 +4,20 @@
4
4
  * `machineConfigToJSON` converts a machine config into a JSON-safe structure
5
5
  * (the `MachineJSON` shape accepted by `createMachineFromConfig`). The boundary
6
6
  * between serializable structure and runtime implementations is explicit:
7
- * functions are represented as code expressions, while actor logic, runtime
8
- * schemas, and other non-code runtime values are replaced with an `{
9
- * "$unserializable": <kind> }` marker rather than silently dropped.
10
- *
11
- * A machine definition is fully portable iff its JSON contains no
12
- * `$unserializable` markers; reviving a definition that has markers requires
13
- * re-providing those implementations (e.g. via `machine.provide(...)` or the
14
- * `actions`/`guards`/`actorSources` maps on `createMachineFromConfig`
15
- * revival).
7
+ * functions are represented as `@code` source objects, while actor logic,
8
+ * runtime schemas, and other non-data runtime values are omitted.
16
9
  */
17
10
  import type { AnyStateMachine } from "./types.js";
18
- export interface UnserializableMarker {
19
- $unserializable: 'function' | 'actor' | 'schema' | 'value';
20
- /** Best-effort identifier (function name, actor logic id) for diagnostics. */
21
- id?: string;
22
- }
23
11
  export interface CodeExpression {
24
- '@type': 'code';
25
- lang: 'ts';
26
- expr: string;
12
+ '@code': string;
13
+ '@lang': 'ts';
27
14
  }
28
15
  /**
29
16
  * Returns the JSON-serializable definition of a machine.
30
17
  *
31
- * Inline functions are represented as `{ "@type": "code", lang: "ts", expr }`.
32
- * Actor logic and runtime schemas appear as `{ "$unserializable": ... }`
33
- * markers. A machine created via `createMachineFromConfig` returns its original
34
- * JSON config (lossless round-trip):
18
+ * Inline functions are represented as `{ "@code": string, "@lang": "ts" }`. A
19
+ * machine created via `createMachineFromConfig` returns its original JSON
20
+ * config (lossless round-trip):
35
21
  *
36
22
  * ```ts
37
23
  * import { serializeMachine, createMachineFromConfig } from 'xstate';
@@ -45,6 +31,6 @@ export interface CodeExpression {
45
31
  export declare function serializeMachine(machine: AnyStateMachine): Record<string, unknown>;
46
32
  /**
47
33
  * Converts a machine config (as passed to `createMachine`) to its JSON-safe
48
- * definition. See module docs for the `$unserializable` marker contract.
34
+ * definition.
49
35
  */
50
36
  export declare function machineConfigToJSON(config: Record<string, unknown>): Record<string, unknown>;