@typeonce/effect-machine 0.10.0 → 0.12.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 +76 -13
- package/dist/Machine.d.ts +202 -90
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +38 -9
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/atom.d.ts +1 -1
- package/dist/internal/machine/atom.d.ts.map +1 -1
- package/dist/internal/machine/atom.js +38 -7
- package/dist/internal/machine/atom.js.map +1 -1
- package/dist/internal/machine/cluster.js +2 -2
- package/dist/internal/machine/cluster.js.map +1 -1
- package/dist/internal/machine/commandRuntime.d.ts.map +1 -1
- package/dist/internal/machine/commandRuntime.js +2 -2
- package/dist/internal/machine/commandRuntime.js.map +1 -1
- package/dist/internal/machine/configuration.d.ts +7 -7
- package/dist/internal/machine/configuration.d.ts.map +1 -1
- package/dist/internal/machine/configuration.js +3 -3
- package/dist/internal/machine/configuration.js.map +1 -1
- package/dist/internal/machine/executionPlan.d.ts +3 -3
- package/dist/internal/machine/executionPlan.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.js +25 -25
- 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 +1 -0
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +4 -0
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/planner.d.ts +2 -2
- package/dist/internal/machine/planner.d.ts.map +1 -1
- package/dist/internal/machine/planner.js +20 -20
- package/dist/internal/machine/planner.js.map +1 -1
- package/dist/internal/machine/process.d.ts +3 -0
- package/dist/internal/machine/process.d.ts.map +1 -1
- package/dist/internal/machine/process.js +6 -3
- package/dist/internal/machine/process.js.map +1 -1
- package/dist/internal/machine/runtime.d.ts +17 -3
- package/dist/internal/machine/runtime.d.ts.map +1 -1
- package/dist/internal/machine/runtime.js +82 -32
- package/dist/internal/machine/runtime.js.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +4 -2
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.js +4 -2
- package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
- package/docs/agent-guide.md +78 -19
- package/package.json +1 -1
- package/src/Machine.ts +704 -96
- package/src/internal/machine/atom.ts +50 -52
- package/src/internal/machine/cluster.ts +2 -2
- package/src/internal/machine/commandRuntime.ts +4 -2
- package/src/internal/machine/configuration.ts +10 -10
- package/src/internal/machine/executionPlan.ts +35 -35
- package/src/internal/machine/invocation.ts +1 -1
- package/src/internal/machine/machine.ts +6 -0
- package/src/internal/machine/planner.ts +30 -24
- package/src/internal/machine/process.ts +60 -3
- package/src/internal/machine/runtime.ts +176 -47
- package/src/unstable/reactivity/AtomMachine.ts +4 -2
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
import * as Data from "effect/Data"
|
|
8
8
|
import * as Effect from "effect/Effect"
|
|
9
9
|
import * as Equal from "effect/Equal"
|
|
10
|
+
import * as Fiber from "effect/Fiber"
|
|
10
11
|
import * as Option from "effect/Option"
|
|
11
12
|
import type * as Schema from "effect/Schema"
|
|
12
13
|
import type * as Scope from "effect/Scope"
|
|
13
14
|
import * as Stream from "effect/Stream"
|
|
14
|
-
import { AsyncResult, Atom,
|
|
15
|
+
import { AsyncResult, Atom, AtomRegistry } from "effect/unstable/reactivity"
|
|
15
16
|
import type * as Machine from "../../Machine.js"
|
|
16
17
|
import type { Bound, ChildMachineAtom, MachineAtom } from "../../unstable/reactivity/AtomMachine.js"
|
|
17
18
|
import * as internalMachine from "./machine.js"
|
|
@@ -72,6 +73,11 @@ type MachineStartError<InitialE, E, InitialR, R, RuntimeError = never> =
|
|
|
72
73
|
| Machine.StoppedError
|
|
73
74
|
| RuntimeError
|
|
74
75
|
|
|
76
|
+
const preparedByMachineAtom = new WeakMap<
|
|
77
|
+
object,
|
|
78
|
+
Atom.Atom<AsyncResult.AsyncResult<Machine.Prepared<any, any, any, any, any, any, any>, any>>
|
|
79
|
+
>()
|
|
80
|
+
|
|
75
81
|
const runMachineAtomEffect = <State, Event, Error, Output, Emitted, StartError, Requirements>(
|
|
76
82
|
get: Atom.AtomContext,
|
|
77
83
|
start: Effect.Effect<Machine.MachineRef<State, Event, Error, Output, Emitted>, StartError, Requirements>
|
|
@@ -83,53 +89,16 @@ const runMachineAtomEffect = <State, Event, Error, Output, Emitted, StartError,
|
|
|
83
89
|
)
|
|
84
90
|
)
|
|
85
91
|
|
|
86
|
-
const
|
|
87
|
-
const States extends Machine.Machine.StateSchemas,
|
|
88
|
-
const Events extends ReadonlyArray<Machine.Machine.TaggedSchema>,
|
|
89
|
-
const Emits extends ReadonlyArray<Machine.Machine.TaggedSchema> = any,
|
|
90
|
-
const Input extends Schema.Top = typeof Schema.Void,
|
|
91
|
-
UnhandledStates extends Machine.Machine.StateIdentifier<States> = Machine.Machine.StateIdentifier<States>,
|
|
92
|
-
E = never,
|
|
93
|
-
R = never,
|
|
94
|
-
InitialE = never,
|
|
95
|
-
InitialR = never,
|
|
96
|
-
FinalStates extends Machine.Machine.StateIdentifier<States> = never,
|
|
97
|
-
Output = never,
|
|
98
|
-
OutputStates extends Machine.Machine.StateIdentifier<States> = never,
|
|
99
|
-
InputEvents extends ReadonlyArray<Machine.Machine.TaggedSchema> = Events,
|
|
100
|
-
ParentEvents extends ReadonlyArray<Machine.Machine.TaggedSchema> = readonly []
|
|
101
|
-
>(
|
|
92
|
+
const startPreparedMachineAtomEffect = <State, Event, Error, Output, Emitted, StartError, Requirements>(
|
|
102
93
|
get: Atom.AtomContext,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
Input,
|
|
108
|
-
UnhandledStates,
|
|
109
|
-
E,
|
|
110
|
-
R,
|
|
111
|
-
InitialE,
|
|
112
|
-
InitialR,
|
|
113
|
-
FinalStates,
|
|
114
|
-
Output,
|
|
115
|
-
Emits,
|
|
116
|
-
OutputStates,
|
|
117
|
-
InputEvents,
|
|
118
|
-
ParentEvents
|
|
94
|
+
prepared: Atom.Atom<
|
|
95
|
+
AsyncResult.AsyncResult<
|
|
96
|
+
Machine.Prepared<State, Event, Error, Output, Emitted, StartError, Requirements>,
|
|
97
|
+
never
|
|
119
98
|
>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
)
|
|
123
|
-
Machine.MachineRef<
|
|
124
|
-
Machine.Machine.Snapshot<States>,
|
|
125
|
-
Machine.Machine.EventInputOf<InputEvents>,
|
|
126
|
-
MachineRuntimeError<E, R>,
|
|
127
|
-
Output,
|
|
128
|
-
Machine.Machine.EmittedEventOf<Emits>
|
|
129
|
-
>,
|
|
130
|
-
MachineStartError<InitialE, E, InitialR, R>,
|
|
131
|
-
MachineRequirements<InitialR, R, Machine.Machine.EventOf<Events>, Machine.Machine.EmitOf<Emits>>
|
|
132
|
-
> => runMachineAtomEffect(get, internalMachine.start(machine as any, ...args) as any)
|
|
99
|
+
>
|
|
100
|
+
): Effect.Effect<never, StartError, Requirements> =>
|
|
101
|
+
runMachineAtomEffect(get, get.result(prepared).pipe(Effect.flatMap((prepared) => prepared.start)))
|
|
133
102
|
|
|
134
103
|
const resumeMachineAtomEffect = (
|
|
135
104
|
get: Atom.AtomContext,
|
|
@@ -144,8 +113,31 @@ type RefEmitted<Ref> = Ref extends Machine.MachineRef<any, any, any, any, infer
|
|
|
144
113
|
|
|
145
114
|
export const emissions = <State, Event, Error, Output, StartError, Emitted>(
|
|
146
115
|
self: MachineAtom<State, Event, Error, Output, StartError, Emitted>
|
|
147
|
-
): Stream.Stream<Emitted, StartError, AtomRegistry.AtomRegistry> =>
|
|
148
|
-
|
|
116
|
+
): Stream.Stream<Emitted, StartError, AtomRegistry.AtomRegistry> => {
|
|
117
|
+
const prepared = preparedByMachineAtom.get(self as object)
|
|
118
|
+
if (prepared === undefined) {
|
|
119
|
+
return Atom.toStreamResult(self.ref).pipe(Stream.flatMap((ref) => ref.emissions))
|
|
120
|
+
}
|
|
121
|
+
return Stream.unwrap(
|
|
122
|
+
Effect.gen(function*() {
|
|
123
|
+
const registry = yield* AtomRegistry.AtomRegistry
|
|
124
|
+
const releasePrepared = yield* Effect.sync(() => registry.mount(prepared))
|
|
125
|
+
yield* Effect.addFinalizer(() => Effect.sync(releasePrepared))
|
|
126
|
+
const machine = yield* Atom.getResult(prepared)
|
|
127
|
+
const pull = yield* Stream.toPull(machine.emissions as Stream.Stream<Emitted>)
|
|
128
|
+
const firstPull = yield* pull.pipe(Effect.forkScoped({ startImmediately: true }))
|
|
129
|
+
const releaseRef = yield* Effect.sync(() => registry.mount(self.ref))
|
|
130
|
+
yield* Effect.addFinalizer(() => Effect.sync(releaseRef))
|
|
131
|
+
yield* Atom.getResult(self.ref)
|
|
132
|
+
let first = true
|
|
133
|
+
return Stream.fromPull(Effect.succeed(Effect.suspend(() => {
|
|
134
|
+
if (!first) return pull
|
|
135
|
+
first = false
|
|
136
|
+
return Fiber.join(firstPull)
|
|
137
|
+
})))
|
|
138
|
+
})
|
|
139
|
+
)
|
|
140
|
+
}
|
|
149
141
|
|
|
150
142
|
export const childEmissions = <Child extends Machine.ChildMachine.Any, StartError>(
|
|
151
143
|
self: ChildMachineAtom<Child, StartError>
|
|
@@ -666,8 +658,11 @@ export const make: {
|
|
|
666
658
|
Machine.Machine.EmittedEventOf<Emits>
|
|
667
659
|
>
|
|
668
660
|
} = ((machine: Machine.Machine.Any, ...args: ReadonlyArray<unknown>) => {
|
|
669
|
-
const
|
|
670
|
-
|
|
661
|
+
const prepared = Atom.make(() => internalMachine.prepare(machine as any, ...(args as [])))
|
|
662
|
+
const ref = Atom.make((get) => startPreparedMachineAtomEffect(get, prepared as any))
|
|
663
|
+
const result = makeFromRefAtom(ref as any)
|
|
664
|
+
preparedByMachineAtom.set(result, prepared as any)
|
|
665
|
+
return result
|
|
671
666
|
}) as any
|
|
672
667
|
|
|
673
668
|
export const resume: {
|
|
@@ -688,8 +683,11 @@ const makeWithRuntime = (
|
|
|
688
683
|
machine: Machine.Machine.Any,
|
|
689
684
|
args: ReadonlyArray<unknown>
|
|
690
685
|
): MachineAtom<any, any, any, any, any> => {
|
|
691
|
-
const
|
|
692
|
-
|
|
686
|
+
const prepared = runtime.atom(() => internalMachine.prepare(machine as any, ...(args as [])))
|
|
687
|
+
const ref = runtime.atom((get) => startPreparedMachineAtomEffect(get, prepared as any))
|
|
688
|
+
const result = makeFromRefAtom(ref as any)
|
|
689
|
+
preparedByMachineAtom.set(result, prepared as any)
|
|
690
|
+
return result
|
|
693
691
|
}
|
|
694
692
|
|
|
695
693
|
const resumeWithRuntime = (
|
|
@@ -317,7 +317,7 @@ export const make = <
|
|
|
317
317
|
if (initial.commands.length > 0) {
|
|
318
318
|
return yield* fail(
|
|
319
319
|
"UnsupportedProcessLocal",
|
|
320
|
-
"Machine
|
|
320
|
+
"Machine commands require a managed local process"
|
|
321
321
|
)
|
|
322
322
|
}
|
|
323
323
|
current = initial.state
|
|
@@ -329,7 +329,7 @@ export const make = <
|
|
|
329
329
|
if (planned.commands.length > 0) {
|
|
330
330
|
return yield* fail(
|
|
331
331
|
"UnsupportedProcessLocal",
|
|
332
|
-
"Machine
|
|
332
|
+
"Machine commands require a managed local process"
|
|
333
333
|
)
|
|
334
334
|
}
|
|
335
335
|
current = planned.next
|
|
@@ -10,7 +10,9 @@ import type { RuntimeCommand } from "./command.js"
|
|
|
10
10
|
import { decodeEmit, decodeEvent } from "./protocol.js"
|
|
11
11
|
import type { ProcessScope } from "./runtime.js"
|
|
12
12
|
|
|
13
|
-
const
|
|
13
|
+
const isMachineTarget = (
|
|
14
|
+
target: unknown
|
|
15
|
+
): target is { readonly send: (event: unknown) => Effect.Effect<void, unknown> } =>
|
|
14
16
|
typeof target === "object" && target !== null && "send" in target && typeof target.send === "function"
|
|
15
17
|
|
|
16
18
|
export const makeLiveRuntime = <Events, Emits>(
|
|
@@ -33,7 +35,7 @@ export const runCommands = <Event>(
|
|
|
33
35
|
) =>
|
|
34
36
|
Effect.forEach(commands, (command) =>
|
|
35
37
|
command._tag === "SendTo"
|
|
36
|
-
?
|
|
38
|
+
? isMachineTarget(command.target)
|
|
37
39
|
? command.target.send(command.event)
|
|
38
40
|
: scope.sendTo(command.target as never, command.event)
|
|
39
41
|
: scope.stopChild(command.child as never), { discard: true })
|
|
@@ -8,7 +8,7 @@ import * as Cause from "effect/Cause"
|
|
|
8
8
|
import * as Effect from "effect/Effect"
|
|
9
9
|
import * as Option from "effect/Option"
|
|
10
10
|
import { hasProperty } from "effect/Predicate"
|
|
11
|
-
import type {
|
|
11
|
+
import type { Machine, MachineTarget } from "../../Machine.js"
|
|
12
12
|
import { MachineSchemaDecodeError } from "./errors.js"
|
|
13
13
|
import {
|
|
14
14
|
decodeBoundary,
|
|
@@ -252,25 +252,25 @@ export interface ActiveConfiguration {
|
|
|
252
252
|
readonly values: ReadonlyMap<string, unknown>
|
|
253
253
|
readonly outputs: ReadonlyMap<string, unknown>
|
|
254
254
|
readonly history: ReadonlyMap<string, HistoryRecord>
|
|
255
|
-
readonly
|
|
255
|
+
readonly machineReferences?: PlanningMachineReferences
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
export interface
|
|
259
|
-
readonly self:
|
|
260
|
-
readonly parent:
|
|
258
|
+
export interface PlanningMachineReferences {
|
|
259
|
+
readonly self: MachineTarget<any>
|
|
260
|
+
readonly parent: MachineTarget<any> | undefined
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
-
export const
|
|
263
|
+
export const withMachineReferences = (
|
|
264
264
|
configuration: ActiveConfiguration,
|
|
265
|
-
|
|
265
|
+
machineReferences: PlanningMachineReferences
|
|
266
266
|
): ActiveConfiguration => ({
|
|
267
267
|
...configuration,
|
|
268
|
-
|
|
268
|
+
machineReferences: { self: machineReferences.self, parent: machineReferences.parent }
|
|
269
269
|
})
|
|
270
270
|
|
|
271
|
-
export const
|
|
271
|
+
export const getMachineReferences = (
|
|
272
272
|
configuration: ActiveConfiguration
|
|
273
|
-
):
|
|
273
|
+
): PlanningMachineReferences | undefined => configuration.machineReferences
|
|
274
274
|
|
|
275
275
|
export interface FinalCompletion {
|
|
276
276
|
readonly path: string
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import * as Effect from "effect/Effect"
|
|
8
|
-
import type {
|
|
8
|
+
import type { Machine, MachineTarget } from "../../Machine.js"
|
|
9
9
|
import { getTargetBuilder, type RuntimeCommand } from "./command.js"
|
|
10
10
|
import {
|
|
11
11
|
type ActiveConfiguration,
|
|
@@ -18,10 +18,10 @@ import {
|
|
|
18
18
|
isDescendantOf,
|
|
19
19
|
normalizeConfigurationSync,
|
|
20
20
|
normalizeTargetConfigurationSync,
|
|
21
|
-
type
|
|
21
|
+
type PlanningMachineReferences,
|
|
22
22
|
snapshotFromConfiguration,
|
|
23
23
|
validateInitialConfiguration,
|
|
24
|
-
|
|
24
|
+
withMachineReferences
|
|
25
25
|
} from "./configuration.js"
|
|
26
26
|
import { InfiniteTransitionError, StoppedError } from "./errors.js"
|
|
27
27
|
import * as InvocationEvent from "./invocationEvent.js"
|
|
@@ -67,28 +67,28 @@ interface IndexedExecutionDescriptor {
|
|
|
67
67
|
>
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
const
|
|
70
|
+
const planningMachineReferences = new WeakMap<Machine.Any, PlanningMachineReferences>()
|
|
71
71
|
|
|
72
|
-
const
|
|
73
|
-
const cached =
|
|
72
|
+
const getPlanningMachineReferences = (machine: Machine.Any): PlanningMachineReferences => {
|
|
73
|
+
const cached = planningMachineReferences.get(machine)
|
|
74
74
|
if (cached !== undefined) return cached
|
|
75
|
-
const self:
|
|
75
|
+
const self: MachineTarget<unknown> = {
|
|
76
76
|
id: machine.id ?? "Machine",
|
|
77
77
|
sessionId: "Machine.plan",
|
|
78
78
|
send: () => Effect.fail(new StoppedError())
|
|
79
79
|
}
|
|
80
80
|
const scope = { self, parent: undefined }
|
|
81
|
-
|
|
81
|
+
planningMachineReferences.set(machine, scope)
|
|
82
82
|
return scope
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
const
|
|
85
|
+
const resolveMachineReferences = (
|
|
86
86
|
machine: Machine.Any,
|
|
87
|
-
|
|
88
|
-
):
|
|
89
|
-
|
|
90
|
-
?
|
|
91
|
-
: { self:
|
|
87
|
+
machineReferences: PlanningMachineReferences | undefined
|
|
88
|
+
): PlanningMachineReferences =>
|
|
89
|
+
machineReferences === undefined
|
|
90
|
+
? getPlanningMachineReferences(machine)
|
|
91
|
+
: { self: machineReferences.self, parent: machineReferences.parent }
|
|
92
92
|
|
|
93
93
|
const indexedStateConfigKeys: ReadonlySet<PropertyKey> = new Set([
|
|
94
94
|
"initial",
|
|
@@ -363,7 +363,7 @@ const makeIndexedTransitionContext = (
|
|
|
363
363
|
configuration: OwnedIndexedState,
|
|
364
364
|
sourceIndex: number,
|
|
365
365
|
event: any,
|
|
366
|
-
|
|
366
|
+
machineReferences?: PlanningMachineReferences
|
|
367
367
|
): any => {
|
|
368
368
|
const source = descriptor.nodes[sourceIndex]!
|
|
369
369
|
const parentIndex = descriptor.parentIndices[sourceIndex]!
|
|
@@ -372,7 +372,7 @@ const makeIndexedTransitionContext = (
|
|
|
372
372
|
ancestors[descriptor.nodes[ancestorIndex]!.path] = configuration.values[ancestorIndex]
|
|
373
373
|
}
|
|
374
374
|
return {
|
|
375
|
-
...
|
|
375
|
+
...resolveMachineReferences(machine, machineReferences),
|
|
376
376
|
state: configuration.values[sourceIndex],
|
|
377
377
|
containingState: parentIndex < 0 ? undefined : configuration.values[parentIndex],
|
|
378
378
|
ancestors,
|
|
@@ -454,7 +454,7 @@ const selectIndexedEventTransitions = (
|
|
|
454
454
|
descriptor: IndexedExecutionDescriptor,
|
|
455
455
|
configuration: OwnedIndexedState,
|
|
456
456
|
event: any,
|
|
457
|
-
|
|
457
|
+
machineReferences?: PlanningMachineReferences
|
|
458
458
|
): ReadonlyArray<IndexedSelectedTransition> => {
|
|
459
459
|
const selected: Array<IndexedSelectedTransition> = []
|
|
460
460
|
for (const leafIndex of configuration.activeLeaves) {
|
|
@@ -476,7 +476,7 @@ const selectIndexedEventTransitions = (
|
|
|
476
476
|
configuration,
|
|
477
477
|
sourceIndex,
|
|
478
478
|
event,
|
|
479
|
-
|
|
479
|
+
machineReferences
|
|
480
480
|
)
|
|
481
481
|
})
|
|
482
482
|
}
|
|
@@ -660,7 +660,7 @@ const planIndexedFlatState = (
|
|
|
660
660
|
configuration: OwnedIndexedState,
|
|
661
661
|
decoded: { readonly _tag: PropertyKey },
|
|
662
662
|
retainMicrosteps: boolean,
|
|
663
|
-
|
|
663
|
+
machineReferences?: PlanningMachineReferences
|
|
664
664
|
): ExecutionMacrostep<OwnedIndexedState> => {
|
|
665
665
|
let current = configuration
|
|
666
666
|
let event: any = decoded
|
|
@@ -712,7 +712,7 @@ const planIndexedFlatState = (
|
|
|
712
712
|
machine,
|
|
713
713
|
transition.transition,
|
|
714
714
|
{
|
|
715
|
-
...
|
|
715
|
+
...resolveMachineReferences(machine, machineReferences),
|
|
716
716
|
state: current.values[sourceIndex],
|
|
717
717
|
containingState: undefined,
|
|
718
718
|
ancestors: {},
|
|
@@ -807,7 +807,7 @@ const planIndexedState = (
|
|
|
807
807
|
configuration: OwnedIndexedState,
|
|
808
808
|
input: unknown,
|
|
809
809
|
retainMicrosteps: boolean,
|
|
810
|
-
|
|
810
|
+
machineReferences?: PlanningMachineReferences
|
|
811
811
|
): ExecutionMacrostep<OwnedIndexedState> => {
|
|
812
812
|
if (InvocationEvent.isInvocationEvent(input)) {
|
|
813
813
|
// Invocation lifecycle transitions retain the generic planner as their
|
|
@@ -816,9 +816,9 @@ const planIndexedState = (
|
|
|
816
816
|
// the representation boundary.
|
|
817
817
|
const planned = planConfiguration(
|
|
818
818
|
machine as any,
|
|
819
|
-
|
|
819
|
+
machineReferences === undefined
|
|
820
820
|
? activeConfigurationFromIndexedState(descriptor, configuration)
|
|
821
|
-
:
|
|
821
|
+
: withMachineReferences(activeConfigurationFromIndexedState(descriptor, configuration), machineReferences),
|
|
822
822
|
input
|
|
823
823
|
)
|
|
824
824
|
return {
|
|
@@ -841,7 +841,7 @@ const planIndexedState = (
|
|
|
841
841
|
}
|
|
842
842
|
const decoded = decodeEventSync(machine, input)
|
|
843
843
|
if (descriptor.flat) {
|
|
844
|
-
return planIndexedFlatState(machine, descriptor, configuration, decoded, retainMicrosteps,
|
|
844
|
+
return planIndexedFlatState(machine, descriptor, configuration, decoded, retainMicrosteps, machineReferences)
|
|
845
845
|
}
|
|
846
846
|
if (descriptor.finalIndices.some((index) => configuration.active[index] === 1)) {
|
|
847
847
|
const active = activeConfigurationFromIndexedState(descriptor, configuration)
|
|
@@ -862,7 +862,7 @@ const planIndexedState = (
|
|
|
862
862
|
}
|
|
863
863
|
}
|
|
864
864
|
|
|
865
|
-
const selections = selectIndexedEventTransitions(machine, descriptor, configuration, decoded,
|
|
865
|
+
const selections = selectIndexedEventTransitions(machine, descriptor, configuration, decoded, machineReferences)
|
|
866
866
|
if (selections.length === 0) {
|
|
867
867
|
return {
|
|
868
868
|
next: configuration,
|
|
@@ -930,7 +930,7 @@ const planIndexedState = (
|
|
|
930
930
|
}
|
|
931
931
|
raisedIndex += 1
|
|
932
932
|
currentEvent = raised
|
|
933
|
-
const raisedSelections = selectIndexedEventTransitions(machine, descriptor, current, raised,
|
|
933
|
+
const raisedSelections = selectIndexedEventTransitions(machine, descriptor, current, raised, machineReferences)
|
|
934
934
|
if (raisedSelections.length === 0) continue
|
|
935
935
|
const step = indexedMicrostep(machine, descriptor, current, raised, raisedSelections)
|
|
936
936
|
current = step.next
|
|
@@ -949,11 +949,11 @@ export interface CompiledExecutionPlan {
|
|
|
949
949
|
state: unknown,
|
|
950
950
|
event: unknown,
|
|
951
951
|
retainMicrosteps?: boolean,
|
|
952
|
-
|
|
952
|
+
machineReferences?: PlanningMachineReferences
|
|
953
953
|
) => ExecutionMacrostep
|
|
954
954
|
readonly initial?: (
|
|
955
955
|
args: ReadonlyArray<unknown>,
|
|
956
|
-
|
|
956
|
+
machineReferences?: PlanningMachineReferences
|
|
957
957
|
) => {
|
|
958
958
|
readonly state: Machine.Snapshot<any>
|
|
959
959
|
readonly configuration: unknown
|
|
@@ -970,12 +970,12 @@ const makeActiveExecutionPlan = (machine: Machine.Any): CompiledExecutionPlan =>
|
|
|
970
970
|
fromConfiguration: (configuration) => configuration,
|
|
971
971
|
toConfiguration: (state) => state as ActiveConfiguration,
|
|
972
972
|
snapshot: (state) => snapshotFromConfiguration(machine, state as ActiveConfiguration),
|
|
973
|
-
plan: (state, event, _retainMicrosteps,
|
|
973
|
+
plan: (state, event, _retainMicrosteps, machineReferences) =>
|
|
974
974
|
planConfiguration(
|
|
975
975
|
machine as any,
|
|
976
|
-
|
|
976
|
+
machineReferences === undefined
|
|
977
977
|
? state as ActiveConfiguration
|
|
978
|
-
:
|
|
978
|
+
: withMachineReferences(state as ActiveConfiguration, machineReferences),
|
|
979
979
|
event as any
|
|
980
980
|
)
|
|
981
981
|
})
|
|
@@ -987,9 +987,9 @@ const makeIndexedExecutionPlan = (
|
|
|
987
987
|
fromConfiguration: (configuration) => ownedIndexedStateFromActive(indexed, configuration),
|
|
988
988
|
toConfiguration: (state) => activeConfigurationFromIndexedState(indexed, state as OwnedIndexedState),
|
|
989
989
|
snapshot: (state) => snapshotFromIndexedState(indexed, state as OwnedIndexedState),
|
|
990
|
-
plan: (state, event, retainMicrosteps = false,
|
|
991
|
-
planIndexedState(machine, indexed, state as OwnedIndexedState, event, retainMicrosteps,
|
|
992
|
-
initial: (args,
|
|
990
|
+
plan: (state, event, retainMicrosteps = false, machineReferences) =>
|
|
991
|
+
planIndexedState(machine, indexed, state as OwnedIndexedState, event, retainMicrosteps, machineReferences),
|
|
992
|
+
initial: (args, machineReferences) => {
|
|
993
993
|
const inputArgs = machine.input === undefined
|
|
994
994
|
? args
|
|
995
995
|
: args.length === 0
|
|
@@ -997,7 +997,7 @@ const makeIndexedExecutionPlan = (
|
|
|
997
997
|
: [decodeInputSync(machine, machine.input, args[0])]
|
|
998
998
|
const initial = machine.initial(...inputArgs as any)
|
|
999
999
|
const normalized = normalizeConfigurationSync(machine, initial as Machine.Snapshot<any>)
|
|
1000
|
-
const active =
|
|
1000
|
+
const active = machineReferences === undefined ? normalized : withMachineReferences(normalized, machineReferences)
|
|
1001
1001
|
validateInitialConfiguration(machine, active)
|
|
1002
1002
|
const completed = completeConfigurationSync(machine, active, InitialEvent).configuration
|
|
1003
1003
|
const configuration = ownedIndexedStateFromActive(indexed, completed)
|
|
@@ -235,7 +235,7 @@ export const startAll = (
|
|
|
235
235
|
.filter((path) => configuration.active.has(path))
|
|
236
236
|
.flatMap((path) => {
|
|
237
237
|
const context = {
|
|
238
|
-
...(Configuration.
|
|
238
|
+
...(Configuration.getMachineReferences(configuration) ?? { self: scope.self, parent: scope.parent }),
|
|
239
239
|
state: configuration.values.get(path),
|
|
240
240
|
containingState: Configuration.getParentValue(machine, configuration, path),
|
|
241
241
|
ancestors: Configuration.getParentValues(machine, configuration, path),
|
|
@@ -104,6 +104,8 @@ const Proto = {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
const makeBoundInvoke = (config: unknown): unknown => config
|
|
108
|
+
|
|
107
109
|
const cloneWithHandlers = (
|
|
108
110
|
self: Machine.Any,
|
|
109
111
|
handlers: Machine.StateConfigs<any, any, any, any, any, any, any>
|
|
@@ -121,6 +123,7 @@ const cloneWithHandlers = (
|
|
|
121
123
|
machine.makeTargetBuilder = self.makeTargetBuilder
|
|
122
124
|
machine.handlers = handlers
|
|
123
125
|
machine.handle = makeHandle(machine)
|
|
126
|
+
machine.invoke = makeBoundInvoke
|
|
124
127
|
Protocol.copyProtocol(self, machine)
|
|
125
128
|
return machine
|
|
126
129
|
}
|
|
@@ -879,6 +882,7 @@ export const make: Make = (<
|
|
|
879
882
|
self.makeTargetBuilder = makeTargetBuilder(config.states, self.stateNodes)
|
|
880
883
|
self.handlers = Object.create(null)
|
|
881
884
|
self.handle = makeHandle(self)
|
|
885
|
+
self.invoke = makeBoundInvoke
|
|
882
886
|
Protocol.setProtocol(self)
|
|
883
887
|
return self
|
|
884
888
|
}) as Make
|
|
@@ -1358,6 +1362,8 @@ export const watch = <State, Event, Error = never, Output = never>(
|
|
|
1358
1362
|
ref: MachineRef<State, Event, Error, Output>
|
|
1359
1363
|
): Stream.Stream<RuntimeOutcome<State, Error, Output>> => internalRuntime.watch(ref)
|
|
1360
1364
|
|
|
1365
|
+
export const prepare = internalProcess.prepare
|
|
1366
|
+
|
|
1361
1367
|
export const start: <
|
|
1362
1368
|
const States extends Machine.StateSchemas,
|
|
1363
1369
|
const Events extends ReadonlyArray<Machine.TaggedSchema>,
|
|
@@ -7,7 +7,13 @@
|
|
|
7
7
|
import * as Cause from "effect/Cause"
|
|
8
8
|
import * as Effect from "effect/Effect"
|
|
9
9
|
import type * as Schema from "effect/Schema"
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
Enqueue,
|
|
12
|
+
InitialEvent as MachineInitialEvent,
|
|
13
|
+
Machine,
|
|
14
|
+
MachineReferences,
|
|
15
|
+
MachineTarget
|
|
16
|
+
} from "../../Machine.js"
|
|
11
17
|
import { getTargetBuilder, makeCollector, type RuntimeCommand } from "./command.js"
|
|
12
18
|
import {
|
|
13
19
|
type ActiveConfiguration,
|
|
@@ -94,35 +100,35 @@ export type TransitionHandler<States extends Machine.StateSchemas, E, R, Context
|
|
|
94
100
|
enqueue: Enqueue<any, any>
|
|
95
101
|
) => Machine.HandlerResult<States, E, R>
|
|
96
102
|
|
|
97
|
-
const
|
|
98
|
-
const
|
|
103
|
+
const rootMachineReferences = new WeakMap<Machine.Any, MachineReferences<any, any>>()
|
|
104
|
+
const scopedMachineReferences = new WeakMap<Machine.Any, MachineReferences<any, any>>()
|
|
99
105
|
|
|
100
|
-
export const
|
|
106
|
+
export const withMachineReferences = (
|
|
101
107
|
machine: Machine.Any,
|
|
102
|
-
|
|
108
|
+
machineReferences: MachineReferences<any, any>
|
|
103
109
|
): Machine.Any => {
|
|
104
110
|
const scoped = Object.create(machine) as Machine.Any
|
|
105
|
-
|
|
111
|
+
scopedMachineReferences.set(scoped, { self: machineReferences.self, parent: machineReferences.parent })
|
|
106
112
|
return scoped
|
|
107
113
|
}
|
|
108
114
|
|
|
109
|
-
const
|
|
115
|
+
const resolveMachineReferences = (
|
|
110
116
|
machine: Machine.Any,
|
|
111
117
|
configuration: ActiveConfiguration
|
|
112
|
-
):
|
|
113
|
-
const scope = configuration.
|
|
118
|
+
): MachineReferences<any, any> => {
|
|
119
|
+
const scope = configuration.machineReferences
|
|
114
120
|
if (scope !== undefined) return scope
|
|
115
|
-
const machineScope =
|
|
121
|
+
const machineScope = scopedMachineReferences.get(machine)
|
|
116
122
|
if (machineScope !== undefined) return machineScope
|
|
117
|
-
const cached =
|
|
123
|
+
const cached = rootMachineReferences.get(machine)
|
|
118
124
|
if (cached !== undefined) return cached
|
|
119
|
-
const self:
|
|
125
|
+
const self: MachineTarget<unknown> = {
|
|
120
126
|
id: machine.id ?? "Machine",
|
|
121
127
|
sessionId: "Machine.plan",
|
|
122
128
|
send: () => Effect.fail(new StoppedError())
|
|
123
129
|
}
|
|
124
130
|
const root = { self, parent: undefined }
|
|
125
|
-
|
|
131
|
+
rootMachineReferences.set(machine, root)
|
|
126
132
|
return root
|
|
127
133
|
}
|
|
128
134
|
|
|
@@ -240,7 +246,7 @@ const completeHistoryConfiguration = (
|
|
|
240
246
|
values,
|
|
241
247
|
outputs: configuration.outputs,
|
|
242
248
|
history: configuration.history,
|
|
243
|
-
|
|
249
|
+
machineReferences: configuration.machineReferences
|
|
244
250
|
} as ActiveConfiguration
|
|
245
251
|
active.add(child.path)
|
|
246
252
|
if (child.schema !== undefined) {
|
|
@@ -249,7 +255,7 @@ const completeHistoryConfiguration = (
|
|
|
249
255
|
throw new Error(`Machine shallow history requires an initial value implementation for state "${path}"`)
|
|
250
256
|
}
|
|
251
257
|
const initialized = collectStateInitializer(machine, initializer, {
|
|
252
|
-
...
|
|
258
|
+
...resolveMachineReferences(machine, current),
|
|
253
259
|
state: current.values.get(path),
|
|
254
260
|
containingState: getParentValue(machine, current, path),
|
|
255
261
|
ancestors: getParentValues(machine, current, path),
|
|
@@ -271,14 +277,14 @@ const completeHistoryConfiguration = (
|
|
|
271
277
|
values,
|
|
272
278
|
outputs: configuration.outputs,
|
|
273
279
|
history: configuration.history,
|
|
274
|
-
|
|
280
|
+
machineReferences: configuration.machineReferences
|
|
275
281
|
} as ActiveConfiguration
|
|
276
282
|
const initializer = valuedMissing.length === 0 ? undefined : machine.handlers[path]?.initial
|
|
277
283
|
if (valuedMissing.length > 0 && initializer === undefined) {
|
|
278
284
|
throw new Error(`Machine shallow history requires an initial value implementation for state "${path}"`)
|
|
279
285
|
}
|
|
280
286
|
const initialized = initializer === undefined ? undefined : collectStateInitializer(machine, initializer, {
|
|
281
|
-
...
|
|
287
|
+
...resolveMachineReferences(machine, current),
|
|
282
288
|
state: current.values.get(path),
|
|
283
289
|
containingState: getParentValue(machine, current, path),
|
|
284
290
|
ancestors: getParentValues(machine, current, path),
|
|
@@ -542,7 +548,7 @@ const makeStateActionContext = <
|
|
|
542
548
|
path: string,
|
|
543
549
|
event: Machine.LifecycleEvent<Events>
|
|
544
550
|
): Machine.StateActionContext<States, Events, Emits, StateId> => ({
|
|
545
|
-
...
|
|
551
|
+
...resolveMachineReferences(machine, configuration),
|
|
546
552
|
state: configuration.values.get(path) as Machine.StateByIdentifier<States, StateId>,
|
|
547
553
|
containingState: getParentValue(machine, configuration, path) as Machine.ParentStateValue<States, StateId>,
|
|
548
554
|
ancestors: getParentValues(machine, configuration, path) as Machine.ParentStateValues<States, StateId>,
|
|
@@ -562,7 +568,7 @@ const makeTransitionContext = <
|
|
|
562
568
|
event: Machine.EventByTag<Events, EventTag>,
|
|
563
569
|
snapshot: Machine.Snapshot<States>
|
|
564
570
|
): Machine.HandlerContext<States, Events, Emits, StateId, EventTag, any, any> => ({
|
|
565
|
-
...
|
|
571
|
+
...resolveMachineReferences(machine, configuration),
|
|
566
572
|
state: configuration.values.get(path) as Machine.StateByIdentifier<States, StateId>,
|
|
567
573
|
containingState: getParentValue(machine, configuration, path) as Machine.ParentStateValue<States, StateId>,
|
|
568
574
|
ancestors: getParentValues(machine, configuration, path) as Machine.ParentStateValues<States, StateId>,
|
|
@@ -584,7 +590,7 @@ const makeDoneContext = <
|
|
|
584
590
|
output: unknown,
|
|
585
591
|
snapshot: Machine.Snapshot<States>
|
|
586
592
|
): Machine.DoneContext<States, Events, Emits, StateId> => ({
|
|
587
|
-
...
|
|
593
|
+
...resolveMachineReferences(machine, configuration),
|
|
588
594
|
state: configuration.values.get(path) as Machine.StateByIdentifier<States, StateId>,
|
|
589
595
|
containingState: getParentValue(machine, configuration, path) as Machine.ParentStateValue<States, StateId>,
|
|
590
596
|
ancestors: getParentValues(machine, configuration, path) as Machine.ParentStateValues<States, StateId>,
|
|
@@ -679,7 +685,7 @@ const selectAlwaysTransitions = <
|
|
|
679
685
|
Machine.AlwaysContext<States, Events, Emits, Machine.StateIdentifier<States>>
|
|
680
686
|
>,
|
|
681
687
|
context: {
|
|
682
|
-
...
|
|
688
|
+
...resolveMachineReferences(machine, configuration),
|
|
683
689
|
state: configuration.values.get(path) as Machine.StateByIdentifier<
|
|
684
690
|
States,
|
|
685
691
|
Machine.StateIdentifier<States>
|
|
@@ -867,7 +873,7 @@ const selectInvocationTransition = <
|
|
|
867
873
|
if (transition === undefined) return []
|
|
868
874
|
const snapshot = snapshotFromConfiguration<States>(machine, configuration)
|
|
869
875
|
const context = {
|
|
870
|
-
...
|
|
876
|
+
...resolveMachineReferences(machine, configuration),
|
|
871
877
|
state: configuration.values.get(event.path),
|
|
872
878
|
containingState: getParentValue(machine, configuration, event.path),
|
|
873
879
|
ancestors: getParentValues(machine, configuration, event.path),
|
|
@@ -1107,10 +1113,10 @@ const resolveChoiceTarget = (
|
|
|
1107
1113
|
]),
|
|
1108
1114
|
outputs: configuration.outputs,
|
|
1109
1115
|
history: configuration.history,
|
|
1110
|
-
...(configuration.
|
|
1116
|
+
...(configuration.machineReferences === undefined ? {} : { machineReferences: configuration.machineReferences })
|
|
1111
1117
|
}
|
|
1112
1118
|
const collected = collectTransition(machine, choice.transition, {
|
|
1113
|
-
...
|
|
1119
|
+
...resolveMachineReferences(machine, provisional),
|
|
1114
1120
|
containingState: getParentValue(machine, provisional, node.path),
|
|
1115
1121
|
ancestors: getParentValues(machine, provisional, node.path),
|
|
1116
1122
|
event,
|