@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
package/README.md CHANGED
@@ -10,6 +10,27 @@ cluster adapter.
10
10
  > This is early-release software. Its API may change, and each release targets
11
11
  > one exact Effect beta.
12
12
 
13
+ ## Design principles
14
+
15
+ - **Type-safe by construction:** reject invalid protocols, compositions, and
16
+ capabilities at compile time where possible, and preserve typed Effect
17
+ failures at runtime.
18
+ - **Explicit and opinionated:** give different semantics different names and
19
+ contracts. Builders and inference remove ceremony without making behavior
20
+ depend on ambiguous omissions.
21
+ - **Readable models:** keep schemas, topology, behavior, and effects concise
22
+ enough that a human can understand the complete model from its definition.
23
+ - **Effect-native:** design toward eventual inclusion in Effect core and follow
24
+ its API shape, module boundaries, ownership, and failure conventions.
25
+
26
+ The package is pre-1.0: a clearer or safer long-term API takes priority over
27
+ backward compatibility. Breaking changes use minor releases, compatible fixes
28
+ use patch releases, and compatibility aliases are not added by default.
29
+
30
+ The core machine model remains local. Distributed identity, placement,
31
+ transport, routing, delivery, and remote lifecycle semantics belong to Effect
32
+ Cluster and are exposed only through explicit integration boundaries.
33
+
13
34
  ## Install
14
35
 
15
36
  ```sh
@@ -136,7 +157,7 @@ data, put it on their compound parent.
136
157
 
137
158
  ### Separate inputs, raised events, and emissions
138
159
 
139
- `events` is the public actor-input protocol. Events raised to the same machine
160
+ `events` is the public machine-input protocol. Events raised to the same machine
140
161
  belong in `internalEvents`. Ephemeral outward notifications have their own
141
162
  `emittedEvents` protocol:
142
163
 
@@ -186,23 +207,33 @@ protocols but cannot expose a finite constructor set; pass a complete event
186
207
  object to `send` or `Machine.plan` for those events.
187
208
 
188
209
  `ref.emissions` is a hot `Stream`: it publishes only notifications produced
189
- after subscription, replays nothing, and completes when the actor terminates.
210
+ after subscription, replays nothing, and completes when the machine terminates.
190
211
  Snapshots remain separate and stateful: `ref.changes` begins with the current
191
- lifecycle snapshot and then follows later changes. Because `Machine.start`
192
- returns only after initialization, startup emissions are not observable from
193
- the returned ref; represent startup facts in state when they must be retained.
212
+ lifecycle snapshot and then follows later changes. Use `Machine.prepare` when
213
+ an observer must be installed before initial-entry actions run:
194
214
 
195
215
  ```ts
196
- const next = ref.emissions.pipe(Stream.take(1), Stream.runHead)
216
+ const prepared = yield * Machine.prepare(machine)
217
+
218
+ yield * prepared.emissions.pipe(
219
+ Stream.runForEach(handleEmission),
220
+ Effect.forkScoped({ startImmediately: true })
221
+ )
222
+
223
+ const ref = yield * prepared.start
197
224
  ```
198
225
 
226
+ `Machine.start(machine)` remains the one-step convenience for callers that do
227
+ not observe startup emissions. Preparation does not retain or replay an
228
+ emission: the observer is simply subscribed before initialization begins.
229
+
199
230
  Invalid event and emission constructions fail the machine with a typed
200
231
  `MachineSchemaDecodeError`; they do not throw from the constructor call.
201
232
 
202
- ### Send explicitly between actors
233
+ ### Send explicitly between machines
203
234
 
204
- `raise` targets the current machine in the same macrostep. `sendTo` targets an
205
- actor mailbox and is processed later. A child declares the subset of parent
235
+ `raise` targets the current machine in the same macrostep. `sendTo` targets a
236
+ machine mailbox and is processed later. A child declares the subset of parent
206
237
  inputs it may send with `parentEvents`:
207
238
 
208
239
  ```ts
@@ -234,15 +265,18 @@ const ParentInputs = Machine.events(Start, ParentEvents)
234
265
  The same child remains isolated and may be started as a root, where `parent` is
235
266
  `undefined`. When `Child` is invoked, the parent definition must accept every
236
267
  event in `parentEvents`; otherwise `.handle(...)` is a compile-time error.
237
- Inside the child, the parent reference accepts only those declared events.
238
- `emit` never sends to the parent: it only publishes on the emitting actor's
268
+ Inside the child, the parent target accepts only those declared events.
269
+ `emit` never sends to the parent: it only publishes on the emitting machine's
239
270
  `emissions` stream.
240
271
 
241
272
  Every handler also receives `self`, which can be targeted with `sendTo` when a
242
273
  later mailbox turn is required. Use `raise` instead for same-macrostep work.
274
+ Both `self` and `parent` are minimal `Machine.MachineTarget<Event>` values. The
275
+ shared `Machine.MachineReferences<InputEvents, ParentEvents>` context keeps
276
+ their input protocols separate without exposing snapshot or lifecycle APIs.
243
277
  Structural state values use distinct names: `containingState` is the immediate
244
278
  valued state in the same statechart, while `ancestors` maps valued ancestor
245
- paths. `parent` always means the owning actor reference.
279
+ paths. `parent` always means the owning machine target.
246
280
 
247
281
  ### Choose the target by scope
248
282
 
@@ -322,6 +356,35 @@ invoke: Machine.invoke({
322
356
  })
323
357
  ```
324
358
 
359
+ The standalone `Machine.invoke(...)` constructor does not know the owning
360
+ definition, so its `self` and `parent` references are non-sendable. When an
361
+ invocation callback sends through either reference, construct it through the
362
+ owning definition so those references use its exact public input and
363
+ `parentEvents` protocols:
364
+
365
+ ```ts
366
+ const definition = Machine.make({
367
+ events: Commands,
368
+ internalEvents: InternalEvents,
369
+ parentEvents: ParentEvents
370
+ // ...
371
+ })
372
+
373
+ const machine = definition.handle({
374
+ Saving: {
375
+ invoke: definition.invoke({
376
+ id: "notify-parent",
377
+ effect: ({ parent }) =>
378
+ parent === undefined
379
+ ? Effect.void
380
+ : parent.send(ParentEvents.SaveStarted()),
381
+ onDone: ({ target }) => target.none(),
382
+ onFailure: ({ target }) => target.none()
383
+ })
384
+ }
385
+ })
386
+ ```
387
+
325
388
  A direct `invoke: { ... }` object is also supported when its lifecycle handlers
326
389
  do not need source-derived context. Reuse one exported
327
390
  `Machine.child(id, machine)` descriptor for invocation, `sendTo`, and child
@@ -362,7 +425,7 @@ const childEmissions = AtomMachine.childEmissions(counterAtom.child(Worker))
362
425
  ```
363
426
 
364
427
  These streams require the same `AtomRegistry`, follow the currently mounted
365
- actor instance, and do not replay notifications from an earlier subscription
428
+ machine instance, and do not replay notifications from an earlier subscription
366
429
  or child instance.
367
430
 
368
431
  ## Persistence