@typeonce/effect-machine 0.31.2 → 0.33.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 +168 -162
- package/dist/Machine.d.ts +495 -284
- 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 +134 -403
- 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 +63 -35
- 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 +11 -13
- 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 +259 -0
- package/package.json +1 -1
- package/src/Machine.ts +1053 -538
- 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 +222 -716
- package/src/internal/machine/planner.ts +74 -62
- 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 +23 -24
- 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
|
@@ -18,37 +18,26 @@ import * as Scope from "effect/Scope"
|
|
|
18
18
|
import * as Stream from "effect/Stream"
|
|
19
19
|
import * as SynchronizedRef from "effect/SynchronizedRef"
|
|
20
20
|
import type * as Take from "effect/Take"
|
|
21
|
+
import type { RuntimeOutcome as PublicRuntimeOutcome, RuntimeSnapshot as PublicRuntimeSnapshot } from "../../Machine.js"
|
|
21
22
|
import type { ChildMachine, Inspection, Machine as MachineDefinition, MachineTarget } from "../../Machine.js"
|
|
23
|
+
import {
|
|
24
|
+
type ChildDescriptor,
|
|
25
|
+
type ChildEntry,
|
|
26
|
+
type ChildKey,
|
|
27
|
+
type ChildObserver,
|
|
28
|
+
type ChildRegistry,
|
|
29
|
+
type ChildSelector,
|
|
30
|
+
matchesChild,
|
|
31
|
+
offerChildObservation,
|
|
32
|
+
registerChild,
|
|
33
|
+
selectRegistryChild,
|
|
34
|
+
takeChildObservations,
|
|
35
|
+
unregisterChild
|
|
36
|
+
} from "./childRegistry.js"
|
|
22
37
|
import { ChildAlreadyExistsError, StoppedError } from "./errors.js"
|
|
23
38
|
import * as InspectionRuntime from "./inspectionRuntime.js"
|
|
24
39
|
import { ChildMachineLogicTypeId } from "./symbols.js"
|
|
25
40
|
|
|
26
|
-
type ChildDescriptor = {
|
|
27
|
-
readonly id: string
|
|
28
|
-
readonly machine: object
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
type ChildEntry =
|
|
32
|
-
| {
|
|
33
|
-
readonly _tag: "Starting"
|
|
34
|
-
readonly token: symbol
|
|
35
|
-
readonly ownerKey?: string
|
|
36
|
-
readonly ownerPath?: string
|
|
37
|
-
ownerActive?: boolean
|
|
38
|
-
}
|
|
39
|
-
| {
|
|
40
|
-
readonly _tag: "Started"
|
|
41
|
-
readonly token: symbol
|
|
42
|
-
readonly descriptor: ChildDescriptor | undefined
|
|
43
|
-
readonly ref: MachineRef<any, any, any, any>
|
|
44
|
-
readonly ownerKey?: string
|
|
45
|
-
readonly ownerPath?: string
|
|
46
|
-
ownerActive?: boolean
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
type ChildSelector = string | ChildDescriptor
|
|
50
|
-
type ChildKey = string | symbol
|
|
51
|
-
|
|
52
41
|
/** @internal */
|
|
53
42
|
export const activeSnapshotObserver: unique symbol = Symbol.for("effect/Machine/activeSnapshotObserver")
|
|
54
43
|
|
|
@@ -131,134 +120,7 @@ type InspectedOffer<Event> = (
|
|
|
131
120
|
deferred?: Deferred.Deferred<AcknowledgedDelivery<unknown>, unknown>
|
|
132
121
|
) => Effect.Effect<void, StoppedError>
|
|
133
122
|
|
|
134
|
-
type
|
|
135
|
-
type ChildObservationBatch = [ChildObservation, ...Array<ChildObservation>]
|
|
136
|
-
|
|
137
|
-
interface ChildObserver {
|
|
138
|
-
readonly child: ChildSelector
|
|
139
|
-
readonly id: string
|
|
140
|
-
values: ChildObservationBatch | undefined
|
|
141
|
-
waiter: Deferred.Deferred<void> | undefined
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const offerChildObservation = (
|
|
145
|
-
observer: ChildObserver,
|
|
146
|
-
value: ChildObservation
|
|
147
|
-
): void => {
|
|
148
|
-
if (observer.values === undefined) {
|
|
149
|
-
observer.values = [value]
|
|
150
|
-
} else {
|
|
151
|
-
observer.values.push(value)
|
|
152
|
-
}
|
|
153
|
-
if (observer.waiter !== undefined) {
|
|
154
|
-
const waiter = observer.waiter
|
|
155
|
-
observer.waiter = undefined
|
|
156
|
-
Deferred.doneUnsafe(waiter, Effect.void)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const takeChildObservations = (
|
|
161
|
-
observer: ChildObserver
|
|
162
|
-
): Effect.Effect<ChildObservationBatch> =>
|
|
163
|
-
Effect.suspend(() => {
|
|
164
|
-
if (observer.values !== undefined) {
|
|
165
|
-
const values = observer.values
|
|
166
|
-
observer.values = undefined
|
|
167
|
-
return Effect.succeed(values)
|
|
168
|
-
}
|
|
169
|
-
const waiter = Deferred.makeUnsafe<void>()
|
|
170
|
-
observer.waiter = waiter
|
|
171
|
-
return Deferred.await(waiter).pipe(Effect.andThen(takeChildObservations(observer)))
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
interface ChildRegistry {
|
|
175
|
-
closed: boolean
|
|
176
|
-
readonly children: Map<ChildKey, ChildEntry>
|
|
177
|
-
observers: Set<ChildObserver> | undefined
|
|
178
|
-
scope: Scope.Closeable | undefined
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const matchesChild = (
|
|
182
|
-
entry: ChildEntry,
|
|
183
|
-
child: ChildSelector
|
|
184
|
-
): entry is Extract<ChildEntry, { readonly _tag: "Started" }> =>
|
|
185
|
-
entry._tag === "Started" && (typeof child === "string" || (
|
|
186
|
-
entry.descriptor !== undefined &&
|
|
187
|
-
entry.descriptor.id === child.id &&
|
|
188
|
-
entry.descriptor.machine === child.machine
|
|
189
|
-
))
|
|
190
|
-
|
|
191
|
-
const selectRegistryChild = (
|
|
192
|
-
registry: ChildRegistry,
|
|
193
|
-
id: string,
|
|
194
|
-
child: ChildSelector
|
|
195
|
-
): ChildObservation => {
|
|
196
|
-
if (registry.closed) return Option.none()
|
|
197
|
-
const entry = registry.children.get(id)
|
|
198
|
-
return entry !== undefined && matchesChild(entry, child) ? Option.some(entry.ref) : Option.none()
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const publishRegistryChange = (registry: ChildRegistry): void => {
|
|
202
|
-
if (registry.observers === undefined) return
|
|
203
|
-
for (const observer of registry.observers) {
|
|
204
|
-
offerChildObservation(observer, selectRegistryChild(registry, observer.id, observer.child))
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const unregisterChild = (registry: ChildRegistry, key: ChildKey, token: symbol): void => {
|
|
209
|
-
const entry = registry.children.get(key)
|
|
210
|
-
if (entry === undefined || entry.token !== token) return
|
|
211
|
-
registry.children.delete(key)
|
|
212
|
-
if (typeof key === "string") publishRegistryChange(registry)
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const registerChild = (
|
|
216
|
-
registry: ChildRegistry,
|
|
217
|
-
key: ChildKey,
|
|
218
|
-
token: symbol,
|
|
219
|
-
ref: MachineRef<any, any, any, any>,
|
|
220
|
-
descriptor: ChildDescriptor | undefined
|
|
221
|
-
): boolean => {
|
|
222
|
-
const entry = registry.children.get(key)
|
|
223
|
-
if (registry.closed || entry === undefined || entry._tag !== "Starting" || entry.token !== token) {
|
|
224
|
-
return false
|
|
225
|
-
}
|
|
226
|
-
registry.children.delete(key)
|
|
227
|
-
const started: ChildEntry = entry.ownerKey === undefined
|
|
228
|
-
? { _tag: "Started", token, descriptor, ref }
|
|
229
|
-
: {
|
|
230
|
-
_tag: "Started",
|
|
231
|
-
token,
|
|
232
|
-
descriptor,
|
|
233
|
-
ref,
|
|
234
|
-
ownerKey: entry.ownerKey,
|
|
235
|
-
ownerPath: entry.ownerPath!,
|
|
236
|
-
ownerActive: entry.ownerActive === true
|
|
237
|
-
}
|
|
238
|
-
registry.children.set(key, started)
|
|
239
|
-
if (typeof key === "string") publishRegistryChange(registry)
|
|
240
|
-
return true
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export type RuntimeSnapshot<State, Error = never, Output = never> =
|
|
244
|
-
| {
|
|
245
|
-
readonly status: "active"
|
|
246
|
-
readonly state: State
|
|
247
|
-
}
|
|
248
|
-
| {
|
|
249
|
-
readonly status: "done"
|
|
250
|
-
readonly state: State
|
|
251
|
-
readonly output: Output
|
|
252
|
-
}
|
|
253
|
-
| {
|
|
254
|
-
readonly status: "error"
|
|
255
|
-
readonly state: State
|
|
256
|
-
readonly cause: Cause.Cause<Error>
|
|
257
|
-
}
|
|
258
|
-
| {
|
|
259
|
-
readonly status: "stopped"
|
|
260
|
-
readonly state: State
|
|
261
|
-
}
|
|
123
|
+
export type RuntimeSnapshot<State, Error = never, Output = never> = PublicRuntimeSnapshot<State, Error, Output>
|
|
262
124
|
|
|
263
125
|
interface VersionedSnapshot<State, Error, Output> {
|
|
264
126
|
readonly revision: number
|
|
@@ -274,38 +136,7 @@ type VersionedSnapshotBatch<State, Error, Output> = [
|
|
|
274
136
|
...Array<VersionedSnapshot<State, Error, Output>>
|
|
275
137
|
]
|
|
276
138
|
|
|
277
|
-
export type RuntimeOutcome<State, Error = never, Output = never> =
|
|
278
|
-
| {
|
|
279
|
-
readonly _tag: "Done"
|
|
280
|
-
readonly output: Output
|
|
281
|
-
readonly snapshot: Extract<RuntimeSnapshot<State, Error, Output>, { readonly status: "done" }>
|
|
282
|
-
}
|
|
283
|
-
| {
|
|
284
|
-
readonly _tag: "Failure"
|
|
285
|
-
readonly error: Error
|
|
286
|
-
readonly cause: Cause.Cause<Error>
|
|
287
|
-
readonly snapshot: Extract<RuntimeSnapshot<State, Error, Output>, { readonly status: "error" }>
|
|
288
|
-
}
|
|
289
|
-
| {
|
|
290
|
-
readonly _tag: "Defect"
|
|
291
|
-
readonly defect: unknown
|
|
292
|
-
readonly cause: Cause.Cause<Error>
|
|
293
|
-
readonly snapshot: Extract<RuntimeSnapshot<State, Error, Output>, { readonly status: "error" }>
|
|
294
|
-
}
|
|
295
|
-
| {
|
|
296
|
-
readonly _tag: "Interrupted"
|
|
297
|
-
readonly cause: Cause.Cause<Error>
|
|
298
|
-
readonly snapshot: Extract<RuntimeSnapshot<State, Error, Output>, { readonly status: "error" }>
|
|
299
|
-
}
|
|
300
|
-
| {
|
|
301
|
-
readonly _tag: "Cause"
|
|
302
|
-
readonly cause: Cause.Cause<Error>
|
|
303
|
-
readonly snapshot: Extract<RuntimeSnapshot<State, Error, Output>, { readonly status: "error" }>
|
|
304
|
-
}
|
|
305
|
-
| {
|
|
306
|
-
readonly _tag: "Stopped"
|
|
307
|
-
readonly snapshot: Extract<RuntimeSnapshot<State, Error, Output>, { readonly status: "stopped" }>
|
|
308
|
-
}
|
|
139
|
+
export type RuntimeOutcome<State, Error = never, Output = never> = PublicRuntimeOutcome<State, Error, Output>
|
|
309
140
|
|
|
310
141
|
export interface MachineRef<out State, in Event, out Error = never, out Output = never, out Emitted = never> {
|
|
311
142
|
readonly id: string
|
|
@@ -29,6 +29,7 @@ import { getNode, getStateNodeSchema } from "./topology.js"
|
|
|
29
29
|
|
|
30
30
|
const EncodedSnapshotSchema = Schema.Struct({
|
|
31
31
|
_tag: Schema.Literal("MachineSnapshot"),
|
|
32
|
+
version: Schema.Literal(2),
|
|
32
33
|
active: Schema.Array(Schema.Struct({
|
|
33
34
|
path: Schema.String,
|
|
34
35
|
value: Schema.optionalKey(Schema.Json)
|
|
@@ -206,6 +207,16 @@ const failEncodeCause = (
|
|
|
206
207
|
machine: Machine.Any,
|
|
207
208
|
cause: Cause.Cause<unknown>
|
|
208
209
|
): Effect.Effect<never, MachineSchemaEncodeError> => {
|
|
210
|
+
if (Cause.hasInterrupts(cause)) {
|
|
211
|
+
return Effect.failCause(
|
|
212
|
+
Cause.map(cause, (error) =>
|
|
213
|
+
error instanceof MachineSchemaEncodeError ? error : new MachineSchemaEncodeError({
|
|
214
|
+
machineId: machine.id,
|
|
215
|
+
boundary: "configuration",
|
|
216
|
+
cause: Cause.fail(error)
|
|
217
|
+
}))
|
|
218
|
+
)
|
|
219
|
+
}
|
|
209
220
|
const error = Cause.findErrorOption(cause)
|
|
210
221
|
return Option.isSome(error) && error.value instanceof MachineSchemaEncodeError
|
|
211
222
|
? Effect.fail(error.value)
|
|
@@ -222,6 +233,16 @@ const failDecodeCause = (
|
|
|
222
233
|
machine: Machine.Any,
|
|
223
234
|
cause: Cause.Cause<unknown>
|
|
224
235
|
): Effect.Effect<never, MachineSchemaDecodeError> => {
|
|
236
|
+
if (Cause.hasInterrupts(cause)) {
|
|
237
|
+
return Effect.failCause(
|
|
238
|
+
Cause.map(cause, (error) =>
|
|
239
|
+
error instanceof MachineSchemaDecodeError ? error : new MachineSchemaDecodeError({
|
|
240
|
+
machineId: machine.id,
|
|
241
|
+
boundary: "configuration",
|
|
242
|
+
cause: Cause.fail(error)
|
|
243
|
+
}))
|
|
244
|
+
)
|
|
245
|
+
}
|
|
225
246
|
const error = Cause.findErrorOption(cause)
|
|
226
247
|
return Option.isSome(error) && error.value instanceof MachineSchemaDecodeError
|
|
227
248
|
? Effect.fail(error.value)
|
|
@@ -392,6 +413,7 @@ export const encodeSnapshot = (
|
|
|
392
413
|
|
|
393
414
|
const encoded: Machine.EncodedSnapshot = {
|
|
394
415
|
_tag: "MachineSnapshot" as const,
|
|
416
|
+
version: 2,
|
|
395
417
|
active,
|
|
396
418
|
...(completed.length === 0 ? {} : { completed }),
|
|
397
419
|
...(Object.keys(history).length === 0 ? {} : { history })
|
|
@@ -18,7 +18,7 @@ export type AllowedStateNodeProperty<Kind extends StateNodeKind> = (typeof State
|
|
|
18
18
|
|
|
19
19
|
export type AllowedPseudoStateAnnotationProperty = (typeof PseudoStateAnnotationProperties)[number]
|
|
20
20
|
|
|
21
|
-
export type StateDefinitionBoundary = "Machine.state" | "Machine.
|
|
21
|
+
export type StateDefinitionBoundary = "Machine.state" | "Machine.make"
|
|
22
22
|
|
|
23
23
|
const hasOwn = (value: object, key: PropertyKey): boolean => Object.prototype.hasOwnProperty.call(value, key)
|
|
24
24
|
|
|
@@ -192,13 +192,14 @@ const validateStateTree = (
|
|
|
192
192
|
boundary: StateDefinitionBoundary,
|
|
193
193
|
states: unknown,
|
|
194
194
|
parent: string,
|
|
195
|
-
allowPseudoStates: boolean
|
|
195
|
+
allowPseudoStates: boolean,
|
|
196
|
+
root = false
|
|
196
197
|
): void => {
|
|
197
198
|
const treePath = parent === "" ? "<root>" : parent
|
|
198
199
|
assertPlainRecord(boundary, treePath, states, "state trees")
|
|
199
200
|
|
|
200
201
|
for (const key of Reflect.ownKeys(states)) {
|
|
201
|
-
const path = validateStateKey(boundary, parent, key)
|
|
202
|
+
const path = root && key === "" ? "" : validateStateKey(boundary, parent, key)
|
|
202
203
|
const node = states[key]
|
|
203
204
|
|
|
204
205
|
// Effect schemas have their own runtime properties. They are complete
|
|
@@ -358,3 +359,35 @@ const captureStateTree = (states: Readonly<Record<string, unknown>>): Readonly<R
|
|
|
358
359
|
/** Captures caller-owned structural containers while preserving schema identity. */
|
|
359
360
|
export const captureStateDefinitions = <States>(states: States): States =>
|
|
360
361
|
captureStateTree(states as Readonly<Record<string, unknown>>) as States
|
|
362
|
+
|
|
363
|
+
/** Root capture keeps descriptor helpers out of the compiled topology. */
|
|
364
|
+
export const captureRoot = (input: unknown, tag = ""): unknown => {
|
|
365
|
+
if (Schema.isSchema(input)) return input
|
|
366
|
+
if (typeof input !== "object" || input === null) return input
|
|
367
|
+
if (
|
|
368
|
+
"~effect/Machine/State" in input && input["~effect/Machine/State"] === "~effect/Machine/State" && "node" in input
|
|
369
|
+
) {
|
|
370
|
+
return input.node
|
|
371
|
+
}
|
|
372
|
+
const config = input as Readonly<Record<string, unknown>>
|
|
373
|
+
const copy: Record<string, unknown> = { ...config }
|
|
374
|
+
if (hasOwn(config, "fields")) {
|
|
375
|
+
if (hasOwn(config, "schema")) fail("Machine.state", tag, "declare fields or schema, not both")
|
|
376
|
+
assertPlainRecord("Machine.state", tag, config.fields, "state fields")
|
|
377
|
+
if (hasOwn(config.fields, "_tag")) fail("Machine.state", tag, "state fields cannot declare _tag")
|
|
378
|
+
copy.schema = Schema.TaggedStruct(tag, config.fields as Schema.Struct.Fields)
|
|
379
|
+
delete copy.fields
|
|
380
|
+
}
|
|
381
|
+
if (hasOwn(config, "states")) {
|
|
382
|
+
assertPlainRecord("Machine.state", tag, config.states, "child states")
|
|
383
|
+
const children: Record<string, unknown> = Object.create(null)
|
|
384
|
+
for (const key of Reflect.ownKeys(config.states)) {
|
|
385
|
+
validateStateKey("Machine.state", tag, key)
|
|
386
|
+
children[key as string] = captureRoot(config.states[key], key as string)
|
|
387
|
+
}
|
|
388
|
+
copy.states = children
|
|
389
|
+
}
|
|
390
|
+
if (tag !== "") return copy
|
|
391
|
+
validateStateTree("Machine.state", { "": copy }, "", false, true)
|
|
392
|
+
return captureStateDefinitions({ "": copy })[""]
|
|
393
|
+
}
|