@typeonce/effect-machine 0.31.1 → 0.32.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 +145 -140
- package/dist/Machine.d.ts +428 -254
- 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 +98 -374
- 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 +71 -39
- 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 +10 -12
- 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 +214 -0
- package/package.json +1 -1
- package/src/Machine.ts +778 -437
- 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 +154 -679
- package/src/internal/machine/planner.ts +82 -66
- 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 +22 -23
- 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,7 +3,7 @@ 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
|
|
6
|
+
import * as Schema from "effect/Schema"
|
|
7
7
|
import type * as Scope from "effect/Scope"
|
|
8
8
|
import type * as Stream from "effect/Stream"
|
|
9
9
|
import type {
|
|
@@ -21,22 +21,31 @@ import type {
|
|
|
21
21
|
MachineSchemaEncodeError,
|
|
22
22
|
Parent,
|
|
23
23
|
ParentMode,
|
|
24
|
-
Runtime,
|
|
25
24
|
RuntimeOutcome,
|
|
26
25
|
SpawnOptions,
|
|
26
|
+
State,
|
|
27
27
|
StoppedError
|
|
28
28
|
} from "../../Machine.js"
|
|
29
29
|
import * as Activities from "./activities.js"
|
|
30
30
|
import * as Configuration from "./configuration.js"
|
|
31
31
|
import type { ChildAlreadyExistsError, InfiniteTransitionError, StartupError } from "./errors.js"
|
|
32
|
+
import * as InvocationDefinition from "./invocationDefinition.js"
|
|
32
33
|
import * as internalPlanner from "./planner.js"
|
|
33
34
|
import * as internalProcess from "./process.js"
|
|
34
35
|
import * as Protocol from "./protocol.js"
|
|
35
36
|
import type { EnsureExecutable } from "./readiness.js"
|
|
37
|
+
import type { ExcludeCompatibleRuntime } from "./requirements.js"
|
|
36
38
|
import * as internalRuntime from "./runtime.js"
|
|
37
39
|
import * as Serialization from "./serialization.js"
|
|
38
40
|
import * as StateDefinition from "./stateDefinition.js"
|
|
39
|
-
import { ChildMachineLogicTypeId
|
|
41
|
+
import { ChildMachineLogicTypeId } from "./symbols.js"
|
|
42
|
+
import {
|
|
43
|
+
getLocalTargetScope,
|
|
44
|
+
getTargetBuilderNode,
|
|
45
|
+
makeSnapshotBuilder,
|
|
46
|
+
makeTargetBuilder,
|
|
47
|
+
withFrom
|
|
48
|
+
} from "./targetBuilder.js"
|
|
40
49
|
import * as Topology from "./topology.js"
|
|
41
50
|
|
|
42
51
|
export {
|
|
@@ -56,15 +65,8 @@ export const InvokeTypeId: unique symbol = Symbol.for("effect/Machine/Invoke")
|
|
|
56
65
|
export const TransitionTypeId: unique symbol = Symbol.for("effect/Machine/Transition")
|
|
57
66
|
const InvokeBuilderDescriptorTypeId: unique symbol = Symbol("effect/Machine/InvokeBuilderDescriptor")
|
|
58
67
|
const ChildMachineTypeId = "~effect/Machine/ChildMachine"
|
|
59
|
-
type IsAny<A> = 0 extends 1 & A ? true : false
|
|
60
68
|
type MachineRuntimeRequirement = internalRuntime.MachineRuntime
|
|
61
|
-
|
|
62
|
-
infer RequiredEvents,
|
|
63
|
-
infer RequiredEmits
|
|
64
|
-
> ? IsAny<Requirements> extends true ? Requirements
|
|
65
|
-
: [RequiredEvents] extends [Events] ? [RequiredEmits] extends [Emits] ? never : Requirements
|
|
66
|
-
: Requirements
|
|
67
|
-
: Requirements
|
|
69
|
+
|
|
68
70
|
type SpawnRequirements<Requirements> = Exclude<Requirements, Scope.Scope>
|
|
69
71
|
type SpawnIdError<Options extends SpawnOptions> = "id" extends keyof Options ? Options extends {
|
|
70
72
|
readonly id?: infer Id
|
|
@@ -77,34 +79,6 @@ type SpawnResult<State, Event, Error, Requirements, Output, SpawnError, InitialE
|
|
|
77
79
|
SpawnError | InitialError,
|
|
78
80
|
MachineRuntimeRequirement | SpawnRequirements<Requirements>
|
|
79
81
|
>
|
|
80
|
-
type DefineStateTreeInput<States extends Machine.StateSchemas> = States
|
|
81
|
-
type ValidateDefinedStates<States extends Machine.StateSchemas> = [States] extends
|
|
82
|
-
[Machine.ValidateStateSchemas<States>] ? []
|
|
83
|
-
: [validation: Machine.ValidateStateSchemas<States>]
|
|
84
|
-
type InvalidDefinedStateTreeInput<States extends Machine.StateSchemas> = [States] extends
|
|
85
|
-
[Machine.ValidateStateSchemas<States>] ? never
|
|
86
|
-
: States & Machine.ValidateStateSchemas<States>
|
|
87
|
-
type ReusableStateNodeConfig =
|
|
88
|
-
| Machine.AtomicStateNodeConfig
|
|
89
|
-
| Machine.CompoundStateNodeConfig
|
|
90
|
-
| Machine.ParallelStateNodeConfig
|
|
91
|
-
interface StateConstructor {
|
|
92
|
-
<const Node extends ReusableStateNodeConfig>(node: Node): Node
|
|
93
|
-
}
|
|
94
|
-
interface StatesConstructor {
|
|
95
|
-
<const States extends Machine.StateSchemas>(
|
|
96
|
-
states: States,
|
|
97
|
-
..._validation: ValidateDefinedStates<NoInfer<States>>
|
|
98
|
-
): Machine.DefinedStates<States>
|
|
99
|
-
<const States extends Machine.StateSchemas>(states: InvalidDefinedStateTreeInput<States>): never
|
|
100
|
-
}
|
|
101
|
-
type ValidateInputEventProtocol<InputEvents extends ReadonlyArray<Machine.TaggedSchema>> = InputEvents extends
|
|
102
|
-
ReadonlyArray<Machine.TaggedSchema> ? unknown : never
|
|
103
|
-
type ValidateInternalEventProtocol<
|
|
104
|
-
InputEvents extends ReadonlyArray<Machine.TaggedSchema>,
|
|
105
|
-
InternalEvents extends ReadonlyArray<Machine.TaggedSchema>
|
|
106
|
-
> = InputEvents | InternalEvents extends ReadonlyArray<Machine.TaggedSchema> ? unknown : never
|
|
107
|
-
|
|
108
82
|
const Proto = {
|
|
109
83
|
...Inspectable.BaseProto,
|
|
110
84
|
...PipeablePrototype,
|
|
@@ -122,6 +96,7 @@ const makeWithHandlers = (
|
|
|
122
96
|
): Machine.Any => {
|
|
123
97
|
const machine = Object.create(Proto)
|
|
124
98
|
machine.states = self.states
|
|
99
|
+
machine.root = self.root
|
|
125
100
|
machine.events = self.events
|
|
126
101
|
machine.internalEvents = self.internalEvents
|
|
127
102
|
machine.emittedEvents = self.emittedEvents
|
|
@@ -164,7 +139,7 @@ type DirectTransitionDescriptor = {
|
|
|
164
139
|
readonly [TransitionBuilderDescriptorTypeId]: typeof TransitionBuilderDescriptorTypeId
|
|
165
140
|
readonly type: "direct"
|
|
166
141
|
readonly selection: Topology.TargetSelection
|
|
167
|
-
readonly
|
|
142
|
+
readonly resolver?: (context: any, enqueue: unknown) => unknown
|
|
168
143
|
readonly reenter: boolean
|
|
169
144
|
readonly declinable: boolean
|
|
170
145
|
}
|
|
@@ -208,7 +183,7 @@ const makeDirectTransitionDescriptor = (
|
|
|
208
183
|
resolve: ((context: any, enqueue: unknown) => unknown) | undefined,
|
|
209
184
|
options: unknown
|
|
210
185
|
): DirectTransitionDescriptor => {
|
|
211
|
-
const shared: Omit<DirectTransitionDescriptor, "
|
|
186
|
+
const shared: Omit<DirectTransitionDescriptor, "resolver"> = {
|
|
212
187
|
[TransitionBuilderDescriptorTypeId]: TransitionBuilderDescriptorTypeId,
|
|
213
188
|
type: "direct",
|
|
214
189
|
selection: plainTargetSelection(selection),
|
|
@@ -216,12 +191,34 @@ const makeDirectTransitionDescriptor = (
|
|
|
216
191
|
}
|
|
217
192
|
return resolve === undefined
|
|
218
193
|
? Object.freeze(shared)
|
|
219
|
-
: Object.freeze({ ...shared, resolve })
|
|
194
|
+
: Object.freeze({ ...shared, resolver: resolve })
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const guardedSelection = (selection: Topology.TargetSelection, predicate: (context: any) => boolean): object => {
|
|
198
|
+
const wrap = (resolve: (context: any, enqueue: unknown) => unknown, options?: unknown) =>
|
|
199
|
+
makeDirectTransitionDescriptor(
|
|
200
|
+
selection,
|
|
201
|
+
(context, enqueue) => predicate(context) ? resolve(context, enqueue) : Topology.makeDeclined(),
|
|
202
|
+
{ ...transitionOptions(options), declinable: true }
|
|
203
|
+
)
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
...wrap((
|
|
206
|
+
context
|
|
207
|
+
) => (selection.kind === "none" ? Topology.makeNoTarget() : constructSelectedTarget(context.target))),
|
|
208
|
+
from: (value: (context: any) => unknown) => wrap((context) => context.target.from(value(context))),
|
|
209
|
+
decoded: (value: (context: any) => unknown) => wrap((context) => context.target.decoded(value(context))),
|
|
210
|
+
resolve: wrap
|
|
211
|
+
})
|
|
220
212
|
}
|
|
221
213
|
|
|
222
214
|
const decorateTransitionSelection = (selection: Topology.TargetSelection): Topology.TargetSelection =>
|
|
223
215
|
Object.freeze({
|
|
224
216
|
...selection,
|
|
217
|
+
guard: (predicate: (context: any) => boolean) => guardedSelection(selection, predicate),
|
|
218
|
+
from: (value: (context: any) => unknown) =>
|
|
219
|
+
makeDirectTransitionDescriptor(selection, (context) => context.target.from(value(context)), undefined),
|
|
220
|
+
decoded: (value: (context: any) => unknown) =>
|
|
221
|
+
makeDirectTransitionDescriptor(selection, (context) => context.target.decoded(value(context)), undefined),
|
|
225
222
|
resolve: (resolve: (context: any, enqueue: unknown) => unknown, options?: unknown) =>
|
|
226
223
|
makeDirectTransitionDescriptor(selection, resolve, options),
|
|
227
224
|
reenter: () => makeDirectTransitionDescriptor(selection, undefined, { reenter: true }),
|
|
@@ -242,14 +239,16 @@ const decorateTransitionSelection = (selection: Topology.TargetSelection): Topol
|
|
|
242
239
|
}
|
|
243
240
|
})
|
|
244
241
|
|
|
245
|
-
const decorateStateUpdateSelection = (selection: Topology.TargetSelection): Topology.TargetSelection =>
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
242
|
+
const decorateStateUpdateSelection = (selection: Topology.TargetSelection): Topology.TargetSelection =>
|
|
243
|
+
Object.freeze({
|
|
244
|
+
...selection,
|
|
245
|
+
from: (value: (context: any) => unknown) =>
|
|
246
|
+
makeDirectTransitionDescriptor(selection, (context) => context.owner.from(value(context)), undefined),
|
|
247
|
+
decoded: (value: (context: any) => unknown) =>
|
|
248
|
+
makeDirectTransitionDescriptor(selection, (context) => context.owner.decoded(value(context)), undefined),
|
|
249
|
+
resolve: (resolve: (context: any, enqueue: unknown) => unknown, options?: unknown) =>
|
|
250
|
+
makeDirectTransitionDescriptor(selection, resolve, options)
|
|
251
|
+
})
|
|
253
252
|
|
|
254
253
|
const noneTransitionSelection = decorateTransitionSelection(Topology.noneTargetSelection)
|
|
255
254
|
|
|
@@ -266,6 +265,10 @@ const makeInitialBuilderDescriptor = (
|
|
|
266
265
|
const decorateInitialSelection = (selection: Topology.TargetSelection): Topology.TargetSelection =>
|
|
267
266
|
Object.freeze({
|
|
268
267
|
...selection,
|
|
268
|
+
from: (value: (context: any) => unknown) =>
|
|
269
|
+
makeInitialBuilderDescriptor(selection, (context) => context.target.from(value(context))),
|
|
270
|
+
decoded: (value: (context: any) => unknown) =>
|
|
271
|
+
makeInitialBuilderDescriptor(selection, (context) => context.target.decoded(value(context))),
|
|
269
272
|
resolve: (resolve: (context: any) => unknown) => makeInitialBuilderDescriptor(selection, resolve)
|
|
270
273
|
})
|
|
271
274
|
|
|
@@ -292,6 +295,12 @@ const decorateInitialSelectorNode = (node: unknown): unknown => {
|
|
|
292
295
|
|
|
293
296
|
const decorateTransitionSelectorNode = (node: unknown): unknown => {
|
|
294
297
|
if (Topology.isTargetSelection(node)) {
|
|
298
|
+
if (node.kind === "state" && node.scope === "full" && hasProperty(node, "initial")) {
|
|
299
|
+
return Object.freeze({
|
|
300
|
+
...decorateTransitionSelection(node),
|
|
301
|
+
initial: decorateTransitionSelection(node.initial as Topology.TargetSelection)
|
|
302
|
+
})
|
|
303
|
+
}
|
|
295
304
|
if (node.kind === "update") return decorateStateUpdateSelection(node)
|
|
296
305
|
return node === Topology.noneTargetSelection ? noneTransitionSelection : decorateTransitionSelection(node)
|
|
297
306
|
}
|
|
@@ -360,7 +369,7 @@ const normalizeTransitionBuilder = (
|
|
|
360
369
|
}
|
|
361
370
|
return {
|
|
362
371
|
target: () => descriptor.selection,
|
|
363
|
-
resolve: descriptor.
|
|
372
|
+
resolve: descriptor.resolver,
|
|
364
373
|
reenter: descriptor.reenter,
|
|
365
374
|
declinable: descriptor.declinable
|
|
366
375
|
}
|
|
@@ -430,7 +439,7 @@ const makeSelectionNode = (
|
|
|
430
439
|
}
|
|
431
440
|
if (
|
|
432
441
|
scope === "branch" && source !== undefined && node.schema !== undefined &&
|
|
433
|
-
(source === path ||
|
|
442
|
+
(source === path || Configuration.isDescendantOf(source, path)) &&
|
|
434
443
|
getTargetBuilderNode(stateNodes, source).type !== "choice"
|
|
435
444
|
) {
|
|
436
445
|
Object.defineProperty(method, "update", {
|
|
@@ -439,6 +448,9 @@ const makeSelectionNode = (
|
|
|
439
448
|
})
|
|
440
449
|
}
|
|
441
450
|
}
|
|
451
|
+
if (node.type === "atomic" && scope === "branch" && source === path && node.schema !== undefined) {
|
|
452
|
+
Object.defineProperty(method, "update", { value: makeStateUpdateSelection(path, "branch"), enumerable: true })
|
|
453
|
+
}
|
|
442
454
|
return method
|
|
443
455
|
}
|
|
444
456
|
|
|
@@ -463,15 +475,12 @@ const makeTargetSelector = (
|
|
|
463
475
|
stateNodes: Machine.StateNodes,
|
|
464
476
|
source: string
|
|
465
477
|
): unknown => {
|
|
466
|
-
const full
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
full[node.key] = makeSelectionNode(stateNodes, node.path, "full")
|
|
470
|
-
}
|
|
471
|
-
}
|
|
478
|
+
const full = Object.assign({}, makeSelectionValue("state", "", "full"), {
|
|
479
|
+
initial: makeSelectionValue("initial", "", "full")
|
|
480
|
+
})
|
|
472
481
|
const branch: Record<string, unknown> = {}
|
|
473
|
-
const root = getTargetBuilderNode(stateNodes,
|
|
474
|
-
branch
|
|
482
|
+
const root = getTargetBuilderNode(stateNodes, stateNodes.roots[0]!)
|
|
483
|
+
addSelectionChildren(branch, stateNodes, root.path, "branch", source)
|
|
475
484
|
const local: Record<string, unknown> = {}
|
|
476
485
|
const localScope = getLocalTargetScope(stateNodes, source)
|
|
477
486
|
if (localScope !== undefined) {
|
|
@@ -486,10 +495,15 @@ const makeTargetSelector = (
|
|
|
486
495
|
}
|
|
487
496
|
return {
|
|
488
497
|
none: Topology.noneTargetSelection,
|
|
498
|
+
self: getTargetBuilderNode(stateNodes, source).schema === undefined ||
|
|
499
|
+
getTargetBuilderNode(stateNodes, source).type === "final"
|
|
500
|
+
? {}
|
|
501
|
+
: { update: makeStateUpdateSelection(source, "branch") },
|
|
502
|
+
root: makeSelectionNode(stateNodes, root.path, "branch", source),
|
|
489
503
|
local,
|
|
490
504
|
branch,
|
|
491
505
|
full,
|
|
492
|
-
history: makeHistorySelectionTree(stateNodes,
|
|
506
|
+
history: makeHistorySelectionTree(stateNodes, "")
|
|
493
507
|
}
|
|
494
508
|
}
|
|
495
509
|
|
|
@@ -580,6 +594,7 @@ const getSelectionBuilder = (
|
|
|
580
594
|
let parts = selection.path!.split(".")
|
|
581
595
|
if (selection.kind === "history") {
|
|
582
596
|
builder = target.history
|
|
597
|
+
if (selection.path !== "") parts.unshift("")
|
|
583
598
|
} else if (selection.scope === "local") {
|
|
584
599
|
builder = target.local
|
|
585
600
|
const scope = getLocalTargetScope(stateNodes, source)
|
|
@@ -588,11 +603,12 @@ const getSelectionBuilder = (
|
|
|
588
603
|
builder = builder.with
|
|
589
604
|
parts = []
|
|
590
605
|
} else {
|
|
591
|
-
parts = selection.path!.slice(scope.length + 1).split(".")
|
|
606
|
+
parts = (scope === "" ? selection.path! : selection.path!.slice(scope.length + 1)).split(".")
|
|
592
607
|
}
|
|
593
608
|
}
|
|
594
609
|
} else if (selection.scope === "branch") {
|
|
595
610
|
builder = target.branch
|
|
611
|
+
if (selection.path !== "") parts.unshift("")
|
|
596
612
|
} else {
|
|
597
613
|
builder = target.full
|
|
598
614
|
}
|
|
@@ -645,7 +661,7 @@ const validateResolvedSelection = (
|
|
|
645
661
|
(selectedNode?.type === "compound" || selectedNode?.type === "parallel")
|
|
646
662
|
if (
|
|
647
663
|
resultPath === undefined ||
|
|
648
|
-
(resultPath !== selection.path && !(acceptsDescendant &&
|
|
664
|
+
(resultPath !== selection.path && !(acceptsDescendant && Configuration.isDescendantOf(resultPath, selection.path!)))
|
|
649
665
|
) {
|
|
650
666
|
throw new Error(
|
|
651
667
|
`Machine transition resolver selected "${selection.path}" but constructed "${resultPath ?? "<invalid>"}"`
|
|
@@ -1005,9 +1021,9 @@ const captureInvokeDefinition = (
|
|
|
1005
1021
|
captured[key] = captureTransition(captured[key], stateNodes, path, key)
|
|
1006
1022
|
}
|
|
1007
1023
|
}
|
|
1008
|
-
return captured
|
|
1024
|
+
return InvocationDefinition.capture(captured, path)
|
|
1009
1025
|
})
|
|
1010
|
-
if (Array.isArray(authored)) return capturedDefinitions
|
|
1026
|
+
if (Array.isArray(authored)) return Object.freeze(capturedDefinitions)
|
|
1011
1027
|
return capturedDefinitions[0]
|
|
1012
1028
|
}
|
|
1013
1029
|
|
|
@@ -1028,6 +1044,14 @@ const flattenHandlers = (
|
|
|
1028
1044
|
throw new Error(`Machine expected state "${path}" handler to be an object`)
|
|
1029
1045
|
}
|
|
1030
1046
|
const { states: childConfig, ...stateConfig } = nodeConfig as Record<string, unknown>
|
|
1047
|
+
if (typeof stateConfig.history === "object" && stateConfig.history !== null) {
|
|
1048
|
+
stateConfig.history = Object.freeze(Object.fromEntries(
|
|
1049
|
+
Object.entries(stateConfig.history).map(([key, entry]) => [
|
|
1050
|
+
key,
|
|
1051
|
+
typeof entry === "object" && entry !== null ? Object.freeze({ ...entry }) : entry
|
|
1052
|
+
])
|
|
1053
|
+
))
|
|
1054
|
+
}
|
|
1031
1055
|
const on = stateConfig.on
|
|
1032
1056
|
if (typeof on === "object" && on !== null) {
|
|
1033
1057
|
const capturedOn = captureEventHandlers(on, stateNodes, path)
|
|
@@ -1073,7 +1097,7 @@ const flattenHandlers = (
|
|
|
1073
1097
|
const makeHandle = (self: Definition.Any): Definition.Any["handle"] =>
|
|
1074
1098
|
((config: Record<string, unknown>) => {
|
|
1075
1099
|
const handlers: Record<PropertyKey, Machine.AnyStateConfig> = Object.create(null)
|
|
1076
|
-
flattenHandlers(handlers, self.stateNodes, self.states, "", config)
|
|
1100
|
+
flattenHandlers(handlers, self.stateNodes, self.states, "", { "": config })
|
|
1077
1101
|
return makeWithHandlers(self, handlers)
|
|
1078
1102
|
}) as Definition.Any["handle"]
|
|
1079
1103
|
|
|
@@ -1114,523 +1138,6 @@ export const isFinal = <
|
|
|
1114
1138
|
state: Machine.Snapshot<States>
|
|
1115
1139
|
): state is Machine.SnapshotContainingFinal<States, FinalStates> => internalPlanner.isFinal(machine as any, state)
|
|
1116
1140
|
|
|
1117
|
-
type SnapshotBuilderOptions = {
|
|
1118
|
-
readonly mode: "initial" | "full"
|
|
1119
|
-
readonly prefix: string
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
type FromMethodKind = "leaf" | "nested"
|
|
1123
|
-
|
|
1124
|
-
const withFrom = <Method extends (value: unknown, ...args: ReadonlyArray<any>) => unknown>(
|
|
1125
|
-
method: Method,
|
|
1126
|
-
kind: FromMethodKind,
|
|
1127
|
-
valued: boolean
|
|
1128
|
-
): {
|
|
1129
|
-
readonly decoded?: Method
|
|
1130
|
-
readonly from: (...args: ReadonlyArray<any>) => unknown
|
|
1131
|
-
} => {
|
|
1132
|
-
const builder: Record<string, unknown> = {}
|
|
1133
|
-
if (valued) {
|
|
1134
|
-
Object.defineProperty(builder, "decoded", {
|
|
1135
|
-
value: method,
|
|
1136
|
-
enumerable: false
|
|
1137
|
-
})
|
|
1138
|
-
}
|
|
1139
|
-
Object.defineProperty(builder, "from", {
|
|
1140
|
-
value: (...args: ReadonlyArray<any>) => {
|
|
1141
|
-
if (!valued) {
|
|
1142
|
-
return method(undefined, ...args)
|
|
1143
|
-
}
|
|
1144
|
-
const omitted = args.length === 0 || (kind === "nested" && args.length === 1 && typeof args[0] === "function")
|
|
1145
|
-
const input = omitted ? {} : args[0]
|
|
1146
|
-
const rest = omitted ? args : args.slice(1)
|
|
1147
|
-
return method(Topology.makeStateInput(input), ...rest)
|
|
1148
|
-
},
|
|
1149
|
-
enumerable: false
|
|
1150
|
-
})
|
|
1151
|
-
return builder as {
|
|
1152
|
-
readonly decoded?: Method
|
|
1153
|
-
readonly from: (...args: ReadonlyArray<any>) => unknown
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
const withInitial = <Builder extends object>(
|
|
1158
|
-
builder: Builder,
|
|
1159
|
-
path: string,
|
|
1160
|
-
valued: boolean,
|
|
1161
|
-
values?: Readonly<Record<string, unknown>>
|
|
1162
|
-
): Builder => {
|
|
1163
|
-
const initial = withFrom(
|
|
1164
|
-
(value: unknown) => Topology.makeInitialTarget(path, value, values),
|
|
1165
|
-
"leaf",
|
|
1166
|
-
valued
|
|
1167
|
-
)
|
|
1168
|
-
Object.defineProperty(builder, "initial", {
|
|
1169
|
-
value: initial,
|
|
1170
|
-
enumerable: false
|
|
1171
|
-
})
|
|
1172
|
-
return builder
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
const makeSnapshotBuilder = (
|
|
1176
|
-
states: Machine.StateTree,
|
|
1177
|
-
options: SnapshotBuilderOptions
|
|
1178
|
-
): unknown => {
|
|
1179
|
-
const builder: Record<string, unknown> = {}
|
|
1180
|
-
for (const key of Object.keys(states)) {
|
|
1181
|
-
const definition = states[key]!
|
|
1182
|
-
const pseudoType = (definition as { readonly type?: unknown }).type
|
|
1183
|
-
if (pseudoType === "history") {
|
|
1184
|
-
continue
|
|
1185
|
-
}
|
|
1186
|
-
const path = options.prefix === "" ? key : `${options.prefix}.${key}`
|
|
1187
|
-
if (pseudoType === "choice") {
|
|
1188
|
-
builder[key] = () => Topology.makeChoiceTarget(path, getParentPathRuntime(path))
|
|
1189
|
-
continue
|
|
1190
|
-
}
|
|
1191
|
-
const node = Topology.getStateNodeDefinition(path, definition)
|
|
1192
|
-
const method = withFrom(
|
|
1193
|
-
(value: unknown, selector?: (builder: unknown) => unknown) =>
|
|
1194
|
-
makeSnapshotForNode(definition, key, value, selector, options),
|
|
1195
|
-
node.states === undefined ? "leaf" : "nested",
|
|
1196
|
-
node.schema !== undefined
|
|
1197
|
-
)
|
|
1198
|
-
builder[key] = node.states === undefined || options.mode !== "full" || options.prefix !== ""
|
|
1199
|
-
? method
|
|
1200
|
-
: withInitial(method, path, node.schema !== undefined)
|
|
1201
|
-
}
|
|
1202
|
-
return builder
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
const makeParallelSnapshotBuilder = (
|
|
1206
|
-
states: Machine.StateTree,
|
|
1207
|
-
options: SnapshotBuilderOptions,
|
|
1208
|
-
regions: Readonly<Record<string, unknown>>
|
|
1209
|
-
): unknown => {
|
|
1210
|
-
const builder: Record<string, unknown> = {}
|
|
1211
|
-
Object.defineProperty(builder, SnapshotBuilderStateTypeId, {
|
|
1212
|
-
value: regions,
|
|
1213
|
-
enumerable: false
|
|
1214
|
-
})
|
|
1215
|
-
for (const key of Object.keys(states)) {
|
|
1216
|
-
const definition = states[key]!
|
|
1217
|
-
const pseudoType = (definition as { readonly type?: unknown }).type
|
|
1218
|
-
if (pseudoType === "history" || pseudoType === "choice") {
|
|
1219
|
-
continue
|
|
1220
|
-
}
|
|
1221
|
-
if (hasProperty(regions, key)) {
|
|
1222
|
-
continue
|
|
1223
|
-
}
|
|
1224
|
-
const path = options.prefix === "" ? key : `${options.prefix}.${key}`
|
|
1225
|
-
const node = Topology.getStateNodeDefinition(path, definition)
|
|
1226
|
-
const method = withFrom(
|
|
1227
|
-
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
1228
|
-
const nextRegions: Record<string, unknown> = {}
|
|
1229
|
-
for (const regionKey of Object.keys(regions)) {
|
|
1230
|
-
nextRegions[regionKey] = regions[regionKey]
|
|
1231
|
-
}
|
|
1232
|
-
nextRegions[key] = makeSnapshotForNode(definition, key, value, selector, options)
|
|
1233
|
-
return makeParallelSnapshotBuilder(states, options, nextRegions)
|
|
1234
|
-
},
|
|
1235
|
-
node.states === undefined ? "leaf" : "nested",
|
|
1236
|
-
node.schema !== undefined
|
|
1237
|
-
)
|
|
1238
|
-
builder[key] = method
|
|
1239
|
-
}
|
|
1240
|
-
return builder
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
const getParallelSnapshotBuilderRegions = (
|
|
1244
|
-
path: string,
|
|
1245
|
-
states: Machine.StateTree,
|
|
1246
|
-
builder: unknown
|
|
1247
|
-
): Readonly<Record<string, unknown>> => {
|
|
1248
|
-
if (typeof builder !== "object" || builder === null || !hasProperty(builder, SnapshotBuilderStateTypeId)) {
|
|
1249
|
-
throw new Error(`Machine expected parallel state "${path}" builder callback to return a builder`)
|
|
1250
|
-
}
|
|
1251
|
-
const regions = (builder as { readonly [SnapshotBuilderStateTypeId]: Readonly<Record<string, unknown>> })[
|
|
1252
|
-
SnapshotBuilderStateTypeId
|
|
1253
|
-
]
|
|
1254
|
-
for (const key of Object.keys(states)) {
|
|
1255
|
-
const pseudoType = (states[key] as { readonly type?: unknown }).type
|
|
1256
|
-
if (pseudoType === "history" || pseudoType === "choice") {
|
|
1257
|
-
continue
|
|
1258
|
-
}
|
|
1259
|
-
if (!hasProperty(regions, key)) {
|
|
1260
|
-
throw new Error(`Machine expected parallel state "${path}" builder callback to provide region "${key}"`)
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
return regions
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
const makeSnapshotForNode = (
|
|
1267
|
-
definition: Machine.TaggedSchema | Machine.StateNodeConfig,
|
|
1268
|
-
key: string,
|
|
1269
|
-
value: unknown,
|
|
1270
|
-
selector: ((builder: unknown) => unknown) | undefined,
|
|
1271
|
-
options: SnapshotBuilderOptions
|
|
1272
|
-
): Record<string, unknown> => {
|
|
1273
|
-
const path = options.prefix === "" ? key : `${options.prefix}.${key}`
|
|
1274
|
-
const node = Topology.getStateNodeDefinition(path, definition)
|
|
1275
|
-
const snapshot: Record<string, unknown> = {
|
|
1276
|
-
path,
|
|
1277
|
-
value
|
|
1278
|
-
}
|
|
1279
|
-
if (node.states === undefined) {
|
|
1280
|
-
return snapshot
|
|
1281
|
-
}
|
|
1282
|
-
if (selector === undefined) {
|
|
1283
|
-
throw new Error(`Machine expected state "${path}" builder to provide active child states`)
|
|
1284
|
-
}
|
|
1285
|
-
if (node.type === "parallel") {
|
|
1286
|
-
const builder = makeParallelSnapshotBuilder(node.states, { ...options, prefix: path }, {})
|
|
1287
|
-
const selected = selector(builder)
|
|
1288
|
-
snapshot.states = getParallelSnapshotBuilderRegions(path, node.states, selected)
|
|
1289
|
-
return snapshot
|
|
1290
|
-
}
|
|
1291
|
-
const childStates = options.mode === "initial" && node.initial !== undefined
|
|
1292
|
-
? { [node.initial]: node.states[node.initial]! }
|
|
1293
|
-
: node.states
|
|
1294
|
-
const selected = selector(makeSnapshotBuilder(childStates, { ...options, prefix: path }))
|
|
1295
|
-
snapshot.state = selected
|
|
1296
|
-
return snapshot
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
const getTargetBuilderNode = (
|
|
1300
|
-
stateNodes: Machine.StateNodes,
|
|
1301
|
-
path: string
|
|
1302
|
-
): Machine.StateNode => {
|
|
1303
|
-
const node = stateNodes.byPath.get(path)
|
|
1304
|
-
if (node === undefined) {
|
|
1305
|
-
throw new Error(`Machine expected state path "${path}" to exist`)
|
|
1306
|
-
}
|
|
1307
|
-
return node
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
const getLocalTargetScope = (
|
|
1311
|
-
stateNodes: Machine.StateNodes,
|
|
1312
|
-
source: string
|
|
1313
|
-
): string | undefined => {
|
|
1314
|
-
let current: string | undefined = source
|
|
1315
|
-
while (current !== undefined) {
|
|
1316
|
-
const node = stateNodes.byPath.get(current)
|
|
1317
|
-
if (node === undefined) {
|
|
1318
|
-
return undefined
|
|
1319
|
-
}
|
|
1320
|
-
if (node.type === "compound") {
|
|
1321
|
-
return node.path
|
|
1322
|
-
}
|
|
1323
|
-
current = node.parent
|
|
1324
|
-
}
|
|
1325
|
-
return undefined
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
const hasTargetValues = (
|
|
1329
|
-
values: Readonly<Record<string, unknown>> | undefined
|
|
1330
|
-
): values is Readonly<Record<string, unknown>> => values !== undefined && Object.keys(values).length > 0
|
|
1331
|
-
|
|
1332
|
-
const makeTargetWithValues = (
|
|
1333
|
-
path: string,
|
|
1334
|
-
value: unknown,
|
|
1335
|
-
values: Readonly<Record<string, unknown>> | undefined
|
|
1336
|
-
): Machine.Target<any, any> =>
|
|
1337
|
-
hasTargetValues(values)
|
|
1338
|
-
? Topology.makeTarget(path as any, value as any, { values: values as any })
|
|
1339
|
-
: Topology.makeTarget(path as any, value as any)
|
|
1340
|
-
|
|
1341
|
-
const getTargetBuilderDefinition = (
|
|
1342
|
-
states: Machine.StateTree,
|
|
1343
|
-
targetPath: string
|
|
1344
|
-
): Machine.TaggedSchema | Machine.StateNodeConfig => {
|
|
1345
|
-
let children = states
|
|
1346
|
-
let path = ""
|
|
1347
|
-
let definition: Machine.TaggedSchema | Machine.StateNodeConfig | undefined
|
|
1348
|
-
for (const key of targetPath.split(".")) {
|
|
1349
|
-
if (!hasProperty(children, key)) {
|
|
1350
|
-
throw new Error(`Machine expected state path "${targetPath}" to exist`)
|
|
1351
|
-
}
|
|
1352
|
-
definition = children[key]!
|
|
1353
|
-
path = path === "" ? key : `${path}.${key}`
|
|
1354
|
-
const node = Topology.getStateNodeDefinition(path, definition)
|
|
1355
|
-
children = node.states ?? {}
|
|
1356
|
-
}
|
|
1357
|
-
return definition!
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
const makeParallelTarget = (
|
|
1361
|
-
states: Machine.StateTree,
|
|
1362
|
-
node: Machine.StateNode,
|
|
1363
|
-
value: unknown,
|
|
1364
|
-
selector: ((builder: unknown) => unknown) | undefined,
|
|
1365
|
-
values: Readonly<Record<string, unknown>> | undefined
|
|
1366
|
-
): Machine.Target<any, any> => {
|
|
1367
|
-
if (selector === undefined) {
|
|
1368
|
-
throw new Error(`Machine expected parallel target "${node.path}" builder to provide every active region`)
|
|
1369
|
-
}
|
|
1370
|
-
const snapshot = makeSnapshotForNode(
|
|
1371
|
-
getTargetBuilderDefinition(states, node.path),
|
|
1372
|
-
node.key,
|
|
1373
|
-
value,
|
|
1374
|
-
selector,
|
|
1375
|
-
{ mode: "full", prefix: node.parent ?? "" }
|
|
1376
|
-
)
|
|
1377
|
-
return Topology.makeTarget(node.path as any, value as any, {
|
|
1378
|
-
snapshot: snapshot as any,
|
|
1379
|
-
values: values as any
|
|
1380
|
-
})
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
const extendTargetValues = (
|
|
1384
|
-
values: Readonly<Record<string, unknown>> | undefined,
|
|
1385
|
-
path: string,
|
|
1386
|
-
value: unknown
|
|
1387
|
-
): Readonly<Record<string, unknown>> => {
|
|
1388
|
-
const next: Record<string, unknown> = {}
|
|
1389
|
-
if (values !== undefined) {
|
|
1390
|
-
for (const key of Object.keys(values)) {
|
|
1391
|
-
next[key] = values[key]
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
next[path] = value
|
|
1395
|
-
return next
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
const makeLocalTargetChildBuilder = (
|
|
1399
|
-
states: Machine.StateTree,
|
|
1400
|
-
stateNodes: Machine.StateNodes,
|
|
1401
|
-
parentPath: string,
|
|
1402
|
-
values: Readonly<Record<string, unknown>> | undefined,
|
|
1403
|
-
source: string
|
|
1404
|
-
): unknown => {
|
|
1405
|
-
const parent = getTargetBuilderNode(stateNodes, parentPath)
|
|
1406
|
-
const builder: Record<string, unknown> = {}
|
|
1407
|
-
for (
|
|
1408
|
-
const childPath of Array.from(stateNodes.byPath.values())
|
|
1409
|
-
.filter((node) => node.parent === parent.path && node.type !== "history")
|
|
1410
|
-
.map((node) => node.path)
|
|
1411
|
-
) {
|
|
1412
|
-
const child = getTargetBuilderNode(stateNodes, childPath)
|
|
1413
|
-
if (child.type === "choice") {
|
|
1414
|
-
builder[child.key] = () => Topology.makeChoiceTarget(child.path, parent.path, values)
|
|
1415
|
-
continue
|
|
1416
|
-
}
|
|
1417
|
-
const method = withFrom(
|
|
1418
|
-
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
1419
|
-
if (child.type === "atomic" || child.type === "final") {
|
|
1420
|
-
return makeTargetWithValues(child.path, value, values)
|
|
1421
|
-
}
|
|
1422
|
-
if (child.type === "parallel") {
|
|
1423
|
-
if (source !== child.path && !source.startsWith(`${child.path}.`)) {
|
|
1424
|
-
return makeParallelTarget(states, child, value, selector, values)
|
|
1425
|
-
}
|
|
1426
|
-
if (selector === undefined) {
|
|
1427
|
-
throw new Error(`Machine expected target "${child.path}" builder to provide an active child state`)
|
|
1428
|
-
}
|
|
1429
|
-
return selector(makeLocalTargetChildBuilder(
|
|
1430
|
-
states,
|
|
1431
|
-
stateNodes,
|
|
1432
|
-
child.path,
|
|
1433
|
-
child.schema === undefined ? values : extendTargetValues(values, child.path, value),
|
|
1434
|
-
source
|
|
1435
|
-
))
|
|
1436
|
-
}
|
|
1437
|
-
if (selector === undefined) {
|
|
1438
|
-
throw new Error(`Machine expected target "${child.path}" builder to provide an active child state`)
|
|
1439
|
-
}
|
|
1440
|
-
return selector(makeLocalTargetChildBuilder(
|
|
1441
|
-
states,
|
|
1442
|
-
stateNodes,
|
|
1443
|
-
child.path,
|
|
1444
|
-
child.schema === undefined ? values : extendTargetValues(values, child.path, value),
|
|
1445
|
-
source
|
|
1446
|
-
))
|
|
1447
|
-
},
|
|
1448
|
-
child.type === "atomic" || child.type === "final" ? "leaf" : "nested",
|
|
1449
|
-
child.schema !== undefined
|
|
1450
|
-
)
|
|
1451
|
-
builder[child.key] = child.type === "atomic" || child.type === "final"
|
|
1452
|
-
? method
|
|
1453
|
-
: withInitial(method, child.path, child.schema !== undefined, values)
|
|
1454
|
-
}
|
|
1455
|
-
return builder
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
|
-
const makeLocalTargetBuilder = (
|
|
1459
|
-
states: Machine.StateTree,
|
|
1460
|
-
stateNodes: Machine.StateNodes,
|
|
1461
|
-
source: string
|
|
1462
|
-
): unknown => {
|
|
1463
|
-
const scope = getLocalTargetScope(stateNodes, source)
|
|
1464
|
-
if (scope === undefined) {
|
|
1465
|
-
return {}
|
|
1466
|
-
}
|
|
1467
|
-
const builder = makeLocalTargetChildBuilder(states, stateNodes, scope, undefined, source) as Record<string, unknown>
|
|
1468
|
-
const scopeNode = getTargetBuilderNode(stateNodes, scope)
|
|
1469
|
-
if (scopeNode.schema !== undefined) {
|
|
1470
|
-
builder.with = withFrom(
|
|
1471
|
-
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
1472
|
-
if (selector === undefined) {
|
|
1473
|
-
throw new Error(`Machine expected target "${scope}" builder to provide an active child state`)
|
|
1474
|
-
}
|
|
1475
|
-
return selector(makeLocalTargetChildBuilder(states, stateNodes, scope, { [scope]: value }, source))
|
|
1476
|
-
},
|
|
1477
|
-
"nested",
|
|
1478
|
-
true
|
|
1479
|
-
)
|
|
1480
|
-
}
|
|
1481
|
-
return builder
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
const addBranchTargetChildren = (
|
|
1485
|
-
builder: Record<string, unknown>,
|
|
1486
|
-
states: Machine.StateTree,
|
|
1487
|
-
stateNodes: Machine.StateNodes,
|
|
1488
|
-
parentPath: string,
|
|
1489
|
-
values: Readonly<Record<string, unknown>> | undefined,
|
|
1490
|
-
source: string
|
|
1491
|
-
): void => {
|
|
1492
|
-
const parent = getTargetBuilderNode(stateNodes, parentPath)
|
|
1493
|
-
for (
|
|
1494
|
-
const childPath of Array.from(stateNodes.byPath.values())
|
|
1495
|
-
.filter((node) => node.parent === parent.path && node.type !== "history")
|
|
1496
|
-
.map((node) => node.path)
|
|
1497
|
-
) {
|
|
1498
|
-
const child = getTargetBuilderNode(stateNodes, childPath)
|
|
1499
|
-
if (child.type === "choice") {
|
|
1500
|
-
builder[child.key] = () => Topology.makeChoiceTarget(child.path, parent.path, values)
|
|
1501
|
-
continue
|
|
1502
|
-
}
|
|
1503
|
-
builder[child.key] = makeBranchTargetNodeBuilder(states, stateNodes, child.path, values, source)
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
const makeBranchTargetNodeBuilder = (
|
|
1508
|
-
states: Machine.StateTree,
|
|
1509
|
-
stateNodes: Machine.StateNodes,
|
|
1510
|
-
path: string,
|
|
1511
|
-
values: Readonly<Record<string, unknown>> | undefined,
|
|
1512
|
-
source: string
|
|
1513
|
-
): unknown => {
|
|
1514
|
-
const node = getTargetBuilderNode(stateNodes, path)
|
|
1515
|
-
if (node.type === "atomic" || node.type === "final") {
|
|
1516
|
-
return withFrom(
|
|
1517
|
-
(value: unknown) => makeTargetWithValues(node.path, value, values),
|
|
1518
|
-
"leaf",
|
|
1519
|
-
node.schema !== undefined
|
|
1520
|
-
)
|
|
1521
|
-
}
|
|
1522
|
-
const builder = withFrom(
|
|
1523
|
-
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
1524
|
-
if (node.type === "parallel") {
|
|
1525
|
-
if (source !== node.path && !source.startsWith(`${node.path}.`)) {
|
|
1526
|
-
return makeParallelTarget(states, node, value, selector, values)
|
|
1527
|
-
}
|
|
1528
|
-
if (selector === undefined) {
|
|
1529
|
-
throw new Error(`Machine expected target "${node.path}" builder to provide an active child state`)
|
|
1530
|
-
}
|
|
1531
|
-
const nextBuilder: Record<string, unknown> = {}
|
|
1532
|
-
addBranchTargetChildren(
|
|
1533
|
-
nextBuilder,
|
|
1534
|
-
states,
|
|
1535
|
-
stateNodes,
|
|
1536
|
-
node.path,
|
|
1537
|
-
node.schema === undefined ? values : extendTargetValues(values, node.path, value),
|
|
1538
|
-
source
|
|
1539
|
-
)
|
|
1540
|
-
return selector(nextBuilder)
|
|
1541
|
-
}
|
|
1542
|
-
if (selector === undefined) {
|
|
1543
|
-
throw new Error(`Machine expected target "${node.path}" builder to provide an active child state`)
|
|
1544
|
-
}
|
|
1545
|
-
const nextBuilder: Record<string, unknown> = {}
|
|
1546
|
-
addBranchTargetChildren(
|
|
1547
|
-
nextBuilder,
|
|
1548
|
-
states,
|
|
1549
|
-
stateNodes,
|
|
1550
|
-
node.path,
|
|
1551
|
-
node.schema === undefined ? values : extendTargetValues(values, node.path, value),
|
|
1552
|
-
source
|
|
1553
|
-
)
|
|
1554
|
-
return selector(nextBuilder)
|
|
1555
|
-
},
|
|
1556
|
-
"nested",
|
|
1557
|
-
node.schema !== undefined
|
|
1558
|
-
) as unknown as Record<string, unknown>
|
|
1559
|
-
withInitial(builder, node.path, node.schema !== undefined, values)
|
|
1560
|
-
if (node.type !== "parallel" || source === node.path || source.startsWith(`${node.path}.`)) {
|
|
1561
|
-
addBranchTargetChildren(builder, states, stateNodes, node.path, values, source)
|
|
1562
|
-
}
|
|
1563
|
-
return builder
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
const makeBranchTargetBuilder = (
|
|
1567
|
-
states: Machine.StateTree,
|
|
1568
|
-
stateNodes: Machine.StateNodes,
|
|
1569
|
-
source: string
|
|
1570
|
-
): unknown => {
|
|
1571
|
-
const rootPath = source.split(".")[0]!
|
|
1572
|
-
const root = getTargetBuilderNode(stateNodes, rootPath)
|
|
1573
|
-
return {
|
|
1574
|
-
[root.key]: makeBranchTargetNodeBuilder(states, stateNodes, root.path, undefined, source)
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
|
|
1578
|
-
const makeHistoryTargetBuilder = (
|
|
1579
|
-
states: Machine.StateTree,
|
|
1580
|
-
prefix: string
|
|
1581
|
-
): unknown => {
|
|
1582
|
-
const builder: Record<string, unknown> = {}
|
|
1583
|
-
for (const key of Object.keys(states)) {
|
|
1584
|
-
const path = prefix === "" ? key : `${prefix}.${key}`
|
|
1585
|
-
const definition = Topology.getStateNodeDefinition(path, states[key]!)
|
|
1586
|
-
if (definition.type === "history") {
|
|
1587
|
-
const parent = getParentPathRuntime(path)
|
|
1588
|
-
builder[key] = () => Topology.makeHistoryTarget(path, parent)
|
|
1589
|
-
continue
|
|
1590
|
-
}
|
|
1591
|
-
if (definition.states !== undefined) {
|
|
1592
|
-
builder[key] = makeHistoryTargetBuilder(definition.states, path)
|
|
1593
|
-
}
|
|
1594
|
-
}
|
|
1595
|
-
return builder
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
const getParentPathRuntime = (path: string): string => {
|
|
1599
|
-
const separator = path.lastIndexOf(".")
|
|
1600
|
-
if (separator < 0) {
|
|
1601
|
-
throw new Error(`Machine expected history state "${path}" to have an active parent`)
|
|
1602
|
-
}
|
|
1603
|
-
return path.slice(0, separator)
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
const makeTargetBuilder = <const States extends Machine.StateSchemas>(
|
|
1607
|
-
states: States,
|
|
1608
|
-
stateNodes: Machine.StateNodes
|
|
1609
|
-
) => {
|
|
1610
|
-
const full = makeSnapshotBuilder(states, { mode: "full", prefix: "" }) as Machine.FullTargetBuilder<States>
|
|
1611
|
-
const history = makeHistoryTargetBuilder(states, "") as Machine.HistoryTargetBuilder<States>
|
|
1612
|
-
return <Source extends Machine.StateNodeIdentifier<States>>(source: Source): Machine.TargetBuilder<States, Source> =>
|
|
1613
|
-
({
|
|
1614
|
-
none: Topology.makeNoTarget,
|
|
1615
|
-
local: makeLocalTargetBuilder(states, stateNodes, source),
|
|
1616
|
-
branch: makeBranchTargetBuilder(states, stateNodes, source),
|
|
1617
|
-
full,
|
|
1618
|
-
history
|
|
1619
|
-
}) as Machine.TargetBuilder<States, Source>
|
|
1620
|
-
}
|
|
1621
|
-
|
|
1622
|
-
const makeInitialSelector = (stateNodes: Machine.StateNodes): unknown => {
|
|
1623
|
-
const selector: Record<string, unknown> = {}
|
|
1624
|
-
for (const node of stateNodes.byPath.values()) {
|
|
1625
|
-
if (node.parent === undefined && node.type !== "history" && node.type !== "choice") {
|
|
1626
|
-
selector[node.key] = node.type === "atomic" || node.type === "final"
|
|
1627
|
-
? makeSelectionMethod("state", node.path, "initial")
|
|
1628
|
-
: Object.freeze({ initial: makeSelectionValue("initial", node.path, "initial") })
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
return Object.freeze(selector)
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
1141
|
const getInitialSelectionBuilder = (
|
|
1635
1142
|
initialBuilder: Record<string, any>,
|
|
1636
1143
|
selection: Topology.TargetSelection
|
|
@@ -1648,17 +1155,18 @@ const getInitialSelectionBuilder = (
|
|
|
1648
1155
|
|
|
1649
1156
|
const captureInitialBranch = (
|
|
1650
1157
|
definition: unknown,
|
|
1651
|
-
|
|
1652
|
-
|
|
1158
|
+
initialBuilder: Record<string, any>,
|
|
1159
|
+
configuration: boolean
|
|
1653
1160
|
): {
|
|
1654
1161
|
readonly selection: Topology.TargetSelection
|
|
1655
1162
|
readonly resolve?: (context: any) => unknown
|
|
1656
1163
|
readonly builder: Record<string, any>
|
|
1657
1164
|
} => {
|
|
1658
|
-
if (typeof definition !== "function") {
|
|
1165
|
+
if (definition !== undefined && typeof definition !== "function") {
|
|
1659
1166
|
throw new Error("Machine initial definition must be a target-first callback")
|
|
1660
1167
|
}
|
|
1661
|
-
const
|
|
1168
|
+
const selector = decorateInitialSelection(makeSelectionValue(configuration ? "state" : "initial", "", "initial"))
|
|
1169
|
+
const result = definition === undefined ? selector : definition(selector)
|
|
1662
1170
|
let selection: Topology.TargetSelection
|
|
1663
1171
|
let resolve: ((context: any) => unknown) | undefined
|
|
1664
1172
|
if (Topology.isTargetSelection(result)) {
|
|
@@ -1694,13 +1202,17 @@ const validateInitialSelection = (result: unknown, selection: Topology.TargetSel
|
|
|
1694
1202
|
const compileInitial = (
|
|
1695
1203
|
definition: unknown,
|
|
1696
1204
|
states: Machine.StateTree,
|
|
1697
|
-
stateNodes: Machine.StateNodes
|
|
1205
|
+
stateNodes: Machine.StateNodes,
|
|
1206
|
+
configuration = false
|
|
1698
1207
|
): {
|
|
1699
1208
|
readonly initial: (input?: unknown) => unknown
|
|
1700
1209
|
readonly definition: Machine.InitialDefinition
|
|
1701
1210
|
} => {
|
|
1702
|
-
const
|
|
1703
|
-
const
|
|
1211
|
+
const rootNode = getTargetBuilderNode(stateNodes, "")
|
|
1212
|
+
const initialBuilder = configuration ?
|
|
1213
|
+
makeSnapshotBuilder(states, { mode: "full", prefix: "" }) as Record<string, any>
|
|
1214
|
+
: { "": withFrom((value: unknown) => Topology.makeInitialTarget("", value), "leaf", rootNode.schema !== undefined) }
|
|
1215
|
+
const branch = captureInitialBranch(definition, initialBuilder, configuration)
|
|
1704
1216
|
return {
|
|
1705
1217
|
initial: (input?: unknown) => {
|
|
1706
1218
|
const result = branch.resolve === undefined
|
|
@@ -1716,62 +1228,35 @@ const compileInitial = (
|
|
|
1716
1228
|
}
|
|
1717
1229
|
}
|
|
1718
1230
|
|
|
1719
|
-
export const state
|
|
1720
|
-
StateDefinition.
|
|
1721
|
-
|
|
1722
|
-
})
|
|
1231
|
+
export const state = (node: unknown): State<Machine.StateNodeConfig> => {
|
|
1232
|
+
const captured = StateDefinition.captureRoot(node) as Machine.StateNodeConfig
|
|
1233
|
+
const access = makeStateHelpers()
|
|
1234
|
+
return Object.freeze({ ...access, "~effect/Machine/State": "~effect/Machine/State", node: captured })
|
|
1235
|
+
}
|
|
1723
1236
|
|
|
1724
|
-
|
|
1725
|
-
states: States
|
|
1726
|
-
): Machine.DefinedStates<States> => {
|
|
1727
|
-
StateDefinition.validateStateDefinitions(states, "Machine.states")
|
|
1728
|
-
const captured = StateDefinition.captureStateDefinitions(states)
|
|
1237
|
+
const makeStateHelpers = (): Machine.StateAccessors<{ readonly "": Machine.StateNodeConfig }> => {
|
|
1729
1238
|
return {
|
|
1730
|
-
|
|
1731
|
-
path: ((path: string) => path) as Machine.DefinedStates<States>["path"],
|
|
1239
|
+
path: ((path: string) => path) as Machine.StateAccessors<{ readonly "": Machine.StateNodeConfig }>["path"],
|
|
1732
1240
|
get:
|
|
1733
1241
|
((snapshot: Machine.AtomicSnapshot<string, unknown>, path: string) =>
|
|
1734
1242
|
Topology.getSnapshotByPath(snapshot, path).pipe(
|
|
1735
1243
|
Option.map((snapshot) => snapshot.value)
|
|
1736
|
-
)) as Machine.
|
|
1244
|
+
)) as Machine.StateAccessors<{ readonly "": Machine.StateNodeConfig }>["get"],
|
|
1737
1245
|
getWithParents: ((snapshot, path) => {
|
|
1738
1246
|
const parents: Record<string, unknown> = {}
|
|
1739
1247
|
return Topology.getSnapshotByPath(snapshot, path, parents).pipe(
|
|
1740
1248
|
Option.map((snapshot) => ({ value: snapshot.value, parents }))
|
|
1741
1249
|
)
|
|
1742
|
-
}) as Machine.
|
|
1743
|
-
getSnapshot: Topology.getSnapshotByPath as unknown as Machine.
|
|
1250
|
+
}) as Machine.StateAccessors<{ readonly "": Machine.StateNodeConfig }>["getWithParents"],
|
|
1251
|
+
getSnapshot: Topology.getSnapshotByPath as unknown as Machine.StateAccessors<
|
|
1252
|
+
{ readonly "": Machine.StateNodeConfig }
|
|
1253
|
+
>["getSnapshot"],
|
|
1744
1254
|
matches:
|
|
1745
1255
|
((snapshot: Machine.AtomicSnapshot<string, unknown>, path: string) =>
|
|
1746
|
-
Option.isSome(Topology.getSnapshotByPath(snapshot, path))) as Machine.
|
|
1256
|
+
Option.isSome(Topology.getSnapshotByPath(snapshot, path))) as Machine.StateAccessors<
|
|
1257
|
+
{ readonly "": Machine.StateNodeConfig }
|
|
1258
|
+
>["matches"]
|
|
1747
1259
|
}
|
|
1748
|
-
}) as StatesConstructor
|
|
1749
|
-
|
|
1750
|
-
type MakeConfig<
|
|
1751
|
-
States extends Machine.StateSchemas,
|
|
1752
|
-
InputEvents extends ReadonlyArray<Machine.TaggedSchema>,
|
|
1753
|
-
Emits extends ReadonlyArray<Machine.TaggedSchema>,
|
|
1754
|
-
Input extends Schema.Top,
|
|
1755
|
-
InitialE,
|
|
1756
|
-
InitialR,
|
|
1757
|
-
InternalEvents extends ReadonlyArray<Machine.TaggedSchema>,
|
|
1758
|
-
ParentDeclaration extends Parent.Any | undefined
|
|
1759
|
-
> = {
|
|
1760
|
-
readonly id?: string
|
|
1761
|
-
readonly states: States & DefineStateTreeInput<NoInfer<States>>
|
|
1762
|
-
readonly events:
|
|
1763
|
-
& Machine.EventProtocol<"public", InputEvents>
|
|
1764
|
-
& ValidateInputEventProtocol<NoInfer<InputEvents>>
|
|
1765
|
-
readonly internalEvents?:
|
|
1766
|
-
& Machine.EventProtocol<"internal", InternalEvents>
|
|
1767
|
-
& ValidateInternalEventProtocol<
|
|
1768
|
-
NoInfer<InputEvents>,
|
|
1769
|
-
NoInfer<InternalEvents>
|
|
1770
|
-
>
|
|
1771
|
-
readonly emittedEvents?: Machine.EventProtocol<"emitted", Emits>
|
|
1772
|
-
readonly parent?: ParentDeclaration
|
|
1773
|
-
readonly input?: Input
|
|
1774
|
-
readonly initial: unknown
|
|
1775
1260
|
}
|
|
1776
1261
|
|
|
1777
1262
|
type MakeResult<
|
|
@@ -1796,40 +1281,7 @@ type MakeResult<
|
|
|
1796
1281
|
Machine.ParentEventsOf<ParentDeclaration>
|
|
1797
1282
|
>
|
|
1798
1283
|
|
|
1799
|
-
|
|
1800
|
-
<
|
|
1801
|
-
const States extends Machine.StateSchemas,
|
|
1802
|
-
const InputEvents extends ReadonlyArray<Machine.TaggedSchema>,
|
|
1803
|
-
const Emits extends ReadonlyArray<Machine.TaggedSchema> = readonly [],
|
|
1804
|
-
const Input extends Schema.Top = typeof Schema.Void,
|
|
1805
|
-
InitialE = never,
|
|
1806
|
-
InitialR = never,
|
|
1807
|
-
const InternalEvents extends ReadonlyArray<Machine.TaggedSchema> = readonly [],
|
|
1808
|
-
const ParentDeclaration extends Parent.Any | undefined = undefined
|
|
1809
|
-
>(
|
|
1810
|
-
config: MakeConfig<States, InputEvents, Emits, Input, InitialE, InitialR, InternalEvents, ParentDeclaration>,
|
|
1811
|
-
..._validation: ValidateDefinedStates<NoInfer<States>>
|
|
1812
|
-
): MakeResult<States, InputEvents, Emits, Input, InitialE, InitialR, InternalEvents, ParentDeclaration>
|
|
1813
|
-
<
|
|
1814
|
-
const States extends Machine.StateSchemas,
|
|
1815
|
-
const InputEvents extends ReadonlyArray<Machine.TaggedSchema>,
|
|
1816
|
-
const Emits extends ReadonlyArray<Machine.TaggedSchema> = readonly [],
|
|
1817
|
-
const Input extends Schema.Top = typeof Schema.Void,
|
|
1818
|
-
InitialE = never,
|
|
1819
|
-
InitialR = never,
|
|
1820
|
-
const InternalEvents extends ReadonlyArray<Machine.TaggedSchema> = readonly [],
|
|
1821
|
-
const ParentDeclaration extends Parent.Any | undefined = undefined
|
|
1822
|
-
>(
|
|
1823
|
-
config:
|
|
1824
|
-
& Omit<
|
|
1825
|
-
MakeConfig<States, InputEvents, Emits, Input, InitialE, InitialR, InternalEvents, ParentDeclaration>,
|
|
1826
|
-
"states"
|
|
1827
|
-
>
|
|
1828
|
-
& { readonly states: InvalidDefinedStateTreeInput<States> }
|
|
1829
|
-
): never
|
|
1830
|
-
}
|
|
1831
|
-
|
|
1832
|
-
export const make: Make = (<
|
|
1284
|
+
export const make = <
|
|
1833
1285
|
const States extends Machine.StateSchemas,
|
|
1834
1286
|
const InputEvents extends ReadonlyArray<Machine.TaggedSchema>,
|
|
1835
1287
|
const Emits extends ReadonlyArray<Machine.TaggedSchema> = readonly [],
|
|
@@ -1841,7 +1293,8 @@ export const make: Make = (<
|
|
|
1841
1293
|
>(
|
|
1842
1294
|
config: {
|
|
1843
1295
|
readonly id?: string
|
|
1844
|
-
readonly
|
|
1296
|
+
readonly root: State<Machine.StateNodeConfig>
|
|
1297
|
+
readonly initialConfiguration?: unknown
|
|
1845
1298
|
readonly events: Machine.EventProtocol<"public", InputEvents>
|
|
1846
1299
|
readonly internalEvents?: Machine.EventProtocol<"internal", InternalEvents>
|
|
1847
1300
|
readonly emittedEvents?: Machine.EventProtocol<"emitted", Emits>
|
|
@@ -1850,25 +1303,31 @@ export const make: Make = (<
|
|
|
1850
1303
|
readonly initial: unknown
|
|
1851
1304
|
}
|
|
1852
1305
|
): MakeResult<States, InputEvents, Emits, Input, InitialE, InitialR, InternalEvents, ParentDeclaration> => {
|
|
1853
|
-
|
|
1306
|
+
const states = Object.freeze({ "": config.root.node })
|
|
1854
1307
|
const self = Object.create(Proto)
|
|
1855
|
-
self.states =
|
|
1308
|
+
self.states = states
|
|
1309
|
+
self.root = config.root
|
|
1856
1310
|
self.events = config.events
|
|
1857
1311
|
self.internalEvents = config.internalEvents ?? Protocol.makeEventProtocol("internal", [] as const)
|
|
1858
1312
|
self.emittedEvents = config.emittedEvents ?? Protocol.makeEventProtocol("emitted", [] as const)
|
|
1859
1313
|
self.parent = config.parent
|
|
1860
1314
|
self.input = config.input
|
|
1861
1315
|
self.id = config.id
|
|
1862
|
-
self.stateNodes = Topology.compileStateNodes(
|
|
1863
|
-
const compiledInitial = compileInitial(
|
|
1316
|
+
self.stateNodes = Topology.compileStateNodes(states)
|
|
1317
|
+
const compiledInitial = compileInitial(
|
|
1318
|
+
config.initialConfiguration ?? config.initial,
|
|
1319
|
+
states,
|
|
1320
|
+
self.stateNodes,
|
|
1321
|
+
config.initialConfiguration !== undefined
|
|
1322
|
+
)
|
|
1864
1323
|
self.initial = compiledInitial.initial
|
|
1865
1324
|
self.initialDefinition = compiledInitial.definition
|
|
1866
|
-
self.makeTargetBuilder = makeTargetBuilder(
|
|
1325
|
+
self.makeTargetBuilder = makeTargetBuilder(states, self.stateNodes)
|
|
1867
1326
|
self.handlers = Object.create(null)
|
|
1868
1327
|
self.handle = makeHandle(self)
|
|
1869
1328
|
Protocol.setProtocol(self)
|
|
1870
1329
|
return self
|
|
1871
|
-
}
|
|
1330
|
+
}
|
|
1872
1331
|
|
|
1873
1332
|
const flattenEventProtocolInputs = <Kind extends Machine.EventProtocolKind>(
|
|
1874
1333
|
kind: Kind,
|
|
@@ -1888,6 +1347,22 @@ export const events = <const Inputs extends ReadonlyArray<Machine.EventProtocolI
|
|
|
1888
1347
|
flattenEventProtocolInputs("public", inputs)
|
|
1889
1348
|
) as Machine.EventProtocol<"public", Machine.EventProtocolInputSchemasOf<"public", Inputs>>
|
|
1890
1349
|
|
|
1350
|
+
const eventFieldSchemas = (
|
|
1351
|
+
cases: Readonly<Record<string, Schema.Struct.Fields>>
|
|
1352
|
+
): ReadonlyArray<Machine.TaggedSchema> => {
|
|
1353
|
+
for (const [tag, fields] of Object.entries(cases)) {
|
|
1354
|
+
if (Object.hasOwn(fields, "_tag")) throw new Error(`Machine event "${tag}" fields cannot declare _tag`)
|
|
1355
|
+
}
|
|
1356
|
+
return Object.keys(cases).length === 0 ? [] : [Schema.TaggedUnion(cases)]
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
export const eventsFromFields = (cases: Readonly<Record<string, Schema.Struct.Fields>>) =>
|
|
1360
|
+
Protocol.makeEventProtocol("public", eventFieldSchemas(cases))
|
|
1361
|
+
export const internalEventsFromFields = (cases: Readonly<Record<string, Schema.Struct.Fields>>) =>
|
|
1362
|
+
Protocol.makeEventProtocol("internal", eventFieldSchemas(cases))
|
|
1363
|
+
export const emittedEventsFromFields = (cases: Readonly<Record<string, Schema.Struct.Fields>>) =>
|
|
1364
|
+
Protocol.makeEventProtocol("emitted", eventFieldSchemas(cases))
|
|
1365
|
+
|
|
1891
1366
|
const makeParent = <
|
|
1892
1367
|
const Mode extends ParentMode,
|
|
1893
1368
|
const Events extends ReadonlyArray<Machine.TaggedSchema>
|
|
@@ -2038,7 +1513,7 @@ export const planInitial: <
|
|
|
2038
1513
|
readonly initialEntryPaths: ReadonlyArray<Machine.StateIdentifier<States>>
|
|
2039
1514
|
readonly state: Machine.Snapshot<States>
|
|
2040
1515
|
readonly commands: ReadonlyArray<Command>
|
|
2041
|
-
readonly emittedEvents: ReadonlyArray<Machine.
|
|
1516
|
+
readonly emittedEvents: ReadonlyArray<Machine.EmittedEventOf<Emits>>
|
|
2042
1517
|
readonly microsteps: ReadonlyArray<{
|
|
2043
1518
|
readonly next: Machine.Snapshot<States>
|
|
2044
1519
|
readonly event: Machine.EventOf<Events> | InitialEventModel
|
|
@@ -2051,7 +1526,7 @@ export const planInitial: <
|
|
|
2051
1526
|
>
|
|
2052
1527
|
readonly commands: ReadonlyArray<Command>
|
|
2053
1528
|
readonly raisedEvents: ReadonlyArray<Machine.EventOf<Events>>
|
|
2054
|
-
readonly emittedEvents: ReadonlyArray<Machine.
|
|
1529
|
+
readonly emittedEvents: ReadonlyArray<Machine.EmittedEventOf<Emits>>
|
|
2055
1530
|
readonly exitPaths: ReadonlyArray<string>
|
|
2056
1531
|
readonly entryPaths: ReadonlyArray<string>
|
|
2057
1532
|
readonly changed: boolean
|
|
@@ -2216,7 +1691,7 @@ export const plan: <
|
|
|
2216
1691
|
& {
|
|
2217
1692
|
readonly next: Machine.Snapshot<States>
|
|
2218
1693
|
readonly commands: ReadonlyArray<Command>
|
|
2219
|
-
readonly emittedEvents: ReadonlyArray<Machine.
|
|
1694
|
+
readonly emittedEvents: ReadonlyArray<Machine.EmittedEventOf<Emits>>
|
|
2220
1695
|
readonly microsteps: ReadonlyArray<{
|
|
2221
1696
|
readonly next: Machine.Snapshot<States>
|
|
2222
1697
|
readonly event: Machine.EventOf<Events> | InitialEventModel
|
|
@@ -2229,7 +1704,7 @@ export const plan: <
|
|
|
2229
1704
|
>
|
|
2230
1705
|
readonly commands: ReadonlyArray<Command>
|
|
2231
1706
|
readonly raisedEvents: ReadonlyArray<Machine.EventOf<Events>>
|
|
2232
|
-
readonly emittedEvents: ReadonlyArray<Machine.
|
|
1707
|
+
readonly emittedEvents: ReadonlyArray<Machine.EmittedEventOf<Emits>>
|
|
2233
1708
|
readonly exitPaths: ReadonlyArray<string>
|
|
2234
1709
|
readonly entryPaths: ReadonlyArray<string>
|
|
2235
1710
|
readonly changed: boolean
|
|
@@ -2450,7 +1925,7 @@ export const start: <
|
|
|
2450
1925
|
ExcludeCompatibleRuntime<
|
|
2451
1926
|
ExecutionServices<InitialR | R>,
|
|
2452
1927
|
Machine.EventOf<Events>,
|
|
2453
|
-
Machine.
|
|
1928
|
+
Machine.EmittedEventOf<Emits>
|
|
2454
1929
|
>
|
|
2455
1930
|
> = internalProcess.start as any
|
|
2456
1931
|
|
|
@@ -2503,6 +1978,6 @@ export const resume: <
|
|
|
2503
1978
|
ExcludeCompatibleRuntime<
|
|
2504
1979
|
ExecutionServices<R>,
|
|
2505
1980
|
Machine.EventOf<Events>,
|
|
2506
|
-
Machine.
|
|
1981
|
+
Machine.EmittedEventOf<Emits>
|
|
2507
1982
|
>
|
|
2508
1983
|
> = internalProcess.resume as any
|