@typeonce/effect-machine 0.19.1 → 0.21.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.
- package/README.md +90 -14
- package/dist/Machine.d.ts +155 -18
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +15 -3
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/atom.d.ts.map +1 -1
- package/dist/internal/machine/atom.js +18 -4
- package/dist/internal/machine/atom.js.map +1 -1
- package/dist/internal/machine/executionPlan.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.js +33 -3
- package/dist/internal/machine/executionPlan.js.map +1 -1
- package/dist/internal/machine/invocation.d.ts.map +1 -1
- package/dist/internal/machine/invocation.js +7 -0
- package/dist/internal/machine/invocation.js.map +1 -1
- package/dist/internal/machine/machine.d.ts +1 -0
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +49 -13
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/planner.d.ts +11 -2
- package/dist/internal/machine/planner.d.ts.map +1 -1
- package/dist/internal/machine/planner.js +49 -9
- package/dist/internal/machine/planner.js.map +1 -1
- package/dist/internal/machine/runtime.d.ts +4 -3
- package/dist/internal/machine/runtime.d.ts.map +1 -1
- package/dist/internal/machine/runtime.js +12 -1
- package/dist/internal/machine/runtime.js.map +1 -1
- package/dist/internal/machine/topology.d.ts +9 -1
- package/dist/internal/machine/topology.d.ts.map +1 -1
- package/dist/internal/machine/topology.js +7 -0
- package/dist/internal/machine/topology.js.map +1 -1
- package/dist/internal/testing/machine/verification.d.ts.map +1 -1
- package/dist/internal/testing/machine/verification.js +15 -3
- package/dist/internal/testing/machine/verification.js.map +1 -1
- package/dist/testing/MachineTest.d.ts +2 -0
- package/dist/testing/MachineTest.d.ts.map +1 -1
- package/dist/testing/MachineTest.js.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +10 -8
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.js +2 -2
- package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
- package/docs/agent-guide.md +48 -0
- package/docs/effect-atom-react.md +28 -0
- package/package.json +1 -1
- package/src/Machine.ts +371 -45
- package/src/internal/machine/atom.ts +26 -18
- package/src/internal/machine/executionPlan.ts +37 -3
- package/src/internal/machine/invocation.ts +13 -1
- package/src/internal/machine/machine.ts +75 -15
- package/src/internal/machine/planner.ts +64 -11
- package/src/internal/machine/runtime.ts +48 -19
- package/src/internal/machine/topology.ts +18 -1
- package/src/internal/testing/machine/verification.ts +16 -3
- package/src/testing/MachineTest.ts +2 -0
- package/src/unstable/reactivity/AtomMachine.ts +10 -8
|
@@ -29,6 +29,8 @@ export const DeclinedTypeId: unique symbol = Symbol("effect/Machine/Declined")
|
|
|
29
29
|
|
|
30
30
|
export const TargetSelectionTypeId: unique symbol = Symbol("effect/Machine/TargetSelection")
|
|
31
31
|
|
|
32
|
+
export const StateUpdateTypeId: unique symbol = Symbol("effect/Machine/StateUpdate")
|
|
33
|
+
|
|
32
34
|
export const SelectedBranchTypeId: unique symbol = Symbol("effect/Machine/SelectedBranch")
|
|
33
35
|
|
|
34
36
|
interface StateInput {
|
|
@@ -73,7 +75,7 @@ export interface Declined {
|
|
|
73
75
|
readonly [DeclinedTypeId]: typeof DeclinedTypeId
|
|
74
76
|
}
|
|
75
77
|
|
|
76
|
-
export type TargetSelectionKind = "state" | "initial" | "history" | "choice" | "none"
|
|
78
|
+
export type TargetSelectionKind = "state" | "initial" | "history" | "choice" | "update" | "none"
|
|
77
79
|
|
|
78
80
|
export type TargetSelectionScope = "local" | "branch" | "full" | "initial"
|
|
79
81
|
|
|
@@ -111,6 +113,21 @@ export const noneTargetSelection: TargetSelection = makeTargetSelection("none",
|
|
|
111
113
|
|
|
112
114
|
export const isTargetSelection = (u: unknown): u is TargetSelection => hasProperty(u, TargetSelectionTypeId)
|
|
113
115
|
|
|
116
|
+
export interface StateUpdate {
|
|
117
|
+
readonly [StateUpdateTypeId]: typeof StateUpdateTypeId
|
|
118
|
+
readonly path: string
|
|
119
|
+
readonly value: unknown
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const makeStateUpdate = (path: string, value: unknown): StateUpdate =>
|
|
123
|
+
Object.freeze({
|
|
124
|
+
[StateUpdateTypeId]: StateUpdateTypeId,
|
|
125
|
+
path,
|
|
126
|
+
value
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
export const isStateUpdate = (u: unknown): u is StateUpdate => hasProperty(u, StateUpdateTypeId)
|
|
130
|
+
|
|
114
131
|
export const makeSelectedBranch = (
|
|
115
132
|
owner: object,
|
|
116
133
|
branchIndex: number,
|
|
@@ -475,7 +475,7 @@ const targetWithinSelection = (
|
|
|
475
475
|
nodeByPath: ReadonlyMap<string, Machine.Machine.StateNode>
|
|
476
476
|
): boolean => {
|
|
477
477
|
const selection = branch.selection
|
|
478
|
-
if (selection.kind === "none") return target === undefined
|
|
478
|
+
if (selection.kind === "none" || selection.kind === "update") return target === undefined
|
|
479
479
|
if (target === undefined || selection.path === undefined) return false
|
|
480
480
|
if (target === selection.path) return true
|
|
481
481
|
const selectedNode = nodeByPath.get(selection.path)
|
|
@@ -564,6 +564,7 @@ export const coverage = <M extends AnyMachine>(
|
|
|
564
564
|
const exitHits = new Set<number>()
|
|
565
565
|
|
|
566
566
|
const transitionCoverage = makeTransitionCoverageCollector(machine)
|
|
567
|
+
const transitionDefinitions = Machine.transitionDefinitions(machine)
|
|
567
568
|
|
|
568
569
|
const declaredEvents = publicEventTags(machine)
|
|
569
570
|
const declaredEventTags = declaredEvents.tags
|
|
@@ -577,6 +578,7 @@ export const coverage = <M extends AnyMachine>(
|
|
|
577
578
|
let microsteps = 0
|
|
578
579
|
let changedMicrosteps = 0
|
|
579
580
|
let targetlessTransitions = 0
|
|
581
|
+
let stateUpdates = 0
|
|
580
582
|
let raisedEvents = 0
|
|
581
583
|
let emittedEvents = 0
|
|
582
584
|
let eventTriggered = 0
|
|
@@ -630,7 +632,13 @@ export const coverage = <M extends AnyMachine>(
|
|
|
630
632
|
hitPaths(microstep.exitPaths, exitHits)
|
|
631
633
|
observeSnapshot(microstep.next)
|
|
632
634
|
for (const retained of microstep.transitions) {
|
|
633
|
-
|
|
635
|
+
const definition = transitionDefinitions.find((candidate) =>
|
|
636
|
+
candidate.source === retained.source && candidate.reenter === retained.reenter &&
|
|
637
|
+
sameTransitionTrigger(candidate.trigger, retained.trigger)
|
|
638
|
+
)
|
|
639
|
+
const branch = definition?.branches[retained.branchIndex]
|
|
640
|
+
if (branch?.selection.kind === "update") stateUpdates += 1
|
|
641
|
+
else if (retained.target === undefined) targetlessTransitions += 1
|
|
634
642
|
if (retained.trigger.type === "event") eventTriggered += 1
|
|
635
643
|
else if (retained.trigger.type === "always") alwaysTriggered += 1
|
|
636
644
|
else if (retained.trigger.type === "done") doneTriggered += 1
|
|
@@ -718,6 +726,7 @@ export const coverage = <M extends AnyMachine>(
|
|
|
718
726
|
total: microsteps,
|
|
719
727
|
changed: changedMicrosteps,
|
|
720
728
|
targetless: targetlessTransitions,
|
|
729
|
+
updates: stateUpdates,
|
|
721
730
|
raised: raisedEvents,
|
|
722
731
|
emitted: emittedEvents,
|
|
723
732
|
eventTriggered,
|
|
@@ -1598,7 +1607,11 @@ export const verify = <M extends AnyMachine>(
|
|
|
1598
1607
|
const resolvedTarget = transition.resolvedTarget === undefined ? undefined : String(transition.resolvedTarget)
|
|
1599
1608
|
const targetNode = target === undefined ? undefined : byPath.get(target)
|
|
1600
1609
|
let expected = target
|
|
1601
|
-
let explanation =
|
|
1610
|
+
let explanation = branches[index]?.selection.kind === "update"
|
|
1611
|
+
? `update owner "${String(branches[index]?.selection.path)}"`
|
|
1612
|
+
: target === undefined
|
|
1613
|
+
? "an unresolved targetless transition"
|
|
1614
|
+
: `target "${target}"`
|
|
1602
1615
|
|
|
1603
1616
|
if (transition.trigger.type === "choice") {
|
|
1604
1617
|
explanation = target === undefined ? "a targetless choice edge" : `choice edge target "${target}"`
|
|
@@ -1822,6 +1822,8 @@ export interface MicrostepCoverageEvidence {
|
|
|
1822
1822
|
readonly total: number
|
|
1823
1823
|
readonly changed: number
|
|
1824
1824
|
readonly targetless: number
|
|
1825
|
+
/** Retained state-value update operations. */
|
|
1826
|
+
readonly updates: number
|
|
1825
1827
|
readonly raised: number
|
|
1826
1828
|
readonly emitted: number
|
|
1827
1829
|
readonly eventTriggered: number
|
|
@@ -148,9 +148,9 @@ export interface MachineAtom<State, Event, Error = never, Output = never, StartE
|
|
|
148
148
|
readonly stop: Atom.Writable<AsyncResult.AsyncResult<void, StartError | NotReadyError>, void>
|
|
149
149
|
|
|
150
150
|
/**
|
|
151
|
-
* Creates a reactive bridge for a directly
|
|
152
|
-
*
|
|
153
|
-
* referenced.
|
|
151
|
+
* Creates a reactive bridge for a directly owned child machine.
|
|
152
|
+
* Descriptors with the same id and machine definition return the same live
|
|
153
|
+
* bridge while it remains referenced.
|
|
154
154
|
*
|
|
155
155
|
* @since 0.4.0
|
|
156
156
|
*/
|
|
@@ -206,7 +206,8 @@ export const childEmissions: <Child extends Machine.ChildMachine.Any, StartError
|
|
|
206
206
|
> = internal.childEmissions
|
|
207
207
|
|
|
208
208
|
/**
|
|
209
|
-
* Reactive access to one
|
|
209
|
+
* Reactive access to one directly owned child machine selected by its
|
|
210
|
+
* descriptor.
|
|
210
211
|
*
|
|
211
212
|
* **Details**
|
|
212
213
|
*
|
|
@@ -295,8 +296,9 @@ export interface ChildMachineAtom<Child extends Machine.ChildMachine.Any, StartE
|
|
|
295
296
|
void
|
|
296
297
|
>
|
|
297
298
|
/**
|
|
298
|
-
* Creates a reactive bridge for a directly owned nested child.
|
|
299
|
-
* same
|
|
299
|
+
* Creates a reactive bridge for a directly owned nested child. Descriptors
|
|
300
|
+
* with the same id and machine definition return the same live bridge while
|
|
301
|
+
* it remains referenced.
|
|
300
302
|
*
|
|
301
303
|
* @since 0.4.0
|
|
302
304
|
*/
|
|
@@ -418,7 +420,7 @@ export const selectSnapshot: <
|
|
|
418
420
|
> = internal.selectSnapshot
|
|
419
421
|
|
|
420
422
|
/**
|
|
421
|
-
* Selects the typed value for an active state path in
|
|
423
|
+
* Selects the typed value for an active state path in a directly owned child.
|
|
422
424
|
*
|
|
423
425
|
* Valid paths and their selected value types are inferred from the child
|
|
424
426
|
* bridge. An inactive child produces `Option.none()`. Keep the returned atom
|
|
@@ -513,7 +515,7 @@ export const matches: <
|
|
|
513
515
|
) => Atom.Atom<AsyncResult.AsyncResult<boolean, StartError | Error>> = internal.matches
|
|
514
516
|
|
|
515
517
|
/**
|
|
516
|
-
* Returns whether a state path is active in
|
|
518
|
+
* Returns whether a state path is active in a directly owned child.
|
|
517
519
|
*
|
|
518
520
|
* Valid paths are inferred from the child bridge snapshot.
|
|
519
521
|
* An inactive child produces `false`. Keep the returned atom stable when
|