@typeonce/effect-machine 0.6.0 → 0.7.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 (54) hide show
  1. package/README.md +4 -3
  2. package/dist/Machine.d.ts +24 -6
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js.map +1 -1
  5. package/dist/internal/machine/atom.d.ts +5 -0
  6. package/dist/internal/machine/atom.d.ts.map +1 -1
  7. package/dist/internal/machine/atom.js +6 -3
  8. package/dist/internal/machine/atom.js.map +1 -1
  9. package/dist/internal/machine/machine.d.ts.map +1 -1
  10. package/dist/internal/machine/machine.js +1 -1
  11. package/dist/internal/machine/machine.js.map +1 -1
  12. package/dist/unstable/reactivity/AtomMachine.d.ts +26 -0
  13. package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
  14. package/dist/unstable/reactivity/AtomMachine.js +23 -0
  15. package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
  16. package/docs/agent-guide.md +14 -0
  17. package/package.json +5 -5
  18. package/src/Machine.ts +6909 -0
  19. package/src/index.ts +1 -0
  20. package/src/internal/machine/activities.ts +108 -0
  21. package/src/internal/machine/atom.ts +684 -0
  22. package/src/internal/machine/cluster.ts +394 -0
  23. package/src/internal/machine/command.ts +58 -0
  24. package/src/internal/machine/commandRuntime.ts +43 -0
  25. package/src/internal/machine/configuration.ts +1331 -0
  26. package/src/internal/machine/errors.ts +87 -0
  27. package/src/internal/machine/executionPlan.ts +996 -0
  28. package/src/internal/machine/invocation.ts +119 -0
  29. package/src/internal/machine/machine.ts +1750 -0
  30. package/src/internal/machine/planner.ts +1933 -0
  31. package/src/internal/machine/process.ts +906 -0
  32. package/src/internal/machine/protocol.ts +322 -0
  33. package/src/internal/machine/readiness.ts +10 -0
  34. package/src/internal/machine/runtime.ts +2512 -0
  35. package/src/internal/machine/serialization.ts +498 -0
  36. package/src/internal/machine/stateDefinition.ts +270 -0
  37. package/src/internal/machine/symbols.ts +2 -0
  38. package/src/internal/machine/topology.ts +479 -0
  39. package/src/internal/testing/machine/arbitrary.ts +102 -0
  40. package/src/internal/testing/machine/exploration.ts +331 -0
  41. package/src/internal/testing/machine/finiteModel.ts +1498 -0
  42. package/src/internal/testing/machine/invariant.ts +372 -0
  43. package/src/internal/testing/machine/probe.ts +79 -0
  44. package/src/internal/testing/machine/referenceModel.ts +1505 -0
  45. package/src/internal/testing/machine/runtime.ts +1710 -0
  46. package/src/internal/testing/machine/runtimeInvariant.ts +486 -0
  47. package/src/internal/testing/machine/trace.ts +150 -0
  48. package/src/internal/testing/machine/verification.ts +1890 -0
  49. package/src/testing/MachineTest.ts +2067 -0
  50. package/src/testing/index.ts +7 -0
  51. package/src/unstable/cluster/ClusterMachine.ts +390 -0
  52. package/src/unstable/cluster/index.ts +1 -0
  53. package/src/unstable/reactivity/AtomMachine.ts +696 -0
  54. 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
+ }