@typeonce/effect-machine 0.31.2 → 0.33.0
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 +168 -162
- package/dist/Machine.d.ts +495 -284
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +91 -111
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/atom.d.ts +3 -4
- package/dist/internal/machine/atom.d.ts.map +1 -1
- package/dist/internal/machine/atom.js +0 -2
- package/dist/internal/machine/atom.js.map +1 -1
- package/dist/internal/machine/childRegistry.d.ts +52 -0
- package/dist/internal/machine/childRegistry.d.ts.map +1 -0
- package/dist/internal/machine/childRegistry.js +74 -0
- package/dist/internal/machine/childRegistry.js.map +1 -0
- package/dist/internal/machine/cluster.d.ts +2 -3
- package/dist/internal/machine/cluster.d.ts.map +1 -1
- package/dist/internal/machine/cluster.js.map +1 -1
- package/dist/internal/machine/configuration.d.ts.map +1 -1
- package/dist/internal/machine/configuration.js +14 -4
- package/dist/internal/machine/configuration.js.map +1 -1
- package/dist/internal/machine/executionPlan.d.ts +1 -0
- package/dist/internal/machine/executionPlan.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.js +97 -53
- package/dist/internal/machine/executionPlan.js.map +1 -1
- package/dist/internal/machine/invocation.d.ts.map +1 -1
- package/dist/internal/machine/invocation.js +4 -2
- package/dist/internal/machine/invocation.js.map +1 -1
- package/dist/internal/machine/invocationDefinition.d.ts +35 -0
- package/dist/internal/machine/invocationDefinition.d.ts.map +1 -0
- package/dist/internal/machine/invocationDefinition.js +21 -0
- package/dist/internal/machine/invocationDefinition.js.map +1 -0
- package/dist/internal/machine/invocationEvent.d.ts +0 -2
- package/dist/internal/machine/invocationEvent.d.ts.map +1 -1
- package/dist/internal/machine/invocationEvent.js +0 -8
- package/dist/internal/machine/invocationEvent.js.map +1 -1
- package/dist/internal/machine/machine.d.ts +21 -43
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +134 -403
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/planner.d.ts +13 -19
- package/dist/internal/machine/planner.d.ts.map +1 -1
- package/dist/internal/machine/planner.js +63 -35
- package/dist/internal/machine/planner.js.map +1 -1
- package/dist/internal/machine/process.d.ts +6 -8
- package/dist/internal/machine/process.d.ts.map +1 -1
- package/dist/internal/machine/process.js +1 -0
- package/dist/internal/machine/process.js.map +1 -1
- package/dist/internal/machine/protocol.d.ts +2 -2
- package/dist/internal/machine/protocol.d.ts.map +1 -1
- package/dist/internal/machine/protocol.js +4 -18
- package/dist/internal/machine/protocol.js.map +1 -1
- package/dist/internal/machine/readiness.d.ts +1 -1
- package/dist/internal/machine/readiness.d.ts.map +1 -1
- package/dist/internal/machine/requirements.d.ts +4 -0
- package/dist/internal/machine/requirements.d.ts.map +1 -0
- package/dist/internal/machine/requirements.js +2 -0
- package/dist/internal/machine/requirements.js.map +1 -0
- package/dist/internal/machine/runtime.d.ts +4 -58
- package/dist/internal/machine/runtime.d.ts.map +1 -1
- package/dist/internal/machine/runtime.js +1 -69
- package/dist/internal/machine/runtime.js.map +1 -1
- package/dist/internal/machine/serialization.d.ts.map +1 -1
- package/dist/internal/machine/serialization.js +16 -0
- package/dist/internal/machine/serialization.js.map +1 -1
- package/dist/internal/machine/stateDefinition.d.ts +3 -1
- package/dist/internal/machine/stateDefinition.d.ts.map +1 -1
- package/dist/internal/machine/stateDefinition.js +36 -2
- package/dist/internal/machine/stateDefinition.js.map +1 -1
- package/dist/internal/machine/targetBuilder.d.ts +16 -0
- package/dist/internal/machine/targetBuilder.d.ts.map +1 -0
- package/dist/internal/machine/targetBuilder.js +333 -0
- package/dist/internal/machine/targetBuilder.js.map +1 -0
- package/dist/internal/machine/topology.js +3 -3
- package/dist/internal/machine/topology.js.map +1 -1
- package/dist/internal/machine/transition.d.ts +16 -0
- package/dist/internal/machine/transition.d.ts.map +1 -0
- package/dist/internal/machine/transition.js +2 -0
- package/dist/internal/machine/transition.js.map +1 -0
- package/dist/internal/testing/machine/finiteModel.d.ts.map +1 -1
- package/dist/internal/testing/machine/finiteModel.js +11 -13
- package/dist/internal/testing/machine/finiteModel.js.map +1 -1
- package/dist/internal/testing/machine/format.d.ts +7 -0
- package/dist/internal/testing/machine/format.d.ts.map +1 -0
- package/dist/internal/testing/machine/format.js +104 -0
- package/dist/internal/testing/machine/format.js.map +1 -0
- package/dist/internal/testing/machine/probe.d.ts +1 -1
- package/dist/internal/testing/machine/probe.d.ts.map +1 -1
- package/dist/internal/testing/machine/probe.js +1 -1
- package/dist/internal/testing/machine/probe.js.map +1 -1
- package/dist/internal/testing/machine/referenceModel.d.ts.map +1 -1
- package/dist/internal/testing/machine/referenceModel.js +15 -19
- package/dist/internal/testing/machine/referenceModel.js.map +1 -1
- package/dist/internal/testing/machine/trace.d.ts +1 -1
- package/dist/internal/testing/machine/trace.d.ts.map +1 -1
- package/dist/internal/testing/machine/trace.js +3 -3
- package/dist/internal/testing/machine/trace.js.map +1 -1
- package/dist/internal/testing/machine/value.d.ts +8 -0
- package/dist/internal/testing/machine/value.d.ts.map +1 -0
- package/dist/internal/testing/machine/value.js +82 -0
- package/dist/internal/testing/machine/value.js.map +1 -0
- package/dist/internal/testing/machine/verification.d.ts +2 -13
- package/dist/internal/testing/machine/verification.d.ts.map +1 -1
- package/dist/internal/testing/machine/verification.js +21 -113
- package/dist/internal/testing/machine/verification.js.map +1 -1
- package/dist/testing/MachineTest.d.ts +89 -104
- package/dist/testing/MachineTest.d.ts.map +1 -1
- package/dist/testing/MachineTest.js +70 -84
- package/dist/testing/MachineTest.js.map +1 -1
- package/dist/unstable/cluster/ClusterMachine.d.ts +10 -13
- package/dist/unstable/cluster/ClusterMachine.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterMachine.js +5 -8
- package/dist/unstable/cluster/ClusterMachine.js.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +26 -61
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.js +17 -26
- package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
- package/docs/agent-guide.md +45 -45
- package/docs/effect-atom-react.md +35 -63
- package/docs/machine-review.md +7 -7
- package/docs/root-api.md +259 -0
- package/package.json +1 -1
- package/src/Machine.ts +1053 -538
- package/src/internal/machine/atom.ts +3 -13
- package/src/internal/machine/childRegistry.ts +141 -0
- package/src/internal/machine/cluster.ts +5 -14
- package/src/internal/machine/configuration.ts +20 -4
- package/src/internal/machine/executionPlan.ts +109 -52
- package/src/internal/machine/invocation.ts +10 -6
- package/src/internal/machine/invocationDefinition.ts +52 -0
- package/src/internal/machine/invocationEvent.ts +0 -8
- package/src/internal/machine/machine.ts +222 -716
- package/src/internal/machine/planner.ts +74 -62
- package/src/internal/machine/process.ts +14 -21
- package/src/internal/machine/protocol.ts +9 -32
- package/src/internal/machine/readiness.ts +1 -0
- package/src/internal/machine/requirements.ts +11 -0
- package/src/internal/machine/runtime.ts +17 -186
- package/src/internal/machine/serialization.ts +22 -0
- package/src/internal/machine/stateDefinition.ts +36 -3
- package/src/internal/machine/targetBuilder.ts +525 -0
- package/src/internal/machine/topology.ts +3 -3
- package/src/internal/machine/transition.ts +26 -0
- package/src/internal/testing/machine/finiteModel.ts +23 -24
- package/src/internal/testing/machine/format.ts +120 -0
- package/src/internal/testing/machine/probe.ts +4 -4
- package/src/internal/testing/machine/referenceModel.ts +25 -17
- package/src/internal/testing/machine/trace.ts +4 -4
- package/src/internal/testing/machine/value.ts +77 -0
- package/src/internal/testing/machine/verification.ts +904 -1109
- package/src/testing/MachineTest.ts +103 -114
- package/src/unstable/cluster/ClusterMachine.ts +10 -20
- package/src/unstable/reactivity/AtomMachine.ts +42 -79
|
@@ -3,15 +3,18 @@ import * as Inspectable from "effect/Inspectable";
|
|
|
3
3
|
import * as Option from "effect/Option";
|
|
4
4
|
import { Prototype as PipeablePrototype } from "effect/Pipeable";
|
|
5
5
|
import { hasProperty } from "effect/Predicate";
|
|
6
|
+
import * as Schema from "effect/Schema";
|
|
6
7
|
import * as Activities from "./activities.js";
|
|
7
8
|
import * as Configuration from "./configuration.js";
|
|
9
|
+
import * as InvocationDefinition from "./invocationDefinition.js";
|
|
8
10
|
import * as internalPlanner from "./planner.js";
|
|
9
11
|
import * as internalProcess from "./process.js";
|
|
10
12
|
import * as Protocol from "./protocol.js";
|
|
11
13
|
import * as internalRuntime from "./runtime.js";
|
|
12
14
|
import * as Serialization from "./serialization.js";
|
|
13
15
|
import * as StateDefinition from "./stateDefinition.js";
|
|
14
|
-
import { ChildMachineLogicTypeId
|
|
16
|
+
import { ChildMachineLogicTypeId } from "./symbols.js";
|
|
17
|
+
import { getLocalTargetScope, getTargetBuilderNode, makeSnapshotBuilder, makeTargetBuilder, withFrom } from "./targetBuilder.js";
|
|
15
18
|
import * as Topology from "./topology.js";
|
|
16
19
|
export { ChildAlreadyExistsError, InfiniteTransitionError, MachineSchemaDecodeError, MachineSchemaEncodeError, ProcessLocalError, StartupError, StoppedError } from "./errors.js";
|
|
17
20
|
export { ChildMachineLogicTypeId, InitialEventTypeId, SnapshotBuilderStateTypeId } from "./symbols.js";
|
|
@@ -34,6 +37,7 @@ const Proto = {
|
|
|
34
37
|
const makeWithHandlers = (self, handlers) => {
|
|
35
38
|
const machine = Object.create(Proto);
|
|
36
39
|
machine.states = self.states;
|
|
40
|
+
machine.root = self.root;
|
|
37
41
|
machine.events = self.events;
|
|
38
42
|
machine.internalEvents = self.internalEvents;
|
|
39
43
|
machine.emittedEvents = self.emittedEvents;
|
|
@@ -57,26 +61,50 @@ const transitionOptions = (options) => {
|
|
|
57
61
|
const configuration = typeof options === "object" && options !== null
|
|
58
62
|
? options
|
|
59
63
|
: {};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
};
|
|
64
|
+
if (hasProperty(configuration, "reenter")) {
|
|
65
|
+
throw new Error("Use .reenter() before construction instead of the resolver reenter option");
|
|
66
|
+
}
|
|
67
|
+
return { declinable: configuration.declinable === true };
|
|
64
68
|
};
|
|
65
|
-
const makeDirectTransitionDescriptor = (selection, resolve, options) => {
|
|
69
|
+
const makeDirectTransitionDescriptor = (selection, resolve, options, reenterSource = false) => {
|
|
66
70
|
const shared = {
|
|
67
71
|
[TransitionBuilderDescriptorTypeId]: TransitionBuilderDescriptorTypeId,
|
|
68
72
|
type: "direct",
|
|
69
73
|
selection: plainTargetSelection(selection),
|
|
74
|
+
reenterSource,
|
|
70
75
|
...transitionOptions(options)
|
|
71
76
|
};
|
|
72
77
|
return resolve === undefined
|
|
73
78
|
? Object.freeze(shared)
|
|
74
|
-
: Object.freeze({ ...shared, resolve });
|
|
79
|
+
: Object.freeze({ ...shared, resolver: resolve });
|
|
80
|
+
};
|
|
81
|
+
// The authored callback crosses an erased schema boundary here. Each builder
|
|
82
|
+
// retains its construction mode, and planning validates both resulting values.
|
|
83
|
+
const constructSelectionValue = (selection, context, method, value) => {
|
|
84
|
+
if (selection.kind === "update")
|
|
85
|
+
return context.owner[method](value);
|
|
86
|
+
if (selection.updatePath === undefined)
|
|
87
|
+
return context.target[method](value);
|
|
88
|
+
const values = value;
|
|
89
|
+
return context.target[method](values.target).update(context.owner[method](values.update));
|
|
90
|
+
};
|
|
91
|
+
const guardedSelection = (selection, predicate, reenterSource) => {
|
|
92
|
+
const wrap = (resolve, options) => makeDirectTransitionDescriptor(selection, (context, enqueue) => predicate(context) ? resolve(context, enqueue) : Topology.makeDeclined(), { ...transitionOptions(options), declinable: true }, reenterSource);
|
|
93
|
+
return Object.freeze({
|
|
94
|
+
...wrap((context) => selection.kind === "none" ? undefined : constructSelectedTarget(context.target)),
|
|
95
|
+
from: (value) => wrap((context) => constructSelectionValue(selection, context, "from", value(context))),
|
|
96
|
+
decoded: (value) => wrap((context) => constructSelectionValue(selection, context, "decoded", value(context))),
|
|
97
|
+
resolve: wrap
|
|
98
|
+
});
|
|
75
99
|
};
|
|
76
|
-
const decorateTransitionSelection = (selection) => Object.freeze({
|
|
100
|
+
const decorateTransitionSelection = (selection, reenterSource = false) => Object.freeze({
|
|
77
101
|
...selection,
|
|
78
|
-
|
|
79
|
-
|
|
102
|
+
...(reenterSource ? makeDirectTransitionDescriptor(selection, undefined, undefined, true) : {}),
|
|
103
|
+
guard: (predicate) => guardedSelection(selection, predicate, reenterSource),
|
|
104
|
+
from: (value) => makeDirectTransitionDescriptor(selection, (context) => constructSelectionValue(selection, context, "from", value(context)), undefined, reenterSource),
|
|
105
|
+
decoded: (value) => makeDirectTransitionDescriptor(selection, (context) => constructSelectionValue(selection, context, "decoded", value(context)), undefined, reenterSource),
|
|
106
|
+
resolve: (resolve, options) => makeDirectTransitionDescriptor(selection, resolve, options, reenterSource),
|
|
107
|
+
reenter: () => decorateTransitionSelection(selection, true),
|
|
80
108
|
updating: (owner) => {
|
|
81
109
|
if (typeof owner !== "function") {
|
|
82
110
|
throw new Error("Machine updating owner must be a state selector");
|
|
@@ -86,14 +114,9 @@ const decorateTransitionSelection = (selection) => Object.freeze({
|
|
|
86
114
|
ownerSelection.scope !== "branch") {
|
|
87
115
|
throw new Error("Machine updating owner must be addressed by one branch state selector");
|
|
88
116
|
}
|
|
89
|
-
return decorateTransitionSelection(Topology.makeTargetSelection(selection.kind, selection.path, selection.scope, ownerSelection.path));
|
|
117
|
+
return decorateTransitionSelection(Topology.makeTargetSelection(selection.kind, selection.path, selection.scope, ownerSelection.path), reenterSource);
|
|
90
118
|
}
|
|
91
119
|
});
|
|
92
|
-
const decorateStateUpdateSelection = (selection) => {
|
|
93
|
-
const update = (resolve, options) => makeDirectTransitionDescriptor(selection, resolve, options);
|
|
94
|
-
Object.assign(update, selection);
|
|
95
|
-
return Object.freeze(update);
|
|
96
|
-
};
|
|
97
120
|
const noneTransitionSelection = decorateTransitionSelection(Topology.noneTargetSelection);
|
|
98
121
|
const makeInitialBuilderDescriptor = (selection, resolve) => Object.freeze({
|
|
99
122
|
[InitialBuilderDescriptorTypeId]: InitialBuilderDescriptorTypeId,
|
|
@@ -102,6 +125,8 @@ const makeInitialBuilderDescriptor = (selection, resolve) => Object.freeze({
|
|
|
102
125
|
});
|
|
103
126
|
const decorateInitialSelection = (selection) => Object.freeze({
|
|
104
127
|
...selection,
|
|
128
|
+
from: (value) => makeInitialBuilderDescriptor(selection, (context) => context.target.from(value(context))),
|
|
129
|
+
decoded: (value) => makeInitialBuilderDescriptor(selection, (context) => context.target.decoded(value(context))),
|
|
105
130
|
resolve: (resolve) => makeInitialBuilderDescriptor(selection, resolve)
|
|
106
131
|
});
|
|
107
132
|
const decorateInitialSelectorNode = (node) => {
|
|
@@ -125,8 +150,12 @@ const decorateInitialSelectorNode = (node) => {
|
|
|
125
150
|
};
|
|
126
151
|
const decorateTransitionSelectorNode = (node) => {
|
|
127
152
|
if (Topology.isTargetSelection(node)) {
|
|
128
|
-
if (node.kind === "
|
|
129
|
-
return
|
|
153
|
+
if (node.kind === "state" && node.scope === "full" && hasProperty(node, "initial")) {
|
|
154
|
+
return Object.freeze({
|
|
155
|
+
...decorateTransitionSelection(node),
|
|
156
|
+
initial: decorateTransitionSelection(node.initial)
|
|
157
|
+
});
|
|
158
|
+
}
|
|
130
159
|
return node === Topology.noneTargetSelection ? noneTransitionSelection : decorateTransitionSelection(node);
|
|
131
160
|
}
|
|
132
161
|
if (typeof node === "function") {
|
|
@@ -145,24 +174,24 @@ const decorateTransitionSelectorNode = (node) => {
|
|
|
145
174
|
}
|
|
146
175
|
return node;
|
|
147
176
|
};
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
};
|
|
177
|
+
const decorateBranches = (declarations, reenterSource = false) => Object.freeze({
|
|
178
|
+
reenter: () => decorateBranches(declarations, true),
|
|
179
|
+
resolve: (resolve, options) => Object.freeze({
|
|
180
|
+
[TransitionBuilderDescriptorTypeId]: TransitionBuilderDescriptorTypeId,
|
|
181
|
+
type: "branches",
|
|
182
|
+
declarations,
|
|
183
|
+
resolve,
|
|
184
|
+
reenterSource,
|
|
185
|
+
...transitionOptions(options)
|
|
186
|
+
})
|
|
187
|
+
});
|
|
188
|
+
const makeTransitionSelector = (stateNodes, source) => Object.freeze({
|
|
189
|
+
...decorateTransitionSelectorNode(makeTargetSelector(stateNodes, source)),
|
|
190
|
+
branches: (declarations) => decorateBranches(declarations)
|
|
191
|
+
});
|
|
163
192
|
const normalizeTransitionBuilder = (transition, stateNodes, path) => {
|
|
164
193
|
const result = transition(makeTransitionSelector(stateNodes, path));
|
|
165
|
-
if (Topology.isTargetSelection(result)) {
|
|
194
|
+
if (Topology.isTargetSelection(result) && !hasProperty(result, TransitionBuilderDescriptorTypeId)) {
|
|
166
195
|
const selection = plainTargetSelection(result);
|
|
167
196
|
return { target: () => selection };
|
|
168
197
|
}
|
|
@@ -173,14 +202,14 @@ const normalizeTransitionBuilder = (transition, stateNodes, path) => {
|
|
|
173
202
|
return {
|
|
174
203
|
branches: () => descriptor.declarations,
|
|
175
204
|
resolve: descriptor.resolve,
|
|
176
|
-
reenter: descriptor.
|
|
205
|
+
reenter: descriptor.reenterSource,
|
|
177
206
|
declinable: descriptor.declinable
|
|
178
207
|
};
|
|
179
208
|
}
|
|
180
209
|
return {
|
|
181
210
|
target: () => descriptor.selection,
|
|
182
|
-
resolve: descriptor.
|
|
183
|
-
reenter: descriptor.
|
|
211
|
+
resolve: descriptor.resolver,
|
|
212
|
+
reenter: descriptor.reenterSource,
|
|
184
213
|
declinable: descriptor.declinable
|
|
185
214
|
};
|
|
186
215
|
};
|
|
@@ -215,7 +244,7 @@ const makeSelectionNode = (stateNodes, path, scope, source) => {
|
|
|
215
244
|
addSelectionChildren(method, stateNodes, path, scope, source);
|
|
216
245
|
}
|
|
217
246
|
if (scope === "branch" && source !== undefined && node.schema !== undefined &&
|
|
218
|
-
(source === path ||
|
|
247
|
+
(source === path || Configuration.isDescendantOf(source, path)) &&
|
|
219
248
|
getTargetBuilderNode(stateNodes, source).type !== "choice") {
|
|
220
249
|
Object.defineProperty(method, "update", {
|
|
221
250
|
value: makeStateUpdateSelection(path, "branch"),
|
|
@@ -223,6 +252,9 @@ const makeSelectionNode = (stateNodes, path, scope, source) => {
|
|
|
223
252
|
});
|
|
224
253
|
}
|
|
225
254
|
}
|
|
255
|
+
if (node.type === "atomic" && scope === "branch" && source === path && node.schema !== undefined) {
|
|
256
|
+
Object.defineProperty(method, "update", { value: makeStateUpdateSelection(path, "branch"), enumerable: true });
|
|
257
|
+
}
|
|
226
258
|
return method;
|
|
227
259
|
};
|
|
228
260
|
const makeHistorySelectionTree = (stateNodes, parent) => {
|
|
@@ -242,15 +274,12 @@ const makeHistorySelectionTree = (stateNodes, parent) => {
|
|
|
242
274
|
return builder;
|
|
243
275
|
};
|
|
244
276
|
const makeTargetSelector = (stateNodes, source) => {
|
|
245
|
-
const full = {}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
full[node.key] = makeSelectionNode(stateNodes, node.path, "full");
|
|
249
|
-
}
|
|
250
|
-
}
|
|
277
|
+
const full = Object.assign({}, makeSelectionValue("state", "", "full"), {
|
|
278
|
+
initial: makeSelectionValue("initial", "", "full")
|
|
279
|
+
});
|
|
251
280
|
const branch = {};
|
|
252
|
-
const root = getTargetBuilderNode(stateNodes,
|
|
253
|
-
branch
|
|
281
|
+
const root = getTargetBuilderNode(stateNodes, stateNodes.roots[0]);
|
|
282
|
+
addSelectionChildren(branch, stateNodes, root.path, "branch", source);
|
|
254
283
|
const local = {};
|
|
255
284
|
const localScope = getLocalTargetScope(stateNodes, source);
|
|
256
285
|
if (localScope !== undefined) {
|
|
@@ -265,10 +294,15 @@ const makeTargetSelector = (stateNodes, source) => {
|
|
|
265
294
|
}
|
|
266
295
|
return {
|
|
267
296
|
none: Topology.noneTargetSelection,
|
|
297
|
+
self: getTargetBuilderNode(stateNodes, source).schema === undefined ||
|
|
298
|
+
getTargetBuilderNode(stateNodes, source).type === "final"
|
|
299
|
+
? {}
|
|
300
|
+
: { update: makeStateUpdateSelection(source, "branch") },
|
|
301
|
+
root: makeSelectionNode(stateNodes, root.path, "branch", source),
|
|
268
302
|
local,
|
|
269
303
|
branch,
|
|
270
304
|
full,
|
|
271
|
-
history: makeHistorySelectionTree(stateNodes,
|
|
305
|
+
history: makeHistorySelectionTree(stateNodes, "")
|
|
272
306
|
};
|
|
273
307
|
};
|
|
274
308
|
const captureDefinitionBranch = (branch, selector, stateNodes, path, trigger) => {
|
|
@@ -327,6 +361,8 @@ const getSelectionBuilder = (target, selection, stateNodes, source) => {
|
|
|
327
361
|
let parts = selection.path.split(".");
|
|
328
362
|
if (selection.kind === "history") {
|
|
329
363
|
builder = target.history;
|
|
364
|
+
if (selection.path !== "")
|
|
365
|
+
parts.unshift("");
|
|
330
366
|
}
|
|
331
367
|
else if (selection.scope === "local") {
|
|
332
368
|
builder = target.local;
|
|
@@ -337,12 +373,14 @@ const getSelectionBuilder = (target, selection, stateNodes, source) => {
|
|
|
337
373
|
parts = [];
|
|
338
374
|
}
|
|
339
375
|
else {
|
|
340
|
-
parts = selection.path.slice(scope.length + 1).split(".");
|
|
376
|
+
parts = (scope === "" ? selection.path : selection.path.slice(scope.length + 1)).split(".");
|
|
341
377
|
}
|
|
342
378
|
}
|
|
343
379
|
}
|
|
344
380
|
else if (selection.scope === "branch") {
|
|
345
381
|
builder = target.branch;
|
|
382
|
+
if (selection.path !== "")
|
|
383
|
+
parts.unshift("");
|
|
346
384
|
}
|
|
347
385
|
else {
|
|
348
386
|
builder = target.full;
|
|
@@ -390,7 +428,7 @@ const validateResolvedSelection = (result, selection, stateNodes) => {
|
|
|
390
428
|
const acceptsDescendant = (selection.scope === "local" || selection.scope === "branch") &&
|
|
391
429
|
(selectedNode?.type === "compound" || selectedNode?.type === "parallel");
|
|
392
430
|
if (resultPath === undefined ||
|
|
393
|
-
(resultPath !== selection.path && !(acceptsDescendant &&
|
|
431
|
+
(resultPath !== selection.path && !(acceptsDescendant && Configuration.isDescendantOf(resultPath, selection.path)))) {
|
|
394
432
|
throw new Error(`Machine transition resolver selected "${selection.path}" but constructed "${resultPath ?? "<invalid>"}"`);
|
|
395
433
|
}
|
|
396
434
|
};
|
|
@@ -457,6 +495,9 @@ const captureNamedBranches = (declarations, path, trigger) => {
|
|
|
457
495
|
if (target.updatePath !== undefined) {
|
|
458
496
|
throw new Error(`Machine transition branch "${key}" cannot declare an updating target`);
|
|
459
497
|
}
|
|
498
|
+
if (hasProperty(target, TransitionBuilderDescriptorTypeId)) {
|
|
499
|
+
throw new Error(`Machine transition branch "${key}" requires a topology selection; apply .reenter() to .branches(...)`);
|
|
500
|
+
}
|
|
460
501
|
if (title !== undefined && (typeof title !== "string" || title.length === 0)) {
|
|
461
502
|
throw new Error(`Machine transition branch "${key}" title must be a non-empty string`);
|
|
462
503
|
}
|
|
@@ -654,10 +695,10 @@ const captureInvokeDefinition = (invoke, stateNodes, path) => {
|
|
|
654
695
|
captured[key] = captureTransition(captured[key], stateNodes, path, key);
|
|
655
696
|
}
|
|
656
697
|
}
|
|
657
|
-
return captured;
|
|
698
|
+
return InvocationDefinition.capture(captured, path);
|
|
658
699
|
});
|
|
659
700
|
if (Array.isArray(authored))
|
|
660
|
-
return capturedDefinitions;
|
|
701
|
+
return Object.freeze(capturedDefinitions);
|
|
661
702
|
return capturedDefinitions[0];
|
|
662
703
|
};
|
|
663
704
|
const flattenHandlers = (handlers, stateNodes, states, prefix, config) => {
|
|
@@ -671,6 +712,12 @@ const flattenHandlers = (handlers, stateNodes, states, prefix, config) => {
|
|
|
671
712
|
throw new Error(`Machine expected state "${path}" handler to be an object`);
|
|
672
713
|
}
|
|
673
714
|
const { states: childConfig, ...stateConfig } = nodeConfig;
|
|
715
|
+
if (typeof stateConfig.history === "object" && stateConfig.history !== null) {
|
|
716
|
+
stateConfig.history = Object.freeze(Object.fromEntries(Object.entries(stateConfig.history).map(([key, entry]) => [
|
|
717
|
+
key,
|
|
718
|
+
typeof entry === "object" && entry !== null ? Object.freeze({ ...entry }) : entry
|
|
719
|
+
])));
|
|
720
|
+
}
|
|
674
721
|
const on = stateConfig.on;
|
|
675
722
|
if (typeof on === "object" && on !== null) {
|
|
676
723
|
const capturedOn = captureEventHandlers(on, stateNodes, path);
|
|
@@ -712,340 +759,11 @@ const flattenHandlers = (handlers, stateNodes, states, prefix, config) => {
|
|
|
712
759
|
};
|
|
713
760
|
const makeHandle = (self) => ((config) => {
|
|
714
761
|
const handlers = Object.create(null);
|
|
715
|
-
flattenHandlers(handlers, self.stateNodes, self.states, "", config);
|
|
762
|
+
flattenHandlers(handlers, self.stateNodes, self.states, "", { "": config });
|
|
716
763
|
return makeWithHandlers(self, handlers);
|
|
717
764
|
});
|
|
718
765
|
export const isMachine = (u) => hasProperty(u, TypeId) && u[TypeId] === TypeId;
|
|
719
766
|
export const isFinal = (machine, state) => internalPlanner.isFinal(machine, state);
|
|
720
|
-
const withFrom = (method, kind, valued) => {
|
|
721
|
-
const builder = {};
|
|
722
|
-
if (valued) {
|
|
723
|
-
Object.defineProperty(builder, "decoded", {
|
|
724
|
-
value: method,
|
|
725
|
-
enumerable: false
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
Object.defineProperty(builder, "from", {
|
|
729
|
-
value: (...args) => {
|
|
730
|
-
if (!valued) {
|
|
731
|
-
return method(undefined, ...args);
|
|
732
|
-
}
|
|
733
|
-
const omitted = args.length === 0 || (kind === "nested" && args.length === 1 && typeof args[0] === "function");
|
|
734
|
-
const input = omitted ? {} : args[0];
|
|
735
|
-
const rest = omitted ? args : args.slice(1);
|
|
736
|
-
return method(Topology.makeStateInput(input), ...rest);
|
|
737
|
-
},
|
|
738
|
-
enumerable: false
|
|
739
|
-
});
|
|
740
|
-
return builder;
|
|
741
|
-
};
|
|
742
|
-
const withInitial = (builder, path, valued, values) => {
|
|
743
|
-
const initial = withFrom((value) => Topology.makeInitialTarget(path, value, values), "leaf", valued);
|
|
744
|
-
Object.defineProperty(builder, "initial", {
|
|
745
|
-
value: initial,
|
|
746
|
-
enumerable: false
|
|
747
|
-
});
|
|
748
|
-
return builder;
|
|
749
|
-
};
|
|
750
|
-
const makeSnapshotBuilder = (states, options) => {
|
|
751
|
-
const builder = {};
|
|
752
|
-
for (const key of Object.keys(states)) {
|
|
753
|
-
const definition = states[key];
|
|
754
|
-
const pseudoType = definition.type;
|
|
755
|
-
if (pseudoType === "history") {
|
|
756
|
-
continue;
|
|
757
|
-
}
|
|
758
|
-
const path = options.prefix === "" ? key : `${options.prefix}.${key}`;
|
|
759
|
-
if (pseudoType === "choice") {
|
|
760
|
-
builder[key] = () => Topology.makeChoiceTarget(path, getParentPathRuntime(path));
|
|
761
|
-
continue;
|
|
762
|
-
}
|
|
763
|
-
const node = Topology.getStateNodeDefinition(path, definition);
|
|
764
|
-
const method = withFrom((value, selector) => makeSnapshotForNode(definition, key, value, selector, options), node.states === undefined ? "leaf" : "nested", node.schema !== undefined);
|
|
765
|
-
builder[key] = node.states === undefined || options.mode !== "full" || options.prefix !== ""
|
|
766
|
-
? method
|
|
767
|
-
: withInitial(method, path, node.schema !== undefined);
|
|
768
|
-
}
|
|
769
|
-
return builder;
|
|
770
|
-
};
|
|
771
|
-
const makeParallelSnapshotBuilder = (states, options, regions) => {
|
|
772
|
-
const builder = {};
|
|
773
|
-
Object.defineProperty(builder, SnapshotBuilderStateTypeId, {
|
|
774
|
-
value: regions,
|
|
775
|
-
enumerable: false
|
|
776
|
-
});
|
|
777
|
-
for (const key of Object.keys(states)) {
|
|
778
|
-
const definition = states[key];
|
|
779
|
-
const pseudoType = definition.type;
|
|
780
|
-
if (pseudoType === "history" || pseudoType === "choice") {
|
|
781
|
-
continue;
|
|
782
|
-
}
|
|
783
|
-
if (hasProperty(regions, key)) {
|
|
784
|
-
continue;
|
|
785
|
-
}
|
|
786
|
-
const path = options.prefix === "" ? key : `${options.prefix}.${key}`;
|
|
787
|
-
const node = Topology.getStateNodeDefinition(path, definition);
|
|
788
|
-
const method = withFrom((value, selector) => {
|
|
789
|
-
const nextRegions = {};
|
|
790
|
-
for (const regionKey of Object.keys(regions)) {
|
|
791
|
-
nextRegions[regionKey] = regions[regionKey];
|
|
792
|
-
}
|
|
793
|
-
nextRegions[key] = makeSnapshotForNode(definition, key, value, selector, options);
|
|
794
|
-
return makeParallelSnapshotBuilder(states, options, nextRegions);
|
|
795
|
-
}, node.states === undefined ? "leaf" : "nested", node.schema !== undefined);
|
|
796
|
-
builder[key] = method;
|
|
797
|
-
}
|
|
798
|
-
return builder;
|
|
799
|
-
};
|
|
800
|
-
const getParallelSnapshotBuilderRegions = (path, states, builder) => {
|
|
801
|
-
if (typeof builder !== "object" || builder === null || !hasProperty(builder, SnapshotBuilderStateTypeId)) {
|
|
802
|
-
throw new Error(`Machine expected parallel state "${path}" builder callback to return a builder`);
|
|
803
|
-
}
|
|
804
|
-
const regions = builder[SnapshotBuilderStateTypeId];
|
|
805
|
-
for (const key of Object.keys(states)) {
|
|
806
|
-
const pseudoType = states[key].type;
|
|
807
|
-
if (pseudoType === "history" || pseudoType === "choice") {
|
|
808
|
-
continue;
|
|
809
|
-
}
|
|
810
|
-
if (!hasProperty(regions, key)) {
|
|
811
|
-
throw new Error(`Machine expected parallel state "${path}" builder callback to provide region "${key}"`);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
return regions;
|
|
815
|
-
};
|
|
816
|
-
const makeSnapshotForNode = (definition, key, value, selector, options) => {
|
|
817
|
-
const path = options.prefix === "" ? key : `${options.prefix}.${key}`;
|
|
818
|
-
const node = Topology.getStateNodeDefinition(path, definition);
|
|
819
|
-
const snapshot = {
|
|
820
|
-
path,
|
|
821
|
-
value
|
|
822
|
-
};
|
|
823
|
-
if (node.states === undefined) {
|
|
824
|
-
return snapshot;
|
|
825
|
-
}
|
|
826
|
-
if (selector === undefined) {
|
|
827
|
-
throw new Error(`Machine expected state "${path}" builder to provide active child states`);
|
|
828
|
-
}
|
|
829
|
-
if (node.type === "parallel") {
|
|
830
|
-
const builder = makeParallelSnapshotBuilder(node.states, { ...options, prefix: path }, {});
|
|
831
|
-
const selected = selector(builder);
|
|
832
|
-
snapshot.states = getParallelSnapshotBuilderRegions(path, node.states, selected);
|
|
833
|
-
return snapshot;
|
|
834
|
-
}
|
|
835
|
-
const childStates = options.mode === "initial" && node.initial !== undefined
|
|
836
|
-
? { [node.initial]: node.states[node.initial] }
|
|
837
|
-
: node.states;
|
|
838
|
-
const selected = selector(makeSnapshotBuilder(childStates, { ...options, prefix: path }));
|
|
839
|
-
snapshot.state = selected;
|
|
840
|
-
return snapshot;
|
|
841
|
-
};
|
|
842
|
-
const getTargetBuilderNode = (stateNodes, path) => {
|
|
843
|
-
const node = stateNodes.byPath.get(path);
|
|
844
|
-
if (node === undefined) {
|
|
845
|
-
throw new Error(`Machine expected state path "${path}" to exist`);
|
|
846
|
-
}
|
|
847
|
-
return node;
|
|
848
|
-
};
|
|
849
|
-
const getLocalTargetScope = (stateNodes, source) => {
|
|
850
|
-
let current = source;
|
|
851
|
-
while (current !== undefined) {
|
|
852
|
-
const node = stateNodes.byPath.get(current);
|
|
853
|
-
if (node === undefined) {
|
|
854
|
-
return undefined;
|
|
855
|
-
}
|
|
856
|
-
if (node.type === "compound") {
|
|
857
|
-
return node.path;
|
|
858
|
-
}
|
|
859
|
-
current = node.parent;
|
|
860
|
-
}
|
|
861
|
-
return undefined;
|
|
862
|
-
};
|
|
863
|
-
const hasTargetValues = (values) => values !== undefined && Object.keys(values).length > 0;
|
|
864
|
-
const makeTargetWithValues = (path, value, values) => hasTargetValues(values)
|
|
865
|
-
? Topology.makeTarget(path, value, { values: values })
|
|
866
|
-
: Topology.makeTarget(path, value);
|
|
867
|
-
const getTargetBuilderDefinition = (states, targetPath) => {
|
|
868
|
-
let children = states;
|
|
869
|
-
let path = "";
|
|
870
|
-
let definition;
|
|
871
|
-
for (const key of targetPath.split(".")) {
|
|
872
|
-
if (!hasProperty(children, key)) {
|
|
873
|
-
throw new Error(`Machine expected state path "${targetPath}" to exist`);
|
|
874
|
-
}
|
|
875
|
-
definition = children[key];
|
|
876
|
-
path = path === "" ? key : `${path}.${key}`;
|
|
877
|
-
const node = Topology.getStateNodeDefinition(path, definition);
|
|
878
|
-
children = node.states ?? {};
|
|
879
|
-
}
|
|
880
|
-
return definition;
|
|
881
|
-
};
|
|
882
|
-
const makeParallelTarget = (states, node, value, selector, values) => {
|
|
883
|
-
if (selector === undefined) {
|
|
884
|
-
throw new Error(`Machine expected parallel target "${node.path}" builder to provide every active region`);
|
|
885
|
-
}
|
|
886
|
-
const snapshot = makeSnapshotForNode(getTargetBuilderDefinition(states, node.path), node.key, value, selector, { mode: "full", prefix: node.parent ?? "" });
|
|
887
|
-
return Topology.makeTarget(node.path, value, {
|
|
888
|
-
snapshot: snapshot,
|
|
889
|
-
values: values
|
|
890
|
-
});
|
|
891
|
-
};
|
|
892
|
-
const extendTargetValues = (values, path, value) => {
|
|
893
|
-
const next = {};
|
|
894
|
-
if (values !== undefined) {
|
|
895
|
-
for (const key of Object.keys(values)) {
|
|
896
|
-
next[key] = values[key];
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
next[path] = value;
|
|
900
|
-
return next;
|
|
901
|
-
};
|
|
902
|
-
const makeLocalTargetChildBuilder = (states, stateNodes, parentPath, values, source) => {
|
|
903
|
-
const parent = getTargetBuilderNode(stateNodes, parentPath);
|
|
904
|
-
const builder = {};
|
|
905
|
-
for (const childPath of Array.from(stateNodes.byPath.values())
|
|
906
|
-
.filter((node) => node.parent === parent.path && node.type !== "history")
|
|
907
|
-
.map((node) => node.path)) {
|
|
908
|
-
const child = getTargetBuilderNode(stateNodes, childPath);
|
|
909
|
-
if (child.type === "choice") {
|
|
910
|
-
builder[child.key] = () => Topology.makeChoiceTarget(child.path, parent.path, values);
|
|
911
|
-
continue;
|
|
912
|
-
}
|
|
913
|
-
const method = withFrom((value, selector) => {
|
|
914
|
-
if (child.type === "atomic" || child.type === "final") {
|
|
915
|
-
return makeTargetWithValues(child.path, value, values);
|
|
916
|
-
}
|
|
917
|
-
if (child.type === "parallel") {
|
|
918
|
-
if (source !== child.path && !source.startsWith(`${child.path}.`)) {
|
|
919
|
-
return makeParallelTarget(states, child, value, selector, values);
|
|
920
|
-
}
|
|
921
|
-
if (selector === undefined) {
|
|
922
|
-
throw new Error(`Machine expected target "${child.path}" builder to provide an active child state`);
|
|
923
|
-
}
|
|
924
|
-
return selector(makeLocalTargetChildBuilder(states, stateNodes, child.path, child.schema === undefined ? values : extendTargetValues(values, child.path, value), source));
|
|
925
|
-
}
|
|
926
|
-
if (selector === undefined) {
|
|
927
|
-
throw new Error(`Machine expected target "${child.path}" builder to provide an active child state`);
|
|
928
|
-
}
|
|
929
|
-
return selector(makeLocalTargetChildBuilder(states, stateNodes, child.path, child.schema === undefined ? values : extendTargetValues(values, child.path, value), source));
|
|
930
|
-
}, child.type === "atomic" || child.type === "final" ? "leaf" : "nested", child.schema !== undefined);
|
|
931
|
-
builder[child.key] = child.type === "atomic" || child.type === "final"
|
|
932
|
-
? method
|
|
933
|
-
: withInitial(method, child.path, child.schema !== undefined, values);
|
|
934
|
-
}
|
|
935
|
-
return builder;
|
|
936
|
-
};
|
|
937
|
-
const makeLocalTargetBuilder = (states, stateNodes, source) => {
|
|
938
|
-
const scope = getLocalTargetScope(stateNodes, source);
|
|
939
|
-
if (scope === undefined) {
|
|
940
|
-
return {};
|
|
941
|
-
}
|
|
942
|
-
const builder = makeLocalTargetChildBuilder(states, stateNodes, scope, undefined, source);
|
|
943
|
-
const scopeNode = getTargetBuilderNode(stateNodes, scope);
|
|
944
|
-
if (scopeNode.schema !== undefined) {
|
|
945
|
-
builder.with = withFrom((value, selector) => {
|
|
946
|
-
if (selector === undefined) {
|
|
947
|
-
throw new Error(`Machine expected target "${scope}" builder to provide an active child state`);
|
|
948
|
-
}
|
|
949
|
-
return selector(makeLocalTargetChildBuilder(states, stateNodes, scope, { [scope]: value }, source));
|
|
950
|
-
}, "nested", true);
|
|
951
|
-
}
|
|
952
|
-
return builder;
|
|
953
|
-
};
|
|
954
|
-
const addBranchTargetChildren = (builder, states, stateNodes, parentPath, values, source) => {
|
|
955
|
-
const parent = getTargetBuilderNode(stateNodes, parentPath);
|
|
956
|
-
for (const childPath of Array.from(stateNodes.byPath.values())
|
|
957
|
-
.filter((node) => node.parent === parent.path && node.type !== "history")
|
|
958
|
-
.map((node) => node.path)) {
|
|
959
|
-
const child = getTargetBuilderNode(stateNodes, childPath);
|
|
960
|
-
if (child.type === "choice") {
|
|
961
|
-
builder[child.key] = () => Topology.makeChoiceTarget(child.path, parent.path, values);
|
|
962
|
-
continue;
|
|
963
|
-
}
|
|
964
|
-
builder[child.key] = makeBranchTargetNodeBuilder(states, stateNodes, child.path, values, source);
|
|
965
|
-
}
|
|
966
|
-
};
|
|
967
|
-
const makeBranchTargetNodeBuilder = (states, stateNodes, path, values, source) => {
|
|
968
|
-
const node = getTargetBuilderNode(stateNodes, path);
|
|
969
|
-
if (node.type === "atomic" || node.type === "final") {
|
|
970
|
-
return withFrom((value) => makeTargetWithValues(node.path, value, values), "leaf", node.schema !== undefined);
|
|
971
|
-
}
|
|
972
|
-
const builder = withFrom((value, selector) => {
|
|
973
|
-
if (node.type === "parallel") {
|
|
974
|
-
if (source !== node.path && !source.startsWith(`${node.path}.`)) {
|
|
975
|
-
return makeParallelTarget(states, node, value, selector, values);
|
|
976
|
-
}
|
|
977
|
-
if (selector === undefined) {
|
|
978
|
-
throw new Error(`Machine expected target "${node.path}" builder to provide an active child state`);
|
|
979
|
-
}
|
|
980
|
-
const nextBuilder = {};
|
|
981
|
-
addBranchTargetChildren(nextBuilder, states, stateNodes, node.path, node.schema === undefined ? values : extendTargetValues(values, node.path, value), source);
|
|
982
|
-
return selector(nextBuilder);
|
|
983
|
-
}
|
|
984
|
-
if (selector === undefined) {
|
|
985
|
-
throw new Error(`Machine expected target "${node.path}" builder to provide an active child state`);
|
|
986
|
-
}
|
|
987
|
-
const nextBuilder = {};
|
|
988
|
-
addBranchTargetChildren(nextBuilder, states, stateNodes, node.path, node.schema === undefined ? values : extendTargetValues(values, node.path, value), source);
|
|
989
|
-
return selector(nextBuilder);
|
|
990
|
-
}, "nested", node.schema !== undefined);
|
|
991
|
-
withInitial(builder, node.path, node.schema !== undefined, values);
|
|
992
|
-
if (node.type !== "parallel" || source === node.path || source.startsWith(`${node.path}.`)) {
|
|
993
|
-
addBranchTargetChildren(builder, states, stateNodes, node.path, values, source);
|
|
994
|
-
}
|
|
995
|
-
return builder;
|
|
996
|
-
};
|
|
997
|
-
const makeBranchTargetBuilder = (states, stateNodes, source) => {
|
|
998
|
-
const rootPath = source.split(".")[0];
|
|
999
|
-
const root = getTargetBuilderNode(stateNodes, rootPath);
|
|
1000
|
-
return {
|
|
1001
|
-
[root.key]: makeBranchTargetNodeBuilder(states, stateNodes, root.path, undefined, source)
|
|
1002
|
-
};
|
|
1003
|
-
};
|
|
1004
|
-
const makeHistoryTargetBuilder = (states, prefix) => {
|
|
1005
|
-
const builder = {};
|
|
1006
|
-
for (const key of Object.keys(states)) {
|
|
1007
|
-
const path = prefix === "" ? key : `${prefix}.${key}`;
|
|
1008
|
-
const definition = Topology.getStateNodeDefinition(path, states[key]);
|
|
1009
|
-
if (definition.type === "history") {
|
|
1010
|
-
const parent = getParentPathRuntime(path);
|
|
1011
|
-
builder[key] = () => Topology.makeHistoryTarget(path, parent);
|
|
1012
|
-
continue;
|
|
1013
|
-
}
|
|
1014
|
-
if (definition.states !== undefined) {
|
|
1015
|
-
builder[key] = makeHistoryTargetBuilder(definition.states, path);
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
return builder;
|
|
1019
|
-
};
|
|
1020
|
-
const getParentPathRuntime = (path) => {
|
|
1021
|
-
const separator = path.lastIndexOf(".");
|
|
1022
|
-
if (separator < 0) {
|
|
1023
|
-
throw new Error(`Machine expected history state "${path}" to have an active parent`);
|
|
1024
|
-
}
|
|
1025
|
-
return path.slice(0, separator);
|
|
1026
|
-
};
|
|
1027
|
-
const makeTargetBuilder = (states, stateNodes) => {
|
|
1028
|
-
const full = makeSnapshotBuilder(states, { mode: "full", prefix: "" });
|
|
1029
|
-
const history = makeHistoryTargetBuilder(states, "");
|
|
1030
|
-
return (source) => ({
|
|
1031
|
-
none: Topology.makeNoTarget,
|
|
1032
|
-
local: makeLocalTargetBuilder(states, stateNodes, source),
|
|
1033
|
-
branch: makeBranchTargetBuilder(states, stateNodes, source),
|
|
1034
|
-
full,
|
|
1035
|
-
history
|
|
1036
|
-
});
|
|
1037
|
-
};
|
|
1038
|
-
const makeInitialSelector = (stateNodes) => {
|
|
1039
|
-
const selector = {};
|
|
1040
|
-
for (const node of stateNodes.byPath.values()) {
|
|
1041
|
-
if (node.parent === undefined && node.type !== "history" && node.type !== "choice") {
|
|
1042
|
-
selector[node.key] = node.type === "atomic" || node.type === "final"
|
|
1043
|
-
? makeSelectionMethod("state", node.path, "initial")
|
|
1044
|
-
: Object.freeze({ initial: makeSelectionValue("initial", node.path, "initial") });
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
return Object.freeze(selector);
|
|
1048
|
-
};
|
|
1049
767
|
const getInitialSelectionBuilder = (initialBuilder, selection) => {
|
|
1050
768
|
const path = selection.path;
|
|
1051
769
|
if (path === undefined || path.includes(".")) {
|
|
@@ -1057,11 +775,12 @@ const getInitialSelectionBuilder = (initialBuilder, selection) => {
|
|
|
1057
775
|
}
|
|
1058
776
|
return builder;
|
|
1059
777
|
};
|
|
1060
|
-
const captureInitialBranch = (definition,
|
|
1061
|
-
if (typeof definition !== "function") {
|
|
778
|
+
const captureInitialBranch = (definition, initialBuilder, configuration) => {
|
|
779
|
+
if (definition !== undefined && typeof definition !== "function") {
|
|
1062
780
|
throw new Error("Machine initial definition must be a target-first callback");
|
|
1063
781
|
}
|
|
1064
|
-
const
|
|
782
|
+
const selector = decorateInitialSelection(makeSelectionValue(configuration ? "state" : "initial", "", "initial"));
|
|
783
|
+
const result = definition === undefined ? selector : definition(selector);
|
|
1065
784
|
let selection;
|
|
1066
785
|
let resolve;
|
|
1067
786
|
if (Topology.isTargetSelection(result)) {
|
|
@@ -1092,9 +811,12 @@ const validateInitialSelection = (result, selection) => {
|
|
|
1092
811
|
throw new Error(`Machine initial resolver selected "${selection.path}" but constructed "${resultPath}"`);
|
|
1093
812
|
}
|
|
1094
813
|
};
|
|
1095
|
-
const compileInitial = (definition, states, stateNodes) => {
|
|
1096
|
-
const
|
|
1097
|
-
const
|
|
814
|
+
const compileInitial = (definition, states, stateNodes, configuration = false) => {
|
|
815
|
+
const rootNode = getTargetBuilderNode(stateNodes, "");
|
|
816
|
+
const initialBuilder = configuration ?
|
|
817
|
+
makeSnapshotBuilder(states, { mode: "full", prefix: "" })
|
|
818
|
+
: { "": withFrom((value) => Topology.makeInitialTarget("", value), "leaf", rootNode.schema !== undefined) };
|
|
819
|
+
const branch = captureInitialBranch(definition, initialBuilder, configuration);
|
|
1098
820
|
return {
|
|
1099
821
|
initial: (input) => {
|
|
1100
822
|
const result = branch.resolve === undefined
|
|
@@ -1109,15 +831,13 @@ const compileInitial = (definition, states, stateNodes) => {
|
|
|
1109
831
|
})
|
|
1110
832
|
};
|
|
1111
833
|
};
|
|
1112
|
-
export const state = (
|
|
1113
|
-
StateDefinition.
|
|
1114
|
-
|
|
1115
|
-
});
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
const captured = StateDefinition.captureStateDefinitions(states);
|
|
834
|
+
export const state = (node) => {
|
|
835
|
+
const captured = StateDefinition.captureRoot(node);
|
|
836
|
+
const access = makeStateHelpers();
|
|
837
|
+
return Object.freeze({ ...access, "~effect/Machine/State": "~effect/Machine/State", node: captured });
|
|
838
|
+
};
|
|
839
|
+
const makeStateHelpers = () => {
|
|
1119
840
|
return {
|
|
1120
|
-
states: captured,
|
|
1121
841
|
path: ((path) => path),
|
|
1122
842
|
get: ((snapshot, path) => Topology.getSnapshotByPath(snapshot, path).pipe(Option.map((snapshot) => snapshot.value))),
|
|
1123
843
|
getWithParents: ((snapshot, path) => {
|
|
@@ -1127,31 +847,42 @@ export const states = ((states) => {
|
|
|
1127
847
|
getSnapshot: Topology.getSnapshotByPath,
|
|
1128
848
|
matches: ((snapshot, path) => Option.isSome(Topology.getSnapshotByPath(snapshot, path)))
|
|
1129
849
|
};
|
|
1130
|
-
}
|
|
1131
|
-
export const make = (
|
|
1132
|
-
|
|
850
|
+
};
|
|
851
|
+
export const make = (config) => {
|
|
852
|
+
const states = Object.freeze({ "": config.root.node });
|
|
1133
853
|
const self = Object.create(Proto);
|
|
1134
|
-
self.states =
|
|
854
|
+
self.states = states;
|
|
855
|
+
self.root = config.root;
|
|
1135
856
|
self.events = config.events;
|
|
1136
857
|
self.internalEvents = config.internalEvents ?? Protocol.makeEventProtocol("internal", []);
|
|
1137
858
|
self.emittedEvents = config.emittedEvents ?? Protocol.makeEventProtocol("emitted", []);
|
|
1138
859
|
self.parent = config.parent;
|
|
1139
860
|
self.input = config.input;
|
|
1140
861
|
self.id = config.id;
|
|
1141
|
-
self.stateNodes = Topology.compileStateNodes(
|
|
1142
|
-
const compiledInitial = compileInitial(config.initial,
|
|
862
|
+
self.stateNodes = Topology.compileStateNodes(states);
|
|
863
|
+
const compiledInitial = compileInitial(config.initialConfiguration ?? config.initial, states, self.stateNodes, config.initialConfiguration !== undefined);
|
|
1143
864
|
self.initial = compiledInitial.initial;
|
|
1144
865
|
self.initialDefinition = compiledInitial.definition;
|
|
1145
|
-
self.makeTargetBuilder = makeTargetBuilder(
|
|
866
|
+
self.makeTargetBuilder = makeTargetBuilder(states, self.stateNodes);
|
|
1146
867
|
self.handlers = Object.create(null);
|
|
1147
868
|
self.handle = makeHandle(self);
|
|
1148
869
|
Protocol.setProtocol(self);
|
|
1149
870
|
return self;
|
|
1150
|
-
}
|
|
871
|
+
};
|
|
1151
872
|
const flattenEventProtocolInputs = (kind, inputs) => inputs.flatMap((input) => Protocol.isEventProtocol(input, kind)
|
|
1152
873
|
? Protocol.eventProtocolSchemas(input)
|
|
1153
874
|
: [input]);
|
|
1154
875
|
export const events = (...inputs) => Protocol.makeEventProtocol("public", flattenEventProtocolInputs("public", inputs));
|
|
876
|
+
const eventFieldSchemas = (cases) => {
|
|
877
|
+
for (const [tag, fields] of Object.entries(cases)) {
|
|
878
|
+
if (Object.hasOwn(fields, "_tag"))
|
|
879
|
+
throw new Error(`Machine event "${tag}" fields cannot declare _tag`);
|
|
880
|
+
}
|
|
881
|
+
return Object.keys(cases).length === 0 ? [] : [Schema.TaggedUnion(cases)];
|
|
882
|
+
};
|
|
883
|
+
export const eventsFromFields = (cases) => Protocol.makeEventProtocol("public", eventFieldSchemas(cases));
|
|
884
|
+
export const internalEventsFromFields = (cases) => Protocol.makeEventProtocol("internal", eventFieldSchemas(cases));
|
|
885
|
+
export const emittedEventsFromFields = (cases) => Protocol.makeEventProtocol("emitted", eventFieldSchemas(cases));
|
|
1155
886
|
const makeParent = (mode, events) => {
|
|
1156
887
|
if (!Protocol.isEventProtocol(events, "public")) {
|
|
1157
888
|
throw new Error("Machine parent declarations require a protocol created with Machine.events");
|