xstate 5.32.1 → 6.0.0-alpha.1

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 (119) hide show
  1. package/README.md +7 -8
  2. package/dist/StateMachine-47e60715.esm.js +720 -0
  3. package/dist/StateMachine-48dcad8f.cjs.js +723 -0
  4. package/dist/StateMachine-6e063ac1.development.cjs.js +740 -0
  5. package/dist/StateMachine-6ec50e21.development.esm.js +737 -0
  6. package/dist/declarations/src/State.d.ts +11 -13
  7. package/dist/declarations/src/StateMachine.d.ts +27 -21
  8. package/dist/declarations/src/StateNode.d.ts +18 -54
  9. package/dist/declarations/src/actions.d.ts +14 -9
  10. package/dist/declarations/src/actors/callback.d.ts +42 -16
  11. package/dist/declarations/src/actors/index.d.ts +9 -6
  12. package/dist/declarations/src/actors/listener.d.ts +18 -0
  13. package/dist/declarations/src/actors/logic.d.ts +105 -0
  14. package/dist/declarations/src/actors/observable.d.ts +72 -27
  15. package/dist/declarations/src/actors/promise.d.ts +133 -48
  16. package/dist/declarations/src/actors/subscription.d.ts +22 -0
  17. package/dist/declarations/src/atom.d.ts +81 -0
  18. package/dist/declarations/src/createActor.d.ts +31 -33
  19. package/dist/declarations/src/createMachine.d.ts +35 -7
  20. package/dist/declarations/src/createMachineFromConfig.d.ts +176 -0
  21. package/dist/declarations/src/graph/graph.d.ts +4 -2
  22. package/dist/declarations/src/index.d.ts +12 -8
  23. package/dist/declarations/src/inspection.d.ts +84 -30
  24. package/dist/declarations/src/mapState.d.ts +4 -2
  25. package/dist/declarations/src/schema.types.d.ts +90 -0
  26. package/dist/declarations/src/serialize.d.ts +44 -0
  27. package/dist/declarations/src/setup.d.ts +251 -135
  28. package/dist/declarations/src/spawn.d.ts +6 -31
  29. package/dist/declarations/src/stateUtils.d.ts +21 -19
  30. package/dist/declarations/src/system.d.ts +8 -7
  31. package/dist/declarations/src/transition.d.ts +5 -5
  32. package/dist/declarations/src/types.d.ts +405 -405
  33. package/dist/declarations/src/types.v6.d.ts +392 -0
  34. package/dist/declarations/src/utils.d.ts +4 -3
  35. package/dist/index-39259ea4.development.esm.js +4948 -0
  36. package/dist/index-688701ed.esm.js +4909 -0
  37. package/dist/index-c35824b4.development.cjs.js +5007 -0
  38. package/dist/index-f0d7107d.cjs.js +4968 -0
  39. package/dist/xstate-actors.cjs.js +12 -838
  40. package/dist/xstate-actors.cjs.mjs +10 -5
  41. package/dist/xstate-actors.development.cjs.js +12 -838
  42. package/dist/xstate-actors.development.cjs.mjs +10 -5
  43. package/dist/xstate-actors.development.esm.js +1 -836
  44. package/dist/xstate-actors.esm.js +1 -836
  45. package/dist/xstate-actors.umd.min.js +1 -1
  46. package/dist/xstate-actors.umd.min.js.map +1 -1
  47. package/dist/xstate-graph.cjs.js +18 -29
  48. package/dist/xstate-graph.development.cjs.js +18 -29
  49. package/dist/xstate-graph.development.esm.js +15 -26
  50. package/dist/xstate-graph.esm.js +15 -26
  51. package/dist/xstate-graph.umd.min.js +1 -1
  52. package/dist/xstate-graph.umd.min.js.map +1 -1
  53. package/dist/xstate.cjs.js +1316 -112
  54. package/dist/xstate.cjs.mjs +22 -22
  55. package/dist/xstate.development.cjs.js +1316 -112
  56. package/dist/xstate.development.cjs.mjs +22 -22
  57. package/dist/xstate.development.esm.js +1278 -76
  58. package/dist/xstate.esm.js +1278 -76
  59. package/dist/xstate.umd.min.js +1 -1
  60. package/dist/xstate.umd.min.js.map +1 -1
  61. package/package.json +3 -47
  62. package/dist/StateMachine-45e79c35.esm.js +0 -560
  63. package/dist/StateMachine-be2e51a3.development.cjs.js +0 -569
  64. package/dist/StateMachine-e0178d48.development.esm.js +0 -566
  65. package/dist/StateMachine-e6732977.cjs.js +0 -563
  66. package/dist/assign-2aa58daa.esm.js +0 -127
  67. package/dist/assign-927227d6.development.cjs.js +0 -135
  68. package/dist/assign-e8f2bd75.cjs.js +0 -129
  69. package/dist/assign-f338cee3.development.esm.js +0 -133
  70. package/dist/declarations/src/actions/assign.d.ts +0 -45
  71. package/dist/declarations/src/actions/cancel.d.ts +0 -39
  72. package/dist/declarations/src/actions/emit.d.ts +0 -44
  73. package/dist/declarations/src/actions/enqueueActions.d.ts +0 -57
  74. package/dist/declarations/src/actions/log.d.ts +0 -16
  75. package/dist/declarations/src/actions/raise.d.ts +0 -21
  76. package/dist/declarations/src/actions/send.d.ts +0 -42
  77. package/dist/declarations/src/actions/spawnChild.d.ts +0 -34
  78. package/dist/declarations/src/actions/stopChild.d.ts +0 -19
  79. package/dist/declarations/src/actors/transition.d.ts +0 -143
  80. package/dist/declarations/src/dev/index.d.ts +0 -14
  81. package/dist/declarations/src/guards.d.ts +0 -128
  82. package/dist/log-410e5e55.development.esm.js +0 -429
  83. package/dist/log-7776fcf2.cjs.js +0 -409
  84. package/dist/log-c2e11c01.development.cjs.js +0 -437
  85. package/dist/log-fa75ec2d.esm.js +0 -401
  86. package/dist/raise-74097812.development.esm.js +0 -2823
  87. package/dist/raise-7c948725.cjs.js +0 -2816
  88. package/dist/raise-964cd4e9.development.cjs.js +0 -2878
  89. package/dist/raise-e974d1c9.esm.js +0 -2761
  90. package/dist/xstate-actions.cjs.d.mts +0 -2
  91. package/dist/xstate-actions.cjs.d.ts +0 -2
  92. package/dist/xstate-actions.cjs.js +0 -23
  93. package/dist/xstate-actions.cjs.mjs +0 -14
  94. package/dist/xstate-actions.development.cjs.js +0 -23
  95. package/dist/xstate-actions.development.cjs.mjs +0 -14
  96. package/dist/xstate-actions.development.esm.js +0 -4
  97. package/dist/xstate-actions.esm.js +0 -4
  98. package/dist/xstate-actions.umd.min.js +0 -2
  99. package/dist/xstate-actions.umd.min.js.map +0 -1
  100. package/dist/xstate-dev.cjs.d.mts +0 -2
  101. package/dist/xstate-dev.cjs.d.ts +0 -2
  102. package/dist/xstate-dev.cjs.js +0 -48
  103. package/dist/xstate-dev.cjs.mjs +0 -5
  104. package/dist/xstate-dev.development.cjs.js +0 -51
  105. package/dist/xstate-dev.development.cjs.mjs +0 -5
  106. package/dist/xstate-dev.development.esm.js +0 -45
  107. package/dist/xstate-dev.esm.js +0 -42
  108. package/dist/xstate-dev.umd.min.js +0 -2
  109. package/dist/xstate-dev.umd.min.js.map +0 -1
  110. package/dist/xstate-guards.cjs.d.mts +0 -2
  111. package/dist/xstate-guards.cjs.d.ts +0 -2
  112. package/dist/xstate-guards.cjs.js +0 -14
  113. package/dist/xstate-guards.cjs.mjs +0 -7
  114. package/dist/xstate-guards.development.cjs.js +0 -14
  115. package/dist/xstate-guards.development.cjs.mjs +0 -7
  116. package/dist/xstate-guards.development.esm.js +0 -2
  117. package/dist/xstate-guards.esm.js +0 -2
  118. package/dist/xstate-guards.umd.min.js +0 -2
  119. package/dist/xstate-guards.umd.min.js.map +0 -1
