@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
package/README.md
CHANGED
|
@@ -420,6 +420,47 @@ choice destinations remain calls such as `to.full.Running()`. Runtime named
|
|
|
420
420
|
branch builders remain callable, including `select.unchanged()`, because their
|
|
421
421
|
result carries the selected branch evidence.
|
|
422
422
|
|
|
423
|
+
### Update an active scope value
|
|
424
|
+
|
|
425
|
+
Use `to.local.update(...)` to replace the value owned by the nearest active
|
|
426
|
+
compound scope without rebuilding its active child. Use
|
|
427
|
+
`to.branch.<path>.update(...)` for a valued compound or parallel ancestor of the
|
|
428
|
+
handler source:
|
|
429
|
+
|
|
430
|
+
```ts
|
|
431
|
+
Increment: ;
|
|
432
|
+
;((to) =>
|
|
433
|
+
to.branch.root.session.update(({ ancestors, target }) => target.from({ count: ancestors["root.session"].count + 1 })))
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
The update keeps the exact active descendants, their values, history records,
|
|
437
|
+
completion outputs, and unrelated parallel regions. It runs no exit or entry
|
|
438
|
+
actions and does not restart state-owned work. Eventless stabilization still
|
|
439
|
+
runs, so an `always` transition can react to the new value.
|
|
440
|
+
|
|
441
|
+
`update` is callable when used directly and is also a static selection for a
|
|
442
|
+
named branch:
|
|
443
|
+
|
|
444
|
+
```ts
|
|
445
|
+
to.branches({
|
|
446
|
+
changed: { target: to.local.update },
|
|
447
|
+
unchanged: { target: to.none }
|
|
448
|
+
}).resolve(({ select, event }) =>
|
|
449
|
+
event.changed
|
|
450
|
+
? select.changed.from({ count: event.count })
|
|
451
|
+
: select.unchanged()
|
|
452
|
+
)
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
The resolver must return `target(value)` or `target.from(input)`. It may return
|
|
456
|
+
`decline()` only with `{ declinable: true }`. Pass `{ reenter: true }` on event
|
|
457
|
+
or invocation transitions when the handler source should exit and enter again.
|
|
458
|
+
Reentry applies to that source, not to the ancestor whose value changed.
|
|
459
|
+
|
|
460
|
+
The selector omits `update` for schema-less scopes, atomic and final states,
|
|
461
|
+
inactive branches, parallel sibling regions, and choice resolvers. Updating a
|
|
462
|
+
parallel sibling requires an event handled by that region.
|
|
463
|
+
|
|
423
464
|
Use `declinable: true` when a resolver may decide that its transition is not
|
|
424
465
|
enabled. Only that resolver receives `decline()`, and its return type expands to
|
|
425
466
|
accept the opaque declined result:
|
|
@@ -582,6 +623,46 @@ entered. Use an Effect containing `Effect.sleep(...)` for generic work, while
|
|
|
582
623
|
`from.timer(...)` keeps timer intent explicit and makes static durations visible
|
|
583
624
|
through activity inspection.
|
|
584
625
|
|
|
626
|
+
### Spawn dynamic child machines
|
|
627
|
+
|
|
628
|
+
Use `from.child(...)` when a state owns a fixed child lifecycle. Use the
|
|
629
|
+
`children` context inside an invoked Effect when the machine process owns an
|
|
630
|
+
open set of children that must survive state changes:
|
|
631
|
+
|
|
632
|
+
```ts
|
|
633
|
+
const Plant = Machine.childFamily(plantMachine)
|
|
634
|
+
|
|
635
|
+
const central = Machine.make({
|
|
636
|
+
events: Machine.events(ResourcesOffered, PlantBroken)
|
|
637
|
+
// ...
|
|
638
|
+
}).handle({
|
|
639
|
+
Commissioning: {
|
|
640
|
+
invoke: (from) =>
|
|
641
|
+
from.effect("commission-wave", ({ children, state }) =>
|
|
642
|
+
Effect.forEach(
|
|
643
|
+
state.plants,
|
|
644
|
+
(input) => children.spawn(Plant(input.id), { input }),
|
|
645
|
+
{ discard: true }
|
|
646
|
+
))
|
|
647
|
+
.onDone((to) => to.full.Operating())
|
|
648
|
+
.onFailure((to) => to.full.CommissioningFailed())
|
|
649
|
+
}
|
|
650
|
+
})
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
`children.spawn` completes after initialization. The new child remains owned
|
|
654
|
+
by the machine process after the commissioning Effect completes or its state
|
|
655
|
+
exits. `children.sendTo` and `children.stop` address one active child from an
|
|
656
|
+
Effect; transition resolvers use `enqueue.sendTo` and `enqueue.stop` with the
|
|
657
|
+
same descriptor. Duplicate active ids fail with `ChildAlreadyExistsError` and
|
|
658
|
+
do not replace the existing child. Earlier successful spawns remain active if
|
|
659
|
+
a later spawn in the same wave fails.
|
|
660
|
+
|
|
661
|
+
The child machine's declared `Machine.parent(...)` events must be accepted by
|
|
662
|
+
the owner. This is checked at each spawn call even though ids and cardinality
|
|
663
|
+
remain dynamic. `scope.spawn(child, { input })` provides the same descriptor
|
|
664
|
+
form for lower-level process logic, where the process event protocol is known.
|
|
665
|
+
|
|
585
666
|
## Reactivity
|
|
586
667
|
|
|
587
668
|
`AtomMachine` runs one lazy machine instance per `AtomRegistry`:
|
|
@@ -603,6 +684,15 @@ The bridge exposes `ref`, `snapshot`, `state`, fail-aware `result`, writable
|
|
|
603
684
|
equality-aware derivations. React applications using `@effect/atom-react` need
|
|
604
685
|
a `RegistryProvider`.
|
|
605
686
|
|
|
687
|
+
Descriptors reconstructed from a `Machine.childFamily` resolve the same child
|
|
688
|
+
bridge by machine identity and id:
|
|
689
|
+
|
|
690
|
+
```ts
|
|
691
|
+
const Plant = Machine.childFamily(plantMachine)
|
|
692
|
+
const plantAtom = centralAtom.child(Plant(selectedPlantId))
|
|
693
|
+
const brokenAtom = AtomMachine.matchesChild(plantAtom, "Broken")
|
|
694
|
+
```
|
|
695
|
+
|
|
606
696
|
Emissions stay streams rather than becoming retained atom state:
|
|
607
697
|
|
|
608
698
|
```ts
|
|
@@ -679,20 +769,6 @@ import { MachineTest } from "@typeonce/effect-machine/testing"
|
|
|
679
769
|
|
|
680
770
|
Each ESM entrypoint is independent and tree-shakeable.
|
|
681
771
|
|
|
682
|
-
## Examples
|
|
683
|
-
|
|
684
|
-
Every package directly under [`examples/`](./examples) has its own lockfile and
|
|
685
|
-
`check` script.
|
|
686
|
-
|
|
687
|
-
| Example | What it demonstrates |
|
|
688
|
-
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
689
|
-
| [Playground](./examples/playground) | Five focused React examples: atomic turnstile commands, state-scoped traffic-light timers, hierarchical microwave safety, a resource-owned media player, and a worker-hosted machine synchronized across tabs |
|
|
690
|
-
| [Pokémon](./examples/pokemon) | Compound workflow states, invoked child machines, typed emissions, Atom reactivity, and a live Effect service |
|
|
691
|
-
| [Platformer](./examples/platformer) | Nested parallel statecharts, typed deep history, raised events, state-scoped timers, deterministic model tests, and a playable SVG adapter |
|
|
692
|
-
|
|
693
|
-
The playground is the shortest path from one concept to working code. The
|
|
694
|
-
standalone examples show larger composition and ownership boundaries.
|
|
695
|
-
|
|
696
772
|
## Reference and development
|
|
697
773
|
|
|
698
774
|
- [API reference](https://effect-machine.typeonce.dev)
|
package/dist/Machine.d.ts
CHANGED
|
@@ -1258,7 +1258,8 @@ export declare namespace Logic {
|
|
|
1258
1258
|
* @category models
|
|
1259
1259
|
* @since 0.4.0
|
|
1260
1260
|
*/
|
|
1261
|
-
interface Spawn {
|
|
1261
|
+
interface Spawn<OwnerEvent = unknown> {
|
|
1262
|
+
<const Child extends ChildMachine.Any>(child: Child & ChildMachine.Executable<Child> & ChildMachine.ParentCompatibility<Child, OwnerEvent>, ...options: ChildMachine.SpawnArgs<Child>): Effect.Effect<ChildMachine.Ref<Child>, ChildAlreadyExistsError | ChildMachine.StartError<Child>, ChildMachine.StartRequirements<Child>>;
|
|
1262
1263
|
<ChildState, ChildEvent, ChildError, ChildRequirements, ChildOutput, ChildInitialError = never>(logic: Logic<ChildState, ChildEvent, ChildError, ChildRequirements, ChildOutput, ChildInitialError>): Effect.Effect<MachineRef<ChildState, ChildEvent, ChildError, ChildOutput>, ChildInitialError, Exclude<ChildRequirements, Scope.Scope>>;
|
|
1263
1264
|
<ChildState, ChildEvent, ChildError, ChildRequirements, ChildOutput, Options extends SpawnOptions, ChildInitialError = never>(logic: Logic<ChildState, ChildEvent, ChildError, ChildRequirements, ChildOutput, ChildInitialError>, options: Options & ChildAddress.OptionsCompatibility<Options, ChildEvent>): Effect.Effect<MachineRef<ChildState, ChildEvent, ChildError, ChildOutput>, SpawnIdError<Options> | ChildInitialError, Exclude<ChildRequirements, Scope.Scope>>;
|
|
1264
1265
|
}
|
|
@@ -1274,7 +1275,7 @@ export declare namespace Logic {
|
|
|
1274
1275
|
/** Address of the owning process, when one exists. */
|
|
1275
1276
|
readonly parent: Address<unknown> | undefined;
|
|
1276
1277
|
/** Starts a child process owned by this scope. */
|
|
1277
|
-
readonly spawn: Spawn
|
|
1278
|
+
readonly spawn: Spawn<Event>;
|
|
1278
1279
|
/** Sends an event to a machine target or typed parent-local child address. */
|
|
1279
1280
|
readonly sendTo: {
|
|
1280
1281
|
<TargetEvent>(target: MachineTarget<TargetEvent>, event: TargetEvent): Effect.Effect<void, StoppedError>;
|
|
@@ -1302,6 +1303,7 @@ export declare namespace Logic {
|
|
|
1302
1303
|
}
|
|
1303
1304
|
declare const ChildAddressTypeId = "~effect/Machine/ChildAddress";
|
|
1304
1305
|
declare const ChildAddressCompatibilityErrorTypeId = "~effect/Machine/ChildAddressCompatibilityError";
|
|
1306
|
+
declare const ChildParentCompatibilityErrorTypeId = "~effect/Machine/ChildParentCompatibilityError";
|
|
1305
1307
|
declare const ChildMachineTypeId = "~effect/Machine/ChildMachine";
|
|
1306
1308
|
type InvokeLifecycleId = string & {
|
|
1307
1309
|
readonly [ChildAddressTypeId]?: never;
|
|
@@ -1342,6 +1344,68 @@ export declare namespace ChildMachine {
|
|
|
1342
1344
|
* @since 0.4.0
|
|
1343
1345
|
*/
|
|
1344
1346
|
type Any = ChildMachine<string, Machine.Any>;
|
|
1347
|
+
/**
|
|
1348
|
+
* Bound constructor for an open family of child descriptors that share one
|
|
1349
|
+
* machine definition.
|
|
1350
|
+
*
|
|
1351
|
+
* @category models
|
|
1352
|
+
* @since 0.20.0
|
|
1353
|
+
*/
|
|
1354
|
+
interface Family<M extends Machine.Any> {
|
|
1355
|
+
<const Id extends string>(id: Id): ChildMachine<Id, M>;
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Ensures a child machine's declared owner protocol is accepted by the
|
|
1359
|
+
* process that will own it.
|
|
1360
|
+
*
|
|
1361
|
+
* @category utility types
|
|
1362
|
+
* @since 0.20.0
|
|
1363
|
+
*/
|
|
1364
|
+
type ParentCompatibility<Child extends Any, OwnerEvent> = Child extends ChildMachine<string, infer M> ? Machine.Any extends M ? {
|
|
1365
|
+
readonly [ChildParentCompatibilityErrorTypeId]: {
|
|
1366
|
+
readonly child: unknown;
|
|
1367
|
+
readonly owner: OwnerEvent;
|
|
1368
|
+
};
|
|
1369
|
+
} : [Machine.EventOf<Machine.ParentEvents<M>>] extends [OwnerEvent] ? unknown : {
|
|
1370
|
+
readonly [ChildParentCompatibilityErrorTypeId]: {
|
|
1371
|
+
readonly child: Machine.EventOf<Machine.ParentEvents<M>>;
|
|
1372
|
+
readonly owner: OwnerEvent;
|
|
1373
|
+
};
|
|
1374
|
+
} : never;
|
|
1375
|
+
/**
|
|
1376
|
+
* Ensures the selected child machine has complete handlers and outputs.
|
|
1377
|
+
*
|
|
1378
|
+
* @category utility types
|
|
1379
|
+
* @since 0.20.0
|
|
1380
|
+
*/
|
|
1381
|
+
type Executable<Child extends Any> = Child["machine"] extends EnsureExecutable<Machine.States<Child["machine"]>, Machine.UnhandledStates<Child["machine"]>, Machine.OutputStates<Child["machine"]>> ? unknown : never;
|
|
1382
|
+
/**
|
|
1383
|
+
* Startup arguments accepted while spawning a child machine.
|
|
1384
|
+
*
|
|
1385
|
+
* @category utility types
|
|
1386
|
+
* @since 0.20.0
|
|
1387
|
+
*/
|
|
1388
|
+
type SpawnArgs<Child extends Any> = Machine.InputSchema<Child["machine"]> extends typeof Schema.Void ? [
|
|
1389
|
+
options?: {
|
|
1390
|
+
readonly input?: never;
|
|
1391
|
+
}
|
|
1392
|
+
] : [options: {
|
|
1393
|
+
readonly input: Machine.Input<Child["machine"]>;
|
|
1394
|
+
}];
|
|
1395
|
+
/**
|
|
1396
|
+
* Typed failures that may occur before a spawned child becomes active.
|
|
1397
|
+
*
|
|
1398
|
+
* @category utility types
|
|
1399
|
+
* @since 0.20.0
|
|
1400
|
+
*/
|
|
1401
|
+
type StartError<Child extends Any> = Child extends ChildMachine<string, infer M> ? Machine.InitialError<M> | Machine.Error<M> | ActionError<Machine.InitialServices<M> | Machine.Services<M>> | InfiniteTransitionError | MachineSchemaDecodeError | StartupError | StoppedError : never;
|
|
1402
|
+
/**
|
|
1403
|
+
* Services needed to initialize a spawned child machine.
|
|
1404
|
+
*
|
|
1405
|
+
* @category utility types
|
|
1406
|
+
* @since 0.20.0
|
|
1407
|
+
*/
|
|
1408
|
+
type StartRequirements<Child extends Any> = Child extends ChildMachine<string, infer M> ? Exclude<ExcludeCompatibleRuntime<Exclude<ExecutionServices<Machine.InitialServices<M> | Machine.Services<M>>, MachineRuntimeRequirement>, Machine.Event<M>, Machine.Emit<M>>, Scope.Scope> : never;
|
|
1345
1409
|
/**
|
|
1346
1410
|
* Running machine reference selected by a child descriptor.
|
|
1347
1411
|
*
|
|
@@ -1357,6 +1421,21 @@ export declare namespace ChildMachine {
|
|
|
1357
1421
|
*/
|
|
1358
1422
|
type Event<Child> = Child extends ChildMachine<string, infer M> ? Machine.EventInput<Machine.InputEvent<M>> : never;
|
|
1359
1423
|
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Effectful operations for child machines owned directly by the current
|
|
1426
|
+
* machine process.
|
|
1427
|
+
*
|
|
1428
|
+
* @category models
|
|
1429
|
+
* @since 0.20.0
|
|
1430
|
+
*/
|
|
1431
|
+
export interface ChildOwner<OwnerEvent> {
|
|
1432
|
+
/** Starts a process-owned child and returns once initialization succeeds. */
|
|
1433
|
+
readonly spawn: <const Child extends ChildMachine.Any>(child: Child & ChildMachine.Executable<Child> & ChildMachine.ParentCompatibility<Child, OwnerEvent>, ...options: ChildMachine.SpawnArgs<Child>) => Effect.Effect<ChildMachine.Ref<Child>, ChildAlreadyExistsError | ChildMachine.StartError<Child>, ChildMachine.StartRequirements<Child>>;
|
|
1434
|
+
/** Sends an event to one active child. Missing children are ignored. */
|
|
1435
|
+
readonly sendTo: <Child extends ChildMachine.Any>(child: Child, event: ChildMachine.Event<Child>) => Effect.Effect<void, StoppedError>;
|
|
1436
|
+
/** Stops one active child. Missing children are ignored. */
|
|
1437
|
+
readonly stop: <Child extends ChildMachine.Any>(child: Child) => Effect.Effect<void>;
|
|
1438
|
+
}
|
|
1360
1439
|
/**
|
|
1361
1440
|
* Parent-local address for a child process that can receive events.
|
|
1362
1441
|
*
|
|
@@ -2155,9 +2234,10 @@ export declare namespace Machine {
|
|
|
2155
2234
|
*
|
|
2156
2235
|
* **Details**
|
|
2157
2236
|
*
|
|
2158
|
-
* Every branch exposes its
|
|
2159
|
-
* A compound local or branch target covers its descendants
|
|
2160
|
-
* `
|
|
2237
|
+
* Every branch exposes its static selection without executing its resolver.
|
|
2238
|
+
* A compound local or branch target covers its descendants. An `update`
|
|
2239
|
+
* selection keeps `target` undefined and records its value owner in
|
|
2240
|
+
* `selection.path`; `none` identifies an explicitly targetless branch.
|
|
2161
2241
|
*
|
|
2162
2242
|
* @category models
|
|
2163
2243
|
* @since 0.4.0
|
|
@@ -2762,6 +2842,20 @@ export declare namespace Machine {
|
|
|
2762
2842
|
readonly [AncestorStateId in ValuedStateIdentifier<States>]: StateByIdentifier<States, AncestorStateId>;
|
|
2763
2843
|
}>;
|
|
2764
2844
|
}
|
|
2845
|
+
/**
|
|
2846
|
+
* Opaque instruction that replaces one active compound or parallel state's
|
|
2847
|
+
* value without changing its active descendants.
|
|
2848
|
+
*
|
|
2849
|
+
* @category models
|
|
2850
|
+
* @since 0.21.0
|
|
2851
|
+
*/
|
|
2852
|
+
interface StateUpdate<States extends StateSchemas, StateId extends ValuedStateIdentifier<States>> {
|
|
2853
|
+
readonly [Topology.StateUpdateTypeId]: typeof Topology.StateUpdateTypeId;
|
|
2854
|
+
readonly path: StateId;
|
|
2855
|
+
readonly value: StateByIdentifier<States, StateId>;
|
|
2856
|
+
}
|
|
2857
|
+
/** @internal */
|
|
2858
|
+
type StateUpdateBuilder<States extends StateSchemas, StateId extends ValuedStateIdentifier<States>> = ((value: StateByIdentifier<States, StateId>) => StateUpdate<States, StateId>) & FromMethod<readonly [input: SchemaByIdentifier<States, StateId>["~type.make.in"]], StateUpdate<States, StateId>>;
|
|
2765
2859
|
/**
|
|
2766
2860
|
* Opaque result returned by an explicitly targetless transition.
|
|
2767
2861
|
*
|
|
@@ -2966,6 +3060,20 @@ export declare namespace Machine {
|
|
|
2966
3060
|
type SelectionNode<AllStates extends StateSchemas, Node, Path extends string, Scope extends "local" | "branch", Builder> = Node extends ChoiceStateNodeConfig ? SelectionMethod<Builder, Path, "choice"> : Node extends {
|
|
2967
3061
|
readonly states: infer Children extends StateSchemas;
|
|
2968
3062
|
} ? SelectionMethod<Builder, Path> & InitialSelectionMethod<Builder, Path> & SelectionTreeWithPrefix<AllStates, Children, Path, Scope, Builder> : SelectionMethod<Builder, Path>;
|
|
3063
|
+
/** @internal */
|
|
3064
|
+
type StateUpdateSelectionForNode<AllStates extends StateSchemas, Node, Path extends string> = Node extends {
|
|
3065
|
+
readonly states: StateSchemas;
|
|
3066
|
+
} ? NodeSchema<Node> extends never ? {} : {
|
|
3067
|
+
readonly update: SelectionValue<StateUpdateBuilder<AllStates, Extract<Path, ValuedStateIdentifier<AllStates>>>, Path, "update">;
|
|
3068
|
+
} : {};
|
|
3069
|
+
/** @internal */
|
|
3070
|
+
type BranchUpdateSelectionPath<AllStates extends StateSchemas, Node, Path extends string, Rest extends string> = StateUpdateSelectionForNode<AllStates, Node, Path> & (Node extends {
|
|
3071
|
+
readonly states: infer Children extends StateSchemas;
|
|
3072
|
+
} ? Rest extends `${infer Head}.${infer Tail}` ? Head extends keyof Children ? {
|
|
3073
|
+
readonly [Key in Head]: BranchUpdateSelectionPath<AllStates, Children[Head], JoinPath<Path, Head>, Tail>;
|
|
3074
|
+
} : {} : Rest extends keyof Children ? {
|
|
3075
|
+
readonly [Key in Rest]: StateUpdateSelectionForNode<AllStates, Children[Rest], JoinPath<Path, Rest>>;
|
|
3076
|
+
} : {} : {});
|
|
2969
3077
|
type FullSelectionNode<AllStates extends StateSchemas, Node, Path extends StateIdentifier<AllStates>, Builder> = Node extends {
|
|
2970
3078
|
readonly states: StateSchemas;
|
|
2971
3079
|
} ? SelectionMethod<Builder, Path> & InitialSelectionMethod<Builder, Path> : SelectionMethod<Builder, Path>;
|
|
@@ -2973,11 +3081,13 @@ export declare namespace Machine {
|
|
|
2973
3081
|
readonly [Key in Extract<ActiveStateKey<States>, keyof FullTargetBuilder<States>>]: FullSelectionNode<States, States[Key], Extract<Key, StateIdentifier<States>>, FullTargetBuilder<States>[Key]>;
|
|
2974
3082
|
};
|
|
2975
3083
|
type BranchTargetSelector<States extends StateSchemas, Source extends StateNodeIdentifier<States>, Root extends string = Source extends `${infer Head}.${string}` ? Head : Source> = Root extends ActiveStateKey<States> ? Root extends keyof BranchTargetBuilder<States, Source> ? {
|
|
2976
|
-
readonly [Key in Root]: SelectionNode<States, States[Key], Key, "branch", BranchTargetBuilder<States, Source>[Key]
|
|
3084
|
+
readonly [Key in Root]: SelectionNode<States, States[Key], Key, "branch", BranchTargetBuilder<States, Source>[Key]> & (Source extends ChoiceIdentifier<States> ? {} : Source extends `${Key}.${infer Rest}` ? BranchUpdateSelectionPath<States, States[Key], Key, Rest> : StateUpdateSelectionForNode<States, States[Key], Key>);
|
|
2977
3085
|
} : {} : {};
|
|
2978
|
-
type LocalTargetSelector<States extends StateSchemas, Source extends StateNodeIdentifier<States>> = NearestCompoundScope<States, Source> extends infer Scope extends StateIdentifier<States> ? ChildrenOf<States, Scope> extends infer Children extends StateSchemas ? LocalTargetBuilder<States, Source> extends infer Builder ? SelectionTreeWithPrefix<States, Children, Scope, "local", Builder> & ("with" extends keyof Builder ? {
|
|
3086
|
+
type LocalTargetSelector<States extends StateSchemas, Source extends StateNodeIdentifier<States>> = NearestCompoundScope<States, Source> extends infer Scope ? [Scope] extends [never] ? {} : Scope extends StateIdentifier<States> ? ChildrenOf<States, Scope> extends infer Children extends StateSchemas ? LocalTargetBuilder<States, Source> extends infer Builder ? SelectionTreeWithPrefix<States, Children, Scope, "local", Builder> & ("with" extends keyof Builder ? {
|
|
2979
3087
|
readonly with: SelectionValue<Builder["with"], Scope>;
|
|
2980
|
-
} : {})
|
|
3088
|
+
} : {}) & (Source extends ChoiceIdentifier<States> ? {} : Scope extends ValuedStateIdentifier<States> ? {
|
|
3089
|
+
readonly update: SelectionValue<StateUpdateBuilder<States, Scope>, Scope, "update">;
|
|
3090
|
+
} : {}) : {} : {} : {} : {};
|
|
2981
3091
|
type HistorySelectionTree<AllStates extends StateSchemas, States extends StateSchemas, Prefix extends string, Builder> = {
|
|
2982
3092
|
readonly [Key in Extract<HistoryContainingKey<States>, keyof Builder>]: States[Key] extends HistoryStateNodeConfig ? SelectionValue<Builder[Key], JoinPath<Prefix, Key>, "history"> : States[Key] extends {
|
|
2983
3093
|
readonly states: infer Children extends StateSchemas;
|
|
@@ -2995,9 +3105,9 @@ export declare namespace Machine {
|
|
|
2995
3105
|
interface TargetSelector<States extends StateSchemas, Source extends StateNodeIdentifier<States>> {
|
|
2996
3106
|
/** Handles the trigger without selecting a destination. */
|
|
2997
3107
|
readonly none: SelectionValue<TargetBuilder<States, Source>["none"], never, "none">;
|
|
2998
|
-
/** Selects a destination
|
|
3108
|
+
/** Selects a destination or updates the nearest active compound scope. */
|
|
2999
3109
|
readonly local: LocalTargetSelector<States, Source>;
|
|
3000
|
-
/** Selects a destination
|
|
3110
|
+
/** Selects a destination or updates a valued active ancestor under the current root. */
|
|
3001
3111
|
readonly branch: BranchTargetSelector<States, Source>;
|
|
3002
3112
|
/** Selects a complete destination under any top-level state. */
|
|
3003
3113
|
readonly full: FullTargetSelector<States>;
|
|
@@ -3060,6 +3170,8 @@ export declare namespace Machine {
|
|
|
3060
3170
|
* @since 0.4.0
|
|
3061
3171
|
*/
|
|
3062
3172
|
type InvokeContext<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateIdentifier<States>, InputEvents extends ReadonlyArray<TaggedSchema> = Events, ParentEvents extends ReadonlyArray<TaggedSchema> = readonly []> = MachineReferences<InputEvents, ParentEvents> & {
|
|
3173
|
+
/** Process-owned child operations for dynamic child machine lifecycles. */
|
|
3174
|
+
readonly children: ChildOwner<EventOf<InputEvents>>;
|
|
3063
3175
|
/** Value owned by the state that owns this invocation. */
|
|
3064
3176
|
readonly state: StateByIdentifier<States, StateId>;
|
|
3065
3177
|
/** Value owned by the nearest schema-backed ancestor, when one exists. */
|
|
@@ -3284,14 +3396,14 @@ export declare namespace Machine {
|
|
|
3284
3396
|
* **Details**
|
|
3285
3397
|
*
|
|
3286
3398
|
* Handlers return snapshots for complete state replacement, target builder
|
|
3287
|
-
* results for path-safe partial transitions,
|
|
3288
|
-
* explicitly targetless transition. Raw decoded state
|
|
3289
|
-
* not accepted at transition boundaries.
|
|
3399
|
+
* results for path-safe partial transitions, state-value updates, or
|
|
3400
|
+
* `target.none()` for an explicitly targetless transition. Raw decoded state
|
|
3401
|
+
* values and `void` are not accepted at transition boundaries.
|
|
3290
3402
|
*
|
|
3291
3403
|
* @category utility types
|
|
3292
3404
|
* @since 0.4.0
|
|
3293
3405
|
*/
|
|
3294
|
-
type HandlerResult<States extends StateSchemas, E, R> = Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>> | StateConstruction<Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>>> | NoTarget;
|
|
3406
|
+
type HandlerResult<States extends StateSchemas, E, R> = Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>> | StateUpdate<States, ValuedStateIdentifier<States>> | StateConstruction<Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>> | StateUpdate<States, ValuedStateIdentifier<States>>> | NoTarget;
|
|
3295
3407
|
/** A choice resolver must always select a typed target synchronously. */
|
|
3296
3408
|
type ChoiceResult<States extends StateSchemas, E, R> = Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>> | StateConstruction<Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>>>;
|
|
3297
3409
|
/**
|
|
@@ -3552,6 +3664,10 @@ export declare namespace Machine {
|
|
|
3552
3664
|
}
|
|
3553
3665
|
type TransitionResolver<Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, Context, Selection> = (context: TransitionResolveContext<Context, Selection>, enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>) => SelectionKind<Selection> extends "none" ? undefined : SelectedTargetResult<Selection> | undefined;
|
|
3554
3666
|
type DeclinableTransitionResolver<Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, Context, Selection> = (context: TransitionResolveContext<Context, Selection> & DeclineCapability, enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>) => (SelectionKind<Selection> extends "none" ? undefined : SelectedTargetResult<Selection> | undefined) | Declined;
|
|
3667
|
+
/** @internal */
|
|
3668
|
+
type StateUpdateResolver<Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, Context, Selection> = (context: TransitionResolveContext<Context, Selection>, enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>) => SelectedTargetResult<Selection>;
|
|
3669
|
+
/** @internal */
|
|
3670
|
+
type DeclinableStateUpdateResolver<Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, Context, Selection> = (context: TransitionResolveContext<Context, Selection> & DeclineCapability, enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>) => SelectedTargetResult<Selection> | Declined;
|
|
3555
3671
|
/** One named destination declared by a branching transition. */
|
|
3556
3672
|
interface TransitionBranchInput<Selection extends TargetSelection<any, any, any> = TargetSelection<any, any, any>> {
|
|
3557
3673
|
/** Exact topology destination available to the branching resolver. */
|
|
@@ -3644,6 +3760,16 @@ export declare namespace Machine {
|
|
|
3644
3760
|
/** Reenters the source using the selected target's default construction. */
|
|
3645
3761
|
readonly reenter: () => BuiltTransition<States, Events, Emits, StateId, Context, Reenter, SelectionKind<Selection> extends "none" ? undefined : SelectedTargetResult<Selection> | undefined, "required">;
|
|
3646
3762
|
} : {} : {});
|
|
3763
|
+
/** @internal */
|
|
3764
|
+
interface StateUpdateTransitionRequired<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Selection extends TargetSelection<any, any, "update">> {
|
|
3765
|
+
(resolve: StateUpdateResolver<Events, Emits, Context, Selection>, options?: TransitionRequiredOptions<Reenter>): BuiltTransition<States, Events, Emits, StateId, Context, Reenter, SelectedTargetResult<Selection>, "required">;
|
|
3766
|
+
}
|
|
3767
|
+
/** @internal */
|
|
3768
|
+
interface StateUpdateTransitionDeclinable<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Selection extends TargetSelection<any, any, "update">> {
|
|
3769
|
+
(resolve: DeclinableStateUpdateResolver<Events, Emits, Context, Selection>, options: TransitionDeclinableOptions<Reenter>): BuiltTransition<States, Events, Emits, StateId, Context, Reenter, SelectedTargetResult<Selection> | Declined, "declinable">;
|
|
3770
|
+
}
|
|
3771
|
+
/** @internal */
|
|
3772
|
+
type StateUpdateTransition<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Acceptance extends TransitionAcceptance, Selection extends TargetSelection<any, any, "update">> = Selection & StateUpdateTransitionRequired<States, Events, Emits, StateId, Context, Reenter, Selection> & ("declinable" extends Acceptance ? StateUpdateTransitionDeclinable<States, Events, Emits, StateId, Context, Reenter, Selection> : {});
|
|
3647
3773
|
/** @internal Type evidence retained by a machine initial-entry declaration. */
|
|
3648
3774
|
interface InitialBuilderEvidence<out Selection> {
|
|
3649
3775
|
readonly [InitialBuilderTypeId]: Types.Covariant<Selection>;
|
|
@@ -3667,7 +3793,7 @@ export declare namespace Machine {
|
|
|
3667
3793
|
type InitialSelector<States extends StateSchemas, Input = void> = InitialSelectorNode<Input, InitialTargetSelector<States>>;
|
|
3668
3794
|
/** Target-first initial-entry declaration accepted by {@link make}. */
|
|
3669
3795
|
type InitialBuilderInput<States extends StateSchemas, Input> = (to: InitialSelector<States, Input>) => InitialBuilderEvidence<TargetSelection<any, any, any>>;
|
|
3670
|
-
type TransitionSelectorNode<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Acceptance extends TransitionAcceptance, Node> = Node extends (...args: infer Args) => infer Selection ? Selection extends TargetSelection<any, any, any> ? ((...args: Args) => TransitionTarget<States, Events, Emits, StateId, Context, Reenter, Acceptance, Selection>) & {
|
|
3796
|
+
type TransitionSelectorNode<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Acceptance extends TransitionAcceptance, Node> = Node extends TargetSelection<any, any, "update"> ? StateUpdateTransition<States, Events, Emits, StateId, Context, Reenter, Acceptance, Node> : Node extends (...args: infer Args) => infer Selection ? Selection extends TargetSelection<any, any, any> ? ((...args: Args) => TransitionTarget<States, Events, Emits, StateId, Context, Reenter, Acceptance, Selection>) & {
|
|
3671
3797
|
readonly [Key in keyof Node]: TransitionSelectorNode<States, Events, Emits, StateId, Context, Reenter, Acceptance, Node[Key]>;
|
|
3672
3798
|
} : never : Node extends TargetSelection<any, any, any> ? TransitionTarget<States, Events, Emits, StateId, Context, Reenter, Acceptance, Node> : {
|
|
3673
3799
|
readonly [Key in keyof Node]: TransitionSelectorNode<States, Events, Emits, StateId, Context, Reenter, Acceptance, Node[Key]>;
|
|
@@ -4827,9 +4953,10 @@ export declare const initialDefinition: <M extends Machine.Any>(machine: M) => M
|
|
|
4827
4953
|
*
|
|
4828
4954
|
* Event handlers retain their handler-key order within each source state and
|
|
4829
4955
|
* are followed by eventless and completion handlers. This function does not
|
|
4830
|
-
* execute resolvers. Every
|
|
4831
|
-
*
|
|
4832
|
-
*
|
|
4956
|
+
* execute resolvers. Every branch exposes its static selection. State updates
|
|
4957
|
+
* retain the updated owner in `selection.path` while leaving `target`
|
|
4958
|
+
* undefined because they do not change topology. `acceptance` reports whether
|
|
4959
|
+
* the resolver may decline the transition.
|
|
4833
4960
|
*
|
|
4834
4961
|
* @category getters
|
|
4835
4962
|
* @since 0.4.0
|
|
@@ -4989,6 +5116,16 @@ export declare const logic: <State, Event = never, Output = void, Error = never,
|
|
|
4989
5116
|
* @since 0.4.0
|
|
4990
5117
|
*/
|
|
4991
5118
|
export declare const child: <const Id extends string, M extends Machine.Any>(id: Id, machine: M) => ChildMachine<Id, M>;
|
|
5119
|
+
/**
|
|
5120
|
+
* Binds one machine definition to an open family of runtime child ids.
|
|
5121
|
+
*
|
|
5122
|
+
* Descriptors created by the returned function are interchangeable with
|
|
5123
|
+
* {@link child} descriptors for the same id and machine definition.
|
|
5124
|
+
*
|
|
5125
|
+
* @category constructors
|
|
5126
|
+
* @since 0.20.0
|
|
5127
|
+
*/
|
|
5128
|
+
export declare const childFamily: <M extends Machine.Any>(machine: M) => ChildMachine.Family<M>;
|
|
4992
5129
|
/**
|
|
4993
5130
|
* Creates a typed parent-local address for lower-level child process logic.
|
|
4994
5131
|
*
|