@typeonce/effect-machine 0.13.0 → 0.14.1

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 (59) hide show
  1. package/README.md +74 -26
  2. package/dist/Machine.d.ts +379 -188
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js +119 -53
  5. package/dist/Machine.js.map +1 -1
  6. package/dist/internal/machine/executionPlan.d.ts.map +1 -1
  7. package/dist/internal/machine/executionPlan.js +14 -6
  8. package/dist/internal/machine/executionPlan.js.map +1 -1
  9. package/dist/internal/machine/machine.d.ts +3 -1
  10. package/dist/internal/machine/machine.d.ts.map +1 -1
  11. package/dist/internal/machine/machine.js +318 -26
  12. package/dist/internal/machine/machine.js.map +1 -1
  13. package/dist/internal/machine/planner.d.ts +13 -0
  14. package/dist/internal/machine/planner.d.ts.map +1 -1
  15. package/dist/internal/machine/planner.js +15 -7
  16. package/dist/internal/machine/planner.js.map +1 -1
  17. package/dist/internal/machine/topology.d.ts +12 -0
  18. package/dist/internal/machine/topology.d.ts.map +1 -1
  19. package/dist/internal/machine/topology.js +17 -10
  20. package/dist/internal/machine/topology.js.map +1 -1
  21. package/dist/internal/testing/machine/exploration.d.ts.map +1 -1
  22. package/dist/internal/testing/machine/exploration.js +11 -2
  23. package/dist/internal/testing/machine/exploration.js.map +1 -1
  24. package/dist/internal/testing/machine/finiteModel.d.ts.map +1 -1
  25. package/dist/internal/testing/machine/finiteModel.js +72 -66
  26. package/dist/internal/testing/machine/finiteModel.js.map +1 -1
  27. package/dist/internal/testing/machine/transitionCoverage.d.ts +20 -0
  28. package/dist/internal/testing/machine/transitionCoverage.d.ts.map +1 -0
  29. package/dist/internal/testing/machine/transitionCoverage.js +80 -0
  30. package/dist/internal/testing/machine/transitionCoverage.js.map +1 -0
  31. package/dist/internal/testing/machine/verification.d.ts.map +1 -1
  32. package/dist/internal/testing/machine/verification.js +171 -33
  33. package/dist/internal/testing/machine/verification.js.map +1 -1
  34. package/dist/testing/MachineTest.d.ts +97 -22
  35. package/dist/testing/MachineTest.d.ts.map +1 -1
  36. package/dist/testing/MachineTest.js +58 -16
  37. package/dist/testing/MachineTest.js.map +1 -1
  38. package/dist/unstable/cluster/ClusterMachine.d.ts +4 -1
  39. package/dist/unstable/cluster/ClusterMachine.d.ts.map +1 -1
  40. package/dist/unstable/cluster/ClusterMachine.js +4 -1
  41. package/dist/unstable/cluster/ClusterMachine.js.map +1 -1
  42. package/dist/unstable/reactivity/AtomMachine.d.ts +12 -3
  43. package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
  44. package/dist/unstable/reactivity/AtomMachine.js +12 -3
  45. package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
  46. package/docs/agent-guide.md +139 -57
  47. package/package.json +1 -1
  48. package/src/Machine.ts +750 -336
  49. package/src/internal/machine/executionPlan.ts +22 -7
  50. package/src/internal/machine/machine.ts +420 -33
  51. package/src/internal/machine/planner.ts +44 -13
  52. package/src/internal/machine/topology.ts +38 -12
  53. package/src/internal/testing/machine/exploration.ts +10 -2
  54. package/src/internal/testing/machine/finiteModel.ts +106 -73
  55. package/src/internal/testing/machine/transitionCoverage.ts +116 -0
  56. package/src/internal/testing/machine/verification.ts +216 -58
  57. package/src/testing/MachineTest.ts +118 -28
  58. package/src/unstable/cluster/ClusterMachine.ts +4 -1
  59. package/src/unstable/reactivity/AtomMachine.ts +12 -3