@@ -0,0 +1,720 @@
1
+ import { P as ProcessingStatus, G as resolveReferencedActor, c 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, n as getStateNodes, W as createMachineSnapshot, X as isInFinalState, a as macrostep, Y as transitionNode, m as matchesEventDescriptor, Z as resolveAndExecuteActionsWithContext, b as createInitEvent, d as initialMicrostep, _ as toStatePath, $ as isStateId, a0 as getStateNodeByPath, a1 as getPersistedSnapshot, a2 as $$ACTOR_TYPE } from './index-688701ed.esm.js';
2
+
3
+ function createSpawner(actorScope, {
4
+ machine,
5
+ context
6
+ }, event, spawnedChildren) {
7
+ const spawn = (src, options) => {
8
+ if (typeof src === 'string') {
9
+ const logic = resolveReferencedActor(machine, src);
10
+ if (!logic) {
11
+ throw new Error(`Actor logic '${src}' not implemented in machine '${machine.id}'`);
12
+ }
13
+ const actor = createActor(logic, {
14
+ id: options?.id,
15
+ parent: actorScope.self,
16
+ syncSnapshot: options?.syncSnapshot,
17
+ input: typeof options?.input === 'function' ? options.input({
18
+ context,
19
+ event,
20
+ self: actorScope.self
21
+ }) : options?.input,
22
+ src,
23
+ systemId: options?.systemId
24
+ });
25
+ spawnedChildren[actor.id] = actor;
26
+ return actor;
27
+ } else {
28
+ const actor = createActor(src, {
29
+ id: options?.id,
30
+ parent: actorScope.self,
31
+ syncSnapshot: options?.syncSnapshot,
32
+ input: options?.input,
33
+ src,
34
+ systemId: options?.systemId
35
+ });
36
+ return actor;
37
+ }
38
+ };
39
+ return (src, options) => {
40
+ const actor = spawn(src, options); // TODO: fix types
41
+ spawnedChildren[actor.id] = actor;
42
+ actorScope.defer(() => {
43
+ if (actor._processingStatus === ProcessingStatus.Stopped) {
44
+ return;
45
+ }
46
+ actor.start();
47
+ });
48
+ return actor;
49
+ };
50
+ }
51
+
52
+ const cache = new WeakMap();
53
+ function memo(object, key, fn) {
54
+ let memoizedData = cache.get(object);
55
+ if (!memoizedData) {
56
+ memoizedData = {
57
+ [key]: fn()
58
+ };
59
+ cache.set(object, memoizedData);
60
+ } else if (!(key in memoizedData)) {
61
+ memoizedData[key] = fn();
62
+ }
63
+ return memoizedData[key];
64
+ }
65
+
66
+ const EMPTY_OBJECT = {};
67
+ const CHOICE_CONFIG_KEYS = ['invoke', 'after', 'on', 'entry', 'exit', 'always', 'states', 'initial', 'onDone', 'timeout', 'onTimeout', 'history', 'target', 'output'];
68
+ class StateNode {
69
+ constructor(/** The raw config used to create the machine. */
70
+ config, options) {
71
+ this.config = config;
72
+ /**
73
+ * The relative key of the state node, which represents its location in the
74
+ * overall state value.
75
+ */
76
+ this.key = void 0;
77
+ /** The unique ID of the state node. */
78
+ this.id = void 0;
79
+ /**
80
+ * The type of this state node:
81
+ *
82
+ * - `'atomic'` - no child state nodes
83
+ * - `'compound'` - nested child state nodes (XOR)
84
+ * - `'parallel'` - orthogonal nested child state nodes (AND)
85
+ * - `'history'` - history state node
86
+ * - `'choice'` - pure routing decision state node
87
+ * - `'final'` - final state node
88
+ */
89
+ this.type = void 0;
90
+ /** The string path from the root machine node to this node. */
91
+ this.path = void 0;
92
+ /** The child state nodes. */
93
+ this.states = void 0;
94
+ /**
95
+ * The type of history on this state node. Can be:
96
+ *
97
+ * - `'shallow'` - recalls only top-level historical state value
98
+ * - `'deep'` - recalls historical state value at all levels
99
+ */
100
+ this.history = void 0;
101
+ /** The action(s) to be executed upon entering the state node. */
102
+ this.entry = void 0;
103
+ /** The action(s) to be executed upon exiting the state node. */
104
+ this.exit = void 0;
105
+ /** The parent state node. */
106
+ this.parent = void 0;
107
+ /** The root machine node. */
108
+ this.machine = void 0;
109
+ /**
110
+ * The meta data associated with this state node, which will be returned in
111
+ * State instances.
112
+ */
113
+ this.meta = void 0;
114
+ /**
115
+ * The output data sent with the "xstate.done.state._id_" event if this is a
116
+ * final state node.
117
+ */
118
+ this.output = void 0;
119
+ /**
120
+ * The order this state node appears. Corresponds to the implicit document
121
+ * order.
122
+ */
123
+ this.order = -1;
124
+ this.description = void 0;
125
+ this.tags = [];
126
+ this.transitions = void 0;
127
+ this.always = void 0;
128
+ this.invoke = void 0;
129
+ this.on = void 0;
130
+ this.after = void 0;
131
+ this.events = void 0;
132
+ this.ownEvents = void 0;
133
+ this.parent = options._parent;
134
+ this.key = options._key;
135
+ this.machine = options._machine;
136
+ this.path = this.parent ? this.parent.path.concat(this.key) : [];
137
+ const firstStateKey = this.config.states ? Object.keys(this.config.states)[0] : undefined;
138
+ this.id = this.config.id || [this.machine.id, ...this.path].join(STATE_DELIMITER);
139
+ this.type = this.config.type || (firstStateKey !== undefined ? 'compound' : this.config.history ? 'history' : 'atomic');
140
+ this.description = this.config.description;
141
+ validateStateNodeConfig(this);
142
+ this.order = this.machine.idMap.size;
143
+ this.machine.idMap.set(this.id, this);
144
+ this.states = this.config.states ? mapValues(this.config.states, (stateConfig, key) => {
145
+ const stateNode = new StateNode(stateConfig, {
146
+ _parent: this,
147
+ _key: key,
148
+ _machine: this.machine
149
+ });
150
+ return stateNode;
151
+ }) : EMPTY_OBJECT;
152
+ if (this.type === 'compound' && !this.config.initial) {
153
+ throw new Error(`No initial state specified for compound state node "#${this.id}".`);
154
+ }
155
+
156
+ // History config
157
+ this.history = this.config.history === true ? 'shallow' : this.config.history || false;
158
+ this.entry = this.config.entry;
159
+ this.exit = this.config.exit;
160
+ if (this.entry) {
161
+ // @ts-expect-error _special is an internal marker not on the Action type
162
+ this.entry._special = true;
163
+ }
164
+ if (this.exit) {
165
+ // @ts-expect-error _special is an internal marker not on the Action type
166
+ this.exit._special = true;
167
+ }
168
+ this.meta = this.config.meta;
169
+ this.output = this.type === 'final' || !this.parent ? this.config.output : undefined;
170
+ this.tags = toArray(config.tags).slice();
171
+ this.invoke = toArray(this.config.invoke).map((invokeConfig, i) => {
172
+ const {
173
+ src,
174
+ systemId
175
+ } = invokeConfig;
176
+ const invokeId = createInvokeId(this.id, i);
177
+ const resolvedId = invokeConfig.id ?? invokeId;
178
+ // Referenced (string) actors keep their logical name so persisted
179
+ // snapshots reference `src: 'fetchUser'` rather than a positional id;
180
+ // only inline logic gets the synthetic source name.
181
+ const sourceName = typeof src === 'string' ? src : `xstate.invoke.${invokeId}`;
182
+ return {
183
+ ...invokeConfig,
184
+ src: sourceName,
185
+ logic: src,
186
+ id: resolvedId,
187
+ systemId
188
+ };
189
+ });
190
+ }
191
+
192
+ /** @internal */
193
+ _initialize() {
194
+ this.after = getDelayedTransitions(this);
195
+ this.transitions = formatTransitions(this);
196
+ if (this.type === 'choice') {
197
+ this.always = formatChoiceTransitions(this);
198
+ } else if (this.config.always) {
199
+ this.always = mapTransitionConfigs(this.config.always, transition => formatTransition(this, NULL_EVENT, transition));
200
+ }
201
+ for (const key of Object.keys(this.states)) {
202
+ this.states[key]._initialize();
203
+ }
204
+ this._refreshEventMetadata();
205
+ }
206
+
207
+ /** @internal */
208
+ _refreshEventMetadata() {
209
+ const on = {};
210
+ const ownEvents = [];
211
+ for (const [descriptor, transitions] of this.transitions) {
212
+ on[descriptor] = transitions.slice();
213
+ if (transitions.some(transition => transition.target || transition.reenter || transition.to)) {
214
+ ownEvents.push(descriptor);
215
+ }
216
+ }
217
+ this.on = on;
218
+ this.ownEvents = ownEvents;
219
+ const events = new Set(ownEvents);
220
+ for (const state of Object.values(this.states)) {
221
+ for (const event of state.events) {
222
+ events.add(event);
223
+ }
224
+ }
225
+ this.events = Array.from(events);
226
+ }
227
+ get initial() {
228
+ return memo(this, 'initial', () => formatInitialTransition(this, this.config.initial));
229
+ }
230
+
231
+ /** @internal */
232
+ next(snapshot, event, self) {
233
+ const eventType = event.type;
234
+ const candidates = memo(this, `candidates-${eventType}`, () => getCandidates(this, eventType));
235
+ for (const candidate of candidates) {
236
+ const guardPassed = evaluateCandidate(candidate, event, snapshot, this, self);
237
+ if (guardPassed) {
238
+ return [candidate];
239
+ }
240
+ }
241
+ return undefined;
242
+ }
243
+ }
244
+ function validateStateNodeConfig(stateNode) {
245
+ const config = stateNode.config;
246
+ if (stateNode.type !== 'choice') {
247
+ if (config.choice !== undefined) {
248
+ throw new Error(`State "${stateNode.id}" has \`choice\`, but \`choice\` can only be used with \`type: 'choice'\`.`);
249
+ }
250
+ return;
251
+ }
252
+ if (typeof config.choice !== 'function') {
253
+ throw new Error(`Choice state "${stateNode.id}" must declare a \`choice\` function.`);
254
+ }
255
+ for (const key of CHOICE_CONFIG_KEYS) {
256
+ if (config[key] !== undefined) {
257
+ throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\`.`);
258
+ }
259
+ }
260
+ }
261
+ function formatChoiceTransitions(stateNode) {
262
+ const choice = stateNode.config.choice;
263
+ const validateChoiceResult = result => {
264
+ if (!result || result.target === undefined) {
265
+ throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
266
+ }
267
+ for (const key of ['actions', 'to', 'context']) {
268
+ if (result[key] !== undefined) {
269
+ throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
270
+ }
271
+ }
272
+ return result;
273
+ };
274
+ return [formatTransition(stateNode, NULL_EVENT, {
275
+ to: args => validateChoiceResult(choice(args))
276
+ })];
277
+ }
278
+ function mapTransitionConfigs(transitionsConfig, mapper) {
279
+ const transitionConfigs = toTransitionConfigArray(transitionsConfig);
280
+ const transitions = new Array(transitionConfigs.length);
281
+ for (let i = 0; i < transitionConfigs.length; i++) {
282
+ transitions[i] = mapper(transitionConfigs[i]);
283
+ }
284
+ return transitions;
285
+ }
286
+ function formatTransitions(stateNode) {
287
+ const transitions = new Map();
288
+ if (stateNode.config.on) {
289
+ for (const descriptor of Object.keys(stateNode.config.on)) {
290
+ if (descriptor === NULL_EVENT) {
291
+ throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
292
+ }
293
+ const transitionsConfig = stateNode.config.on[descriptor];
294
+ transitions.set(descriptor, mapTransitionConfigs(transitionsConfig, transition => formatTransition(stateNode, descriptor, transition)));
295
+ }
296
+ }
297
+ if (stateNode.config.onDone) {
298
+ const descriptor = `xstate.done.state.${stateNode.id}`;
299
+ transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onDone, transition => formatTransition(stateNode, descriptor, transition)));
300
+ }
301
+ const createCancelInvokeTimeoutTransition = (descriptor, timeoutEventType) => formatTransition(stateNode, descriptor, {
302
+ to: (_args, enq) => {
303
+ enq.cancel(timeoutEventType);
304
+ return {};
305
+ }
306
+ });
307
+ const formatInvokeCompletionTransition = (descriptor, transitionConfig, timeoutEventType) => {
308
+ const {
309
+ target,
310
+ to,
311
+ reenter,
312
+ ...rest
313
+ } = transitionConfig;
314
+ return formatTransition(stateNode, descriptor, {
315
+ ...rest,
316
+ reenter,
317
+ to: (args, enq) => {
318
+ if (to) {
319
+ let didEnqueue = false;
320
+ const trackingEnqueue = new Proxy(enq, {
321
+ apply(target, thisArg, argArray) {
322
+ didEnqueue = true;
323
+ return Reflect.apply(target, thisArg, argArray);
324
+ },
325
+ get(target, prop, receiver) {
326
+ const value = Reflect.get(target, prop, receiver);
327
+ if (typeof value !== 'function') {
328
+ return value;
329
+ }
330
+ return (...argArray) => {
331
+ didEnqueue = true;
332
+ return value.apply(target, argArray);
333
+ };
334
+ }
335
+ });
336
+ const result = to(args, trackingEnqueue);
337
+ if (result !== undefined || didEnqueue) {
338
+ enq.cancel(timeoutEventType);
339
+ }
340
+ return result;
341
+ }
342
+ enq.cancel(timeoutEventType);
343
+ return {
344
+ target,
345
+ reenter
346
+ };
347
+ }
348
+ });
349
+ };
350
+ for (const invokeDef of stateNode.invoke) {
351
+ const invokeTimeoutEventType = invokeDef.timeout !== undefined ? createInvokeTimeoutEvent(invokeDef.id).type : undefined;
352
+ if (invokeDef.onDone) {
353
+ const descriptor = `xstate.done.actor.${invokeDef.id}`;
354
+ const invokeDoneTransitions = mapTransitionConfigs(invokeDef.onDone, transition => invokeTimeoutEventType ? formatInvokeCompletionTransition(descriptor, transition, invokeTimeoutEventType) : formatTransition(stateNode, descriptor, transition));
355
+ if (invokeTimeoutEventType) {
356
+ invokeDoneTransitions.push(createCancelInvokeTimeoutTransition(descriptor, invokeTimeoutEventType));
357
+ }
358
+ transitions.set(descriptor, invokeDoneTransitions);
359
+ } else if (invokeTimeoutEventType) {
360
+ const descriptor = `xstate.done.actor.${invokeDef.id}`;
361
+ transitions.set(descriptor, [createCancelInvokeTimeoutTransition(descriptor, invokeTimeoutEventType)]);
362
+ }
363
+ if (invokeDef.onError) {
364
+ const descriptor = `xstate.error.actor.${invokeDef.id}`;
365
+ transitions.set(descriptor, mapTransitionConfigs(invokeDef.onError, transition => invokeTimeoutEventType ? formatInvokeCompletionTransition(descriptor, transition, invokeTimeoutEventType) : formatTransition(stateNode, descriptor, transition)));
366
+ }
367
+ if (invokeDef.onSnapshot) {
368
+ const descriptor = `xstate.snapshot.${invokeDef.id}`;
369
+ transitions.set(descriptor, mapTransitionConfigs(invokeDef.onSnapshot, transition => formatTransition(stateNode, descriptor, transition)));
370
+ }
371
+ }
372
+ for (const delayedTransition of stateNode.after) {
373
+ let existing = transitions.get(delayedTransition.eventType);
374
+ if (!existing) {
375
+ existing = [];
376
+ transitions.set(delayedTransition.eventType, existing);
377
+ }
378
+ existing.push(delayedTransition);
379
+ }
380
+ return transitions;
381
+ }
382
+ function formatInitialTransition(stateNode, _target) {
383
+ const targetString = typeof _target === 'object' && _target !== null ? _target.target : _target;
384
+ const input = typeof _target === 'object' && _target !== null ? _target.input : undefined;
385
+ const resolvedTarget = typeof targetString === 'string' ? stateNode.states[targetString] : undefined;
386
+ if (!resolvedTarget && targetString) {
387
+ throw new Error(`Initial state node "${targetString}" not found on parent state node #${stateNode.id}`);
388
+ }
389
+ const transition = {
390
+ source: stateNode,
391
+ target: resolvedTarget ? [resolvedTarget] : undefined,
392
+ input
393
+ };
394
+ return transition;
395
+ }
396
+
397
+ const STATE_IDENTIFIER = '#';
398
+ class StateMachine {
399
+ constructor(/** The raw config used to create the machine. */
400
+ config, implementations) {
401
+ this.config = config;
402
+ /** The machine's own version. */
403
+ this.version = void 0;
404
+ this.schemas = void 0;
405
+ this.implementations = void 0;
406
+ /** Runtime options for machine execution. */
407
+ this.options = void 0;
408
+ /** @internal */
409
+ this.idMap = new Map();
410
+ this.root = void 0;
411
+ this.id = void 0;
412
+ this.states = void 0;
413
+ this.events = void 0;
414
+ this.internalEventDescriptors = void 0;
415
+ /**
416
+ * The original JSON definition this machine was created from (set by
417
+ * `createMachineFromConfig`), if any. Used by `serializeMachine` for lossless
418
+ * round-trips.
419
+ *
420
+ * @internal
421
+ */
422
+ this._json = void 0;
423
+ this.id = config.id || '(machine)';
424
+ this.implementations = {
425
+ actors: config.actors ?? {},
426
+ actions: config.actions ?? {},
427
+ delays: config.delays ?? {},
428
+ guards: config.guards ?? {},
429
+ ...implementations
430
+ };
431
+ this.version = this.config.version;
432
+ this.schemas = this.config.schemas;
433
+ this.internalEventDescriptors = this.config.internalEvents ?? [];
434
+ this.options = {
435
+ maxIterations: Infinity,
436
+ ...this.config.options
437
+ };
438
+ this.transition = this.transition.bind(this);
439
+ this.getInitialSnapshot = this.getInitialSnapshot.bind(this);
440
+ this.getPersistedSnapshot = this.getPersistedSnapshot.bind(this);
441
+ this.restoreSnapshot = this.restoreSnapshot.bind(this);
442
+ this.start = this.start.bind(this);
443
+ this.root = new StateNode(config, {
444
+ _key: this.id,
445
+ _machine: this
446
+ });
447
+ this.root._initialize();
448
+ formatRouteTransitions(this.root);
449
+ this.root._refreshEventMetadata();
450
+ this.states = this.root.states; // TODO: remove!
451
+ this.events = this.root.events;
452
+ }
453
+
454
+ /**
455
+ * Clones this state machine with the provided implementations.
456
+ *
457
+ * @param implementations Options (`actions`, `guards`, `actors`, `delays`) to
458
+ * recursively merge with the existing options.
459
+ * @returns A new `StateMachine` instance with the provided implementations.
460
+ */
461
+ provide(implementations) {
462
+ const {
463
+ actions,
464
+ guards,
465
+ actors,
466
+ delays
467
+ } = this.implementations;
468
+ const provided = new StateMachine(this.config, {
469
+ actions: {
470
+ ...actions,
471
+ ...implementations.actions
472
+ },
473
+ guards: {
474
+ ...guards,
475
+ ...implementations.guards
476
+ },
477
+ actors: {
478
+ ...actors,
479
+ ...implementations.actors
480
+ },
481
+ delays: {
482
+ ...delays,
483
+ ...implementations.delays
484
+ }
485
+ });
486
+ // Providing implementations does not change the serializable definition.
487
+ provided._json = this._json;
488
+ return provided;
489
+ }
490
+ resolveState(config) {
491
+ const resolvedStateValue = resolveStateValue(this.root, config.value);
492
+ const nodeSet = getAllStateNodes(getStateNodes(this.root, resolvedStateValue));
493
+ const nodes = [...nodeSet];
494
+ return createMachineSnapshot({
495
+ _nodes: nodes,
496
+ value: resolvedStateValue,
497
+ context: config.context || {},
498
+ children: {},
499
+ status: isInFinalState(nodeSet, this.root) ? 'done' : config.status || 'active',
500
+ output: config.output,
501
+ error: config.error,
502
+ historyValue: config.historyValue
503
+ }, this);
504
+ }
505
+
506
+ /**
507
+ * Determines the next snapshot given the current `snapshot` and received
508
+ * `event`. Calculates a full macrostep from all microsteps.
509
+ *
510
+ * @param snapshot The current snapshot
511
+ * @param event The received event
512
+ */
513
+ transition(snapshot, event, actorScope) {
514
+ return macrostep(snapshot, event, actorScope, []).snapshot;
515
+ }
516
+
517
+ /**
518
+ * Determines the next state given the current `state` and `event`. Calculates
519
+ * a microstep.
520
+ *
521
+ * @param state The current state
522
+ * @param event The received event
523
+ */
524
+ microstep(snapshot, event, actorScope) {
525
+ const {
526
+ microsteps
527
+ } = macrostep(snapshot, event, actorScope, []);
528
+ const snapshots = new Array(microsteps.length);
529
+ for (let i = 0; i < microsteps.length; i++) {
530
+ snapshots[i] = microsteps[i][0];
531
+ }
532
+ return snapshots;
533
+ }
534
+ getTransitionData(snapshot, event, self) {
535
+ return transitionNode(this.root, snapshot.value, snapshot, event, self) || [];
536
+ }
537
+ isInternalEventType(eventType) {
538
+ for (const descriptor of this.internalEventDescriptors) {
539
+ if (matchesEventDescriptor(eventType, descriptor)) {
540
+ return true;
541
+ }
542
+ }
543
+ return false;
544
+ }
545
+
546
+ /**
547
+ * The initial state _before_ evaluating any microsteps. This "pre-initial"
548
+ * state is provided to initial actions executed in the initial state.
549
+ *
550
+ * @internal
551
+ */
552
+ _getPreInitialState(actorScope, initEvent) {
553
+ const {
554
+ context
555
+ } = this.config;
556
+ const preInitial = createMachineSnapshot({
557
+ context: typeof context !== 'function' && context ? context : {},
558
+ _nodes: [this.root],
559
+ children: {},
560
+ status: 'active'
561
+ }, this);
562
+ if (typeof context === 'function') {
563
+ const children = {};
564
+ const spawn = createSpawner(actorScope, preInitial, initEvent, children);
565
+ const resolvedContext = context({
566
+ spawn,
567
+ input: initEvent.input,
568
+ self: actorScope.self,
569
+ actors: this.implementations.actors
570
+ });
571
+ const nextState = resolveAndExecuteActionsWithContext(preInitial, initEvent, actorScope, []);
572
+ if (resolvedContext) {
573
+ nextState.context = resolvedContext;
574
+ }
575
+ if (Object.keys(children).length > 0) {
576
+ nextState.children = {
577
+ ...nextState.children,
578
+ ...children
579
+ };
580
+ }
581
+ return nextState;
582
+ }
583
+ return preInitial;
584
+ }
585
+
586
+ /**
587
+ * Returns the initial `State` instance, with reference to `self` as an
588
+ * `ActorRef`.
589
+ */
590
+ getInitialSnapshot(actorScope, input) {
591
+ const initEvent = createInitEvent(input); // TODO: fix;
592
+ const internalQueue = [];
593
+ const preInitialState = this._getPreInitialState(actorScope, initEvent);
594
+ const [nextState] = initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
595
+ const {
596
+ snapshot: macroState
597
+ } = macrostep(nextState, initEvent, actorScope, internalQueue);
598
+ return macroState;
599
+ }
600
+ start(snapshot) {
601
+ // Start rehydrated children that were active when persisted. Freshly
602
+ // invoked/spawned children are NOT started here — they start via deferred
603
+ // `@xstate.start` actions so sync start errors route to `onError`.
604
+ if (!snapshot?.children) {
605
+ return;
606
+ }
607
+ for (const child of Object.values(snapshot.children)) {
608
+ if (child._rehydrated && child.getSnapshot?.().status === 'active') {
609
+ child.start();
610
+ }
611
+ }
612
+ }
613
+ getStateNodeById(stateId) {
614
+ const fullPath = toStatePath(stateId);
615
+ const relativePath = fullPath.slice(1);
616
+ const resolvedStateId = isStateId(fullPath[0]) ? fullPath[0].slice(STATE_IDENTIFIER.length) : fullPath[0];
617
+ const stateNode = this.idMap.get(resolvedStateId);
618
+ if (!stateNode) {
619
+ throw new Error(`Child state node '#${resolvedStateId}' does not exist on machine '${this.id}'`);
620
+ }
621
+ return getStateNodeByPath(stateNode, relativePath);
622
+ }
623
+ getPersistedSnapshot(snapshot, options) {
624
+ return getPersistedSnapshot(snapshot, options);
625
+ }
626
+ restoreSnapshot(snapshot, _actorScope) {
627
+ const persistedVersion = snapshot.version;
628
+ if (persistedVersion !== this.version) {
629
+ const migrate = this.config.migrate;
630
+ if (typeof migrate !== 'function') {
631
+ throw new Error(`Persisted snapshot version '${persistedVersion}' does not match machine version '${this.version}'.`);
632
+ }
633
+ snapshot = migrate(snapshot, persistedVersion);
634
+ }
635
+ const snapshotData = snapshot;
636
+ const children = {};
637
+ const snapshotChildren = snapshotData.children;
638
+ for (const actorId of Object.keys(snapshotChildren)) {
639
+ const actorData = snapshotChildren[actorId];
640
+ const childState = actorData.snapshot;
641
+ const src = actorData.src;
642
+ const logic = typeof src === 'string' ? resolveReferencedActor(this, src) : src;
643
+ if (!logic) {
644
+ continue;
645
+ }
646
+ const actor = createActor(logic, {
647
+ id: actorId,
648
+ parent: _actorScope.self,
649
+ syncSnapshot: actorData.syncSnapshot,
650
+ snapshot: childState,
651
+ src,
652
+ systemId: actorData.systemId
653
+ });
654
+ // Mark so `start()` knows to start this child (freshly invoked/spawned
655
+ // children are started via deferred `@xstate.start` actions instead).
656
+ actor._rehydrated = true;
657
+ children[actorId] = actor;
658
+ }
659
+ const reviveHistoryValue = historyValue => {
660
+ if (!historyValue || typeof historyValue !== 'object') {
661
+ return {};
662
+ }
663
+ const revived = {};
664
+ for (const key of Object.keys(historyValue)) {
665
+ const arr = historyValue[key];
666
+ for (const item of arr) {
667
+ let resolved;
668
+ if (item instanceof StateNode) {
669
+ resolved = item;
670
+ } else {
671
+ try {
672
+ resolved = this.root.machine.getStateNodeById(item.id);
673
+ } catch {
674
+ }
675
+ }
676
+ if (!resolved) {
677
+ continue;
678
+ }
679
+ revived[key] ??= [];
680
+ revived[key].push(resolved);
681
+ }
682
+ }
683
+ return revived;
684
+ };
685
+ const revivedHistoryValue = reviveHistoryValue(snapshotData.historyValue);
686
+ const nodes = Array.from(getAllStateNodes(getStateNodes(this.root, snapshotData.value)));
687
+ const {
688
+ version: _persistedSnapshotVersion,
689
+ ...persistedRest
690
+ } = snapshot;
691
+ const restoredSnapshot = createMachineSnapshot({
692
+ ...persistedRest,
693
+ children,
694
+ _nodes: nodes,
695
+ value: snapshotData.value,
696
+ historyValue: revivedHistoryValue
697
+ }, this);
698
+ const seen = new WeakSet();
699
+ function reviveContext(contextPart) {
700
+ if (seen.has(contextPart)) {
701
+ return;
702
+ }
703
+ seen.add(contextPart);
704
+ for (const key of Object.keys(contextPart)) {
705
+ const value = contextPart[key];
706
+ if (value && typeof value === 'object') {
707
+ if ('xstate$$type' in value && value.xstate$$type === $$ACTOR_TYPE) {
708
+ contextPart[key] = children[value.id];
709
+ continue;
710
+ }
711
+ reviveContext(value);
712
+ }
713
+ }
714
+ }
715
+ reviveContext(restoredSnapshot.context);
716
+ return restoredSnapshot;
717
+ }
718
+ }
719
+
720
+ export { StateMachine as S, StateNode as a };