@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.
Files changed (58) hide show
  1. package/README.md +76 -13
  2. package/dist/Machine.d.ts +202 -90
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js +38 -9
  5. package/dist/Machine.js.map +1 -1
  6. package/dist/internal/machine/atom.d.ts +1 -1
  7. package/dist/internal/machine/atom.d.ts.map +1 -1
  8. package/dist/internal/machine/atom.js +38 -7
  9. package/dist/internal/machine/atom.js.map +1 -1
  10. package/dist/internal/machine/cluster.js +2 -2
  11. package/dist/internal/machine/cluster.js.map +1 -1
  12. package/dist/internal/machine/commandRuntime.d.ts.map +1 -1
  13. package/dist/internal/machine/commandRuntime.js +2 -2
  14. package/dist/internal/machine/commandRuntime.js.map +1 -1
  15. package/dist/internal/machine/configuration.d.ts +7 -7
  16. package/dist/internal/machine/configuration.d.ts.map +1 -1
  17. package/dist/internal/machine/configuration.js +3 -3
  18. package/dist/internal/machine/configuration.js.map +1 -1
  19. package/dist/internal/machine/executionPlan.d.ts +3 -3
  20. package/dist/internal/machine/executionPlan.d.ts.map +1 -1
  21. package/dist/internal/machine/executionPlan.js +25 -25
  22. package/dist/internal/machine/executionPlan.js.map +1 -1
  23. package/dist/internal/machine/invocation.js +1 -1
  24. package/dist/internal/machine/invocation.js.map +1 -1
  25. package/dist/internal/machine/machine.d.ts +1 -0
  26. package/dist/internal/machine/machine.d.ts.map +1 -1
  27. package/dist/internal/machine/machine.js +4 -0
  28. package/dist/internal/machine/machine.js.map +1 -1
  29. package/dist/internal/machine/planner.d.ts +2 -2
  30. package/dist/internal/machine/planner.d.ts.map +1 -1
  31. package/dist/internal/machine/planner.js +20 -20
  32. package/dist/internal/machine/planner.js.map +1 -1
  33. package/dist/internal/machine/process.d.ts +3 -0
  34. package/dist/internal/machine/process.d.ts.map +1 -1
  35. package/dist/internal/machine/process.js +6 -3
  36. package/dist/internal/machine/process.js.map +1 -1
  37. package/dist/internal/machine/runtime.d.ts +17 -3
  38. package/dist/internal/machine/runtime.d.ts.map +1 -1
  39. package/dist/internal/machine/runtime.js +82 -32
  40. package/dist/internal/machine/runtime.js.map +1 -1
  41. package/dist/unstable/reactivity/AtomMachine.d.ts +4 -2
  42. package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
  43. package/dist/unstable/reactivity/AtomMachine.js +4 -2
  44. package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
  45. package/docs/agent-guide.md +78 -19
  46. package/package.json +1 -1
  47. package/src/Machine.ts +704 -96
  48. package/src/internal/machine/atom.ts +50 -52
  49. package/src/internal/machine/cluster.ts +2 -2
  50. package/src/internal/machine/commandRuntime.ts +4 -2
  51. package/src/internal/machine/configuration.ts +10 -10
  52. package/src/internal/machine/executionPlan.ts +35 -35
  53. package/src/internal/machine/invocation.ts +1 -1
  54. package/src/internal/machine/machine.ts +6 -0
  55. package/src/internal/machine/planner.ts +30 -24
  56. package/src/internal/machine/process.ts +60 -3
  57. package/src/internal/machine/runtime.ts +176 -47
  58. package/src/unstable/reactivity/AtomMachine.ts +4 -2
@@ -20,8 +20,10 @@ export { NotReadyError } from "../../internal/machine/atom.js";
20
20
  export { ChildNotActiveError } from "../../internal/machine/atom.js";
21
21
  const ExternalRequirementsTypeId = "~effect/reactivity/AtomMachine/ExternalRequirements";