package/README.md CHANGED
@@ -66,19 +66,31 @@ const CounterDefinition = Machine.make({
66
66
  id: "Counter",
67
67
  states: States.states,
68
68
  events: CounterEvent,
69
- initial: () => States.initial.Idle.from()
69
+ initial: {
70
+ target: (to) => to.Idle(),
71
+ resolve: ({ target }) => target.from()
72
+ }
70
73
  })
71
74
 
72
75
  const Counter = CounterDefinition.handle({
73
76
  Idle: {
74
77
  on: {
75
- Start: ({ target }) => target.full.Running.from({ count: 0 })
78
+ Start: Machine.transition({
79
+ target: (to) => to.full.Running(),
80
+ resolve: ({ target }) => target.from({ count: 0 })
81
+ })
76
82
  }
77
83
  },
78
84
  Running: {
79
85
  on: {
80
- Increment: ({ state, target }) => target.full.Running.from({ count: state.count + 1 }),
81
- Stop: ({ target }) => target.full.Idle.from()
86
+ Increment: Machine.transition({
87
+ target: (to) => to.full.Running(),
88
+ resolve: ({ state, target }) => target.from({ count: state.count + 1 })
89
+ }),
90
+ Stop: Machine.transition({
91
+ target: (to) => to.full.Idle(),
92
+ resolve: ({ target }) => target.from()
93
+ })
82
94
  }
83
95
  }
84
96
  })
@@ -111,8 +123,7 @@ Use this order to preserve inference and keep boundaries explicit:
111
123
  Use `.from(...)` when constructing a new state from fields:
112
124
 
113
125
  ```ts
114
- target.local.Saving.from({ draft: event.draft })
115
- States.initial.Form.from({ draft: "" }, (form) => form.Editing.from())
126
+ target.from({ draft: event.draft })
116
127
  ```
117
128
 
118
129
  The machine runs these inputs through the state schema while planning. Schema
@@ -124,10 +135,12 @@ When sibling states share fields, remove the source discriminator and pass the
124
135
  remaining fields through the target schema:
125
136
 
126
137
  ```ts
127
- Submit: ;
128
- ;(({ state, target }) => {
129
- const { _tag: _, ...fields } = state
130
- return target.local.Saving.from({ ...fields, attempt: 1 })
138
+ Submit: Machine.transition({
139
+ target: (to) => to.local.Saving(),
140
+ resolve: ({ state, target }) => {
141
+ const { _tag: _, ...fields } = state
142
+ return target.from({ ...fields, attempt: 1 })
143
+ }
131
144
  })
132
145
  ```
133
146
 
@@ -144,7 +157,10 @@ const States = Machine.defineStates({
144
157
  }
145
158
  })
146
159
 
147
- States.initial.Form.from((form) => form.Editing.from())
160
+ initial: {
161
+ target: (to) => to.Form.initial(),
162
+ resolve: ({ target }) => target((form) => form.Editing.from())
163
+ }
148
164
  ```
149
165
 
150
166
  Schema-less states remain active, targetable, matchable, and visible through
@@ -181,7 +197,10 @@ const definition = Machine.make({
181
197
  events: CommandEvent,
182
198
  internalEvents: InternalEvent,
183
199
  emittedEvents: Emissions,
184
- initial: () => States.initial.Idle.from()
200
+ initial: {
201
+ target: (to) => to.Idle(),
202
+ resolve: ({ target }) => target.from()
203
+ }
185
204
  })
186
205
  ```
187
206
 
