@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
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
} from "./configuration.js"
|
|
41
41
|
import { InfiniteTransitionError, MachineSchemaDecodeError, StartupError, StoppedError } from "./errors.js"
|
|
42
42
|
import { getStateInitializeValues, makeStateInitializeBuilder } from "./initialization.js"
|
|
43
|
+
import * as InvocationDefinition from "./invocationDefinition.js"
|
|
43
44
|
import * as InvocationEvent from "./invocationEvent.js"
|
|
44
45
|
import { decodeEventSync, decodeInputSync, decodeStateValueSync } from "./protocol.js"
|
|
45
46
|
import { InitialEventTypeId } from "./symbols.js"
|
|
@@ -56,9 +57,15 @@ import {
|
|
|
56
57
|
isStateUpdate,
|
|
57
58
|
isTarget,
|
|
58
59
|
makeChoiceTarget,
|
|
60
|
+
makeStateInput,
|
|
59
61
|
makeTarget,
|
|
60
62
|
TargetSnapshotTypeId
|
|
61
63
|
} from "./topology.js"
|
|
64
|
+
import type {
|
|
65
|
+
EventTransition,
|
|
66
|
+
TransitionEvaluator,
|
|
67
|
+
TransitionHandler as CapturedTransitionHandler
|
|
68
|
+
} from "./transition.js"
|
|
62
69
|
|
|
63
70
|
export type MicrostepPlan<State, Event, E, R> = {
|
|
64
71
|
readonly next: State
|
|
@@ -104,21 +111,12 @@ export type MacrostepPlan<State, Event, E, R, Output> =
|
|
|
104
111
|
}
|
|
105
112
|
)
|
|
106
113
|
|
|
107
|
-
export type TransitionHandler<States extends Machine.StateSchemas, E, R, Context> =
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
readonly result: Machine.HandlerResult<States, E, R> | Machine.Declined
|
|
114
|
-
readonly branchIndex: number
|
|
115
|
-
readonly branchKey: string | undefined
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
type TransitionEvaluator<States extends Machine.StateSchemas, E, R, Context> = (
|
|
119
|
-
context: Context,
|
|
120
|
-
enqueue: Enqueue<any, any>
|
|
121
|
-
) => TransitionEvaluation<States, E, R>
|
|
114
|
+
export type TransitionHandler<States extends Machine.StateSchemas, E, R, Context> = CapturedTransitionHandler<
|
|
115
|
+
States,
|
|
116
|
+
E,
|
|
117
|
+
R,
|
|
118
|
+
Context
|
|
119
|
+
>
|
|
122
120
|
|
|
123
121
|
type PlanningMachineReferences = {
|
|
124
122
|
readonly self: MachineTarget<any>
|
|
@@ -170,16 +168,6 @@ const resolveMachineReferences = (
|
|
|
170
168
|
return root
|
|
171
169
|
}
|
|
172
170
|
|
|
173
|
-
type EventTransition<States extends Machine.StateSchemas, E, R, Context> =
|
|
174
|
-
| TransitionHandler<States, E, R, Context>
|
|
175
|
-
| {
|
|
176
|
-
readonly reenter?: boolean
|
|
177
|
-
readonly declinable?: boolean
|
|
178
|
-
readonly targets?: ReadonlyArray<string>
|
|
179
|
-
readonly transition: TransitionHandler<States, E, R, Context>
|
|
180
|
-
readonly evaluate?: TransitionEvaluator<States, E, R, Context>
|
|
181
|
-
}
|
|
182
|
-
|
|
183
171
|
export type MicrostepTransition<States extends Machine.StateSchemas, E, R, Context> = {
|
|
184
172
|
readonly reenter: boolean
|
|
185
173
|
readonly declinable: boolean
|
|
@@ -344,7 +332,9 @@ const completeHistoryConfiguration = (
|
|
|
344
332
|
if (child.schema !== undefined) {
|
|
345
333
|
const initializer = machine.handlers[path]?.initialize
|
|
346
334
|
if (initializer === undefined) {
|
|
347
|
-
|
|
335
|
+
values.set(child.path, decodeStateValueSync(machine, child, makeStateInput({})))
|
|
336
|
+
changed = true
|
|
337
|
+
continue
|
|
348
338
|
}
|
|
349
339
|
const initialized = collectStateInitializer(machine, initializer, {
|
|
350
340
|
...resolveMachineReferences(machine, current),
|
|
@@ -374,9 +364,6 @@ const completeHistoryConfiguration = (
|
|
|
374
364
|
machineReferences: configuration.machineReferences
|
|
375
365
|
} as ActiveConfiguration
|
|
376
366
|
const initializer = valuedMissing.length === 0 ? undefined : machine.handlers[path]?.initialize
|
|
377
|
-
if (valuedMissing.length > 0 && initializer === undefined) {
|
|
378
|
-
throw new Error(`Machine shallow history requires an initial value implementation for state "${path}"`)
|
|
379
|
-
}
|
|
380
367
|
const initialized = initializer === undefined ? undefined : collectStateInitializer(machine, initializer, {
|
|
381
368
|
...resolveMachineReferences(machine, current),
|
|
382
369
|
state: current.values.get(path),
|
|
@@ -392,8 +379,11 @@ const completeHistoryConfiguration = (
|
|
|
392
379
|
const child = getNode(machine, childPath)
|
|
393
380
|
active.add(child.path)
|
|
394
381
|
if (child.schema !== undefined) {
|
|
382
|
+
if (initialized === undefined) {
|
|
383
|
+
values.set(child.path, decodeStateValueSync(machine, child, makeStateInput({})))
|
|
384
|
+
continue
|
|
385
|
+
}
|
|
395
386
|
if (
|
|
396
|
-
initialized === undefined ||
|
|
397
387
|
initializedValues === undefined || !Object.prototype.hasOwnProperty.call(initializedValues, child.key)
|
|
398
388
|
) {
|
|
399
389
|
throw new Error(`Machine parallel state initializer for "${path}" must return region "${child.key}"`)
|
|
@@ -468,6 +458,7 @@ function resolveHistoryTarget(
|
|
|
468
458
|
const completed = completeHistoryConfiguration(machine, restored, event)
|
|
469
459
|
const snapshot = snapshotFromConfigurationAtPath(machine, completed.configuration, target.parent)
|
|
470
460
|
const values = Object.fromEntries(completed.configuration.values)
|
|
461
|
+
if (target.parent !== "" && configuration.active.has("")) delete values[""]
|
|
471
462
|
return {
|
|
472
463
|
target: makeTarget(target.parent as any, snapshot.value as any, {
|
|
473
464
|
snapshot: snapshot as any,
|
|
@@ -487,7 +478,7 @@ function resolveHistoryTarget(
|
|
|
487
478
|
}
|
|
488
479
|
const collected = collectTransition(machine, fallback, {
|
|
489
480
|
event,
|
|
490
|
-
target: getTargetBuilder(machine, target.parent).full,
|
|
481
|
+
target: getTargetBuilder(machine, target.parent).full[""],
|
|
491
482
|
owner: target.parent
|
|
492
483
|
})
|
|
493
484
|
if (collected.state === undefined || isHistoryTarget(collected.state) || !isSnapshot(collected.state)) {
|
|
@@ -531,6 +522,7 @@ function resolveHistoryTarget(
|
|
|
531
522
|
}
|
|
532
523
|
const snapshot = snapshotFromConfigurationAtPath(machine, fallbackConfiguration, target.parent)
|
|
533
524
|
const values = Object.fromEntries(fallbackConfiguration.values)
|
|
525
|
+
if (target.parent !== "" && configuration.active.has("")) delete values[""]
|
|
534
526
|
return {
|
|
535
527
|
target: makeTarget(target.parent as any, snapshot.value as any, {
|
|
536
528
|
snapshot: snapshot as any,
|
|
@@ -765,7 +757,7 @@ const collectStateActions = <
|
|
|
765
757
|
) => {
|
|
766
758
|
const commands: Array<RuntimeCommand> = []
|
|
767
759
|
const raisedEvents: Array<Machine.EventOf<Events>> = []
|
|
768
|
-
const emittedEvents: Array<Machine.
|
|
760
|
+
const emittedEvents: Array<Machine.EmittedEventOf<Emits>> = []
|
|
769
761
|
for (const path of paths) {
|
|
770
762
|
const collected = collectStateAction<
|
|
771
763
|
Machine.StateActionContext<States, Events, Emits, Machine.StateIdentifier<States>>,
|
|
@@ -784,7 +776,7 @@ const collectStateActions = <
|
|
|
784
776
|
)
|
|
785
777
|
commands.push(...collected.commands)
|
|
786
778
|
raisedEvents.push(...collected.raisedEvents)
|
|
787
|
-
emittedEvents.push(...collected.emittedEvents as ReadonlyArray<Machine.
|
|
779
|
+
emittedEvents.push(...collected.emittedEvents as ReadonlyArray<Machine.EmittedEventOf<Emits>>)
|
|
788
780
|
}
|
|
789
781
|
return { commands, emittedEvents, raisedEvents }
|
|
790
782
|
}
|
|
@@ -1024,7 +1016,7 @@ const selectInvocationTransition = <
|
|
|
1024
1016
|
): ReadonlyArray<SelectedTransition<States, E, R, any>> => {
|
|
1025
1017
|
if (!configuration.active.has(event.path)) return []
|
|
1026
1018
|
const config = machine.handlers[event.path] as Machine.AnyStateConfig | undefined
|
|
1027
|
-
const invoke =
|
|
1019
|
+
const invoke = InvocationDefinition.definitions(config?.invoke).find((definition) => {
|
|
1028
1020
|
const id = "child" in definition ? definition.child?.id : definition.id
|
|
1029
1021
|
return String(id) === event.id
|
|
1030
1022
|
})
|
|
@@ -1096,7 +1088,7 @@ export const validateDeclaredTransitionTarget = (
|
|
|
1096
1088
|
const actual = typeof target === "object" && target !== null && "path" in target
|
|
1097
1089
|
? String(target.path)
|
|
1098
1090
|
: "<unknown>"
|
|
1099
|
-
if (!declaredTargets.some((path) => actual === path || actual.startsWith(`${path}.`))) {
|
|
1091
|
+
if (!declaredTargets.some((path) => actual === path || (path === "" || actual.startsWith(`${path}.`)))) {
|
|
1100
1092
|
const triggerLabel = trigger.type === "event" ? String(trigger.event) : trigger.type
|
|
1101
1093
|
throw new Error(
|
|
1102
1094
|
`Machine transition from "${sourcePath}" on "${triggerLabel}" returned target "${actual}" outside declared targets: ${
|
|
@@ -1277,15 +1269,19 @@ function resolveChoiceTarget(
|
|
|
1277
1269
|
if (choice === undefined || typeof choice.transition !== "function") {
|
|
1278
1270
|
throw new Error(`Machine choice state "${node.path}" requires an implementation`)
|
|
1279
1271
|
}
|
|
1272
|
+
const provisionalValues = new Map(configuration.values)
|
|
1273
|
+
for (const [path, value] of Object.entries(extracted.values)) {
|
|
1274
|
+
const valueNode = getNode(machine, path)
|
|
1275
|
+
if (valueNode.schema !== undefined) {
|
|
1276
|
+
provisionalValues.set(path, decodeStateValueSync(machine, valueNode, value))
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1280
1279
|
const provisional: ActiveConfiguration = {
|
|
1281
1280
|
active: new Set([
|
|
1282
1281
|
...configuration.active,
|
|
1283
1282
|
...Object.keys(extracted.values)
|
|
1284
1283
|
]),
|
|
1285
|
-
values:
|
|
1286
|
-
...configuration.values,
|
|
1287
|
-
...Object.entries(extracted.values)
|
|
1288
|
-
]),
|
|
1284
|
+
values: provisionalValues,
|
|
1289
1285
|
outputs: configuration.outputs,
|
|
1290
1286
|
history: configuration.history,
|
|
1291
1287
|
...(configuration.machineReferences === undefined ? {} : { machineReferences: configuration.machineReferences })
|
|
@@ -1382,10 +1378,9 @@ const collectEvaluatedTransition = <
|
|
|
1382
1378
|
? (() => {
|
|
1383
1379
|
const node = getNode(machine, stateUpdate.path)
|
|
1384
1380
|
if (
|
|
1385
|
-
!state.active.has(node.path) || node.schema === undefined
|
|
1386
|
-
(node.type !== "compound" && node.type !== "parallel")
|
|
1381
|
+
!state.active.has(node.path) || node.schema === undefined
|
|
1387
1382
|
) {
|
|
1388
|
-
throw new Error(`Machine state update owner "${node.path}" must be an active valued
|
|
1383
|
+
throw new Error(`Machine state update owner "${node.path}" must be an active valued state`)
|
|
1389
1384
|
}
|
|
1390
1385
|
return {
|
|
1391
1386
|
path: node.path,
|
|
@@ -1703,13 +1698,17 @@ export const planInitialSync = <
|
|
|
1703
1698
|
: args.length === 0
|
|
1704
1699
|
? (decodeInputSync(machine, machine.input, undefined), args)
|
|
1705
1700
|
: [decodeInputSync(machine, machine.input, args[0])] as [...Machine.InputArgs<Input>]
|
|
1706
|
-
const
|
|
1701
|
+
const initial = machine.initial(...inputArgs)
|
|
1707
1702
|
const emptyConfiguration: ActiveConfiguration = {
|
|
1708
1703
|
active: new Set(),
|
|
1709
1704
|
values: new Map(),
|
|
1710
1705
|
outputs: new Map(),
|
|
1711
1706
|
history: new Map()
|
|
1712
1707
|
}
|
|
1708
|
+
const rootResolution = isInitialTarget(initial)
|
|
1709
|
+
? resolveInitialTarget(machine, emptyConfiguration, initial, InitialEvent)
|
|
1710
|
+
: undefined
|
|
1711
|
+
const state = rootResolution?.target ?? initial
|
|
1713
1712
|
const initialChoice = choiceFromTarget(state)
|
|
1714
1713
|
const choiceResolution = initialChoice === undefined
|
|
1715
1714
|
? undefined
|
|
@@ -1725,9 +1724,11 @@ export const planInitialSync = <
|
|
|
1725
1724
|
const initialHistoryChoiceTransitions: Array<ResolvedChoiceTransition> = []
|
|
1726
1725
|
const resolvedInitialTargets: Array<unknown> = []
|
|
1727
1726
|
for (
|
|
1728
|
-
const target of choiceResolution
|
|
1727
|
+
const target of choiceResolution !== undefined
|
|
1728
|
+
? [choiceResolution.target, ...choiceResolution.additionalTargets]
|
|
1729
|
+
: rootResolution === undefined
|
|
1729
1730
|
? []
|
|
1730
|
-
: [
|
|
1731
|
+
: [rootResolution.target]
|
|
1731
1732
|
) {
|
|
1732
1733
|
if (!isHistoryTarget(target)) {
|
|
1733
1734
|
resolvedInitialTargets.push(target)
|
|
@@ -1740,7 +1741,7 @@ export const planInitialSync = <
|
|
|
1740
1741
|
initialHistoryEmittedEvents.push(...history.emittedEvents)
|
|
1741
1742
|
initialHistoryChoiceTransitions.push(...history.transitions)
|
|
1742
1743
|
}
|
|
1743
|
-
let resolvedConfiguration =
|
|
1744
|
+
let resolvedConfiguration = resolvedInitialTargets.length === 0
|
|
1744
1745
|
? normalizeConfigurationSync<States>(machine, state as Machine.Snapshot<States>)
|
|
1745
1746
|
: normalizeTargetConfigurationSync<States>(
|
|
1746
1747
|
machine,
|
|
@@ -1757,18 +1758,21 @@ export const planInitialSync = <
|
|
|
1757
1758
|
)
|
|
1758
1759
|
}
|
|
1759
1760
|
const configuration: ActiveConfiguration = resolvedConfiguration
|
|
1760
|
-
validateInitialConfiguration(machine, configuration)
|
|
1761
|
+
if (machine.initialDefinition.selection.kind === "initial") validateInitialConfiguration(machine, configuration)
|
|
1761
1762
|
const startingState = snapshotFromConfiguration<States>(machine, configuration)
|
|
1762
1763
|
const initialEntryPaths = getInitialEntryPaths(machine, configuration)
|
|
1763
1764
|
const commands = [
|
|
1765
|
+
...(rootResolution?.commands ?? []),
|
|
1764
1766
|
...(choiceResolution?.commands ?? []),
|
|
1765
1767
|
...initialHistoryActions
|
|
1766
1768
|
]
|
|
1767
1769
|
const raisedEvents = [
|
|
1770
|
+
...(rootResolution?.raisedEvents ?? []),
|
|
1768
1771
|
...(choiceResolution?.raisedEvents ?? []),
|
|
1769
1772
|
...initialHistoryRaisedEvents
|
|
1770
1773
|
]
|
|
1771
1774
|
const emittedEvents = [
|
|
1775
|
+
...(rootResolution?.emittedEvents ?? []),
|
|
1772
1776
|
...(choiceResolution?.emittedEvents ?? []),
|
|
1773
1777
|
...initialHistoryEmittedEvents
|
|
1774
1778
|
]
|
|
@@ -1786,21 +1790,27 @@ export const planInitialSync = <
|
|
|
1786
1790
|
[...entry.commands],
|
|
1787
1791
|
[...raisedEvents, ...entry.raisedEvents] as Array<Machine.EventOf<Events>>,
|
|
1788
1792
|
[...emittedEvents, ...entry.emittedEvents],
|
|
1789
|
-
choiceResolution === undefined
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1793
|
+
choiceResolution === undefined && (rootResolution?.transitions.length ?? 0) === 0 &&
|
|
1794
|
+
initialHistoryChoiceTransitions.length === 0 ?
|
|
1795
|
+
[] :
|
|
1796
|
+
[{
|
|
1797
|
+
next: configuration,
|
|
1798
|
+
event: InitialEvent,
|
|
1799
|
+
transitions: [
|
|
1800
|
+
...(rootResolution?.transitions ?? []),
|
|
1801
|
+
...(choiceResolution?.transitions ?? []),
|
|
1802
|
+
...initialHistoryChoiceTransitions
|
|
1803
|
+
],
|
|
1804
|
+
commands,
|
|
1805
|
+
raisedEvents: [
|
|
1806
|
+
...raisedEvents
|
|
1807
|
+
] as ReadonlyArray<Machine.EventOf<Events>>,
|
|
1808
|
+
emittedEvents,
|
|
1809
|
+
exitPaths: [],
|
|
1810
|
+
entryPaths: [],
|
|
1811
|
+
changed: false,
|
|
1812
|
+
stabilize: false
|
|
1813
|
+
}]
|
|
1804
1814
|
)
|
|
1805
1815
|
|
|
1806
1816
|
const planned = {
|
|
@@ -1811,7 +1821,7 @@ export const planInitialSync = <
|
|
|
1811
1821
|
...commands,
|
|
1812
1822
|
...settled.commands
|
|
1813
1823
|
],
|
|
1814
|
-
emittedEvents: settled.emittedEvents as ReadonlyArray<Machine.
|
|
1824
|
+
emittedEvents: settled.emittedEvents as ReadonlyArray<Machine.EmittedEventOf<Emits>>,
|
|
1815
1825
|
microsteps: settled.microsteps.map((step) => ({
|
|
1816
1826
|
next: snapshotFromConfiguration<States>(machine, step.next),
|
|
1817
1827
|
event: step.event,
|
|
@@ -2204,6 +2214,7 @@ const macrostepConfiguration = <
|
|
|
2204
2214
|
throw new Error("Machine reached a terminal configuration without a completed root output")
|
|
2205
2215
|
}
|
|
2206
2216
|
return {
|
|
2217
|
+
event: decodedEvent,
|
|
2207
2218
|
next: completed.configuration,
|
|
2208
2219
|
commands: [],
|
|
2209
2220
|
emittedEvents: [],
|
|
@@ -2222,6 +2233,7 @@ const macrostepConfiguration = <
|
|
|
2222
2233
|
)
|
|
2223
2234
|
if (selections.length === 0) {
|
|
2224
2235
|
return {
|
|
2236
|
+
event: decodedEvent,
|
|
2225
2237
|
next: configuration,
|
|
2226
2238
|
commands: [],
|
|
2227
2239
|
emittedEvents: [],
|
|
@@ -2240,7 +2252,10 @@ const macrostepConfiguration = <
|
|
|
2240
2252
|
const raisedEvents = [...step.raisedEvents]
|
|
2241
2253
|
const emittedEvents = [...step.emittedEvents]
|
|
2242
2254
|
const microsteps = [step]
|
|
2243
|
-
return
|
|
2255
|
+
return {
|
|
2256
|
+
...settle(machine, step.next, decodedEvent as any, commands, raisedEvents, emittedEvents, microsteps),
|
|
2257
|
+
event: decodedEvent
|
|
2258
|
+
}
|
|
2244
2259
|
}
|
|
2245
2260
|
|
|
2246
2261
|
const snapshotMacrostep = <
|
|
@@ -2251,9 +2266,10 @@ const snapshotMacrostep = <
|
|
|
2251
2266
|
Output
|
|
2252
2267
|
>(
|
|
2253
2268
|
machine: Machine.Any,
|
|
2254
|
-
settled: MacrostepPlan<ActiveConfiguration, Event, E, R, Output>
|
|
2255
|
-
): MacrostepPlan<Machine.Snapshot<States>, Event, E, R, Output> => {
|
|
2269
|
+
settled: MacrostepPlan<ActiveConfiguration, Event, E, R, Output> & { readonly event: unknown }
|
|
2270
|
+
): MacrostepPlan<Machine.Snapshot<States>, Event, E, R, Output> & { readonly event: unknown } => {
|
|
2256
2271
|
const planned = {
|
|
2272
|
+
event: settled.event,
|
|
2257
2273
|
next: snapshotFromConfiguration<States>(machine, settled.next),
|
|
2258
2274
|
commands: settled.commands,
|
|
2259
2275
|
emittedEvents: settled.emittedEvents,
|
|
@@ -16,19 +16,10 @@ import type { StoppedError } from "./errors.js"
|
|
|
16
16
|
import * as ExecutionPlan from "./executionPlan.js"
|
|
17
17
|
import * as Invocation from "./invocation.js"
|
|
18
18
|
import * as internalPlanner from "./planner.js"
|
|
19
|
+
import type { ExcludeCompatibleRuntime } from "./requirements.js"
|
|
19
20
|
import * as internalRuntime from "./runtime.js"
|
|
20
21
|
import * as Serialization from "./serialization.js"
|
|
21
22
|
|
|
22
|
-
type IsAny<A> = 0 extends (1 & A) ? true : false
|
|
23
|
-
|
|
24
|
-
type ExcludeCompatibleRuntime<Requirements, Events, Emits> = Requirements extends Runtime.Requirement<
|
|
25
|
-
infer RequiredEvents,
|
|
26
|
-
infer RequiredEmits
|
|
27
|
-
> ? IsAny<Requirements> extends true ? Requirements
|
|
28
|
-
: [RequiredEvents] extends [Events] ? [RequiredEmits] extends [Emits] ? never : Requirements
|
|
29
|
-
: Requirements
|
|
30
|
-
: Requirements
|
|
31
|
-
|
|
32
23
|
type ProcessEntry<States extends Machine.StateSchemas, Input extends Schema.Top> =
|
|
33
24
|
| {
|
|
34
25
|
readonly _tag: "Initial"
|
|
@@ -50,6 +41,7 @@ const runSequentialDiscard = <E, R>(
|
|
|
50
41
|
|
|
51
42
|
const acknowledgedPlan = (
|
|
52
43
|
planned: {
|
|
44
|
+
readonly event: unknown
|
|
53
45
|
readonly next: unknown
|
|
54
46
|
readonly commands: ReadonlyArray<unknown>
|
|
55
47
|
readonly emittedEvents: ReadonlyArray<unknown>
|
|
@@ -69,6 +61,7 @@ const acknowledgedPlan = (
|
|
|
69
61
|
},
|
|
70
62
|
snapshot: (state: unknown) => unknown
|
|
71
63
|
): unknown => ({
|
|
64
|
+
event: planned.event,
|
|
72
65
|
next: snapshot(planned.next),
|
|
73
66
|
commands: planned.commands,
|
|
74
67
|
emittedEvents: planned.emittedEvents,
|
|
@@ -397,7 +390,7 @@ const makeProcessLogic: <
|
|
|
397
390
|
ExcludeCompatibleRuntime<
|
|
398
391
|
Exclude<ExecutionServices<InitialR | R>, internalRuntime.MachineRuntime>,
|
|
399
392
|
Machine.EventOf<Events>,
|
|
400
|
-
Machine.
|
|
393
|
+
Machine.EmittedEventOf<Emits>
|
|
401
394
|
>,
|
|
402
395
|
Output,
|
|
403
396
|
| InitialE
|
|
@@ -469,7 +462,7 @@ const makeProcessLogic: <
|
|
|
469
462
|
? undefined
|
|
470
463
|
: CommandRuntime.runEmittedEvents(
|
|
471
464
|
planned.emittedEvents,
|
|
472
|
-
CommandRuntime.makeLiveRuntime<Machine.EventOf<Events>, Machine.
|
|
465
|
+
CommandRuntime.makeLiveRuntime<Machine.EventOf<Events>, Machine.EmittedEventOf<Emits>>(machine, scope)
|
|
473
466
|
)
|
|
474
467
|
const result = Effect.succeed({
|
|
475
468
|
state: planned.state,
|
|
@@ -531,7 +524,7 @@ const makeProcessLogic: <
|
|
|
531
524
|
// so the Effect scheduler remains responsible for cooperative yield.
|
|
532
525
|
let configuration: Configuration.ActiveConfiguration | undefined
|
|
533
526
|
let pendingMessage: Option.Option<internalRuntime.ProcessMessage<Machine.EventOf<Events>>> = Option.none()
|
|
534
|
-
let liveRuntime: Runtime<Machine.EventOf<Events>, Machine.
|
|
527
|
+
let liveRuntime: Runtime<Machine.EventOf<Events>, Machine.EmittedEventOf<Emits>> | undefined
|
|
535
528
|
while (terminal === undefined) {
|
|
536
529
|
const message = Option.isSome(pendingMessage) ? pendingMessage.value : yield* receiveMessage
|
|
537
530
|
pendingMessage = Option.none()
|
|
@@ -563,7 +556,7 @@ const makeProcessLogic: <
|
|
|
563
556
|
current = next
|
|
564
557
|
if (planned.emittedEvents.length > 0) {
|
|
565
558
|
yield* CommandRuntime.runEmittedEvents(
|
|
566
|
-
planned.emittedEvents as ReadonlyArray<Machine.
|
|
559
|
+
planned.emittedEvents as ReadonlyArray<Machine.EmittedEventOf<Emits>>,
|
|
567
560
|
liveRuntime ??= CommandRuntime.makeLiveRuntime(machine, context)
|
|
568
561
|
)
|
|
569
562
|
}
|
|
@@ -639,7 +632,7 @@ const makeProcessLogic: <
|
|
|
639
632
|
// worker can continue draining an already queued batch.
|
|
640
633
|
configuration = undefined
|
|
641
634
|
let pendingMessage: Option.Option<internalRuntime.ProcessMessage<Machine.EventOf<Events>>> = Option.none()
|
|
642
|
-
let liveRuntime: Runtime<Machine.EventOf<Events>, Machine.
|
|
635
|
+
let liveRuntime: Runtime<Machine.EventOf<Events>, Machine.EmittedEventOf<Emits>> | undefined
|
|
643
636
|
|
|
644
637
|
// Match the compact non-invoke loop while retaining state-scoped
|
|
645
638
|
// child lifecycle work at the same ordered Effect boundaries.
|
|
@@ -687,7 +680,7 @@ const makeProcessLogic: <
|
|
|
687
680
|
current = next
|
|
688
681
|
if (planned.emittedEvents.length > 0) {
|
|
689
682
|
yield* CommandRuntime.runEmittedEvents(
|
|
690
|
-
planned.emittedEvents as ReadonlyArray<Machine.
|
|
683
|
+
planned.emittedEvents as ReadonlyArray<Machine.EmittedEventOf<Emits>>,
|
|
691
684
|
liveRuntime ??= CommandRuntime.makeLiveRuntime(machine, context)
|
|
692
685
|
)
|
|
693
686
|
}
|
|
@@ -741,7 +734,7 @@ const makeProcessLogic: <
|
|
|
741
734
|
ExcludeCompatibleRuntime<
|
|
742
735
|
Exclude<ExecutionServices<InitialR | R>, internalRuntime.MachineRuntime>,
|
|
743
736
|
Machine.EventOf<Events>,
|
|
744
|
-
Machine.
|
|
737
|
+
Machine.EmittedEventOf<Emits>
|
|
745
738
|
>,
|
|
746
739
|
Output,
|
|
747
740
|
| InitialE
|
|
@@ -781,7 +774,7 @@ export const toProcessLogic: <
|
|
|
781
774
|
ExcludeCompatibleRuntime<
|
|
782
775
|
Exclude<ExecutionServices<InitialR | R>, internalRuntime.MachineRuntime>,
|
|
783
776
|
Machine.EventOf<Events>,
|
|
784
|
-
Machine.
|
|
777
|
+
Machine.EmittedEventOf<Emits>
|
|
785
778
|
>,
|
|
786
779
|
Output,
|
|
787
780
|
| InitialE
|
|
@@ -887,7 +880,7 @@ export const start: <
|
|
|
887
880
|
ExcludeCompatibleRuntime<
|
|
888
881
|
Exclude<ExecutionServices<InitialR | R>, internalRuntime.MachineRuntime>,
|
|
889
882
|
Machine.EventOf<Events>,
|
|
890
|
-
Machine.
|
|
883
|
+
Machine.EmittedEventOf<Emits>
|
|
891
884
|
>
|
|
892
885
|
> = (machine, ...args) =>
|
|
893
886
|
internalRuntime.startProcess(
|
|
@@ -931,7 +924,7 @@ export const prepare: <
|
|
|
931
924
|
ExcludeCompatibleRuntime<
|
|
932
925
|
Exclude<ExecutionServices<InitialR | R>, internalRuntime.MachineRuntime>,
|
|
933
926
|
Machine.EventOf<Events>,
|
|
934
|
-
Machine.
|
|
927
|
+
Machine.EmittedEventOf<Emits>
|
|
935
928
|
>
|
|
936
929
|
>
|
|
937
930
|
> = (machine, ...args) =>
|
|
@@ -966,7 +959,7 @@ export const resume: <
|
|
|
966
959
|
ExcludeCompatibleRuntime<
|
|
967
960
|
Exclude<ExecutionServices<R>, internalRuntime.MachineRuntime>,
|
|
968
961
|
Machine.EventOf<Events>,
|
|
969
|
-
Machine.
|
|
962
|
+
Machine.EmittedEventOf<Emits>
|
|
970
963
|
>
|
|
971
964
|
> = (machine, snapshot) =>
|
|
972
965
|
internalRuntime.startProcess(
|
|
@@ -24,9 +24,7 @@ interface MachineProtocolSchemas {
|
|
|
24
24
|
readonly event: Schema.Top
|
|
25
25
|
readonly emit: Schema.Top
|
|
26
26
|
readonly eventConstructors: ReadonlySet<object>
|
|
27
|
-
readonly trustedEvents: WeakSet<object>
|
|
28
27
|
readonly emissionConstructors: ReadonlySet<object>
|
|
29
|
-
readonly trustedEmissions: WeakSet<object>
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
interface EventProtocolDefinition {
|
|
@@ -171,9 +169,7 @@ export const setProtocol = (machine: Machine.Any): void => {
|
|
|
171
169
|
event: Schema.Union(events),
|
|
172
170
|
emit: Schema.Union(emittedEvents),
|
|
173
171
|
eventConstructors: collectEventConstructors(events),
|
|
174
|
-
|
|
175
|
-
emissionConstructors: collectEventConstructors(emittedEvents),
|
|
176
|
-
trustedEmissions: new WeakSet()
|
|
172
|
+
emissionConstructors: collectEventConstructors(emittedEvents)
|
|
177
173
|
})
|
|
178
174
|
}
|
|
179
175
|
|
|
@@ -419,11 +415,6 @@ const decodeEventConstruction = (
|
|
|
419
415
|
})
|
|
420
416
|
)
|
|
421
417
|
)
|
|
422
|
-
),
|
|
423
|
-
Effect.tap((event) =>
|
|
424
|
-
Effect.sync(() =>
|
|
425
|
-
(boundary === "event" ? protocol.trustedEvents : protocol.trustedEmissions).add(event as object)
|
|
426
|
-
)
|
|
427
418
|
)
|
|
428
419
|
)
|
|
429
420
|
}
|
|
@@ -453,13 +444,9 @@ const decodeEventConstructionSync = (
|
|
|
453
444
|
boundary,
|
|
454
445
|
event: String(construction._tag)
|
|
455
446
|
})
|
|
456
|
-
;(boundary === "event" ? protocol.trustedEvents : protocol.trustedEmissions).add(event as object)
|
|
457
447
|
return event
|
|
458
448
|
}
|
|
459
449
|
|
|
460
|
-
const isTrustedEvent = (protocol: MachineProtocolSchemas, event: unknown): boolean =>
|
|
461
|
-
typeof event === "object" && event !== null && protocol.trustedEvents.has(event)
|
|
462
|
-
|
|
463
450
|
export const decodeInput = <Input extends Schema.Top>(
|
|
464
451
|
machine: Machine.Any,
|
|
465
452
|
schema: Input,
|
|
@@ -478,10 +465,9 @@ export const decodeEvent = <const Events extends ReadonlyArray<Machine.TaggedSch
|
|
|
478
465
|
MachineSchemaDecodeError
|
|
479
466
|
>
|
|
480
467
|
}
|
|
481
|
-
if (isTrustedEvent(protocol, event)) {
|
|
482
|
-
return Effect.succeed(event as Machine.EventOf<Events>)
|
|
483
|
-
}
|
|
484
468
|
const eventName = getEventName(event)
|
|
469
|
+
// Decoded objects can escape to user code and be mutated. Validation is local
|
|
470
|
+
// to this delivery; object identity is never evidence of continued validity.
|
|
485
471
|
return decodeBoundary<Machine.EventOf<Events>>(
|
|
486
472
|
machine,
|
|
487
473
|
protocol.event,
|
|
@@ -498,9 +484,6 @@ export const decodeEventSync = <const Events extends ReadonlyArray<Machine.Tagge
|
|
|
498
484
|
if (isEventConstruction(event)) {
|
|
499
485
|
return decodeEventConstructionSync(machine, protocol, event, "event") as Machine.EventOf<Events>
|
|
500
486
|
}
|
|
501
|
-
if (isTrustedEvent(protocol, event)) {
|
|
502
|
-
return event as Machine.EventOf<Events>
|
|
503
|
-
}
|
|
504
487
|
const eventName = getEventName(event)
|
|
505
488
|
return decodeBoundarySync<Machine.EventOf<Events>>(
|
|
506
489
|
machine,
|
|
@@ -513,19 +496,16 @@ export const decodeEventSync = <const Events extends ReadonlyArray<Machine.Tagge
|
|
|
513
496
|
export const decodeEmit = <const Emits extends ReadonlyArray<Machine.TaggedSchema>>(
|
|
514
497
|
machine: Machine.Any,
|
|
515
498
|
event: unknown
|
|
516
|
-
): Effect.Effect<Machine.
|
|
499
|
+
): Effect.Effect<Machine.EmittedEventOf<Emits>, MachineSchemaDecodeError> => {
|
|
517
500
|
const protocol = getProtocolSchemas(machine)
|
|
518
501
|
if (isEventConstruction(event)) {
|
|
519
502
|
return decodeEventConstruction(machine, protocol, event, "emission") as Effect.Effect<
|
|
520
|
-
Machine.
|
|
503
|
+
Machine.EmittedEventOf<Emits>,
|
|
521
504
|
MachineSchemaDecodeError
|
|
522
505
|
>
|
|
523
506
|
}
|
|
524
|
-
if (typeof event === "object" && event !== null && protocol.trustedEmissions.has(event)) {
|
|
525
|
-
return Effect.succeed(event as Machine.EmitOf<Emits>)
|
|
526
|
-
}
|
|
527
507
|
const eventName = getEventName(event)
|
|
528
|
-
return decodeBoundary<Machine.
|
|
508
|
+
return decodeBoundary<Machine.EmittedEventOf<Emits>>(
|
|
529
509
|
machine,
|
|
530
510
|
protocol.emit,
|
|
531
511
|
event,
|
|
@@ -536,16 +516,13 @@ export const decodeEmit = <const Emits extends ReadonlyArray<Machine.TaggedSchem
|
|
|
536
516
|
export const decodeEmitSync = <const Emits extends ReadonlyArray<Machine.TaggedSchema>>(
|
|
537
517
|
machine: Machine.Any,
|
|
538
518
|
event: unknown
|
|
539
|
-
): Machine.
|
|
519
|
+
): Machine.EmittedEventOf<Emits> => {
|
|
540
520
|
const protocol = getProtocolSchemas(machine)
|
|
541
521
|
if (isEventConstruction(event)) {
|
|
542
|
-
return decodeEventConstructionSync(machine, protocol, event, "emission") as Machine.
|
|
543
|
-
}
|
|
544
|
-
if (typeof event === "object" && event !== null && protocol.trustedEmissions.has(event)) {
|
|
545
|
-
return event as Machine.EmitOf<Emits>
|
|
522
|
+
return decodeEventConstructionSync(machine, protocol, event, "emission") as Machine.EmittedEventOf<Emits>
|
|
546
523
|
}
|
|
547
524
|
const eventName = getEventName(event)
|
|
548
|
-
return decodeBoundarySync<Machine.
|
|
525
|
+
return decodeBoundarySync<Machine.EmittedEventOf<Emits>>(
|
|
549
526
|
machine,
|
|
550
527
|
protocol.emit,
|
|
551
528
|
event,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Runtime } from "../../Machine.js"
|
|
2
|
+
|
|
3
|
+
export type IsAny<A> = 0 extends (1 & A) ? true : false
|
|
4
|
+
|
|
5
|
+
export type ExcludeCompatibleRuntime<Requirements, Events, Emits> = Requirements extends Runtime.Requirement<
|
|
6
|
+
infer RequiredEvents,
|
|
7
|
+
infer RequiredEmits
|
|
8
|
+
> ? IsAny<Requirements> extends true ? Requirements
|
|
9
|
+
: [RequiredEvents] extends [Events] ? [RequiredEmits] extends [Emits] ? never : Requirements
|
|
10
|
+
: Requirements
|
|
11
|
+
: Requirements
|