@typeonce/effect-machine 0.31.2 → 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.
Files changed (151) hide show
  1. package/README.md +145 -140
  2. package/dist/Machine.d.ts +428 -254
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js +91 -111
  5. package/dist/Machine.js.map +1 -1
  6. package/dist/internal/machine/atom.d.ts +3 -4
  7. package/dist/internal/machine/atom.d.ts.map +1 -1
  8. package/dist/internal/machine/atom.js +0 -2
  9. package/dist/internal/machine/atom.js.map +1 -1
  10. package/dist/internal/machine/childRegistry.d.ts +52 -0
  11. package/dist/internal/machine/childRegistry.d.ts.map +1 -0
  12. package/dist/internal/machine/childRegistry.js +74 -0
  13. package/dist/internal/machine/childRegistry.js.map +1 -0
  14. package/dist/internal/machine/cluster.d.ts +2 -3
  15. package/dist/internal/machine/cluster.d.ts.map +1 -1
  16. package/dist/internal/machine/cluster.js.map +1 -1
  17. package/dist/internal/machine/configuration.d.ts.map +1 -1
  18. package/dist/internal/machine/configuration.js +14 -4
  19. package/dist/internal/machine/configuration.js.map +1 -1
  20. package/dist/internal/machine/executionPlan.d.ts +1 -0
  21. package/dist/internal/machine/executionPlan.d.ts.map +1 -1
  22. package/dist/internal/machine/executionPlan.js +97 -53
  23. package/dist/internal/machine/executionPlan.js.map +1 -1
  24. package/dist/internal/machine/invocation.d.ts.map +1 -1
  25. package/dist/internal/machine/invocation.js +4 -2
  26. package/dist/internal/machine/invocation.js.map +1 -1
  27. package/dist/internal/machine/invocationDefinition.d.ts +35 -0
  28. package/dist/internal/machine/invocationDefinition.d.ts.map +1 -0
  29. package/dist/internal/machine/invocationDefinition.js +21 -0
  30. package/dist/internal/machine/invocationDefinition.js.map +1 -0
  31. package/dist/internal/machine/invocationEvent.d.ts +0 -2
  32. package/dist/internal/machine/invocationEvent.d.ts.map +1 -1
  33. package/dist/internal/machine/invocationEvent.js +0 -8
  34. package/dist/internal/machine/invocationEvent.js.map +1 -1
  35. package/dist/internal/machine/machine.d.ts +21 -43
  36. package/dist/internal/machine/machine.d.ts.map +1 -1
  37. package/dist/internal/machine/machine.js +98 -374
  38. package/dist/internal/machine/machine.js.map +1 -1
  39. package/dist/internal/machine/planner.d.ts +13 -19
  40. package/dist/internal/machine/planner.d.ts.map +1 -1
  41. package/dist/internal/machine/planner.js +63 -35
  42. package/dist/internal/machine/planner.js.map +1 -1
  43. package/dist/internal/machine/process.d.ts +6 -8
  44. package/dist/internal/machine/process.d.ts.map +1 -1
  45. package/dist/internal/machine/process.js +1 -0
  46. package/dist/internal/machine/process.js.map +1 -1
  47. package/dist/internal/machine/protocol.d.ts +2 -2
  48. package/dist/internal/machine/protocol.d.ts.map +1 -1
  49. package/dist/internal/machine/protocol.js +4 -18
  50. package/dist/internal/machine/protocol.js.map +1 -1
  51. package/dist/internal/machine/readiness.d.ts +1 -1
  52. package/dist/internal/machine/readiness.d.ts.map +1 -1
  53. package/dist/internal/machine/requirements.d.ts +4 -0
  54. package/dist/internal/machine/requirements.d.ts.map +1 -0
  55. package/dist/internal/machine/requirements.js +2 -0
  56. package/dist/internal/machine/requirements.js.map +1 -0
  57. package/dist/internal/machine/runtime.d.ts +4 -58
  58. package/dist/internal/machine/runtime.d.ts.map +1 -1
  59. package/dist/internal/machine/runtime.js +1 -69
  60. package/dist/internal/machine/runtime.js.map +1 -1
  61. package/dist/internal/machine/serialization.d.ts.map +1 -1
  62. package/dist/internal/machine/serialization.js +16 -0
  63. package/dist/internal/machine/serialization.js.map +1 -1
  64. package/dist/internal/machine/stateDefinition.d.ts +3 -1
  65. package/dist/internal/machine/stateDefinition.d.ts.map +1 -1
  66. package/dist/internal/machine/stateDefinition.js +36 -2
  67. package/dist/internal/machine/stateDefinition.js.map +1 -1
  68. package/dist/internal/machine/targetBuilder.d.ts +16 -0
  69. package/dist/internal/machine/targetBuilder.d.ts.map +1 -0
  70. package/dist/internal/machine/targetBuilder.js +333 -0
  71. package/dist/internal/machine/targetBuilder.js.map +1 -0
  72. package/dist/internal/machine/topology.js +3 -3
  73. package/dist/internal/machine/topology.js.map +1 -1
  74. package/dist/internal/machine/transition.d.ts +16 -0
  75. package/dist/internal/machine/transition.d.ts.map +1 -0
  76. package/dist/internal/machine/transition.js +2 -0
  77. package/dist/internal/machine/transition.js.map +1 -0
  78. package/dist/internal/testing/machine/finiteModel.d.ts.map +1 -1
  79. package/dist/internal/testing/machine/finiteModel.js +10 -12
  80. package/dist/internal/testing/machine/finiteModel.js.map +1 -1
  81. package/dist/internal/testing/machine/format.d.ts +7 -0
  82. package/dist/internal/testing/machine/format.d.ts.map +1 -0
  83. package/dist/internal/testing/machine/format.js +104 -0
  84. package/dist/internal/testing/machine/format.js.map +1 -0
  85. package/dist/internal/testing/machine/probe.d.ts +1 -1
  86. package/dist/internal/testing/machine/probe.d.ts.map +1 -1
  87. package/dist/internal/testing/machine/probe.js +1 -1
  88. package/dist/internal/testing/machine/probe.js.map +1 -1
  89. package/dist/internal/testing/machine/referenceModel.d.ts.map +1 -1
  90. package/dist/internal/testing/machine/referenceModel.js +15 -19
  91. package/dist/internal/testing/machine/referenceModel.js.map +1 -1
  92. package/dist/internal/testing/machine/trace.d.ts +1 -1
  93. package/dist/internal/testing/machine/trace.d.ts.map +1 -1
  94. package/dist/internal/testing/machine/trace.js +3 -3
  95. package/dist/internal/testing/machine/trace.js.map +1 -1
  96. package/dist/internal/testing/machine/value.d.ts +8 -0
  97. package/dist/internal/testing/machine/value.d.ts.map +1 -0
  98. package/dist/internal/testing/machine/value.js +82 -0
  99. package/dist/internal/testing/machine/value.js.map +1 -0
  100. package/dist/internal/testing/machine/verification.d.ts +2 -13
  101. package/dist/internal/testing/machine/verification.d.ts.map +1 -1
  102. package/dist/internal/testing/machine/verification.js +21 -113
  103. package/dist/internal/testing/machine/verification.js.map +1 -1
  104. package/dist/testing/MachineTest.d.ts +89 -104
  105. package/dist/testing/MachineTest.d.ts.map +1 -1
  106. package/dist/testing/MachineTest.js +70 -84
  107. package/dist/testing/MachineTest.js.map +1 -1
  108. package/dist/unstable/cluster/ClusterMachine.d.ts +10 -13
  109. package/dist/unstable/cluster/ClusterMachine.d.ts.map +1 -1
  110. package/dist/unstable/cluster/ClusterMachine.js +5 -8
  111. package/dist/unstable/cluster/ClusterMachine.js.map +1 -1
  112. package/dist/unstable/reactivity/AtomMachine.d.ts +26 -61
  113. package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
  114. package/dist/unstable/reactivity/AtomMachine.js +17 -26
  115. package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
  116. package/docs/agent-guide.md +45 -45
  117. package/docs/effect-atom-react.md +35 -63
  118. package/docs/machine-review.md +7 -7
  119. package/docs/root-api.md +214 -0
  120. package/package.json +1 -1
  121. package/src/Machine.ts +778 -437
  122. package/src/internal/machine/atom.ts +3 -13
  123. package/src/internal/machine/childRegistry.ts +141 -0
  124. package/src/internal/machine/cluster.ts +5 -14
  125. package/src/internal/machine/configuration.ts +20 -4
  126. package/src/internal/machine/executionPlan.ts +109 -52
  127. package/src/internal/machine/invocation.ts +10 -6
  128. package/src/internal/machine/invocationDefinition.ts +52 -0
  129. package/src/internal/machine/invocationEvent.ts +0 -8
  130. package/src/internal/machine/machine.ts +154 -679
  131. package/src/internal/machine/planner.ts +74 -62
  132. package/src/internal/machine/process.ts +14 -21
  133. package/src/internal/machine/protocol.ts +9 -32
  134. package/src/internal/machine/readiness.ts +1 -0
  135. package/src/internal/machine/requirements.ts +11 -0
  136. package/src/internal/machine/runtime.ts +17 -186
  137. package/src/internal/machine/serialization.ts +22 -0
  138. package/src/internal/machine/stateDefinition.ts +36 -3
  139. package/src/internal/machine/targetBuilder.ts +525 -0
  140. package/src/internal/machine/topology.ts +3 -3
  141. package/src/internal/machine/transition.ts +26 -0
  142. package/src/internal/testing/machine/finiteModel.ts +22 -23
  143. package/src/internal/testing/machine/format.ts +120 -0
  144. package/src/internal/testing/machine/probe.ts +4 -4
  145. package/src/internal/testing/machine/referenceModel.ts +25 -17
  146. package/src/internal/testing/machine/trace.ts +4 -4
  147. package/src/internal/testing/machine/value.ts +77 -0
  148. package/src/internal/testing/machine/verification.ts +904 -1109
  149. package/src/testing/MachineTest.ts +103 -114
  150. package/src/unstable/cluster/ClusterMachine.ts +10 -20
  151. 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 ChildObservation = Option.Option<MachineRef<any, any, any, any>>
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.states" | "Machine.make"
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
+ }