@@ -293,16 +312,22 @@ const child = Machine.make({
293
312
  states: ChildStates.states,
294
313
  events: ChildEvents,
295
314
  parentEvents: ParentEvents,
296
- initial: () => ChildStates.initial.Working.from()
315
+ initial: {
316
+ target: (to) => to.Working(),
317
+ resolve: ({ target }) => target.from()
318
+ }
297
319
  }).handle({
298
320
  Working: {
299
321
  on: {
300
- Finish: ({ parent, target }, enqueue) => {
301
- if (parent !== undefined) {
302
- enqueue.sendTo(parent, ParentEvents.ChildFinished({ id: "job-1" }))
322
+ Finish: Machine.transition({
323
+ target: (to) => to.full.Done(),
324
+ resolve: ({ parent, target }, enqueue) => {
325
+ if (parent !== undefined) {
326
+ enqueue.sendTo(parent, ParentEvents.ChildFinished({ id: "job-1" }))
327
+ }
328
+ return target.from()
303
329
  }
304
- return target.full.Done.from()
305
- }
330
+ })
306
331
  }
307
332
  },
308
333
  Done: {}
@@ -377,8 +402,14 @@ Loading: {
377
402
  invoke: Machine.invoke({
378
403
  id: "save-document",
379
404
  effect: () => saveDocument,
380
- onDone: ({ output, target }) => target.full.Saved({ id: output.id }),
381
- onFailure: ({ error, target }) => target.full.Failed({ message: String(error) })
405
+ onDone: Machine.transition({
406
+ target: (to) => to.full.Saved(),
407
+ resolve: ({ output, target }) => target.from({ id: output.id })
408
+ }),
409
+ onFailure: Machine.transition({
410
+ target: (to) => to.full.Failed(),
411
+ resolve: ({ error, target }) => target.from({ message: String(error) })
412
+ })
382
413
  })
383
414
  }
384
415
 
@@ -386,7 +417,10 @@ Waiting: {
386
417
  invoke: Machine.invoke({
387
418
  id: "save-timeout",
388
419
  after: "3 seconds",
389
- onDone: ({ target }) => target.full.Failed({ message: "Timed out" })
420
+ onDone: Machine.transition({
421
+ target: (to) => to.full.Failed(),
422
+ resolve: ({ target }) => target.from({ message: "Timed out" })
423
+ })
390
424
  })
391
425
  }
392
426
  ```
@@ -401,8 +435,14 @@ for state-dependent Effects:
401
435
  invoke: Machine.invoke({
402
436
  id: "load-document",
403
437
  effect: ({ state }) => loadDocument(state.documentId),
404
- onDone: ({ output, target }) => target.full.Ready({ document: output }),
405
- onFailure: ({ error, target }) => target.full.Failed({ message: error.message })
438
+ onDone: Machine.transition({
439
+ target: (to) => to.full.Ready(),
440
+ resolve: ({ output, target }) => target.from({ document: output })
441
+ }),
442
+ onFailure: Machine.transition({
443
+ target: (to) => to.full.Failed(),
444
+ resolve: ({ error, target }) => target.from({ message: error.message })
445
+ })
406
446
  })
407
447
  ```
408
448
 
@@ -428,8 +468,14 @@ const machine = definition.handle({
428
468
  parent === undefined
429
469
  ? Effect.void
430
470
  : parent.send(ParentEvents.SaveStarted()),
431
- onDone: ({ target }) => target.none(),
432
- onFailure: ({ target }) => target.none()
471
+ onDone: Machine.transition({
472
+ target: (to) => to.none(),
473
+ resolve: () => undefined
474
+ }),
475
+ onFailure: Machine.transition({
476
+ target: (to) => to.none(),
477
+ resolve: () => undefined
478
+ })
433
479
  })
434
480
  }
435
481
  })
@@ -501,8 +547,10 @@ encoded snapshot.
501
547
  The testing entrypoint provides complementary layers:
502
548
 
503
549
  - `MachineTest.run` and `verify` inspect pure planner traces;
550
+ - `coverage` reports exact transition-definition and conditional-branch hits;
504
551
  - invariants and generated scenarios check application laws;
505
- - `explore` performs bounded breadth-first state-space exploration;
552
+ - `explore` performs bounded breadth-first state-space exploration and retains
553
+ exact transition-definition and branch coverage for every plan it computes;
506
554
  - `probe` causally acknowledges live runtime commands;
507
555
  - runtime command models cover timers, invokes, bursts, and scheduling.
508
556