xstate 6.0.0-alpha.48 → 6.0.0-alpha.49
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/README.md +23 -0
- package/dist/{StateMachine-b09d2b00.cjs.js → StateMachine-0adb3a70.cjs.js} +1 -1
- package/dist/{StateMachine-b3a890bf.development.cjs.js → StateMachine-29450e6d.development.cjs.js} +1 -1
- package/dist/{StateMachine-8329769a.esm.js → StateMachine-2af31c11.esm.js} +1 -1
- package/dist/{StateMachine-88b3c26a.development.esm.js → StateMachine-faf50c5c.development.esm.js} +1 -1
- package/dist/{createActor-27287c65.esm.js → createActor-268165d4.esm.js} +1 -1
- package/dist/{createActor-309d77eb.development.esm.js → createActor-88709f74.development.esm.js} +1 -1
- package/dist/{createActor-cc3d6dde.development.cjs.js → createActor-a1e0dffb.development.cjs.js} +0 -3
- package/dist/{createActor-9b41ade9.cjs.js → createActor-b4dd05ae.cjs.js} +0 -3
- package/dist/declarations/src/fsm/createFSMActor.d.ts +67 -0
- package/dist/declarations/src/fsm/index.d.ts +2 -0
- package/dist/declarations/src/fsm.d.ts +5 -4
- package/dist/{effectDescriptor-b1f5deb6.esm.js → effectDescriptor-30c9a744.esm.js} +1 -1
- package/dist/{effectDescriptor-7707794b.development.esm.js → effectDescriptor-39d22100.development.esm.js} +1 -1
- package/dist/{effectDescriptor-a1678d06.development.cjs.js → effectDescriptor-7ff6802f.development.cjs.js} +1 -1
- package/dist/{effectDescriptor-bd36a33e.cjs.js → effectDescriptor-be348e50.cjs.js} +1 -1
- package/dist/fsm-7a2e9697.cjs.js +777 -0
- package/dist/fsm-b804b3e9.esm.js +775 -0
- package/dist/fsm-c1316948.development.cjs.js +777 -0
- package/dist/fsm-e18a7cb4.development.esm.js +775 -0
- package/dist/{types-81d03bef.esm.js → types-3c3455f7.esm.js} +1 -1
- package/dist/{types-1793b8b6.development.esm.js → types-adda3842.development.esm.js} +1 -1
- package/dist/{types-7e468202.development.cjs.js → types-b3fea5bd.development.cjs.js} +1 -1
- package/dist/{types-9c1bc85f.cjs.js → types-fbabaeee.cjs.js} +1 -1
- package/dist/xstate-actors.cjs.js +1 -1
- package/dist/xstate-actors.development.cjs.js +1 -1
- package/dist/xstate-actors.development.esm.js +2 -2
- package/dist/xstate-actors.esm.js +2 -2
- package/dist/xstate-durable.cjs.js +2 -2
- package/dist/xstate-durable.development.cjs.js +2 -2
- package/dist/xstate-durable.development.esm.js +2 -2
- package/dist/xstate-durable.esm.js +2 -2
- package/dist/xstate-fsm.cjs.d.mts +2 -0
- package/dist/xstate-fsm.cjs.d.ts +2 -0
- package/dist/xstate-fsm.cjs.js +409 -0
- package/dist/xstate-fsm.cjs.mjs +5 -0
- package/dist/xstate-fsm.development.cjs.js +409 -0
- package/dist/xstate-fsm.development.cjs.mjs +5 -0
- package/dist/xstate-fsm.development.esm.js +403 -0
- package/dist/xstate-fsm.esm.js +403 -0
- package/dist/xstate-fsm.umd.min.js +2 -0
- package/dist/xstate-fsm.umd.min.js.map +1 -0
- package/dist/xstate-graph.cjs.js +2 -2
- package/dist/xstate-graph.development.cjs.js +2 -2
- package/dist/xstate-graph.development.esm.js +2 -2
- package/dist/xstate-graph.esm.js +2 -2
- package/dist/xstate-scxml.cjs.js +3 -3
- package/dist/xstate-scxml.development.cjs.js +3 -3
- package/dist/xstate-scxml.development.esm.js +3 -3
- package/dist/xstate-scxml.esm.js +3 -3
- package/dist/xstate-validation.cjs.js +1 -1
- package/dist/xstate-validation.development.cjs.js +1 -1
- package/dist/xstate-validation.development.esm.js +1 -1
- package/dist/xstate-validation.esm.js +1 -1
- package/dist/xstate.cjs.js +6 -380
- package/dist/xstate.development.cjs.js +6 -380
- package/dist/xstate.development.esm.js +10 -384
- package/dist/xstate.esm.js +10 -384
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/fsm/package.json +8 -0
- package/package.json +18 -2
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var fsm = require('./fsm-c1316948.development.cjs.js');
|
|
6
|
+
require('./createActor-a1e0dffb.development.cjs.js');
|
|
7
|
+
|
|
8
|
+
var FSMActorStatus = /*#__PURE__*/function (FSMActorStatus) {
|
|
9
|
+
FSMActorStatus[FSMActorStatus["NotStarted"] = 0] = "NotStarted";
|
|
10
|
+
FSMActorStatus[FSMActorStatus["Running"] = 1] = "Running";
|
|
11
|
+
FSMActorStatus[FSMActorStatus["Stopped"] = 2] = "Stopped";
|
|
12
|
+
return FSMActorStatus;
|
|
13
|
+
}(FSMActorStatus || {});
|
|
14
|
+
let nextSessionId = 0;
|
|
15
|
+
function addressSegment(id) {
|
|
16
|
+
return id.replaceAll('%', '%25').replaceAll('/', '%2F');
|
|
17
|
+
}
|
|
18
|
+
const timerMaps = new WeakMap();
|
|
19
|
+
const registryMaps = new WeakMap();
|
|
20
|
+
class FSMSystem {
|
|
21
|
+
constructor(_clock) {
|
|
22
|
+
this._clock = _clock;
|
|
23
|
+
}
|
|
24
|
+
createActorRef(logic, options) {
|
|
25
|
+
return new FSMActor(logic, options);
|
|
26
|
+
}
|
|
27
|
+
spawnActor() {}
|
|
28
|
+
startActor(actor) {
|
|
29
|
+
actor.start();
|
|
30
|
+
}
|
|
31
|
+
stopActor(actor) {
|
|
32
|
+
actor._stop();
|
|
33
|
+
}
|
|
34
|
+
terminateActor(actor, termination) {
|
|
35
|
+
actor._terminate(termination);
|
|
36
|
+
}
|
|
37
|
+
emitEvent(source, event) {
|
|
38
|
+
source._emit(event);
|
|
39
|
+
}
|
|
40
|
+
sendEvent(_, target, event) {
|
|
41
|
+
target._send(event);
|
|
42
|
+
}
|
|
43
|
+
_relay(source, target, event) {
|
|
44
|
+
this.sendEvent(source, target, event);
|
|
45
|
+
}
|
|
46
|
+
scheduleTimer(source, id, delay) {
|
|
47
|
+
let actorTimers = timerMaps.get(source);
|
|
48
|
+
if (!actorTimers) {
|
|
49
|
+
actorTimers = new Map();
|
|
50
|
+
timerMaps.set(source, actorTimers);
|
|
51
|
+
}
|
|
52
|
+
actorTimers.set(id, this._clock.setTimeout(() => {
|
|
53
|
+
actorTimers.delete(id);
|
|
54
|
+
source._send({
|
|
55
|
+
type: 'xstate.timer',
|
|
56
|
+
id
|
|
57
|
+
});
|
|
58
|
+
}, delay));
|
|
59
|
+
}
|
|
60
|
+
cancelTimer(source, id) {
|
|
61
|
+
const actorTimers = timerMaps.get(source);
|
|
62
|
+
const timeout = actorTimers?.get(id);
|
|
63
|
+
if (timeout !== undefined) {
|
|
64
|
+
this._clock.clearTimeout(timeout);
|
|
65
|
+
actorTimers.delete(id);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
cancelAllTimers(source) {
|
|
69
|
+
const actorTimers = timerMaps.get(source);
|
|
70
|
+
for (const timeout of actorTimers?.values() ?? []) {
|
|
71
|
+
this._clock.clearTimeout(timeout);
|
|
72
|
+
}
|
|
73
|
+
actorTimers?.clear();
|
|
74
|
+
}
|
|
75
|
+
_set(key, actor) {
|
|
76
|
+
let registry = registryMaps.get(this);
|
|
77
|
+
if (!registry) {
|
|
78
|
+
registry = new Map();
|
|
79
|
+
registryMaps.set(this, registry);
|
|
80
|
+
}
|
|
81
|
+
registry.set(key, actor);
|
|
82
|
+
}
|
|
83
|
+
get(key) {
|
|
84
|
+
return registryMaps.get(this)?.get(key);
|
|
85
|
+
}
|
|
86
|
+
getAll() {
|
|
87
|
+
return Object.fromEntries(registryMaps.get(this) ?? []);
|
|
88
|
+
}
|
|
89
|
+
_unregister(actor) {
|
|
90
|
+
const registry = registryMaps.get(this);
|
|
91
|
+
for (const [key, value] of registry ?? []) {
|
|
92
|
+
if (value === actor) {
|
|
93
|
+
registry.delete(key);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** A compact actor runtime for logic returned by `createFSM(...)`. */
|
|
100
|
+
class FSMActor {
|
|
101
|
+
constructor(logic, options = {}) {
|
|
102
|
+
this.logic = logic;
|
|
103
|
+
this.options = options;
|
|
104
|
+
this._snapshot = void 0;
|
|
105
|
+
this._effects = void 0;
|
|
106
|
+
this._queue = void 0;
|
|
107
|
+
this._processing = false;
|
|
108
|
+
this._observers = void 0;
|
|
109
|
+
this._listeners = void 0;
|
|
110
|
+
this._trigger = void 0;
|
|
111
|
+
this._restored = false;
|
|
112
|
+
this._processingStatus = FSMActorStatus.NotStarted;
|
|
113
|
+
this.id = void 0;
|
|
114
|
+
this.sessionId = void 0;
|
|
115
|
+
this.address = void 0;
|
|
116
|
+
this.ref = this;
|
|
117
|
+
this.src = void 0;
|
|
118
|
+
this.system = void 0;
|
|
119
|
+
this._parent = void 0;
|
|
120
|
+
this.id = options.id ?? logic.id ?? '(fsm)';
|
|
121
|
+
this.sessionId = options._sessionId ?? `fsm:${nextSessionId++}`;
|
|
122
|
+
this.src = options.src ?? logic;
|
|
123
|
+
this._parent = options.parent;
|
|
124
|
+
this.address = this._parent ? `${this._parent.address}/${addressSegment(this.id)}` : addressSegment(this.id);
|
|
125
|
+
this.system = this._parent?.system ?? new FSMSystem(options.clock ?? {
|
|
126
|
+
setTimeout,
|
|
127
|
+
clearTimeout
|
|
128
|
+
});
|
|
129
|
+
if (options.registryKey) {
|
|
130
|
+
this.system._set(options.registryKey, this);
|
|
131
|
+
}
|
|
132
|
+
const persisted = options.snapshot ?? options.state;
|
|
133
|
+
try {
|
|
134
|
+
if (persisted !== undefined) {
|
|
135
|
+
this._restored = true;
|
|
136
|
+
this._snapshot = logic.restoreSnapshot?.(persisted, this) ?? persisted;
|
|
137
|
+
this._effects = [];
|
|
138
|
+
} else {
|
|
139
|
+
[this._snapshot, this._effects] = logic.initialTransition(options.input, this);
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
this._snapshot = {
|
|
143
|
+
status: 'error',
|
|
144
|
+
output: undefined,
|
|
145
|
+
error
|
|
146
|
+
};
|
|
147
|
+
this._effects = [];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
get self() {
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
get logger() {
|
|
154
|
+
return this.options.logger ?? console.log;
|
|
155
|
+
}
|
|
156
|
+
defer(fn) {
|
|
157
|
+
fn();
|
|
158
|
+
}
|
|
159
|
+
get emit() {
|
|
160
|
+
const emit = event => this.system.emitEvent(this, event);
|
|
161
|
+
Object.defineProperty(this, 'emit', {
|
|
162
|
+
value: emit
|
|
163
|
+
});
|
|
164
|
+
return emit;
|
|
165
|
+
}
|
|
166
|
+
stopChild(child) {
|
|
167
|
+
child._stop();
|
|
168
|
+
}
|
|
169
|
+
actionExecutor(effect) {
|
|
170
|
+
effect.exec();
|
|
171
|
+
}
|
|
172
|
+
start() {
|
|
173
|
+
if (this._processingStatus !== FSMActorStatus.NotStarted) {
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
176
|
+
this._processingStatus = FSMActorStatus.Running;
|
|
177
|
+
try {
|
|
178
|
+
this.runEffects(this._effects);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
this.fail(error);
|
|
181
|
+
return this;
|
|
182
|
+
}
|
|
183
|
+
if (this._snapshot.status === 'error') {
|
|
184
|
+
this.fail(this._snapshot.error);
|
|
185
|
+
return this;
|
|
186
|
+
}
|
|
187
|
+
this._effects = [];
|
|
188
|
+
if (this._processingStatus === FSMActorStatus.Stopped) {
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
this.logic.start?.(this._snapshot, this, {
|
|
193
|
+
restored: this._restored
|
|
194
|
+
});
|
|
195
|
+
} catch (error) {
|
|
196
|
+
this.fail(error);
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
if (this._restored) {
|
|
200
|
+
const timers = this._snapshot.timers ?? {};
|
|
201
|
+
for (const timer of Object.values(timers)) {
|
|
202
|
+
const delay = !this.system._clock.now && timer.startedAt !== undefined ? Math.min(timer.delay, Math.max(0, timer.startedAt + timer.delay - Date.now())) : timer.delay;
|
|
203
|
+
this.system.scheduleTimer(this, timer.id, delay);
|
|
204
|
+
}
|
|
205
|
+
this._restored = false;
|
|
206
|
+
}
|
|
207
|
+
this.notify();
|
|
208
|
+
this.flush();
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
send(event) {
|
|
212
|
+
if (this._processingStatus === FSMActorStatus.Stopped) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
(this._queue ??= []).push(event);
|
|
216
|
+
this.flush();
|
|
217
|
+
}
|
|
218
|
+
_send(event) {
|
|
219
|
+
this.send(event);
|
|
220
|
+
}
|
|
221
|
+
flush() {
|
|
222
|
+
if (this._processing || this._processingStatus !== FSMActorStatus.Running || !this._queue?.length) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
this._processing = true;
|
|
226
|
+
let event;
|
|
227
|
+
while (this._processingStatus === FSMActorStatus.Running && (event = this._queue?.shift())) {
|
|
228
|
+
try {
|
|
229
|
+
const [snapshot, effects] = this.logic.transition(this._snapshot, event, this);
|
|
230
|
+
this._snapshot = snapshot;
|
|
231
|
+
this.runEffects(effects);
|
|
232
|
+
if (this._snapshot.status === 'active') {
|
|
233
|
+
this.notify();
|
|
234
|
+
}
|
|
235
|
+
} catch (error) {
|
|
236
|
+
this.fail(error);
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
this._processing = false;
|
|
241
|
+
}
|
|
242
|
+
runEffects(effects) {
|
|
243
|
+
for (const effect of effects) {
|
|
244
|
+
effect.exec();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
getSnapshot() {
|
|
248
|
+
return this._snapshot;
|
|
249
|
+
}
|
|
250
|
+
getPersistedSnapshot(options) {
|
|
251
|
+
return this.logic.getPersistedSnapshot(this._snapshot, options);
|
|
252
|
+
}
|
|
253
|
+
toJSON() {
|
|
254
|
+
return {
|
|
255
|
+
xstate$type: 'actorRef',
|
|
256
|
+
id: this.id,
|
|
257
|
+
address: this.address,
|
|
258
|
+
src: typeof this.src === 'string' ? this.src : undefined
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
_stop() {
|
|
262
|
+
if (this._processingStatus === FSMActorStatus.Stopped) {
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
if (this._processingStatus === FSMActorStatus.Running) {
|
|
266
|
+
const [snapshot, effects] = this.logic.transition(this._snapshot, {
|
|
267
|
+
type: '@xstate.stop'
|
|
268
|
+
}, this);
|
|
269
|
+
this._snapshot = snapshot;
|
|
270
|
+
this.runEffects(effects);
|
|
271
|
+
}
|
|
272
|
+
this._processingStatus = FSMActorStatus.Stopped;
|
|
273
|
+
this.system.cancelAllTimers(this);
|
|
274
|
+
this.system._unregister(this);
|
|
275
|
+
this._queue = undefined;
|
|
276
|
+
for (const observer of this._observers ?? []) {
|
|
277
|
+
observer.complete?.();
|
|
278
|
+
}
|
|
279
|
+
this._observers?.clear();
|
|
280
|
+
return this;
|
|
281
|
+
}
|
|
282
|
+
stop() {
|
|
283
|
+
if (this._parent) {
|
|
284
|
+
throw new Error('A non-root actor cannot be stopped directly.');
|
|
285
|
+
}
|
|
286
|
+
return this._stop();
|
|
287
|
+
}
|
|
288
|
+
subscribe(observerOrNext, error, complete) {
|
|
289
|
+
const observer = typeof observerOrNext === 'function' ? {
|
|
290
|
+
next: observerOrNext,
|
|
291
|
+
error,
|
|
292
|
+
complete
|
|
293
|
+
} : observerOrNext ?? {};
|
|
294
|
+
if (this._processingStatus === FSMActorStatus.Stopped) {
|
|
295
|
+
const snapshot = this._snapshot;
|
|
296
|
+
if (snapshot.status === 'done') {
|
|
297
|
+
observer.complete?.();
|
|
298
|
+
} else if (snapshot.status === 'error') {
|
|
299
|
+
observer.error?.(snapshot.error);
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
unsubscribe() {}
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
(this._observers ??= new Set()).add(observer);
|
|
306
|
+
return {
|
|
307
|
+
unsubscribe: () => this._observers?.delete(observer)
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
on(type, handler) {
|
|
311
|
+
let listeners = this._listeners?.get(type);
|
|
312
|
+
if (!listeners) {
|
|
313
|
+
listeners = new Set();
|
|
314
|
+
(this._listeners ??= new Map()).set(type, listeners);
|
|
315
|
+
}
|
|
316
|
+
listeners.add(handler);
|
|
317
|
+
return {
|
|
318
|
+
unsubscribe: () => listeners.delete(handler)
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
_emit(event) {
|
|
322
|
+
for (const listeners of [this._listeners?.get(event.type), this._listeners?.get('*')]) {
|
|
323
|
+
for (const listener of listeners ?? []) {
|
|
324
|
+
listener(event);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
_terminate(termination) {
|
|
329
|
+
this.notify();
|
|
330
|
+
this._processingStatus = FSMActorStatus.Stopped;
|
|
331
|
+
this.system.cancelAllTimers(this);
|
|
332
|
+
this.system._unregister(this);
|
|
333
|
+
for (const observer of this._observers ?? []) {
|
|
334
|
+
if (termination.status === 'error') {
|
|
335
|
+
observer.error?.(termination.error);
|
|
336
|
+
} else {
|
|
337
|
+
observer.complete?.();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
this._observers?.clear();
|
|
341
|
+
this._listeners?.clear();
|
|
342
|
+
}
|
|
343
|
+
fail(error) {
|
|
344
|
+
this._snapshot = {
|
|
345
|
+
...this._snapshot,
|
|
346
|
+
status: 'error',
|
|
347
|
+
output: undefined,
|
|
348
|
+
error
|
|
349
|
+
};
|
|
350
|
+
this._processingStatus = FSMActorStatus.Stopped;
|
|
351
|
+
this.system.cancelAllTimers(this);
|
|
352
|
+
this.system._unregister(this);
|
|
353
|
+
this._queue = undefined;
|
|
354
|
+
for (const observer of this._observers ?? []) {
|
|
355
|
+
observer.error?.(error);
|
|
356
|
+
}
|
|
357
|
+
this._observers?.clear();
|
|
358
|
+
this._listeners?.clear();
|
|
359
|
+
}
|
|
360
|
+
notify() {
|
|
361
|
+
for (const observer of this._observers ?? []) {
|
|
362
|
+
observer.next?.(this._snapshot);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
_isRunning() {
|
|
366
|
+
return this._processingStatus === FSMActorStatus.Running;
|
|
367
|
+
}
|
|
368
|
+
_inspectTransition() {}
|
|
369
|
+
get trigger() {
|
|
370
|
+
return this._trigger ??= new Proxy({}, {
|
|
371
|
+
get: (_, type) => payload => this.send({
|
|
372
|
+
...payload,
|
|
373
|
+
type
|
|
374
|
+
})
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
select(selector, equal = Object.is) {
|
|
378
|
+
return {
|
|
379
|
+
get: () => selector(this._snapshot),
|
|
380
|
+
subscribe: observerOrNext => {
|
|
381
|
+
const observer = typeof observerOrNext === 'function' ? {
|
|
382
|
+
next: observerOrNext
|
|
383
|
+
} : observerOrNext;
|
|
384
|
+
let selected = selector(this._snapshot);
|
|
385
|
+
return this.subscribe({
|
|
386
|
+
next: snapshot => {
|
|
387
|
+
const next = selector(snapshot);
|
|
388
|
+
if (!equal(selected, next)) {
|
|
389
|
+
selected = next;
|
|
390
|
+
observer.next?.(next);
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
error: observer.error,
|
|
394
|
+
complete: observer.complete
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
[Symbol.observable]() {
|
|
400
|
+
return this;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
function createFSMActor(logic, options) {
|
|
404
|
+
return new FSMActor(logic, options);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
exports.createFSM = fsm.createFSM;
|
|
408
|
+
exports.FSMActor = FSMActor;
|
|
409
|
+
exports.createFSMActor = createFSMActor;
|