xstate 5.0.0-alpha.6 → 5.0.0-beta.11
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.
- package/actions/dist/xstate-actions.cjs.d.mts +2 -0
- package/actions/dist/xstate-actions.cjs.d.mts.map +1 -0
- package/actions/dist/xstate-actions.cjs.d.ts +1 -0
- package/actions/dist/xstate-actions.cjs.d.ts.map +1 -0
- package/actions/dist/xstate-actions.cjs.js +29 -5
- package/actions/dist/xstate-actions.cjs.mjs +24 -0
- package/actions/dist/{xstate-actions.cjs.dev.js → xstate-actions.development.cjs.js} +3 -3
- package/actions/dist/xstate-actions.development.esm.js +2 -0
- package/actions/dist/xstate-actions.esm.js +2 -2
- package/actions/dist/xstate-actions.umd.min.js +1 -1
- package/actions/dist/xstate-actions.umd.min.js.map +1 -1
- package/actors/dist/xstate-actors.cjs.d.mts +2 -0
- package/actors/dist/xstate-actors.cjs.d.mts.map +1 -0
- package/actors/dist/xstate-actors.cjs.d.ts +1 -0
- package/actors/dist/xstate-actors.cjs.d.ts.map +1 -0
- package/actors/dist/xstate-actors.cjs.js +20 -5
- package/actors/dist/xstate-actors.cjs.mjs +15 -0
- package/actors/dist/{xstate-actors.cjs.dev.js → xstate-actors.development.cjs.js} +3 -2
- package/actors/dist/xstate-actors.development.esm.js +2 -0
- package/actors/dist/xstate-actors.esm.js +2 -2
- package/actors/dist/xstate-actors.umd.min.js +1 -1
- package/actors/dist/xstate-actors.umd.min.js.map +1 -1
- package/dev/dist/xstate-dev.cjs.d.mts +2 -0
- package/dev/dist/xstate-dev.cjs.d.mts.map +1 -0
- package/dev/dist/xstate-dev.cjs.d.ts +1 -0
- package/dev/dist/xstate-dev.cjs.d.ts.map +1 -0
- package/dev/dist/xstate-dev.cjs.js +45 -4
- package/dev/dist/xstate-dev.cjs.mjs +5 -0
- package/{dist/index-ebaab3c9.cjs.dev.js → dev/dist/xstate-dev.development.cjs.js} +6 -7
- package/{dist/index-50bd0aff.esm.js → dev/dist/xstate-dev.development.esm.js} +6 -8
- package/dev/dist/xstate-dev.esm.js +42 -1
- package/dev/dist/xstate-dev.umd.min.js +1 -1
- package/dev/dist/xstate-dev.umd.min.js.map +1 -1
- package/dist/actions-26f9aa9d.cjs.js +3388 -0
- package/dist/actions-acbe7aa1.development.cjs.js +3423 -0
- package/dist/actions-b82e841e.esm.js +3306 -0
- package/dist/actions-cff79077.development.esm.js +3341 -0
- package/dist/declarations/src/State.d.ts +2 -3
- package/dist/declarations/src/StateMachine.d.ts +6 -6
- package/dist/declarations/src/StateNode.d.ts +3 -9
- package/dist/declarations/src/actions/send.d.ts +0 -7
- package/dist/declarations/src/actions.d.ts +9 -8
- package/dist/declarations/src/actors/index.d.ts +2 -1
- package/dist/declarations/src/actors/observable.d.ts +1 -2
- package/dist/declarations/src/actors/promise.d.ts +1 -2
- package/dist/declarations/src/guards.d.ts +2 -2
- package/dist/declarations/src/index.d.ts +13 -29
- package/dist/declarations/src/interpreter.d.ts +5 -4
- package/dist/declarations/src/stateUtils.d.ts +9 -14
- package/dist/declarations/src/typegenTypes.d.ts +7 -1
- package/dist/declarations/src/types.d.ts +18 -92
- package/dist/declarations/src/utils.d.ts +3 -6
- package/dist/declarations/src/waitFor.d.ts +33 -0
- package/dist/xstate.cjs.d.mts +2 -0
- package/dist/xstate.cjs.d.mts.map +1 -0
- package/dist/xstate.cjs.d.ts +1 -0
- package/dist/xstate.cjs.d.ts.map +1 -0
- package/dist/xstate.cjs.js +802 -4
- package/dist/xstate.cjs.mjs +38 -0
- package/dist/xstate.development.cjs.js +808 -0
- package/dist/xstate.development.esm.js +770 -0
- package/dist/xstate.esm.js +594 -706
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/guards/dist/xstate-guards.cjs.d.mts +2 -0
- package/guards/dist/xstate-guards.cjs.d.mts.map +1 -0
- package/guards/dist/xstate-guards.cjs.d.ts +1 -0
- package/guards/dist/xstate-guards.cjs.d.ts.map +1 -0
- package/guards/dist/xstate-guards.cjs.js +13 -5
- package/guards/dist/xstate-guards.cjs.mjs +8 -0
- package/guards/dist/{xstate-guards.cjs.dev.js → xstate-guards.development.cjs.js} +2 -2
- package/guards/dist/xstate-guards.development.esm.js +2 -0
- package/guards/dist/xstate-guards.esm.js +2 -2
- package/guards/dist/xstate-guards.umd.min.js +1 -1
- package/guards/dist/xstate-guards.umd.min.js.map +1 -1
- package/package.json +58 -1
- package/actions/dist/xstate-actions.cjs.prod.js +0 -31
- package/actors/dist/xstate-actors.cjs.prod.js +0 -21
- package/dev/dist/xstate-dev.cjs.dev.js +0 -11
- package/dev/dist/xstate-dev.cjs.prod.js +0 -48
- package/dist/actions-41b74cdc.esm.js +0 -4287
- package/dist/actions-bf7bb1c5.cjs.dev.js +0 -4342
- package/dist/actions-c46e4911.cjs.prod.js +0 -4304
- package/dist/declarations/actions/dynamicAction.d.ts +0 -5
- package/dist/declarations/src/Mailbox.d.ts +0 -12
- package/dist/declarations/src/actions/invoke.d.ts +0 -3
- package/dist/declarations/src/environment.d.ts +0 -1
- package/dist/declarations/src/memo.d.ts +0 -2
- package/dist/declarations/src/schema.d.ts +0 -2
- package/dist/declarations/src/spawn.d.ts +0 -2
- package/dist/declarations/src/system.d.ts +0 -2
- package/dist/xstate.cjs.dev.js +0 -921
- package/dist/xstate.cjs.prod.js +0 -921
- package/guards/dist/xstate-guards.cjs.prod.js +0 -15
package/dist/xstate.cjs.js
CHANGED
|
@@ -1,7 +1,805 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var actors_dist_xstateActors = require('./actions-26f9aa9d.cjs.js');
|
|
6
|
+
require('../dev/dist/xstate-dev.cjs.js');
|
|
7
|
+
|
|
8
|
+
const EMPTY_OBJECT = {};
|
|
9
|
+
class StateNode {
|
|
10
|
+
/**
|
|
11
|
+
* The relative key of the state node, which represents its location in the overall state value.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The unique ID of the state node.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The type of this state node:
|
|
20
|
+
*
|
|
21
|
+
* - `'atomic'` - no child state nodes
|
|
22
|
+
* - `'compound'` - nested child state nodes (XOR)
|
|
23
|
+
* - `'parallel'` - orthogonal nested child state nodes (AND)
|
|
24
|
+
* - `'history'` - history state node
|
|
25
|
+
* - `'final'` - final state node
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The string path from the root machine node to this node.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The child state nodes.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The type of history on this state node. Can be:
|
|
38
|
+
*
|
|
39
|
+
* - `'shallow'` - recalls only top-level historical state value
|
|
40
|
+
* - `'deep'` - recalls historical state value at all levels
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The action(s) to be executed upon entering the state node.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The action(s) to be executed upon exiting the state node.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The parent state node.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The root machine node.
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The meta data associated with this state node, which will be returned in State instances.
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The output data sent with the "done.state._id_" event if this is a final state node.
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The order this state node appears. Corresponds to the implicit document order.
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
constructor(
|
|
72
|
+
/**
|
|
73
|
+
* The raw config used to create the machine.
|
|
74
|
+
*/
|
|
75
|
+
config, options) {
|
|
76
|
+
this.config = config;
|
|
77
|
+
this.key = void 0;
|
|
78
|
+
this.id = void 0;
|
|
79
|
+
this.type = void 0;
|
|
80
|
+
this.path = void 0;
|
|
81
|
+
this.states = void 0;
|
|
82
|
+
this.history = void 0;
|
|
83
|
+
this.entry = void 0;
|
|
84
|
+
this.exit = void 0;
|
|
85
|
+
this.parent = void 0;
|
|
86
|
+
this.machine = void 0;
|
|
87
|
+
this.meta = void 0;
|
|
88
|
+
this.output = void 0;
|
|
89
|
+
this.order = -1;
|
|
90
|
+
this.description = void 0;
|
|
91
|
+
this.tags = [];
|
|
92
|
+
this.transitions = void 0;
|
|
93
|
+
this.always = void 0;
|
|
94
|
+
this.parent = options._parent;
|
|
95
|
+
this.key = options._key;
|
|
96
|
+
this.machine = options._machine;
|
|
97
|
+
this.path = this.parent ? this.parent.path.concat(this.key) : [];
|
|
98
|
+
this.id = this.config.id || [this.machine.id, ...this.path].join(this.machine.delimiter);
|
|
99
|
+
this.type = this.config.type || (this.config.states && Object.keys(this.config.states).length ? 'compound' : this.config.history ? 'history' : 'atomic');
|
|
100
|
+
this.description = this.config.description;
|
|
101
|
+
this.order = this.machine.idMap.size;
|
|
102
|
+
this.machine.idMap.set(this.id, this);
|
|
103
|
+
this.states = this.config.states ? actors_dist_xstateActors.mapValues(this.config.states, (stateConfig, key) => {
|
|
104
|
+
const stateNode = new StateNode(stateConfig, {
|
|
105
|
+
_parent: this,
|
|
106
|
+
_key: key,
|
|
107
|
+
_machine: this.machine
|
|
108
|
+
});
|
|
109
|
+
return stateNode;
|
|
110
|
+
}) : EMPTY_OBJECT;
|
|
111
|
+
if (this.type === 'compound' && !this.config.initial) {
|
|
112
|
+
throw new Error(`No initial state specified for compound state node "#${this.id}". Try adding { initial: "${Object.keys(this.states)[0]}" } to the state config.`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// History config
|
|
116
|
+
this.history = this.config.history === true ? 'shallow' : this.config.history || false;
|
|
117
|
+
this.entry = actors_dist_xstateActors.toActionObjects(this.config.entry);
|
|
118
|
+
this.exit = actors_dist_xstateActors.toActionObjects(this.config.exit);
|
|
119
|
+
this.meta = this.config.meta;
|
|
120
|
+
this.output = this.type === 'final' ? this.config.output : undefined;
|
|
121
|
+
this.tags = actors_dist_xstateActors.toArray(config.tags);
|
|
122
|
+
}
|
|
123
|
+
_initialize() {
|
|
124
|
+
this.transitions = actors_dist_xstateActors.formatTransitions(this);
|
|
125
|
+
if (this.config.always) {
|
|
126
|
+
this.always = actors_dist_xstateActors.toTransitionConfigArray(actors_dist_xstateActors.NULL_EVENT, this.config.always).map(t => actors_dist_xstateActors.formatTransition(this, t));
|
|
127
|
+
}
|
|
128
|
+
Object.keys(this.states).forEach(key => {
|
|
129
|
+
this.states[key]._initialize();
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The well-structured state node definition.
|
|
135
|
+
*/
|
|
136
|
+
get definition() {
|
|
137
|
+
return {
|
|
138
|
+
id: this.id,
|
|
139
|
+
key: this.key,
|
|
140
|
+
version: this.machine.version,
|
|
141
|
+
type: this.type,
|
|
142
|
+
initial: this.initial ? {
|
|
143
|
+
target: this.initial.target,
|
|
144
|
+
source: this,
|
|
145
|
+
actions: this.initial.actions,
|
|
146
|
+
eventType: null,
|
|
147
|
+
reenter: false,
|
|
148
|
+
toJSON: () => ({
|
|
149
|
+
target: this.initial.target.map(t => `#${t.id}`),
|
|
150
|
+
source: `#${this.id}`,
|
|
151
|
+
actions: this.initial.actions,
|
|
152
|
+
eventType: null
|
|
153
|
+
})
|
|
154
|
+
} : undefined,
|
|
155
|
+
history: this.history,
|
|
156
|
+
states: actors_dist_xstateActors.mapValues(this.states, state => {
|
|
157
|
+
return state.definition;
|
|
158
|
+
}),
|
|
159
|
+
on: this.on,
|
|
160
|
+
transitions: this.transitions,
|
|
161
|
+
entry: this.entry,
|
|
162
|
+
exit: this.exit,
|
|
163
|
+
meta: this.meta,
|
|
164
|
+
order: this.order || -1,
|
|
165
|
+
output: this.output,
|
|
166
|
+
invoke: this.invoke,
|
|
167
|
+
description: this.description,
|
|
168
|
+
tags: this.tags
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
toJSON() {
|
|
172
|
+
return this.definition;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The behaviors invoked as actors by this state node.
|
|
177
|
+
*/
|
|
178
|
+
get invoke() {
|
|
179
|
+
return actors_dist_xstateActors.memo(this, 'invoke', () => actors_dist_xstateActors.toArray(this.config.invoke).map((invocable, i) => {
|
|
180
|
+
const generatedId = actors_dist_xstateActors.createInvokeId(this.id, i);
|
|
181
|
+
const invokeConfig = actors_dist_xstateActors.toInvokeConfig(invocable, generatedId);
|
|
182
|
+
const resolvedId = invokeConfig.id || generatedId;
|
|
183
|
+
const {
|
|
184
|
+
src,
|
|
185
|
+
systemId
|
|
186
|
+
} = invokeConfig;
|
|
187
|
+
const resolvedSrc = actors_dist_xstateActors.isString(src) ? src : !('type' in src) ? resolvedId : src;
|
|
188
|
+
if (!this.machine.options.actors[resolvedId] && typeof src !== 'string' && !('type' in src)) {
|
|
189
|
+
this.machine.options.actors = {
|
|
190
|
+
...this.machine.options.actors,
|
|
191
|
+
// TODO: this should accept `src` as-is
|
|
192
|
+
[resolvedId]: src
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
type: actors_dist_xstateActors.invoke,
|
|
197
|
+
...invokeConfig,
|
|
198
|
+
src: resolvedSrc,
|
|
199
|
+
id: resolvedId,
|
|
200
|
+
systemId: systemId,
|
|
201
|
+
toJSON() {
|
|
202
|
+
const {
|
|
203
|
+
onDone,
|
|
204
|
+
onError,
|
|
205
|
+
...invokeDefValues
|
|
206
|
+
} = invokeConfig;
|
|
207
|
+
return {
|
|
208
|
+
...invokeDefValues,
|
|
209
|
+
type: actors_dist_xstateActors.invoke,
|
|
210
|
+
src: resolvedSrc,
|
|
211
|
+
id: resolvedId
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* The mapping of events to transitions.
|
|
220
|
+
*/
|
|
221
|
+
get on() {
|
|
222
|
+
return actors_dist_xstateActors.memo(this, 'on', () => {
|
|
223
|
+
const transitions = this.transitions;
|
|
224
|
+
return transitions.reduce((map, transition) => {
|
|
225
|
+
map[transition.eventType] = map[transition.eventType] || [];
|
|
226
|
+
map[transition.eventType].push(transition);
|
|
227
|
+
return map;
|
|
228
|
+
}, {});
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
get after() {
|
|
232
|
+
return actors_dist_xstateActors.memo(this, 'delayedTransitions', () => actors_dist_xstateActors.getDelayedTransitions(this));
|
|
233
|
+
}
|
|
234
|
+
get initial() {
|
|
235
|
+
return actors_dist_xstateActors.memo(this, 'initial', () => actors_dist_xstateActors.formatInitialTransition(this, this.config.initial || []));
|
|
236
|
+
}
|
|
237
|
+
next(state, event) {
|
|
238
|
+
const eventType = event.type;
|
|
239
|
+
const actions = [];
|
|
240
|
+
let selectedTransition;
|
|
241
|
+
const candidates = actors_dist_xstateActors.memo(this, `candidates-${eventType}`, () => actors_dist_xstateActors.getCandidates(this, eventType));
|
|
242
|
+
for (const candidate of candidates) {
|
|
243
|
+
const {
|
|
244
|
+
guard
|
|
245
|
+
} = candidate;
|
|
246
|
+
const resolvedContext = state.context;
|
|
247
|
+
let guardPassed = false;
|
|
248
|
+
try {
|
|
249
|
+
guardPassed = !guard || actors_dist_xstateActors.evaluateGuard(guard, resolvedContext, event, state);
|
|
250
|
+
} catch (err) {
|
|
251
|
+
throw new Error(`Unable to evaluate guard '${guard.type}' in transition for event '${eventType}' in state node '${this.id}':\n${err.message}`);
|
|
252
|
+
}
|
|
253
|
+
if (guardPassed) {
|
|
254
|
+
actions.push(...candidate.actions);
|
|
255
|
+
selectedTransition = candidate;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return selectedTransition ? [selectedTransition] : undefined;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* The target state value of the history state node, if it exists. This represents the
|
|
264
|
+
* default state value to transition to if no history value exists yet.
|
|
265
|
+
*/
|
|
266
|
+
get target() {
|
|
267
|
+
if (this.type === 'history') {
|
|
268
|
+
const historyConfig = this.config;
|
|
269
|
+
return historyConfig.target;
|
|
270
|
+
}
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* All the state node IDs of this state node and its descendant state nodes.
|
|
276
|
+
*/
|
|
277
|
+
get stateIds() {
|
|
278
|
+
const childStateIds = actors_dist_xstateActors.flatten(Object.keys(this.states).map(stateKey => {
|
|
279
|
+
return this.states[stateKey].stateIds;
|
|
280
|
+
}));
|
|
281
|
+
return [this.id].concat(childStateIds);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* All the event types accepted by this state node and its descendants.
|
|
286
|
+
*/
|
|
287
|
+
get events() {
|
|
288
|
+
return actors_dist_xstateActors.memo(this, 'events', () => {
|
|
289
|
+
const {
|
|
290
|
+
states
|
|
291
|
+
} = this;
|
|
292
|
+
const events = new Set(this.ownEvents);
|
|
293
|
+
if (states) {
|
|
294
|
+
for (const stateId of Object.keys(states)) {
|
|
295
|
+
const state = states[stateId];
|
|
296
|
+
if (state.states) {
|
|
297
|
+
for (const event of state.events) {
|
|
298
|
+
events.add(`${event}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return Array.from(events);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* All the events that have transitions directly from this state node.
|
|
309
|
+
*
|
|
310
|
+
* Excludes any inert events.
|
|
311
|
+
*/
|
|
312
|
+
get ownEvents() {
|
|
313
|
+
const events = new Set(this.transitions.filter(transition => {
|
|
314
|
+
return !(!transition.target && !transition.actions.length && !transition.reenter);
|
|
315
|
+
}).map(transition => transition.eventType));
|
|
316
|
+
return Array.from(events);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const STATE_IDENTIFIER = '#';
|
|
321
|
+
function createDefaultOptions() {
|
|
322
|
+
return {
|
|
323
|
+
actions: {},
|
|
324
|
+
actors: {},
|
|
325
|
+
delays: {},
|
|
326
|
+
guards: {},
|
|
327
|
+
context: {}
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
class StateMachine {
|
|
331
|
+
// TODO: this getter should be removed
|
|
332
|
+
getContext(input) {
|
|
333
|
+
return this.getContextAndActions(undefined, input)[0];
|
|
334
|
+
}
|
|
335
|
+
getContextAndActions(actorCtx, input) {
|
|
336
|
+
const actions = [];
|
|
337
|
+
const {
|
|
338
|
+
context
|
|
339
|
+
} = this.config;
|
|
340
|
+
const resolvedContext = typeof context === 'function' ? context({
|
|
341
|
+
spawn: actors_dist_xstateActors.createSpawner(actorCtx?.self, this, undefined,
|
|
342
|
+
// TODO: this requires `| undefined` for all referenced dynamic inputs that are spawnable in the context factory,
|
|
343
|
+
actors_dist_xstateActors.createInitEvent(input), actions),
|
|
344
|
+
input
|
|
345
|
+
}) : context;
|
|
346
|
+
return [resolvedContext || {}, actions];
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* The machine's own version.
|
|
350
|
+
*/
|
|
351
|
+
|
|
352
|
+
constructor(
|
|
353
|
+
/**
|
|
354
|
+
* The raw config used to create the machine.
|
|
355
|
+
*/
|
|
356
|
+
config, options) {
|
|
357
|
+
this.config = config;
|
|
358
|
+
this.version = void 0;
|
|
359
|
+
this.delimiter = void 0;
|
|
360
|
+
this.options = void 0;
|
|
361
|
+
this.types = void 0;
|
|
362
|
+
this.__xstatenode = true;
|
|
363
|
+
this.idMap = new Map();
|
|
364
|
+
this.root = void 0;
|
|
365
|
+
this.id = void 0;
|
|
366
|
+
this.states = void 0;
|
|
367
|
+
this.events = void 0;
|
|
368
|
+
this.__TContext = void 0;
|
|
369
|
+
this.__TEvent = void 0;
|
|
370
|
+
this.__TAction = void 0;
|
|
371
|
+
this.__TActorMap = void 0;
|
|
372
|
+
this.__TResolvedTypesMeta = void 0;
|
|
373
|
+
this.id = config.id || '(machine)';
|
|
374
|
+
this.options = Object.assign(createDefaultOptions(), options);
|
|
375
|
+
this.delimiter = this.config.delimiter || actors_dist_xstateActors.STATE_DELIMITER;
|
|
376
|
+
this.version = this.config.version;
|
|
377
|
+
this.types = this.config.types ?? {};
|
|
378
|
+
this.transition = this.transition.bind(this);
|
|
379
|
+
this.root = new StateNode(config, {
|
|
380
|
+
_key: this.id,
|
|
381
|
+
_machine: this
|
|
382
|
+
});
|
|
383
|
+
this.root._initialize();
|
|
384
|
+
this.states = this.root.states; // TODO: remove!
|
|
385
|
+
this.events = this.root.events;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Clones this state machine with the provided implementations
|
|
390
|
+
* and merges the `context` (if provided).
|
|
391
|
+
*
|
|
392
|
+
* @param implementations Options (`actions`, `guards`, `actors`, `delays`, `context`)
|
|
393
|
+
* to recursively merge with the existing options.
|
|
394
|
+
*
|
|
395
|
+
* @returns A new `StateMachine` instance with the provided implementations.
|
|
396
|
+
*/
|
|
397
|
+
provide(implementations) {
|
|
398
|
+
const {
|
|
399
|
+
actions,
|
|
400
|
+
guards,
|
|
401
|
+
actors,
|
|
402
|
+
delays
|
|
403
|
+
} = this.options;
|
|
404
|
+
return new StateMachine(this.config, {
|
|
405
|
+
actions: {
|
|
406
|
+
...actions,
|
|
407
|
+
...implementations.actions
|
|
408
|
+
},
|
|
409
|
+
guards: {
|
|
410
|
+
...guards,
|
|
411
|
+
...implementations.guards
|
|
412
|
+
},
|
|
413
|
+
actors: {
|
|
414
|
+
...actors,
|
|
415
|
+
...implementations.actors
|
|
416
|
+
},
|
|
417
|
+
delays: {
|
|
418
|
+
...delays,
|
|
419
|
+
...implementations.delays
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Resolves the given `state` to a new `State` instance relative to this machine.
|
|
426
|
+
*
|
|
427
|
+
* This ensures that `.nextEvents` represent the correct values.
|
|
428
|
+
*
|
|
429
|
+
* @param state The state to resolve
|
|
430
|
+
*/
|
|
431
|
+
resolveState(state) {
|
|
432
|
+
const configurationSet = actors_dist_xstateActors.getConfiguration(actors_dist_xstateActors.getStateNodes(this.root, state.value));
|
|
433
|
+
const configuration = Array.from(configurationSet);
|
|
434
|
+
return this.createState({
|
|
435
|
+
...state,
|
|
436
|
+
value: actors_dist_xstateActors.resolveStateValue(this.root, state.value),
|
|
437
|
+
configuration,
|
|
438
|
+
done: actors_dist_xstateActors.isInFinalState(configuration)
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
resolveStateValue(stateValue) {
|
|
442
|
+
const resolvedStateValue = actors_dist_xstateActors.resolveStateValue(this.root, stateValue);
|
|
443
|
+
const resolvedContext = this.getContext();
|
|
444
|
+
return this.resolveState(actors_dist_xstateActors.State.from(resolvedStateValue, resolvedContext, this));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Determines the next state given the current `state` and received `event`.
|
|
449
|
+
* Calculates a full macrostep from all microsteps.
|
|
450
|
+
*
|
|
451
|
+
* @param state The current State instance or state value
|
|
452
|
+
* @param event The received event
|
|
453
|
+
*/
|
|
454
|
+
transition(state = this.initialState, event, actorCtx) {
|
|
455
|
+
const currentState = state instanceof actors_dist_xstateActors.State ? state : this.resolveStateValue(state);
|
|
456
|
+
// TODO: handle error events in a better way
|
|
457
|
+
if (actors_dist_xstateActors.isErrorEvent(event) && !currentState.nextEvents.some(nextEvent => nextEvent === event.type)) {
|
|
458
|
+
throw event.data;
|
|
459
|
+
}
|
|
460
|
+
const {
|
|
461
|
+
state: nextState
|
|
462
|
+
} = actors_dist_xstateActors.macrostep(currentState, event, actorCtx);
|
|
463
|
+
return nextState;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Determines the next state given the current `state` and `event`.
|
|
468
|
+
* Calculates a microstep.
|
|
469
|
+
*
|
|
470
|
+
* @param state The current state
|
|
471
|
+
* @param event The received event
|
|
472
|
+
*/
|
|
473
|
+
microstep(state = this.initialState, event, actorCtx) {
|
|
474
|
+
return actors_dist_xstateActors.macrostep(state, event, actorCtx).microstates;
|
|
475
|
+
}
|
|
476
|
+
getTransitionData(state, event) {
|
|
477
|
+
return actors_dist_xstateActors.transitionNode(this.root, state.value, state, event) || [];
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* The initial state _before_ evaluating any microsteps.
|
|
482
|
+
* This "pre-initial" state is provided to initial actions executed in the initial state.
|
|
483
|
+
*/
|
|
484
|
+
getPreInitialState(actorCtx, input) {
|
|
485
|
+
const [context, actions] = this.getContextAndActions(actorCtx, input);
|
|
486
|
+
const config = actors_dist_xstateActors.getInitialConfiguration(this.root);
|
|
487
|
+
const preInitial = this.resolveState(this.createState({
|
|
488
|
+
value: {},
|
|
489
|
+
// TODO: this is computed in state constructor
|
|
490
|
+
context,
|
|
491
|
+
event: actors_dist_xstateActors.createInitEvent({}),
|
|
492
|
+
actions: [],
|
|
493
|
+
meta: undefined,
|
|
494
|
+
configuration: config,
|
|
495
|
+
transitions: [],
|
|
496
|
+
children: {}
|
|
497
|
+
}));
|
|
498
|
+
preInitial._initial = true;
|
|
499
|
+
preInitial.actions.unshift(...actions);
|
|
500
|
+
if (actorCtx) {
|
|
501
|
+
const {
|
|
502
|
+
nextState
|
|
503
|
+
} = actors_dist_xstateActors.resolveActionsAndContext(actions, actors_dist_xstateActors.initEvent, preInitial, actorCtx);
|
|
504
|
+
preInitial.children = nextState.children;
|
|
505
|
+
preInitial.actions = nextState.actions;
|
|
506
|
+
}
|
|
507
|
+
return preInitial;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* The initial State instance, which includes all actions to be executed from
|
|
512
|
+
* entering the initial state.
|
|
513
|
+
*/
|
|
514
|
+
get initialState() {
|
|
515
|
+
return this.getInitialState();
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Returns the initial `State` instance, with reference to `self` as an `ActorRef`.
|
|
520
|
+
*/
|
|
521
|
+
getInitialState(actorCtx, input) {
|
|
522
|
+
const initEvent = actors_dist_xstateActors.createInitEvent(input); // TODO: fix;
|
|
523
|
+
|
|
524
|
+
const preInitialState = this.getPreInitialState(actorCtx, input);
|
|
525
|
+
const nextState = actors_dist_xstateActors.microstep([], preInitialState, actorCtx, initEvent);
|
|
526
|
+
nextState.actions.unshift(...preInitialState.actions);
|
|
527
|
+
const {
|
|
528
|
+
state: macroState
|
|
529
|
+
} = actors_dist_xstateActors.macrostep(nextState, initEvent, actorCtx);
|
|
530
|
+
return macroState;
|
|
531
|
+
}
|
|
532
|
+
start(state, actorCtx) {
|
|
533
|
+
state.actions.forEach(action => {
|
|
534
|
+
action.execute?.(actorCtx);
|
|
535
|
+
});
|
|
536
|
+
Object.values(state.children).forEach(child => {
|
|
537
|
+
if (child.status === 0) {
|
|
538
|
+
try {
|
|
539
|
+
child.start?.();
|
|
540
|
+
} catch (err) {
|
|
541
|
+
// TODO: unify error handling when child starts
|
|
542
|
+
actorCtx.self.send(actors_dist_xstateActors.error(child.id, err));
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
getStateNodeById(stateId) {
|
|
548
|
+
const fullPath = stateId.split(this.delimiter);
|
|
549
|
+
const relativePath = fullPath.slice(1);
|
|
550
|
+
const resolvedStateId = actors_dist_xstateActors.isStateId(fullPath[0]) ? fullPath[0].slice(STATE_IDENTIFIER.length) : fullPath[0];
|
|
551
|
+
const stateNode = this.idMap.get(resolvedStateId);
|
|
552
|
+
if (!stateNode) {
|
|
553
|
+
throw new Error(`Child state node '#${resolvedStateId}' does not exist on machine '${this.id}'`);
|
|
554
|
+
}
|
|
555
|
+
return actors_dist_xstateActors.getStateNodeByPath(stateNode, relativePath);
|
|
556
|
+
}
|
|
557
|
+
get definition() {
|
|
558
|
+
return {
|
|
559
|
+
context: this.getContext(),
|
|
560
|
+
...this.root.definition
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
toJSON() {
|
|
564
|
+
return this.definition;
|
|
565
|
+
}
|
|
566
|
+
getPersistedState(state) {
|
|
567
|
+
return actors_dist_xstateActors.getPersistedState(state);
|
|
568
|
+
}
|
|
569
|
+
createState(stateConfig) {
|
|
570
|
+
const state = stateConfig instanceof actors_dist_xstateActors.State ? stateConfig : new actors_dist_xstateActors.State(stateConfig, this);
|
|
571
|
+
const {
|
|
572
|
+
nextState: resolvedState
|
|
573
|
+
} = actors_dist_xstateActors.resolveActionsAndContext(state.actions, state.event, state, undefined);
|
|
574
|
+
return resolvedState;
|
|
575
|
+
}
|
|
576
|
+
getStatus(state) {
|
|
577
|
+
return state.done ? {
|
|
578
|
+
status: 'done',
|
|
579
|
+
data: state.output
|
|
580
|
+
} : {
|
|
581
|
+
status: 'active'
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
restoreState(state, _actorCtx) {
|
|
585
|
+
const children = {};
|
|
586
|
+
Object.keys(state.children).forEach(actorId => {
|
|
587
|
+
const actorData = state.children[actorId];
|
|
588
|
+
const childState = actorData.state;
|
|
589
|
+
const src = actorData.src;
|
|
590
|
+
const behavior = src ? actors_dist_xstateActors.resolveReferencedActor(this.options.actors[src])?.src : undefined;
|
|
591
|
+
if (!behavior) {
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
const actorState = behavior.restoreState?.(childState, _actorCtx);
|
|
595
|
+
const actorRef = actors_dist_xstateActors.interpret(behavior, {
|
|
596
|
+
id: actorId,
|
|
597
|
+
state: actorState
|
|
598
|
+
});
|
|
599
|
+
children[actorId] = actorRef;
|
|
600
|
+
});
|
|
601
|
+
const restoredState = this.createState(new actors_dist_xstateActors.State({
|
|
602
|
+
...state,
|
|
603
|
+
children
|
|
604
|
+
}, this));
|
|
605
|
+
|
|
606
|
+
// TODO: DRY this up
|
|
607
|
+
restoredState.configuration.forEach(stateNode => {
|
|
608
|
+
if (stateNode.invoke) {
|
|
609
|
+
stateNode.invoke.forEach(invokeConfig => {
|
|
610
|
+
const {
|
|
611
|
+
id,
|
|
612
|
+
src
|
|
613
|
+
} = invokeConfig;
|
|
614
|
+
if (children[id]) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
const referenced = actors_dist_xstateActors.resolveReferencedActor(this.options.actors[src]);
|
|
618
|
+
if (referenced) {
|
|
619
|
+
const actorRef = actors_dist_xstateActors.interpret(referenced.src, {
|
|
620
|
+
id,
|
|
621
|
+
parent: _actorCtx?.self,
|
|
622
|
+
input: 'input' in invokeConfig ? invokeConfig.input : referenced.input
|
|
623
|
+
});
|
|
624
|
+
children[id] = actorRef;
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
restoredState.actions = [];
|
|
630
|
+
return restoredState;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**@deprecated an internal property acting as a "phantom" type, not meant to be used at runtime */
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function createMachine(config, implementations) {
|
|
637
|
+
return new StateMachine(config, implementations);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function mapState(stateMap, stateId) {
|
|
641
|
+
let foundStateId;
|
|
642
|
+
for (const mappedStateId of Object.keys(stateMap)) {
|
|
643
|
+
if (actors_dist_xstateActors.matchesState(mappedStateId, stateId) && (!foundStateId || stateId.length > foundStateId.length)) {
|
|
644
|
+
foundStateId = mappedStateId;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return stateMap[foundStateId];
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
class SimulatedClock {
|
|
651
|
+
constructor() {
|
|
652
|
+
this.timeouts = new Map();
|
|
653
|
+
this._now = 0;
|
|
654
|
+
this._id = 0;
|
|
655
|
+
}
|
|
656
|
+
now() {
|
|
657
|
+
return this._now;
|
|
658
|
+
}
|
|
659
|
+
getId() {
|
|
660
|
+
return this._id++;
|
|
661
|
+
}
|
|
662
|
+
setTimeout(fn, timeout) {
|
|
663
|
+
const id = this.getId();
|
|
664
|
+
this.timeouts.set(id, {
|
|
665
|
+
start: this.now(),
|
|
666
|
+
timeout,
|
|
667
|
+
fn
|
|
668
|
+
});
|
|
669
|
+
return id;
|
|
670
|
+
}
|
|
671
|
+
clearTimeout(id) {
|
|
672
|
+
this.timeouts.delete(id);
|
|
673
|
+
}
|
|
674
|
+
set(time) {
|
|
675
|
+
if (this._now > time) {
|
|
676
|
+
throw new Error('Unable to travel back in time');
|
|
677
|
+
}
|
|
678
|
+
this._now = time;
|
|
679
|
+
this.flushTimeouts();
|
|
680
|
+
}
|
|
681
|
+
flushTimeouts() {
|
|
682
|
+
[...this.timeouts].sort(([_idA, timeoutA], [_idB, timeoutB]) => {
|
|
683
|
+
const endA = timeoutA.start + timeoutA.timeout;
|
|
684
|
+
const endB = timeoutB.start + timeoutB.timeout;
|
|
685
|
+
return endB > endA ? -1 : 1;
|
|
686
|
+
}).forEach(([id, timeout]) => {
|
|
687
|
+
if (this.now() - timeout.start >= timeout.timeout) {
|
|
688
|
+
this.timeouts.delete(id);
|
|
689
|
+
timeout.fn.call(null);
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
increment(ms) {
|
|
694
|
+
this._now += ms;
|
|
695
|
+
this.flushTimeouts();
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
const defaultWaitForOptions = {
|
|
700
|
+
timeout: 10_000 // 10 seconds
|
|
701
|
+
};
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Subscribes to an actor ref and waits for its emitted value to satisfy
|
|
705
|
+
* a predicate, and then resolves with that value.
|
|
706
|
+
* Will throw if the desired state is not reached after a timeout
|
|
707
|
+
* (defaults to 10 seconds).
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```js
|
|
711
|
+
* const state = await waitFor(someService, state => {
|
|
712
|
+
* return state.hasTag('loaded');
|
|
713
|
+
* });
|
|
714
|
+
*
|
|
715
|
+
* state.hasTag('loaded'); // true
|
|
716
|
+
* ```
|
|
717
|
+
*
|
|
718
|
+
* @param actorRef The actor ref to subscribe to
|
|
719
|
+
* @param predicate Determines if a value matches the condition to wait for
|
|
720
|
+
* @param options
|
|
721
|
+
* @returns A promise that eventually resolves to the emitted value
|
|
722
|
+
* that matches the condition
|
|
723
|
+
*/
|
|
724
|
+
function waitFor(actorRef, predicate, options) {
|
|
725
|
+
const resolvedOptions = {
|
|
726
|
+
...defaultWaitForOptions,
|
|
727
|
+
...options
|
|
728
|
+
};
|
|
729
|
+
return new Promise((res, rej) => {
|
|
730
|
+
let done = false;
|
|
731
|
+
const handle = resolvedOptions.timeout === Infinity ? undefined : setTimeout(() => {
|
|
732
|
+
sub.unsubscribe();
|
|
733
|
+
rej(new Error(`Timeout of ${resolvedOptions.timeout} ms exceeded`));
|
|
734
|
+
}, resolvedOptions.timeout);
|
|
735
|
+
const dispose = () => {
|
|
736
|
+
clearTimeout(handle);
|
|
737
|
+
done = true;
|
|
738
|
+
sub?.unsubscribe();
|
|
739
|
+
};
|
|
740
|
+
function checkEmitted(emitted) {
|
|
741
|
+
if (predicate(emitted)) {
|
|
742
|
+
dispose();
|
|
743
|
+
res(emitted);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
let sub; // avoid TDZ when disposing synchronously
|
|
747
|
+
|
|
748
|
+
// See if the current snapshot already matches the predicate
|
|
749
|
+
checkEmitted(actorRef.getSnapshot());
|
|
750
|
+
if (done) {
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
sub = actorRef.subscribe({
|
|
754
|
+
next: checkEmitted,
|
|
755
|
+
error: err => {
|
|
756
|
+
dispose();
|
|
757
|
+
rej(err);
|
|
758
|
+
},
|
|
759
|
+
complete: () => {
|
|
760
|
+
dispose();
|
|
761
|
+
rej(new Error(`Actor terminated without satisfying predicate`));
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
if (done) {
|
|
765
|
+
sub.unsubscribe();
|
|
766
|
+
}
|
|
767
|
+
});
|
|
7
768
|
}
|
|
769
|
+
|
|
770
|
+
exports.ActionTypes = actors_dist_xstateActors.ActionTypes;
|
|
771
|
+
exports.Interpreter = actors_dist_xstateActors.Interpreter;
|
|
772
|
+
exports.InterpreterStatus = actors_dist_xstateActors.ActorStatus;
|
|
773
|
+
exports.SpecialTargets = actors_dist_xstateActors.SpecialTargets;
|
|
774
|
+
exports.State = actors_dist_xstateActors.State;
|
|
775
|
+
exports.and = actors_dist_xstateActors.and;
|
|
776
|
+
exports.assign = actors_dist_xstateActors.assign;
|
|
777
|
+
exports.cancel = actors_dist_xstateActors.cancel;
|
|
778
|
+
exports.choose = actors_dist_xstateActors.choose;
|
|
779
|
+
exports.doneInvoke = actors_dist_xstateActors.doneInvoke;
|
|
780
|
+
exports.forwardTo = actors_dist_xstateActors.forwardTo;
|
|
781
|
+
exports.fromCallback = actors_dist_xstateActors.fromCallback;
|
|
782
|
+
exports.fromEventObservable = actors_dist_xstateActors.fromEventObservable;
|
|
783
|
+
exports.fromObservable = actors_dist_xstateActors.fromObservable;
|
|
784
|
+
exports.fromPromise = actors_dist_xstateActors.fromPromise;
|
|
785
|
+
exports.fromTransition = actors_dist_xstateActors.fromTransition;
|
|
786
|
+
exports.getStateNodes = actors_dist_xstateActors.getStateNodes;
|
|
787
|
+
exports.interpret = actors_dist_xstateActors.interpret;
|
|
788
|
+
exports.log = actors_dist_xstateActors.log;
|
|
789
|
+
exports.matchesState = actors_dist_xstateActors.matchesState;
|
|
790
|
+
exports.not = actors_dist_xstateActors.not;
|
|
791
|
+
exports.or = actors_dist_xstateActors.or;
|
|
792
|
+
exports.pathToStateValue = actors_dist_xstateActors.pathToStateValue;
|
|
793
|
+
exports.pure = actors_dist_xstateActors.pure;
|
|
794
|
+
exports.raise = actors_dist_xstateActors.raise;
|
|
795
|
+
exports.sendParent = actors_dist_xstateActors.sendParent;
|
|
796
|
+
exports.sendTo = actors_dist_xstateActors.sendTo;
|
|
797
|
+
exports.stateIn = actors_dist_xstateActors.stateIn;
|
|
798
|
+
exports.stop = actors_dist_xstateActors.stop;
|
|
799
|
+
exports.toObserver = actors_dist_xstateActors.toObserver;
|
|
800
|
+
exports.SimulatedClock = SimulatedClock;
|
|
801
|
+
exports.StateMachine = StateMachine;
|
|
802
|
+
exports.StateNode = StateNode;
|
|
803
|
+
exports.createMachine = createMachine;
|
|
804
|
+
exports.mapState = mapState;
|
|
805
|
+
exports.waitFor = waitFor;
|