@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.
- package/README.md +74 -26
- package/dist/Machine.d.ts +379 -188
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +119 -53
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/executionPlan.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.js +14 -6
- package/dist/internal/machine/executionPlan.js.map +1 -1
- package/dist/internal/machine/machine.d.ts +3 -1
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +318 -26
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/planner.d.ts +13 -0
- package/dist/internal/machine/planner.d.ts.map +1 -1
- package/dist/internal/machine/planner.js +15 -7
- package/dist/internal/machine/planner.js.map +1 -1
- package/dist/internal/machine/topology.d.ts +12 -0
- package/dist/internal/machine/topology.d.ts.map +1 -1
- package/dist/internal/machine/topology.js +17 -10
- package/dist/internal/machine/topology.js.map +1 -1
- package/dist/internal/testing/machine/exploration.d.ts.map +1 -1
- package/dist/internal/testing/machine/exploration.js +11 -2
- package/dist/internal/testing/machine/exploration.js.map +1 -1
- package/dist/internal/testing/machine/finiteModel.d.ts.map +1 -1
- package/dist/internal/testing/machine/finiteModel.js +72 -66
- package/dist/internal/testing/machine/finiteModel.js.map +1 -1
- package/dist/internal/testing/machine/transitionCoverage.d.ts +20 -0
- package/dist/internal/testing/machine/transitionCoverage.d.ts.map +1 -0
- package/dist/internal/testing/machine/transitionCoverage.js +80 -0
- package/dist/internal/testing/machine/transitionCoverage.js.map +1 -0
- package/dist/internal/testing/machine/verification.d.ts.map +1 -1
- package/dist/internal/testing/machine/verification.js +171 -33
- package/dist/internal/testing/machine/verification.js.map +1 -1
- package/dist/testing/MachineTest.d.ts +97 -22
- package/dist/testing/MachineTest.d.ts.map +1 -1
- package/dist/testing/MachineTest.js +58 -16
- package/dist/testing/MachineTest.js.map +1 -1
- package/dist/unstable/cluster/ClusterMachine.d.ts +4 -1
- package/dist/unstable/cluster/ClusterMachine.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterMachine.js +4 -1
- package/dist/unstable/cluster/ClusterMachine.js.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +12 -3
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.js +12 -3
- package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
- package/docs/agent-guide.md +139 -57
- package/package.json +1 -1
- package/src/Machine.ts +750 -336
- package/src/internal/machine/executionPlan.ts +22 -7
- package/src/internal/machine/machine.ts +420 -33
- package/src/internal/machine/planner.ts +44 -13
- package/src/internal/machine/topology.ts +38 -12
- package/src/internal/testing/machine/exploration.ts +10 -2
- package/src/internal/testing/machine/finiteModel.ts +106 -73
- package/src/internal/testing/machine/transitionCoverage.ts +116 -0
- package/src/internal/testing/machine/verification.ts +216 -58
- package/src/testing/MachineTest.ts +118 -28
- package/src/unstable/cluster/ClusterMachine.ts +4 -1
- 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:
|
|
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:
|
|
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:
|
|
81
|
-
|
|
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.
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
315
|
+
initial: {
|
|
316
|
+
target: (to) => to.Working(),
|
|
317
|
+
resolve: ({ target }) => target.from()
|
|
318
|
+
}
|
|
297
319
|
}).handle({
|
|
298
320
|
Working: {
|
|
299
321
|
on: {
|
|
300
|
-
Finish: ({
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
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:
|
|
381
|
-
|
|
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:
|
|
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:
|
|
405
|
-
|
|
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: ({
|
|
432
|
-
|
|
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
|
|