@systemfsoftware/xstate 0.0.0-bootstrap.0 → 6.0.0-beta.65
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/CHANGELOG.md +57 -0
- package/LICENSE +22 -0
- package/README.md +640 -2
- package/dist/actors-LxMBvgxO.mjs +472 -0
- package/dist/actors.d.ts +3 -0
- package/dist/actors.mjs +3 -0
- package/dist/base.types-DF8ZPiXj.d.ts +210 -0
- package/dist/createActor-BGHd7i8Q.mjs +4851 -0
- package/dist/durable.d.ts +211 -0
- package/dist/durable.mjs +283 -0
- package/dist/effectDescriptor-EvNuy6U3.d.ts +91 -0
- package/dist/fsm.d.ts +139 -0
- package/dist/fsm.mjs +60 -0
- package/dist/graph.d.ts +160 -0
- package/dist/graph.mjs +667 -0
- package/dist/index-CKUyiMZC.d.ts +1832 -0
- package/dist/index-DDWoKIF5.d.ts +512 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.mjs +7 -0
- package/dist/schema.types-tsIbgQd-.mjs +46 -0
- package/dist/src-zLWug7SF.mjs +2641 -0
- package/dist/transition-ZMXyPI-x.mjs +258 -0
- package/dist/types-B2EAwOk-.d.ts +3511 -0
- package/dist/utils-CXBxxp3Z.mjs +146 -0
- package/dist/validation.d.ts +49 -0
- package/dist/validation.mjs +216 -0
- package/package.json +81 -5
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { D as createSpawnEffect, K as setInertActorScopeSnapshot, S as beginSpawnAllocation, U as attachSnapshotActorRef, W as createInertActorScope, c as getProperAncestors, h as macrostep, it as isAtomicStateNode, j as finalizeTransitionResult, lt as getActorIdPrefix, p as initialMicrostep, rt as isRemoteActorRef, wt as createInitEvent, yt as hasAmbientInspector } from "./createActor-BGHd7i8Q.mjs";
|
|
2
|
+
// src/effectDescriptor.ts
|
|
3
|
+
/**
|
|
4
|
+
* Returns the serializable descriptor for an executable effect: the same
|
|
5
|
+
* discriminants (`kind`, `type`) with actor references replaced by logical
|
|
6
|
+
* addresses and actor sources by source keys. Payload fields pass through by
|
|
7
|
+
* reference.
|
|
8
|
+
*
|
|
9
|
+
* @experimental
|
|
10
|
+
*/
|
|
11
|
+
function getEffectDescriptor(effect) {
|
|
12
|
+
if (effect.kind === "action") return {
|
|
13
|
+
kind: "action",
|
|
14
|
+
type: effect.type,
|
|
15
|
+
params: effect.params
|
|
16
|
+
};
|
|
17
|
+
if (effect.kind === "emit") return {
|
|
18
|
+
kind: "emit",
|
|
19
|
+
type: effect.type,
|
|
20
|
+
source: effect.source.address,
|
|
21
|
+
event: effect.event
|
|
22
|
+
};
|
|
23
|
+
switch (effect.type) {
|
|
24
|
+
case "@xstate.spawn": return {
|
|
25
|
+
kind: "builtin",
|
|
26
|
+
type: "@xstate.spawn",
|
|
27
|
+
source: effect.source?.address,
|
|
28
|
+
actor: effect.actor.address,
|
|
29
|
+
id: effect.id,
|
|
30
|
+
src: getActorIdPrefix(effect.src),
|
|
31
|
+
input: effect.input
|
|
32
|
+
};
|
|
33
|
+
case "@xstate.start": return {
|
|
34
|
+
kind: "builtin",
|
|
35
|
+
type: "@xstate.start",
|
|
36
|
+
source: effect.source?.address,
|
|
37
|
+
actor: effect.actor.address,
|
|
38
|
+
id: effect.id
|
|
39
|
+
};
|
|
40
|
+
case "@xstate.raise": return {
|
|
41
|
+
kind: "builtin",
|
|
42
|
+
type: "@xstate.raise",
|
|
43
|
+
source: effect.source.address,
|
|
44
|
+
event: effect.event,
|
|
45
|
+
id: effect.id,
|
|
46
|
+
delay: effect.delay
|
|
47
|
+
};
|
|
48
|
+
case "@xstate.sendTo": return {
|
|
49
|
+
kind: "builtin",
|
|
50
|
+
type: "@xstate.sendTo",
|
|
51
|
+
source: effect.source.address,
|
|
52
|
+
target: effect.target?.address,
|
|
53
|
+
incarnation: isRemoteActorRef(effect.target) ? effect.target.sessionId : void 0,
|
|
54
|
+
event: effect.event,
|
|
55
|
+
id: effect.id,
|
|
56
|
+
delay: effect.delay
|
|
57
|
+
};
|
|
58
|
+
case "@xstate.cancel": return {
|
|
59
|
+
kind: "builtin",
|
|
60
|
+
type: "@xstate.cancel",
|
|
61
|
+
source: effect.source.address,
|
|
62
|
+
id: effect.id
|
|
63
|
+
};
|
|
64
|
+
case "@xstate.stop": return {
|
|
65
|
+
kind: "builtin",
|
|
66
|
+
type: "@xstate.stop",
|
|
67
|
+
source: effect.source.address,
|
|
68
|
+
actor: effect.actor.address,
|
|
69
|
+
id: effect.id
|
|
70
|
+
};
|
|
71
|
+
case "@xstate.terminate": return {
|
|
72
|
+
kind: "builtin",
|
|
73
|
+
type: "@xstate.terminate",
|
|
74
|
+
source: effect.source.address,
|
|
75
|
+
actor: effect.actor.address,
|
|
76
|
+
id: effect.id,
|
|
77
|
+
status: effect.status,
|
|
78
|
+
output: effect.output,
|
|
79
|
+
error: effect.error
|
|
80
|
+
};
|
|
81
|
+
case "@xstate.deadLetter": return {
|
|
82
|
+
kind: "builtin",
|
|
83
|
+
type: "@xstate.deadLetter",
|
|
84
|
+
source: effect.source?.address,
|
|
85
|
+
target: effect.target?.address,
|
|
86
|
+
event: effect.event,
|
|
87
|
+
reason: effect.reason,
|
|
88
|
+
issues: effect.detail?.issues,
|
|
89
|
+
error: effect.detail?.error
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// src/transition.ts
|
|
94
|
+
function attachMicrostepActorRefs(microsteps, actorScope, inputSnapshot) {
|
|
95
|
+
const result = microsteps.map(([snapshot, actions, transitions]) => [
|
|
96
|
+
snapshot,
|
|
97
|
+
actions,
|
|
98
|
+
transitions ?? []
|
|
99
|
+
]);
|
|
100
|
+
if (!result.length) return result;
|
|
101
|
+
const finalSnapshot = result.at(-1)[0];
|
|
102
|
+
setInertActorScopeSnapshot(actorScope, finalSnapshot, false);
|
|
103
|
+
if (finalSnapshot !== inputSnapshot) attachSnapshotActorRef(actorScope, finalSnapshot);
|
|
104
|
+
for (const [snapshot] of result) if (snapshot !== inputSnapshot && snapshot !== finalSnapshot) {
|
|
105
|
+
const snapshotScope = createInertActorScope(snapshot.machine, snapshot, void 0, actorScope);
|
|
106
|
+
attachSnapshotActorRef(snapshotScope, snapshot);
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Given actor `logic`, a `snapshot`, and an `event`, returns a tuple of the
|
|
112
|
+
* `nextSnapshot` and `actions` to execute.
|
|
113
|
+
*
|
|
114
|
+
* This is a pure function that does not execute `actions`.
|
|
115
|
+
*
|
|
116
|
+
* @public
|
|
117
|
+
*/
|
|
118
|
+
function transition(logic, snapshot, event) {
|
|
119
|
+
const actorScope = createInertActorScope(logic, snapshot);
|
|
120
|
+
setInertActorScopeSnapshot(actorScope, snapshot, false);
|
|
121
|
+
const [nextSnapshot, effects] = finalizeTransitionResult(actorScope, snapshot, logic.transition(snapshot, event, actorScope));
|
|
122
|
+
setInertActorScopeSnapshot(actorScope, nextSnapshot, false);
|
|
123
|
+
const returnedSnapshot = nextSnapshot === snapshot ? nextSnapshot : attachSnapshotActorRef(actorScope, nextSnapshot);
|
|
124
|
+
inspectPureTransition(actorScope, returnedSnapshot, event);
|
|
125
|
+
return [returnedSnapshot, effects];
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Returns `true` when `result` (from {@link transition}) means no transition
|
|
129
|
+
* handled the event: the snapshot is the same object as `previousSnapshot`
|
|
130
|
+
* and there are no effects. A handled event always yields a new snapshot
|
|
131
|
+
* object, even when nothing in it changed.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
*
|
|
135
|
+
* ```ts
|
|
136
|
+
* const result = transition(machine, snapshot, event);
|
|
137
|
+
* if (isUnhandled(snapshot, result)) {
|
|
138
|
+
* console.warn(`Unhandled event: ${event.type}`);
|
|
139
|
+
* }
|
|
140
|
+
* ```
|
|
141
|
+
*
|
|
142
|
+
* @public
|
|
143
|
+
*/
|
|
144
|
+
function isUnhandled(previousSnapshot, result) {
|
|
145
|
+
return result[0] === previousSnapshot && result[1].length === 0;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Given actor `logic` and optional `input`, returns a tuple of the
|
|
149
|
+
* `nextSnapshot` and `actions` to execute from the initial transition (no
|
|
150
|
+
* previous state).
|
|
151
|
+
*
|
|
152
|
+
* This is a pure function that does not execute `actions`.
|
|
153
|
+
*
|
|
154
|
+
* @public
|
|
155
|
+
*/
|
|
156
|
+
function initialTransition(logic, ...[input]) {
|
|
157
|
+
const actorScope = createInertActorScope(logic);
|
|
158
|
+
const [nextSnapshot, executableActions] = finalizeTransitionResult(actorScope, void 0, logic.initialTransition(input, actorScope));
|
|
159
|
+
setInertActorScopeSnapshot(actorScope, nextSnapshot, false);
|
|
160
|
+
const returnedSnapshot = attachSnapshotActorRef(actorScope, nextSnapshot);
|
|
161
|
+
inspectPureTransition(actorScope, returnedSnapshot, createInitEvent(input));
|
|
162
|
+
return [returnedSnapshot, executableActions];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Emits the `@xstate.transition` inspection event for a snapshot produced by
|
|
166
|
+
* the pure transition path, where no live actor loop does it. Free unless an
|
|
167
|
+
* inspector is ambiently installed (a durable execution created with
|
|
168
|
+
* `inspect`): only then is the snapshot's actor ref materialized to emit.
|
|
169
|
+
*/
|
|
170
|
+
function inspectPureTransition(actorScope, snapshot, event) {
|
|
171
|
+
if (!hasAmbientInspector()) return;
|
|
172
|
+
const self = actorScope.self;
|
|
173
|
+
if (self?.system._hasInspectionObservers?.()) self._inspectTransition(snapshot, event);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Given a state `machine`, a `snapshot`, and an `event`, returns an array of
|
|
177
|
+
* microsteps, where each microstep is a tuple of
|
|
178
|
+
* `[snapshot, actions, transitions]`. `transitions` are the transitions taken
|
|
179
|
+
* in that microstep,
|
|
180
|
+
* including eventless transitions and transitions for raised events; it is
|
|
181
|
+
* empty for microsteps that take no transition (for example, a stop or timer
|
|
182
|
+
* microstep).
|
|
183
|
+
*
|
|
184
|
+
* This is a pure function that does not execute `actions`.
|
|
185
|
+
*
|
|
186
|
+
* @public
|
|
187
|
+
*/
|
|
188
|
+
function getMicrosteps(machine, snapshot, event) {
|
|
189
|
+
const actorScope = createInertActorScope(machine, snapshot);
|
|
190
|
+
beginSpawnAllocation(actorScope);
|
|
191
|
+
const { microsteps } = macrostep(snapshot, event, actorScope, []);
|
|
192
|
+
return attachMicrostepActorRefs(microsteps, actorScope, snapshot);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Given a state `machine` and optional `input`, returns an array of microsteps
|
|
196
|
+
* from the initial transition, where each microstep is a tuple of
|
|
197
|
+
* `[snapshot, actions, transitions]`. `transitions` are the transitions taken
|
|
198
|
+
* in that microstep (see {@link getMicrosteps}); it is empty for the first
|
|
199
|
+
* microstep, which enters the initial states.
|
|
200
|
+
*
|
|
201
|
+
* This is a pure function that does not execute `actions`.
|
|
202
|
+
*
|
|
203
|
+
* @public
|
|
204
|
+
*/
|
|
205
|
+
function getInitialMicrosteps(machine, ...[input]) {
|
|
206
|
+
const actorScope = createInertActorScope(machine);
|
|
207
|
+
beginSpawnAllocation(actorScope);
|
|
208
|
+
const initEvent = createInitEvent(input);
|
|
209
|
+
const internalQueue = [];
|
|
210
|
+
const preInitialSnapshot = machine._getPreInitialState(actorScope, initEvent);
|
|
211
|
+
const contextSpawnEffects = Object.values(preInitialSnapshot.children).filter(Boolean).map((actor) => createSpawnEffect(actor));
|
|
212
|
+
const first = initialMicrostep(machine.root, preInitialSnapshot, actorScope, initEvent, internalQueue);
|
|
213
|
+
const { microsteps } = macrostep(first[0], initEvent, actorScope, internalQueue, [[
|
|
214
|
+
first[0],
|
|
215
|
+
[...contextSpawnEffects, ...first[1]],
|
|
216
|
+
[]
|
|
217
|
+
]]);
|
|
218
|
+
return attachMicrostepActorRefs(microsteps, actorScope);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Gets all potential next transitions from the current state.
|
|
222
|
+
*
|
|
223
|
+
* Returns all transitions that are available from the current state, including:
|
|
224
|
+
*
|
|
225
|
+
* - All transitions from atomic states (leaf states in the current state
|
|
226
|
+
* configuration)
|
|
227
|
+
* - All transitions from ancestor states (parent states that may handle events)
|
|
228
|
+
* - All guarded transitions (regardless of whether their guards would pass)
|
|
229
|
+
* - Always (eventless) transitions
|
|
230
|
+
* - After (delayed) transitions
|
|
231
|
+
*
|
|
232
|
+
* The order of transitions is deterministic:
|
|
233
|
+
*
|
|
234
|
+
* 1. Atomic states are processed in document order
|
|
235
|
+
* 2. For each atomic state, transitions are collected from the state itself first,
|
|
236
|
+
* then its ancestors
|
|
237
|
+
* 3. Within each state node, transitions are in the order they appear in the state
|
|
238
|
+
* definition
|
|
239
|
+
*
|
|
240
|
+
* @param state - The current machine snapshot
|
|
241
|
+
* @returns Array of transition definitions from the current state, in
|
|
242
|
+
* deterministic order
|
|
243
|
+
* @public
|
|
244
|
+
*/
|
|
245
|
+
function getNextTransitions(state) {
|
|
246
|
+
if (state.status !== "active") return [];
|
|
247
|
+
const potentialTransitions = [];
|
|
248
|
+
const atomicStates = state.nodes.filter(isAtomicStateNode);
|
|
249
|
+
const visited = /* @__PURE__ */ new Set();
|
|
250
|
+
for (const stateNode of atomicStates) for (const s of [stateNode].concat(getProperAncestors(stateNode, void 0))) {
|
|
251
|
+
if (visited.has(s.id)) continue;
|
|
252
|
+
visited.add(s.id);
|
|
253
|
+
for (const [, transitions] of s.transitions.entries()) potentialTransitions.push(...transitions);
|
|
254
|
+
if (s.always) potentialTransitions.push(...s.always);
|
|
255
|
+
}
|
|
256
|
+
return potentialTransitions;
|
|
257
|
+
}
|
|
258
|
+
export { isUnhandled as a, initialTransition as i, getMicrosteps as n, transition as o, getNextTransitions as r, getEffectDescriptor as s, getInitialMicrosteps as t };
|