22
22
  /**
23
- * Observes ephemeral notifications from the actor owned by a machine atom.
24
- * The stream requires an `AtomRegistry` and does not replay earlier emissions.
23
+ * Observes ephemeral notifications from the running machine owned by a machine
24
+ * atom. When this stream activates a fresh bridge, it subscribes before machine
25
+ * initialization and observes initial-entry emissions. It never replays
26
+ * emissions from a machine that was already running.
25
27
  *
26
28
  * @category getters
27
29
  * @since 0.10.0
@@ -1 +1 @@
1
- {"version":3,"file":"AtomMachine.js","sourceRoot":"","sources":["../../../src/unstable/reactivity/AtomMachine.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,QAAQ,MAAM,gCAAgC,CAAA;AAK1D;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAE9D;;;;;GAKG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAMpE,MAAM,0BAA0B,GAAG,qDAAqD,CAAA;AAoIxF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GAE+C,QAAQ,CAAC,SAAS,CAAA;AAEvF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAMvB,QAAQ,CAAC,cAAc,CAAA;AAkJ3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,MAAM,MAAM,GASf,QAAQ,CAAC,MAAM,CAAA;AAEnB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,cAAc,GASvB,QAAQ,CAAC,cAAc,CAAA;AAE3B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,WAAW,GASpB,QAAQ,CAAC,WAAW,CAAA;AAExB;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAS5B,QAAQ,CAAC,mBAAmB,CAAA;AAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,OAAO,GAUmD,QAAQ,CAAC,OAAO,CAAA;AAEvF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAMrB,QAAQ,CAAC,YAAY,CAAA;AAEzB,MAAM,uBAAuB,GAAG,kDAAkD,CAAA;AAgHlF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,IAAI,GAoDb,QAAQ,CAAC,IAAI,CAAA;AAEjB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,MAAM,GAQf,QAAQ,CAAC,MAAM,CAAA;AAEnB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,IAAI,GAEoB,QAAQ,CAAC,IAAI,CAAA"}
1
+ {"version":3,"file":"AtomMachine.js","sourceRoot":"","sources":["../../../src/unstable/reactivity/AtomMachine.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,QAAQ,MAAM,gCAAgC,CAAA;AAK1D;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAE9D;;;;;GAKG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAMpE,MAAM,0BAA0B,GAAG,qDAAqD,CAAA;AAoIxF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,SAAS,GAE+C,QAAQ,CAAC,SAAS,CAAA;AAEvF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAMvB,QAAQ,CAAC,cAAc,CAAA;AAkJ3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,MAAM,MAAM,GASf,QAAQ,CAAC,MAAM,CAAA;AAEnB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,cAAc,GASvB,QAAQ,CAAC,cAAc,CAAA;AAE3B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,WAAW,GASpB,QAAQ,CAAC,WAAW,CAAA;AAExB;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAS5B,QAAQ,CAAC,mBAAmB,CAAA;AAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,OAAO,GAUmD,QAAQ,CAAC,OAAO,CAAA;AAEvF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAMrB,QAAQ,CAAC,YAAY,CAAA;AAEzB,MAAM,uBAAuB,GAAG,kDAAkD,CAAA;AAgHlF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,IAAI,GAoDb,QAAQ,CAAC,IAAI,CAAA;AAEjB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,MAAM,GAQf,QAAQ,CAAC,MAAM,CAAA;AAEnB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,IAAI,GAEoB,QAAQ,CAAC,IAAI,CAAA"}
@@ -4,6 +4,21 @@ This is the model-facing reference for the currently published
4
4
  `@typeonce/effect-machine` API. Prefer these patterns over reconstructing the API
5
5
  from its internal implementation.
6
6
 
7
+ ## Design priorities
8
+
9
+ Prefer, in order: compile-time type safety, explicit and opinionated semantics,
10
+ readable and concise machine models, and alignment with Effect core. Convenience
11
+ must come from builders and inference rather than ambiguous omissions or weaker
12
+ contracts. The package is pre-1.0, so improve or remove an existing API when a
13
+ clearer long-term design replaces it; do not preserve an inferior design with
14
+ aliases by default.
15
+
16
+ Keep the core machine model local. Before adding a public name or capability,
17
+ check Effect's existing modules and especially Cluster. Distributed identity,
18
+ placement, discovery, transport, routing, delivery, sharding, and remote
19
+ lifecycle belong to Cluster; expose integration through an explicit adapter
20
+ instead of creating a similar local abstraction with different semantics.
21
+
7
22
  ## Public imports
8
23
 
9
24
  ```ts
@@ -88,7 +103,7 @@ the deferred constructors preserve that identity after decoding.
88
103
  - Reuse an exported child descriptor for inline invocation, `sendTo`, and child
89
104
  lookup. Independently constructed descriptors are equivalent only when both
90
105
  their id and machine identity match.
91
- - `events` is the public actor-input protocol. `internalEvents` contains
106
+ - `events` is the public machine-input protocol. `internalEvents` contains
92
107
  machine-local raised events. `parentEvents` describes the public events a
93
108
  child may send to its owner. `emittedEvents` describes outward ephemeral
94
109
  notifications and is never delivered implicitly to a parent.
@@ -105,15 +120,16 @@ its extra control is required:
105
120
  `AtomMachine.resume(machine, snapshot)` for service-free machines.
106
121
  - Use one invocation object: `effect` for one-shot work, `after` for a timer,
107
122
  `logic` for reusable process logic, and `child` for a complete child
108
- statechart. `Machine.invoke({...})` preserves owner context and source
109
- channels across sibling lifecycle handlers. Use a direct object only when its
110
- lifecycle handlers do not need source-derived context.
123
+ statechart. `Machine.invoke({...})` preserves owner state and source channels
124
+ across sibling lifecycle handlers. Use `definition.invoke({...})` when a
125
+ callback uses `self` or `parent`; the bound constructor preserves the
126
+ definition's exact public input and `parentEvents` protocols.
111
127
  - Use `Machine.child(id, machine)` for a complete statechart descriptor and
112
128
  `Machine.childAddress<Event>(id)` for a low-level process address. A logic
113
129
  invocation is addressable only when `Machine.invoke` receives that
114
130
  address explicitly.
115
131
  - Use the callback's `enqueue` argument for `raise`, `emit`, `sendTo`, and
116
- `stop`. These operations record closed actor commands and do not run Effects.
132
+ `stop`. These operations record closed machine commands and do not run Effects.
117
133
 
118
134
  ## Atomic, compound, parallel, and history states
119
135
 
@@ -320,7 +336,7 @@ the default.
320
336
  The machine's readiness type tracks missing defaults and shallow initializers.
321
337
  History is an overwriteable register, not a stack: restoration does not consume
322
338
  it, and the next parent exit replaces it. Entry actions and invokes run again;
323
- prior effects, actors, and timers are not rewound.
339
+ prior effects, machine instances, and timers are not rewound.
324
340
 
325
341
  ## Choosing a target
326
342
 
@@ -406,7 +422,7 @@ only schema-backed paths; use `matches` or `getSnapshot` for any active path.
406
422
  `context.containingState` is the immediate typed state value (`undefined` at a
407
423
  root or when that state is schema-less). `context.ancestors` contains only
408
424
  valued structural ancestors. This is separate from `context.parent`, which is
409
- the owning actor reference or `undefined` for a root actor. Use full state paths
425
+ the owning machine target or `undefined` for a root machine. Use full state paths
410
426
  when another ancestor value is needed:
411
427
 
412
428
  ```ts
@@ -490,7 +506,7 @@ are an upper bound on concrete destinations, not an exhaustive result set.
490
506
  `reenter: true` remains meaningful with `target.none()`: the source exits and
491
507
  enters again while its logical configuration is retained.
492
508
 
493
- Closed statechart and actor operations use `enqueue`:
509
+ Closed statechart and machine operations use `enqueue`:
494
510
 
495
511
  ```ts
496
512
  Submit: ({ target }, enqueue) => {
@@ -499,7 +515,7 @@ Submit: ({ target }, enqueue) => {
499
515
  }
500
516
  ```
501
517
 
502
- Declare emission constructors separately from actor inputs:
518
+ Declare emission constructors separately from machine inputs:
503
519
 
504
520
  ```ts
505
521
  const Emissions = Machine.emittedEvents(SaveRequested, AuditRecorded)
@@ -513,12 +529,24 @@ const definition = Machine.make({
513
529
  ```
514
530
 
515
531
  `enqueue.raise(...)` is a same-macrostep input to self. `enqueue.sendTo(...)`
516
- targets an actor mailbox and is processed later. `enqueue.emit(...)` is neither:
532
+ targets a machine mailbox and is processed later. `enqueue.emit(...)` is neither:
517
533
  it publishes a one-off outward notification. Observe it with
518
- `ref.emissions`, a hot non-replayed `Stream` that completes with the actor.
534
+ `ref.emissions`, a hot non-replayed `Stream` that completes with the machine.
519
535
  `ref.changes` is stateful and begins with the current lifecycle snapshot.
520
- Startup emissions occur before `Machine.start` returns and therefore are not
521
- visible through the returned ref; use state for facts that must be retained.
536
+ Use `Machine.prepare(machine)` to obtain `changes` and `emissions` before
537
+ initialization. Subscribe to the desired stream and then evaluate
538
+ `prepared.start`. `Machine.start(machine)` remains the one-step convenience
539
+ when startup observation is unnecessary. Emissions are still never retained or
540
+ replayed; state remains the representation for facts that must be retained.
541
+
542
+ ```ts
543
+ const prepared = yield* Machine.prepare(machine)
544
+ yield* prepared.emissions.pipe(
545
+ Stream.runForEach(handleEmission),
546
+ Effect.forkScoped({ startImmediately: true })
547
+ )
548
+ const ref = yield* prepared.start
549
+ ```
522
550
 
523
551
  For child-to-parent input, export a public builder protocol and reuse it at both
524
552
  composition boundaries:
@@ -551,10 +579,12 @@ const parent = Machine.make({
551
579
  Invoking the child under a parent that lacks any required `parentEvents` case
552
580
  is a type error. Within child handlers, `parent` accepts only that protocol.
553
581
  The same child may run as a root, where `parent` is `undefined`. `self` accepts
554
- the machine's public inputs. Neither actor reference is a structural state
555
- value; use `containingState` and `ancestors` for statechart ancestry.
582
+ the machine's public inputs. Both are minimal `MachineTarget<Event>` values,
583
+ provided by the shared `MachineReferences<InputEvents, ParentEvents>` handler
584
+ context. Neither machine target is a structural state value; use
585
+ `containingState` and `ancestors` for statechart ancestry.
556
586
 
557
- Atom-backed actors retain the same transient semantics. Use
587
+ Atom-backed machines retain the same transient semantics. Use
558
588
  `AtomMachine.emissions(machineAtom)` for a root and
559
589
  `AtomMachine.childEmissions(childAtom)` for the currently active child. Both
560
590
  return streams requiring the corresponding `AtomRegistry`; emissions are not
@@ -682,6 +712,33 @@ invoke: Machine.invoke({
682
712
  })
683
713
  ```
684
714
 
715
+ The standalone constructor cannot know the owning machine's input protocols,
716
+ so its `self` and `parent` references are non-sendable. When a source sends
717
+ through either reference, use the owning definition's bound constructor:
718
+
719
+ ```ts
720
+ const definition = Machine.make({
721
+ events: Commands,
722
+ internalEvents: InternalEvents,
723
+ parentEvents: ParentEvents,
724
+ // ...
725
+ })
726
+
727
+ const machine = definition.handle({
728
+ Saving: {
729
+ invoke: definition.invoke({
730
+ id: "notify-parent",
731
+ effect: ({ parent }) =>
732
+ parent === undefined
733
+ ? Effect.void
734
+ : parent.send(ParentEvents.SaveStarted()),
735
+ onDone: ({ target }) => target.none(),
736
+ onFailure: ({ target }) => target.none()
737
+ })
738
+ }
739
+ })
740
+ ```
741
+
685
742
  A direct `invoke: { ... }` object remains available when lifecycle handlers do
686
743
  not need source-derived context.
687
744
 
@@ -729,9 +786,11 @@ parentRef.child(Editor)
729
786
  parentAtom.child(Editor)
730
787
  ```
731
788
 
732
- Child emissions are delivered through the parent's internal protocol.
733
- `onSnapshot`, `onDone`, and `onFailure` are direct parent transitions. Invoked
734
- child IDs must be unique while simultaneously active.
789
+ Child emissions remain on the child's hot `emissions` stream; they are never
790
+ delivered implicitly to the parent. A child sends an input explicitly with
791
+ `enqueue.sendTo(parent, ParentEvents.Example())`. `onSnapshot`, `onDone`, and
792
+ `onFailure` are direct parent transitions. Invoked child IDs must be unique
793
+ while simultaneously active.
735
794
 
736
795
  Descriptors with the same id and machine identity address the same child, even
737
796
  when independently constructed. The descriptor objects themselves are not
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typeonce/effect-machine",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Schema-first state machines and statecharts for Effect",
5
5
  "author": "Sandro Maglione",
6
6
  "repository": {