@typeonce/effect-machine 0.6.0 → 0.6.1
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/package.json +5 -5
- package/src/Machine.ts +6873 -0
- package/src/index.ts +1 -0
- package/src/internal/machine/activities.ts +108 -0
- package/src/internal/machine/atom.ts +636 -0
- package/src/internal/machine/cluster.ts +394 -0
- package/src/internal/machine/command.ts +58 -0
- package/src/internal/machine/commandRuntime.ts +43 -0
- package/src/internal/machine/configuration.ts +1331 -0
- package/src/internal/machine/errors.ts +87 -0
- package/src/internal/machine/executionPlan.ts +996 -0
- package/src/internal/machine/invocation.ts +119 -0
- package/src/internal/machine/machine.ts +1747 -0
- package/src/internal/machine/planner.ts +1933 -0
- package/src/internal/machine/process.ts +906 -0
- package/src/internal/machine/protocol.ts +322 -0
- package/src/internal/machine/readiness.ts +10 -0
- package/src/internal/machine/runtime.ts +2512 -0
- package/src/internal/machine/serialization.ts +498 -0
- package/src/internal/machine/stateDefinition.ts +270 -0
- package/src/internal/machine/symbols.ts +2 -0
- package/src/internal/machine/topology.ts +479 -0
- package/src/internal/testing/machine/arbitrary.ts +102 -0
- package/src/internal/testing/machine/exploration.ts +331 -0
- package/src/internal/testing/machine/finiteModel.ts +1498 -0
- package/src/internal/testing/machine/invariant.ts +372 -0
- package/src/internal/testing/machine/probe.ts +79 -0
- package/src/internal/testing/machine/referenceModel.ts +1505 -0
- package/src/internal/testing/machine/runtime.ts +1710 -0
- package/src/internal/testing/machine/runtimeInvariant.ts +486 -0
- package/src/internal/testing/machine/trace.ts +150 -0
- package/src/internal/testing/machine/verification.ts +1890 -0
- package/src/testing/MachineTest.ts +2067 -0
- package/src/testing/index.ts +7 -0
- package/src/unstable/cluster/ClusterMachine.ts +390 -0
- package/src/unstable/cluster/index.ts +1 -0
- package/src/unstable/reactivity/AtomMachine.ts +649 -0
- package/src/unstable/reactivity/index.ts +1 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal state-scoped invocation orchestration.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.4.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as Effect from "effect/Effect"
|
|
8
|
+
import type { Machine } from "../../Machine.js"
|
|
9
|
+
import * as Configuration from "./configuration.js"
|
|
10
|
+
import * as Planner from "./planner.js"
|
|
11
|
+
import type * as Runtime from "./runtime.js"
|
|
12
|
+
|
|
13
|
+
/** @internal */
|
|
14
|
+
export type AnyConfig = Machine.InvokeConfig<
|
|
15
|
+
any,
|
|
16
|
+
any,
|
|
17
|
+
any,
|
|
18
|
+
any,
|
|
19
|
+
any,
|
|
20
|
+
any,
|
|
21
|
+
any,
|
|
22
|
+
any,
|
|
23
|
+
any,
|
|
24
|
+
any,
|
|
25
|
+
any,
|
|
26
|
+
any,
|
|
27
|
+
any
|
|
28
|
+
>
|
|
29
|
+
|
|
30
|
+
/** @internal */
|
|
31
|
+
export const makeKey = (path: string, id: string): string => `${path.length}:${path}${id}`
|
|
32
|
+
|
|
33
|
+
/** @internal */
|
|
34
|
+
export const makeChildId = (path: string, id: string): string => `Machine.invoke:${makeKey(path, id)}`
|
|
35
|
+
|
|
36
|
+
const resolve = (
|
|
37
|
+
config: Machine.AnyStateConfig | undefined,
|
|
38
|
+
context: Machine.InvokeContext<any, any, any, any>
|
|
39
|
+
): ReadonlyArray<AnyConfig> => {
|
|
40
|
+
const definition = config?.invoke
|
|
41
|
+
const invokes = typeof definition === "function" ? definition(context) : definition
|
|
42
|
+
if (invokes === undefined) return []
|
|
43
|
+
return Array.isArray(invokes) ? invokes as ReadonlyArray<AnyConfig> : [invokes as AnyConfig]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const runSequentialDiscard = <E, R>(
|
|
47
|
+
effects: ReadonlyArray<Effect.Effect<void, E, R>>
|
|
48
|
+
): Effect.Effect<void, E, R> =>
|
|
49
|
+
effects.length === 0
|
|
50
|
+
? Effect.void
|
|
51
|
+
: effects.length === 1
|
|
52
|
+
? effects[0]!
|
|
53
|
+
: Effect.all(effects, { discard: true })
|
|
54
|
+
|
|
55
|
+
const start = (
|
|
56
|
+
scope: Runtime.ProcessScope<any>,
|
|
57
|
+
ownedChildren: Runtime.OwnedChildRuntime,
|
|
58
|
+
path: string,
|
|
59
|
+
config: AnyConfig
|
|
60
|
+
): Effect.Effect<void, any, any> =>
|
|
61
|
+
Effect.suspend(() => {
|
|
62
|
+
const invokeId = String(config.id)
|
|
63
|
+
const key = makeKey(path, invokeId)
|
|
64
|
+
const childId = config.address === undefined ? makeChildId(path, invokeId) : String(config.address)
|
|
65
|
+
return ownedChildren.spawn(config.src as () => Runtime.ProcessLogic<any, any, any, any, any, any>, {
|
|
66
|
+
key,
|
|
67
|
+
path,
|
|
68
|
+
id: childId,
|
|
69
|
+
duplicateId: invokeId,
|
|
70
|
+
...(config.descriptor === undefined ? undefined : { descriptor: config.descriptor }),
|
|
71
|
+
sendParent: (isCurrent, event) => isCurrent() ? scope.self.send(event) : Effect.void,
|
|
72
|
+
onOutcome: (isCurrent, outcome) => {
|
|
73
|
+
if (outcome._tag === "Stopped" || !isCurrent()) return Effect.void
|
|
74
|
+
if (outcome._tag !== "Done") return scope.failCause(outcome.cause)
|
|
75
|
+
const mappedEvent = config.onDone === undefined
|
|
76
|
+
? outcome.output
|
|
77
|
+
: config.onDone({ id: config.id, output: outcome.output })
|
|
78
|
+
return mappedEvent === undefined
|
|
79
|
+
? Effect.void
|
|
80
|
+
: scope.self.send(mappedEvent).pipe(Effect.catchTag("StoppedError", () => Effect.void))
|
|
81
|
+
},
|
|
82
|
+
...(config.snapshot === undefined ? undefined : {
|
|
83
|
+
onSnapshot: (isCurrent: () => boolean, snapshot: any) => {
|
|
84
|
+
if (!isCurrent()) return Effect.void
|
|
85
|
+
const mappedEvent = config.snapshot!({ id: config.id, snapshot })
|
|
86
|
+
return mappedEvent === undefined
|
|
87
|
+
? Effect.void
|
|
88
|
+
: scope.self.send(mappedEvent).pipe(Effect.catchTag("StoppedError", () => Effect.void))
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Starts every invocation owned by active entry paths in deterministic entry
|
|
96
|
+
* order. `undefined` keeps the compiled drain free of empty Effect nodes.
|
|
97
|
+
*
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
100
|
+
export const startAll = (
|
|
101
|
+
machine: Machine.Any,
|
|
102
|
+
scope: Runtime.ProcessScope<any>,
|
|
103
|
+
ownedChildren: Runtime.OwnedChildRuntime,
|
|
104
|
+
configuration: Configuration.ActiveConfiguration,
|
|
105
|
+
paths: ReadonlyArray<string>,
|
|
106
|
+
event: Machine.LifecycleEvent<any>
|
|
107
|
+
): Effect.Effect<void, any, any> | undefined => {
|
|
108
|
+
const effects = Planner.sortEntryPaths(machine, paths)
|
|
109
|
+
.filter((path) => configuration.active.has(path))
|
|
110
|
+
.flatMap((path) =>
|
|
111
|
+
resolve(Configuration.getStateConfigByPath(machine, path), {
|
|
112
|
+
state: Configuration.getActiveValue(configuration, path),
|
|
113
|
+
parent: Configuration.getParentValue(machine, configuration, path),
|
|
114
|
+
parents: Configuration.getParentValues(machine, configuration, path),
|
|
115
|
+
event
|
|
116
|
+
}).map((config) => start(scope, ownedChildren, path, config))
|
|
117
|
+
)
|
|
118
|
+
return effects.length === 0 ? undefined : runSequentialDiscard(effects)
|
|
119
|
+
}
|