@typeonce/effect-machine 0.7.0 → 0.8.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 +21 -0
- package/dist/Machine.d.ts +159 -140
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +3 -1
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/atom.d.ts +8 -2
- package/dist/internal/machine/atom.d.ts.map +1 -1
- package/dist/internal/machine/atom.js.map +1 -1
- package/dist/internal/machine/configuration.d.ts.map +1 -1
- package/dist/internal/machine/configuration.js +103 -20
- package/dist/internal/machine/configuration.js.map +1 -1
- package/dist/internal/machine/executionPlan.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.js +6 -0
- package/dist/internal/machine/executionPlan.js.map +1 -1
- package/dist/internal/machine/invocation.js +1 -1
- package/dist/internal/machine/invocation.js.map +1 -1
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +22 -16
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/planner.d.ts +10 -0
- package/dist/internal/machine/planner.d.ts.map +1 -1
- package/dist/internal/machine/planner.js +45 -35
- package/dist/internal/machine/planner.js.map +1 -1
- package/dist/internal/machine/serialization.d.ts.map +1 -1
- package/dist/internal/machine/serialization.js +53 -21
- package/dist/internal/machine/serialization.js.map +1 -1
- package/dist/internal/machine/stateDefinition.d.ts +4 -4
- package/dist/internal/machine/stateDefinition.d.ts.map +1 -1
- package/dist/internal/machine/stateDefinition.js +18 -11
- package/dist/internal/machine/stateDefinition.js.map +1 -1
- package/dist/internal/machine/topology.d.ts +5 -5
- package/dist/internal/machine/topology.d.ts.map +1 -1
- package/dist/internal/machine/topology.js +16 -13
- package/dist/internal/machine/topology.js.map +1 -1
- package/dist/internal/testing/machine/verification.d.ts.map +1 -1
- package/dist/internal/testing/machine/verification.js +10 -3
- package/dist/internal/testing/machine/verification.js.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +8 -2
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
- package/docs/agent-guide.md +56 -28
- package/package.json +2 -2
- package/src/Machine.ts +371 -296
- package/src/internal/machine/atom.ts +10 -3
- package/src/internal/machine/configuration.ts +102 -23
- package/src/internal/machine/executionPlan.ts +6 -0
- package/src/internal/machine/invocation.ts +1 -1
- package/src/internal/machine/machine.ts +85 -57
- package/src/internal/machine/planner.ts +49 -38
- package/src/internal/machine/serialization.ts +56 -31
- package/src/internal/machine/stateDefinition.ts +22 -11
- package/src/internal/machine/topology.ts +21 -18
- package/src/internal/testing/machine/verification.ts +13 -3
- package/src/unstable/reactivity/AtomMachine.ts +9 -2
|
@@ -431,6 +431,13 @@ type SnapshotIdentifier<State> = SnapshotNode<State> extends infer Node ?
|
|
|
431
431
|
Node extends { readonly path: infer Path extends string } ? Path : never
|
|
432
432
|
: never
|
|
433
433
|
|
|
434
|
+
type ValuedSnapshotIdentifier<State> = SnapshotNode<State> extends infer Node ?
|
|
435
|
+
Node extends { readonly path: infer Path extends string; readonly value: infer Value } ?
|
|
436
|
+
[Value] extends [undefined] ? never
|
|
437
|
+
: Path
|
|
438
|
+
: never
|
|
439
|
+
: never
|
|
440
|
+
|
|
434
441
|
type SnapshotValueByIdentifier<State, Path extends SnapshotIdentifier<State>> = SnapshotNode<State> extends infer Node ?
|
|
435
442
|
Node extends { readonly path: Path; readonly value: infer Value } ? Value : never
|
|
436
443
|
: never
|
|
@@ -443,7 +450,7 @@ type ChildState<Child extends Machine.ChildMachine.Any> = RefState<Machine.Child
|
|
|
443
450
|
|
|
444
451
|
const selectValueByPath = <
|
|
445
452
|
State extends Machine.Machine.AtomicSnapshot<string, unknown>,
|
|
446
|
-
Path extends
|
|
453
|
+
Path extends ValuedSnapshotIdentifier<State>
|
|
447
454
|
>(
|
|
448
455
|
snapshot: State,
|
|
449
456
|
path: Path
|
|
@@ -467,7 +474,7 @@ export const select = <
|
|
|
467
474
|
Error,
|
|
468
475
|
Output,
|
|
469
476
|
StartError,
|
|
470
|
-
const Path extends
|
|
477
|
+
const Path extends ValuedSnapshotIdentifier<State>
|
|
471
478
|
>(
|
|
472
479
|
self: MachineAtom<State, Event, Error, Output, StartError>,
|
|
473
480
|
path: Path
|
|
@@ -498,7 +505,7 @@ export const selectSnapshot = <
|
|
|
498
505
|
export const selectChild = <
|
|
499
506
|
Child extends Machine.ChildMachine.Any,
|
|
500
507
|
StartError,
|
|
501
|
-
const Path extends
|
|
508
|
+
const Path extends ValuedSnapshotIdentifier<ChildState<Child>>
|
|
502
509
|
>(
|
|
503
510
|
self: ChildMachineAtom<Child, StartError>,
|
|
504
511
|
path: Path
|
|
@@ -84,7 +84,7 @@ const historyFromSnapshot = (
|
|
|
84
84
|
const active = new Set<string>()
|
|
85
85
|
const values = new Map<string, unknown>()
|
|
86
86
|
for (const activePath of entry.active) {
|
|
87
|
-
if (active.has(activePath)
|
|
87
|
+
if (active.has(activePath)) {
|
|
88
88
|
throw new Error(`Machine snapshot contains invalid remembered state "${activePath}"`)
|
|
89
89
|
}
|
|
90
90
|
const node = getNode(machine, activePath)
|
|
@@ -96,9 +96,15 @@ const historyFromSnapshot = (
|
|
|
96
96
|
throw new Error(`Machine snapshot contains invalid remembered value for "${activePath}"`)
|
|
97
97
|
}
|
|
98
98
|
active.add(activePath)
|
|
99
|
-
|
|
99
|
+
const hasValue = Object.prototype.hasOwnProperty.call(entry.values, activePath)
|
|
100
|
+
if (node.schema === undefined) {
|
|
101
|
+
if (hasValue) throw new Error(`Machine snapshot contains a value for structural state "${activePath}"`)
|
|
102
|
+
} else {
|
|
103
|
+
if (!hasValue) throw new Error(`Machine snapshot omits remembered value for "${activePath}"`)
|
|
104
|
+
values.set(activePath, decodeStateValueSync(machine, node, entry.values[activePath]))
|
|
105
|
+
}
|
|
100
106
|
}
|
|
101
|
-
if (!active.has(historyNode.parent) || Object.keys(entry.values).length !==
|
|
107
|
+
if (!active.has(historyNode.parent) || Object.keys(entry.values).length !== values.size) {
|
|
102
108
|
throw new Error(`Machine snapshot contains incomplete history record "${path}"`)
|
|
103
109
|
}
|
|
104
110
|
history.set(path, {
|
|
@@ -138,7 +144,6 @@ const historyFromSnapshotEffect = Effect.fnUntraced(function*(
|
|
|
138
144
|
const node = machine.stateNodes.byPath.get(activePath)
|
|
139
145
|
if (
|
|
140
146
|
active.has(activePath) || node === undefined || node.type === "history" || node.type === "choice" ||
|
|
141
|
-
!Object.prototype.hasOwnProperty.call(entry.values, activePath) ||
|
|
142
147
|
!(isPathInSubtree(activePath, historyNode.parent) ||
|
|
143
148
|
getPathToRoot(machine, historyNode.parent).includes(activePath))
|
|
144
149
|
) {
|
|
@@ -152,15 +157,39 @@ const historyFromSnapshotEffect = Effect.fnUntraced(function*(
|
|
|
152
157
|
)
|
|
153
158
|
}
|
|
154
159
|
active.add(activePath)
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
const hasValue = Object.prototype.hasOwnProperty.call(entry.values, activePath)
|
|
161
|
+
if (node.schema === undefined) {
|
|
162
|
+
if (hasValue) {
|
|
163
|
+
return yield* Effect.fail(
|
|
164
|
+
new MachineSchemaDecodeError({
|
|
165
|
+
machineId: machine.id,
|
|
166
|
+
boundary: "history",
|
|
167
|
+
state: activePath,
|
|
168
|
+
cause: Cause.die(new Error(`Machine snapshot contains a value for structural state "${activePath}"`))
|
|
169
|
+
})
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
if (!hasValue) {
|
|
174
|
+
return yield* Effect.fail(
|
|
175
|
+
new MachineSchemaDecodeError({
|
|
176
|
+
machineId: machine.id,
|
|
177
|
+
boundary: "history",
|
|
178
|
+
state: activePath,
|
|
179
|
+
cause: Cause.die(new Error(`Machine snapshot omits remembered value for "${activePath}"`))
|
|
180
|
+
})
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
values.set(
|
|
184
|
+
activePath,
|
|
185
|
+
yield* decodeBoundary(machine, getStateNodeSchema(node), entry.values[activePath], {
|
|
186
|
+
boundary: "history",
|
|
187
|
+
state: activePath
|
|
188
|
+
})
|
|
189
|
+
)
|
|
190
|
+
}
|
|
162
191
|
}
|
|
163
|
-
if (!active.has(historyNode.parent) || Object.keys(entry.values).length !==
|
|
192
|
+
if (!active.has(historyNode.parent) || Object.keys(entry.values).length !== values.size) {
|
|
164
193
|
return yield* Effect.fail(
|
|
165
194
|
new MachineSchemaDecodeError({
|
|
166
195
|
machineId: machine.id,
|
|
@@ -212,7 +241,7 @@ const historyToSnapshot = (
|
|
|
212
241
|
entries[path] = {
|
|
213
242
|
mode: record.mode,
|
|
214
243
|
active,
|
|
215
|
-
values: Object.fromEntries(
|
|
244
|
+
values: Object.fromEntries(record.values)
|
|
216
245
|
}
|
|
217
246
|
}
|
|
218
247
|
return entries
|
|
@@ -329,7 +358,9 @@ export const getParentValues = (
|
|
|
329
358
|
const paths = getPathToRoot(machine, path)
|
|
330
359
|
for (let index = 0; index < paths.length - 1; index++) {
|
|
331
360
|
const parent = paths[index]!
|
|
332
|
-
|
|
361
|
+
if (configuration.values.has(parent)) {
|
|
362
|
+
parents[parent] = configuration.values.get(parent)
|
|
363
|
+
}
|
|
333
364
|
}
|
|
334
365
|
return parents
|
|
335
366
|
}
|
|
@@ -340,7 +371,7 @@ export const getParentValue = (
|
|
|
340
371
|
path: string
|
|
341
372
|
): unknown => {
|
|
342
373
|
const parent = getNode(machine, path).parent
|
|
343
|
-
return parent === undefined ? undefined :
|
|
374
|
+
return parent === undefined ? undefined : configuration.values.get(parent)
|
|
344
375
|
}
|
|
345
376
|
|
|
346
377
|
export const getInitialEntryPaths = (
|
|
@@ -368,7 +399,7 @@ export const snapshotFromPath = <const States extends Machine.StateSchemas>(
|
|
|
368
399
|
const node = getNode(machine, path)
|
|
369
400
|
const snapshot: Record<string, unknown> = {
|
|
370
401
|
path,
|
|
371
|
-
value:
|
|
402
|
+
value: configuration.values.get(path)
|
|
372
403
|
}
|
|
373
404
|
if (node.type === "compound") {
|
|
374
405
|
const child = node.children.find((child) => configuration.active.has(child))
|
|
@@ -438,9 +469,14 @@ export const configurationFromSnapshot = (
|
|
|
438
469
|
|
|
439
470
|
const visit = (current: Machine.AtomicSnapshot<string, unknown>): void => {
|
|
440
471
|
const node = getNode(machine, String(current.path))
|
|
441
|
-
const value = decodeStateValueSync(machine, node, current.value)
|
|
442
472
|
active.add(node.path)
|
|
443
|
-
|
|
473
|
+
if (node.schema === undefined) {
|
|
474
|
+
if (current.value !== undefined) {
|
|
475
|
+
throw new Error(`Machine structural snapshot "${node.path}" cannot contain a value`)
|
|
476
|
+
}
|
|
477
|
+
} else {
|
|
478
|
+
values.set(node.path, decodeStateValueSync(machine, node, current.value))
|
|
479
|
+
}
|
|
444
480
|
if (node.type === "compound") {
|
|
445
481
|
if (!hasProperty(current, "state") || !isSnapshot(current.state)) {
|
|
446
482
|
throw new Error(`Machine expected compound snapshot "${node.path}" to include an active child state`)
|
|
@@ -520,9 +556,14 @@ export const configurationFromSnapshotEffect = Effect.fnUntraced(function*(
|
|
|
520
556
|
current: Machine.AtomicSnapshot<string, unknown>
|
|
521
557
|
) {
|
|
522
558
|
const node = getNode(machine, String(current.path))
|
|
523
|
-
const value = yield* decodeStateValue(machine, node, current.value)
|
|
524
559
|
active.add(node.path)
|
|
525
|
-
|
|
560
|
+
if (node.schema === undefined) {
|
|
561
|
+
if (current.value !== undefined) {
|
|
562
|
+
throw new Error(`Machine structural snapshot "${node.path}" cannot contain a value`)
|
|
563
|
+
}
|
|
564
|
+
} else {
|
|
565
|
+
values.set(node.path, yield* decodeStateValue(machine, node, current.value))
|
|
566
|
+
}
|
|
526
567
|
if (node.type === "compound") {
|
|
527
568
|
if (!hasProperty(current, "state") || !isSnapshot(current.state)) {
|
|
528
569
|
throw new Error(`Machine expected compound snapshot "${node.path}" to include an active child state`)
|
|
@@ -645,7 +686,9 @@ export const captureHistory = (
|
|
|
645
686
|
}
|
|
646
687
|
const values = new Map<string, unknown>()
|
|
647
688
|
for (const path of active) {
|
|
648
|
-
values.
|
|
689
|
+
if (current.values.has(path)) {
|
|
690
|
+
values.set(path, current.values.get(path))
|
|
691
|
+
}
|
|
649
692
|
}
|
|
650
693
|
history.set(node.path, {
|
|
651
694
|
mode,
|
|
@@ -722,6 +765,15 @@ export const configurationFromTargetPathEffect = Effect.fnUntraced(function*(
|
|
|
722
765
|
for (const currentPath of paths) {
|
|
723
766
|
const currentNode = getNode(machine, currentPath)
|
|
724
767
|
active.add(currentPath)
|
|
768
|
+
if (currentNode.schema === undefined) {
|
|
769
|
+
const supplied = currentPath === node.path ?
|
|
770
|
+
value
|
|
771
|
+
: providedValues !== undefined && hasOwn(providedValues, currentPath) ?
|
|
772
|
+
providedValues[currentPath]
|
|
773
|
+
: undefined
|
|
774
|
+
if (supplied !== undefined) throw new Error(`Machine structural target "${currentPath}" cannot contain a value`)
|
|
775
|
+
continue
|
|
776
|
+
}
|
|
725
777
|
if (currentPath === node.path) {
|
|
726
778
|
values.set(currentPath, yield* decodeStateValue(machine, currentNode, value))
|
|
727
779
|
} else if (providedValues !== undefined && hasOwn(providedValues, currentPath)) {
|
|
@@ -783,6 +835,12 @@ export const configurationFromTargetSnapshotEffect = Effect.fnUntraced(function*
|
|
|
783
835
|
for (const ancestor of paths.slice(0, -1)) {
|
|
784
836
|
const node = getNode(machine, ancestor)
|
|
785
837
|
active.add(ancestor)
|
|
838
|
+
if (node.schema === undefined) {
|
|
839
|
+
if (providedValues !== undefined && hasOwn(providedValues, ancestor)) {
|
|
840
|
+
throw new Error(`Machine structural target "${ancestor}" cannot contain a value`)
|
|
841
|
+
}
|
|
842
|
+
continue
|
|
843
|
+
}
|
|
786
844
|
if (providedValues !== undefined && hasOwn(providedValues, ancestor)) {
|
|
787
845
|
values.set(ancestor, yield* decodeStateValue(machine, node, providedValues[ancestor]))
|
|
788
846
|
} else if (current.values.has(ancestor)) {
|
|
@@ -816,6 +874,9 @@ export const configurationFromTargetSnapshotEffect = Effect.fnUntraced(function*
|
|
|
816
874
|
if (!isPathInSubtree(providedPath, child)) continue
|
|
817
875
|
const providedNode = getNode(machine, providedPath)
|
|
818
876
|
active.add(providedPath)
|
|
877
|
+
if (providedNode.schema === undefined) {
|
|
878
|
+
throw new Error(`Machine structural target "${providedPath}" cannot contain a value`)
|
|
879
|
+
}
|
|
819
880
|
values.set(providedPath, yield* decodeStateValue(machine, providedNode, providedValue))
|
|
820
881
|
}
|
|
821
882
|
}
|
|
@@ -885,6 +946,15 @@ const configurationFromTargetPathSync = (
|
|
|
885
946
|
for (const currentPath of paths) {
|
|
886
947
|
const currentNode = getNode(machine, currentPath)
|
|
887
948
|
active.add(currentPath)
|
|
949
|
+
if (currentNode.schema === undefined) {
|
|
950
|
+
const supplied = currentPath === node.path ?
|
|
951
|
+
value
|
|
952
|
+
: providedValues !== undefined && hasOwn(providedValues, currentPath) ?
|
|
953
|
+
providedValues[currentPath]
|
|
954
|
+
: undefined
|
|
955
|
+
if (supplied !== undefined) throw new Error(`Machine structural target "${currentPath}" cannot contain a value`)
|
|
956
|
+
continue
|
|
957
|
+
}
|
|
888
958
|
if (currentPath === node.path) {
|
|
889
959
|
values.set(currentPath, decodeStateValueSync(machine, currentNode, value))
|
|
890
960
|
} else if (providedValues !== undefined && hasOwn(providedValues, currentPath)) {
|
|
@@ -932,6 +1002,12 @@ const configurationFromTargetSnapshotSync = (
|
|
|
932
1002
|
for (const ancestor of paths.slice(0, -1)) {
|
|
933
1003
|
const node = getNode(machine, ancestor)
|
|
934
1004
|
active.add(ancestor)
|
|
1005
|
+
if (node.schema === undefined) {
|
|
1006
|
+
if (providedValues !== undefined && hasOwn(providedValues, ancestor)) {
|
|
1007
|
+
throw new Error(`Machine structural target "${ancestor}" cannot contain a value`)
|
|
1008
|
+
}
|
|
1009
|
+
continue
|
|
1010
|
+
}
|
|
935
1011
|
if (providedValues !== undefined && hasOwn(providedValues, ancestor)) {
|
|
936
1012
|
values.set(ancestor, decodeStateValueSync(machine, node, providedValues[ancestor]))
|
|
937
1013
|
} else if (current.values.has(ancestor)) {
|
|
@@ -960,6 +1036,9 @@ const configurationFromTargetSnapshotSync = (
|
|
|
960
1036
|
if (!isPathInSubtree(providedPath, child)) continue
|
|
961
1037
|
const providedNode = getNode(machine, providedPath)
|
|
962
1038
|
active.add(providedPath)
|
|
1039
|
+
if (providedNode.schema === undefined) {
|
|
1040
|
+
throw new Error(`Machine structural target "${providedPath}" cannot contain a value`)
|
|
1041
|
+
}
|
|
963
1042
|
values.set(providedPath, decodeStateValueSync(machine, providedNode, providedValue))
|
|
964
1043
|
}
|
|
965
1044
|
}
|
|
@@ -1098,7 +1177,7 @@ export const resolveFinalOutputEffect: <
|
|
|
1098
1177
|
) {
|
|
1099
1178
|
const node = getNode(machine, path)
|
|
1100
1179
|
const output = getStateConfigByPath(machine, path)?.output?.({
|
|
1101
|
-
state:
|
|
1180
|
+
state: configuration.values.get(path),
|
|
1102
1181
|
parent: getParentValue(machine, configuration, path),
|
|
1103
1182
|
parents: getParentValues(machine, configuration, path),
|
|
1104
1183
|
event,
|
|
@@ -1251,7 +1330,7 @@ const resolveFinalOutputSync = <const Events extends ReadonlyArray<Machine.Tagge
|
|
|
1251
1330
|
): unknown => {
|
|
1252
1331
|
const node = getNode(machine, path)
|
|
1253
1332
|
const output = getStateConfigByPath(machine, path)?.output?.({
|
|
1254
|
-
state:
|
|
1333
|
+
state: configuration.values.get(path),
|
|
1255
1334
|
parent: getParentValue(machine, configuration, path),
|
|
1256
1335
|
parents: getParentValues(machine, configuration, path),
|
|
1257
1336
|
event,
|
|
@@ -100,6 +100,12 @@ const compileIndexedExecutionDescriptor = (
|
|
|
100
100
|
if (node.type === "choice" || node.type === "history") {
|
|
101
101
|
return undefined
|
|
102
102
|
}
|
|
103
|
+
// Structural active states deliberately use the generic semantic
|
|
104
|
+
// reference until the indexed value table represents absent values as an
|
|
105
|
+
// explicit capability rather than an `undefined` slot.
|
|
106
|
+
if (node.schema === undefined) {
|
|
107
|
+
return undefined
|
|
108
|
+
}
|
|
103
109
|
if (node.type === "atomic" || node.type === "final") {
|
|
104
110
|
leafPaths.push(node.path)
|
|
105
111
|
}
|
|
@@ -109,7 +109,7 @@ export const startAll = (
|
|
|
109
109
|
.filter((path) => configuration.active.has(path))
|
|
110
110
|
.flatMap((path) =>
|
|
111
111
|
resolve(Configuration.getStateConfigByPath(machine, path), {
|
|
112
|
-
state:
|
|
112
|
+
state: configuration.values.get(path),
|
|
113
113
|
parent: Configuration.getParentValue(machine, configuration, path),
|
|
114
114
|
parents: Configuration.getParentValues(machine, configuration, path),
|
|
115
115
|
event
|
|
@@ -278,10 +278,14 @@ type FromMethodKind = "leaf" | "nested"
|
|
|
278
278
|
|
|
279
279
|
const withFrom = <Method extends (value: unknown, ...args: ReadonlyArray<any>) => unknown>(
|
|
280
280
|
method: Method,
|
|
281
|
-
kind: FromMethodKind
|
|
281
|
+
kind: FromMethodKind,
|
|
282
|
+
valued: boolean
|
|
282
283
|
): Method & { readonly from: (...args: ReadonlyArray<any>) => unknown } => {
|
|
283
284
|
Object.defineProperty(method, "from", {
|
|
284
285
|
value: (...args: ReadonlyArray<any>) => {
|
|
286
|
+
if (!valued) {
|
|
287
|
+
return method(undefined, ...args)
|
|
288
|
+
}
|
|
285
289
|
const omitted = args.length === 0 || (kind === "nested" && args.length === 1 && typeof args[0] === "function")
|
|
286
290
|
const input = omitted ? {} : args[0]
|
|
287
291
|
const rest = omitted ? args : args.slice(1)
|
|
@@ -312,7 +316,8 @@ const makeSnapshotBuilder = (
|
|
|
312
316
|
builder[key] = withFrom(
|
|
313
317
|
(value: unknown, selector?: (builder: unknown) => unknown) =>
|
|
314
318
|
makeSnapshotForNode(definition, key, value, selector, options),
|
|
315
|
-
node.states === undefined ? "leaf" : "nested"
|
|
319
|
+
node.states === undefined ? "leaf" : "nested",
|
|
320
|
+
node.schema !== undefined
|
|
316
321
|
)
|
|
317
322
|
}
|
|
318
323
|
return builder
|
|
@@ -339,14 +344,18 @@ const makeParallelSnapshotBuilder = (
|
|
|
339
344
|
}
|
|
340
345
|
const path = options.prefix === "" ? key : `${options.prefix}.${key}`
|
|
341
346
|
const node = Topology.getStateNodeDefinition(path, definition)
|
|
342
|
-
builder[key] = withFrom(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
347
|
+
builder[key] = withFrom(
|
|
348
|
+
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
349
|
+
const nextRegions: Record<string, unknown> = {}
|
|
350
|
+
for (const regionKey of Object.keys(regions)) {
|
|
351
|
+
nextRegions[regionKey] = regions[regionKey]
|
|
352
|
+
}
|
|
353
|
+
nextRegions[key] = makeSnapshotForNode(definition, key, value, selector, options)
|
|
354
|
+
return makeParallelSnapshotBuilder(states, options, nextRegions)
|
|
355
|
+
},
|
|
356
|
+
node.states === undefined ? "leaf" : "nested",
|
|
357
|
+
node.schema !== undefined
|
|
358
|
+
)
|
|
350
359
|
}
|
|
351
360
|
return builder
|
|
352
361
|
}
|
|
@@ -525,13 +534,25 @@ const makeLocalTargetChildBuilder = (
|
|
|
525
534
|
builder[child.key] = () => Topology.makeChoiceTarget(child.path, parent.path, values)
|
|
526
535
|
continue
|
|
527
536
|
}
|
|
528
|
-
builder[child.key] = withFrom(
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
if (
|
|
534
|
-
|
|
537
|
+
builder[child.key] = withFrom(
|
|
538
|
+
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
539
|
+
if (child.type === "atomic" || child.type === "final") {
|
|
540
|
+
return makeTargetWithValues(child.path, value, values)
|
|
541
|
+
}
|
|
542
|
+
if (child.type === "parallel") {
|
|
543
|
+
if (source !== child.path && !source.startsWith(`${child.path}.`)) {
|
|
544
|
+
return makeParallelTarget(states, child, value, selector, values)
|
|
545
|
+
}
|
|
546
|
+
if (selector === undefined) {
|
|
547
|
+
throw new Error(`Machine expected target "${child.path}" builder to provide an active child state`)
|
|
548
|
+
}
|
|
549
|
+
return selector(makeLocalTargetChildBuilder(
|
|
550
|
+
states,
|
|
551
|
+
stateNodes,
|
|
552
|
+
child.path,
|
|
553
|
+
child.schema === undefined ? values : extendTargetValues(values, child.path, value),
|
|
554
|
+
source
|
|
555
|
+
))
|
|
535
556
|
}
|
|
536
557
|
if (selector === undefined) {
|
|
537
558
|
throw new Error(`Machine expected target "${child.path}" builder to provide an active child state`)
|
|
@@ -540,21 +561,13 @@ const makeLocalTargetChildBuilder = (
|
|
|
540
561
|
states,
|
|
541
562
|
stateNodes,
|
|
542
563
|
child.path,
|
|
543
|
-
extendTargetValues(values, child.path, value),
|
|
564
|
+
child.schema === undefined ? values : extendTargetValues(values, child.path, value),
|
|
544
565
|
source
|
|
545
566
|
))
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
return selector(makeLocalTargetChildBuilder(
|
|
551
|
-
states,
|
|
552
|
-
stateNodes,
|
|
553
|
-
child.path,
|
|
554
|
-
extendTargetValues(values, child.path, value),
|
|
555
|
-
source
|
|
556
|
-
))
|
|
557
|
-
}, child.type === "atomic" || child.type === "final" ? "leaf" : "nested")
|
|
567
|
+
},
|
|
568
|
+
child.type === "atomic" || child.type === "final" ? "leaf" : "nested",
|
|
569
|
+
child.schema !== undefined
|
|
570
|
+
)
|
|
558
571
|
}
|
|
559
572
|
return builder
|
|
560
573
|
}
|
|
@@ -569,12 +582,19 @@ const makeLocalTargetBuilder = (
|
|
|
569
582
|
return {}
|
|
570
583
|
}
|
|
571
584
|
const builder = makeLocalTargetChildBuilder(states, stateNodes, scope, undefined, source) as Record<string, unknown>
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
585
|
+
const scopeNode = getTargetBuilderNode(stateNodes, scope)
|
|
586
|
+
if (scopeNode.schema !== undefined) {
|
|
587
|
+
builder.with = withFrom(
|
|
588
|
+
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
589
|
+
if (selector === undefined) {
|
|
590
|
+
throw new Error(`Machine expected target "${scope}" builder to provide an active child state`)
|
|
591
|
+
}
|
|
592
|
+
return selector(makeLocalTargetChildBuilder(states, stateNodes, scope, { [scope]: value }, source))
|
|
593
|
+
},
|
|
594
|
+
"nested",
|
|
595
|
+
true
|
|
596
|
+
)
|
|
597
|
+
}
|
|
578
598
|
return builder
|
|
579
599
|
}
|
|
580
600
|
|
|
@@ -610,12 +630,31 @@ const makeBranchTargetNodeBuilder = (
|
|
|
610
630
|
): unknown => {
|
|
611
631
|
const node = getTargetBuilderNode(stateNodes, path)
|
|
612
632
|
if (node.type === "atomic" || node.type === "final") {
|
|
613
|
-
return withFrom(
|
|
633
|
+
return withFrom(
|
|
634
|
+
(value: unknown) => makeTargetWithValues(node.path, value, values),
|
|
635
|
+
"leaf",
|
|
636
|
+
node.schema !== undefined
|
|
637
|
+
)
|
|
614
638
|
}
|
|
615
|
-
const builder = withFrom(
|
|
616
|
-
|
|
617
|
-
if (
|
|
618
|
-
|
|
639
|
+
const builder = withFrom(
|
|
640
|
+
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
641
|
+
if (node.type === "parallel") {
|
|
642
|
+
if (source !== node.path && !source.startsWith(`${node.path}.`)) {
|
|
643
|
+
return makeParallelTarget(states, node, value, selector, values)
|
|
644
|
+
}
|
|
645
|
+
if (selector === undefined) {
|
|
646
|
+
throw new Error(`Machine expected target "${node.path}" builder to provide an active child state`)
|
|
647
|
+
}
|
|
648
|
+
const nextBuilder: Record<string, unknown> = {}
|
|
649
|
+
addBranchTargetChildren(
|
|
650
|
+
nextBuilder,
|
|
651
|
+
states,
|
|
652
|
+
stateNodes,
|
|
653
|
+
node.path,
|
|
654
|
+
node.schema === undefined ? values : extendTargetValues(values, node.path, value),
|
|
655
|
+
source
|
|
656
|
+
)
|
|
657
|
+
return selector(nextBuilder)
|
|
619
658
|
}
|
|
620
659
|
if (selector === undefined) {
|
|
621
660
|
throw new Error(`Machine expected target "${node.path}" builder to provide an active child state`)
|
|
@@ -626,25 +665,14 @@ const makeBranchTargetNodeBuilder = (
|
|
|
626
665
|
states,
|
|
627
666
|
stateNodes,
|
|
628
667
|
node.path,
|
|
629
|
-
extendTargetValues(values, node.path, value),
|
|
668
|
+
node.schema === undefined ? values : extendTargetValues(values, node.path, value),
|
|
630
669
|
source
|
|
631
670
|
)
|
|
632
671
|
return selector(nextBuilder)
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const nextBuilder: Record<string, unknown> = {}
|
|
638
|
-
addBranchTargetChildren(
|
|
639
|
-
nextBuilder,
|
|
640
|
-
states,
|
|
641
|
-
stateNodes,
|
|
642
|
-
node.path,
|
|
643
|
-
extendTargetValues(values, node.path, value),
|
|
644
|
-
source
|
|
645
|
-
)
|
|
646
|
-
return selector(nextBuilder)
|
|
647
|
-
}, "nested") as unknown as Record<string, unknown>
|
|
672
|
+
},
|
|
673
|
+
"nested",
|
|
674
|
+
node.schema !== undefined
|
|
675
|
+
) as unknown as Record<string, unknown>
|
|
648
676
|
if (node.type !== "parallel" || source === node.path || source.startsWith(`${node.path}.`)) {
|
|
649
677
|
addBranchTargetChildren(builder, states, stateNodes, node.path, values, source)
|
|
650
678
|
}
|