@typeonce/effect-machine 0.21.0 → 0.22.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 (44) hide show
  1. package/README.md +83 -14
  2. package/dist/Machine.d.ts +142 -52
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js +2 -2
  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 +23 -9
  8. package/dist/internal/machine/executionPlan.js.map +1 -1
  9. package/dist/internal/machine/initialization.d.ts.map +1 -1
  10. package/dist/internal/machine/initialization.js +7 -2
  11. package/dist/internal/machine/initialization.js.map +1 -1
  12. package/dist/internal/machine/machine.d.ts.map +1 -1
  13. package/dist/internal/machine/machine.js +94 -13
  14. package/dist/internal/machine/machine.js.map +1 -1
  15. package/dist/internal/machine/planner.d.ts +5 -0
  16. package/dist/internal/machine/planner.d.ts.map +1 -1
  17. package/dist/internal/machine/planner.js +23 -9
  18. package/dist/internal/machine/planner.js.map +1 -1
  19. package/dist/internal/machine/topology.d.ts +10 -1
  20. package/dist/internal/machine/topology.d.ts.map +1 -1
  21. package/dist/internal/machine/topology.js +10 -2
  22. package/dist/internal/machine/topology.js.map +1 -1
  23. package/dist/internal/testing/machine/finiteModel.d.ts.map +1 -1
  24. package/dist/internal/testing/machine/finiteModel.js +3 -3
  25. package/dist/internal/testing/machine/finiteModel.js.map +1 -1
  26. package/dist/internal/testing/machine/verification.d.ts.map +1 -1
  27. package/dist/internal/testing/machine/verification.js +11 -9
  28. package/dist/internal/testing/machine/verification.js.map +1 -1
  29. package/dist/testing/MachineTest.d.ts +3 -3
  30. package/dist/testing/MachineTest.js +3 -3
  31. package/dist/unstable/reactivity/AtomMachine.d.ts +1 -1
  32. package/dist/unstable/reactivity/AtomMachine.js +1 -1
  33. package/docs/agent-guide.md +36 -5
  34. package/package.json +1 -1
  35. package/src/Machine.ts +325 -87
  36. package/src/internal/machine/executionPlan.ts +31 -9
  37. package/src/internal/machine/initialization.ts +10 -2
  38. package/src/internal/machine/machine.ts +131 -15
  39. package/src/internal/machine/planner.ts +26 -8
  40. package/src/internal/machine/topology.ts +22 -2
  41. package/src/internal/testing/machine/finiteModel.ts +7 -3
  42. package/src/internal/testing/machine/verification.ts +18 -10
  43. package/src/testing/MachineTest.ts +3 -3
  44. package/src/unstable/reactivity/AtomMachine.ts +1 -1
package/src/Machine.ts CHANGED
@@ -286,7 +286,7 @@ export interface Definition<
286
286
  * on: {
287
287
  * Increment: (to) =>
288
288
  * to.full.Count().resolve(({ event, state, target }) =>
289
- * target(new Count({ value: state.value + event.by })))
289
+ * target.decoded(new Count({ value: state.value + event.by })))
290
290
  * }
291
291
  * }
292
292
  * })
@@ -972,6 +972,16 @@ type FromMethod<Arguments extends ReadonlyArray<unknown>, Result> = {
972
972
  readonly from: FromCallable<Arguments, Machine.StateConstruction<Result>>
973
973
  }
974
974
 
975
+ type DecodedMethod<Arguments extends ReadonlyArray<unknown>, Result> = {
976
+ /**
977
+ * Constructs the selected state from an already-decoded schema value. The
978
+ * machine validates the value against the schema's type side while planning.
979
+ *
980
+ * @since 0.22.0
981
+ */
982
+ readonly decoded: (...args: Arguments) => Result
983
+ }
984
+
975
985
  type ConstructionResult<Result> = Result | Machine.StateConstruction<Result>
976
986
 
977
987
  type UnwrapConstruction<Result> = Result extends Machine.StateConstruction<infer Value> ? Value : Result
@@ -997,9 +1007,7 @@ type NodeBuilderMethod<
997
1007
  > = Machine.NodeSchema<Node> extends never ? {
998
1008
  readonly from: FromCallable<FromArguments, FromResult>
999
1009
  }
1000
- :
1001
- & ((...args: Arguments) => Result)
1002
- & { readonly from: FromCallable<FromArguments, FromResult> }
1010
+ : DecodedMethod<Arguments, Result> & { readonly from: FromCallable<FromArguments, FromResult> }
1003
1011
 
1004
1012
  type NodeMethod<
1005
1013
  Node,
@@ -1007,7 +1015,7 @@ type NodeMethod<
1007
1015
  Result,
1008
1016
  FromArguments extends ReadonlyArray<unknown>
1009
1017
  > = Machine.NodeSchema<Node> extends never ? FromMethod<FromArguments, Result>
1010
- : ((...args: Arguments) => Result) & FromMethod<FromArguments, Result>
1018
+ : DecodedMethod<Arguments, Result> & FromMethod<FromArguments, Result>
1011
1019
 
1012
1020
  type NodeMethodWithInitial<
1013
1021
  Node,
@@ -1020,7 +1028,7 @@ type NodeMethodWithInitial<
1020
1028
  readonly initial: InitialTargetFactory<Node, Path>
1021
1029
  }
1022
1030
  :
1023
- & ((...args: Arguments) => Result)
1031
+ & DecodedMethod<Arguments, Result>
1024
1032
  & {
1025
1033
  readonly from: FromCallable<FromArguments, Machine.StateConstruction<Result>>
1026
1034
  readonly initial: InitialTargetFactory<Node, Path>
@@ -1038,11 +1046,11 @@ interface InitialTargetFactory<
1038
1046
  Node,
1039
1047
  Path extends string
1040
1048
  > {
1041
- (...args: WithNodeValue<Node, readonly []>): Machine.InitialTarget<Path>
1042
1049
  readonly from: FromCallable<
1043
1050
  WithNodeInput<Node, readonly []>,
1044
1051
  Machine.StateConstruction<Machine.InitialTarget<Path>>
1045
1052
  >
1053
+ readonly decoded: (...args: WithNodeValue<Node, readonly []>) => Machine.InitialTarget<Path>
1046
1054
  }
1047
1055
 
1048
1056
  type NodeConstructionSelectorFromCallable<Node, Builder, Result> = Machine.NodeSchema<Node> extends never ? {
@@ -1056,15 +1064,14 @@ type NestedTargetMethod<Node, Builder, Result, Path extends string> = Machine.No
1056
1064
  readonly from: NodeConstructionSelectorFromCallable<Node, Builder, Result>
1057
1065
  readonly initial: InitialTargetFactory<Node, Path>
1058
1066
  }
1059
- :
1060
- & (<Selected extends ConstructionResult<Result>>(
1067
+ : {
1068
+ readonly decoded: <Selected extends ConstructionResult<Result>>(
1061
1069
  value: NodeValue<Node>,
1062
1070
  state: (builder: Builder) => Selected
1063
- ) => Selected)
1064
- & {
1065
- readonly from: NodeConstructionSelectorFromCallable<Node, Builder, Result>
1066
- readonly initial: InitialTargetFactory<Node, Path>
1067
- }
1071
+ ) => Selected
1072
+ readonly from: NodeConstructionSelectorFromCallable<Node, Builder, Result>
1073
+ readonly initial: InitialTargetFactory<Node, Path>
1074
+ }
1068
1075
 
1069
1076
  type ConstructionSelectorFromCallable<Input, Builder, Result> = {} extends Input ? {
1070
1077
  <Selected extends ConstructionResult<Result>>(
@@ -1100,9 +1107,10 @@ type InitialSnapshotMethod<
1100
1107
  InitialSnapshotResult<States, StateId, Prefix>
1101
1108
  >
1102
1109
  :
1103
- & ((
1104
- ...args: InitialSnapshotArguments<States, StateId, Prefix>
1105
- ) => InitialSnapshotResult<States, StateId, Prefix>)
1110
+ & DecodedMethod<
1111
+ InitialSnapshotArguments<States, StateId, Prefix>,
1112
+ InitialSnapshotResult<States, StateId, Prefix>
1113
+ >
1106
1114
  & FromMethod<
1107
1115
  InitialSnapshotFromArguments<States, StateId, Prefix>,
1108
1116
  InitialSnapshotResult<States, StateId, Prefix>
@@ -1242,9 +1250,10 @@ type FullSnapshotMethod<
1242
1250
  FullSnapshotResult<States, StateId, Prefix>
1243
1251
  >
1244
1252
  :
1245
- & ((
1246
- ...args: FullSnapshotArguments<States, StateId, Prefix>
1247
- ) => FullSnapshotResult<States, StateId, Prefix>)
1253
+ & DecodedMethod<
1254
+ FullSnapshotArguments<States, StateId, Prefix>,
1255
+ FullSnapshotResult<States, StateId, Prefix>
1256
+ >
1248
1257
  & FromMethod<
1249
1258
  FullSnapshotFromArguments<States, StateId, Prefix>,
1250
1259
  FullSnapshotResult<States, StateId, Prefix>
@@ -1416,9 +1425,10 @@ type HistorySnapshotMethod<
1416
1425
  HistorySnapshotResult<States, StateId, Prefix, Owner>
1417
1426
  >
1418
1427
  :
1419
- & ((
1420
- ...args: HistorySnapshotArguments<States, StateId, Prefix, Owner>
1421
- ) => HistorySnapshotResult<States, StateId, Prefix, Owner>)
1428
+ & DecodedMethod<
1429
+ HistorySnapshotArguments<States, StateId, Prefix, Owner>,
1430
+ HistorySnapshotResult<States, StateId, Prefix, Owner>
1431
+ >
1422
1432
  & FromMethod<
1423
1433
  HistorySnapshotFromArguments<States, StateId, Prefix, Owner>,
1424
1434
  HistorySnapshotResult<States, StateId, Prefix, Owner>
@@ -1645,20 +1655,19 @@ type LocalTargetBuilderForScope<
1645
1655
  *
1646
1656
  * @since 0.4.0
1647
1657
  */
1648
- readonly with:
1649
- & (<Result extends ConstructionResult<LocalTargetResultWithPrefix<States, Children, Scope>>>(
1658
+ readonly with: {
1659
+ readonly decoded: <Result extends ConstructionResult<LocalTargetResultWithPrefix<States, Children, Scope>>>(
1650
1660
  value: Machine.StateByIdentifier<States, Scope>,
1651
1661
  state: (
1652
1662
  builder: LocalTargetBuilderWithPrefix<States, Children, Scope, Source>
1653
1663
  ) => Result
1654
- ) => Result)
1655
- & {
1656
- readonly from: ConstructionSelectorFromCallable<
1657
- Machine.SchemaByIdentifier<States, Scope>["~type.make.in"],
1658
- LocalTargetBuilderWithPrefix<States, Children, Scope, Source>,
1659
- LocalTargetResultWithPrefix<States, Children, Scope>
1660
- >
1661
- }
1664
+ ) => Result
1665
+ readonly from: ConstructionSelectorFromCallable<
1666
+ Machine.SchemaByIdentifier<States, Scope>["~type.make.in"],
1667
+ LocalTargetBuilderWithPrefix<States, Children, Scope, Source>,
1668
+ LocalTargetResultWithPrefix<States, Children, Scope>
1669
+ >
1670
+ }
1662
1671
  } :
1663
1672
  {})
1664
1673
  : {}
@@ -3557,6 +3566,7 @@ export declare namespace Machine {
3557
3566
  readonly type: "direct"
3558
3567
  readonly target: Path | undefined
3559
3568
  readonly selection: TransitionTargetSelection<Path | undefined>
3569
+ readonly updates: ReadonlyArray<string>
3560
3570
  }
3561
3571
  | {
3562
3572
  readonly type: "branch"
@@ -3564,6 +3574,7 @@ export declare namespace Machine {
3564
3574
  readonly title: string
3565
3575
  readonly target: Path | undefined
3566
3576
  readonly selection: TransitionTargetSelection<Path | undefined>
3577
+ readonly updates: ReadonlyArray<string>
3567
3578
  }
3568
3579
 
3569
3580
  /** The statically selected root entry for machine startup. */
@@ -3635,6 +3646,8 @@ export declare namespace Machine {
3635
3646
  * Choice microsteps retain each intermediate pseudo-state edge separately.
3636
3647
  */
3637
3648
  readonly resolvedTarget: TargetPath | undefined
3649
+ /** Retained valued owners replaced by this transition. */
3650
+ readonly updates: ReadonlyArray<string>
3638
3651
  }
3639
3652
 
3640
3653
  /**
@@ -4473,21 +4486,42 @@ export declare namespace Machine {
4473
4486
  States extends StateSchemas,
4474
4487
  StateId extends ValuedStateIdentifier<States>
4475
4488
  > {
4476
- readonly [Topology.StateUpdateTypeId]: typeof Topology.StateUpdateTypeId
4477
- readonly path: StateId
4478
- readonly value: StateByIdentifier<States, StateId>
4489
+ readonly [Topology.StateUpdateTypeId]: {
4490
+ readonly states: Types.Covariant<States>
4491
+ readonly owner: Types.Covariant<StateId>
4492
+ }
4493
+ }
4494
+
4495
+ /**
4496
+ * Opaque result that combines one topology target with one retained owner
4497
+ * value replacement in the same microstep.
4498
+ *
4499
+ * @category models
4500
+ * @since 0.22.0
4501
+ */
4502
+ export interface CombinedTarget<
4503
+ Result,
4504
+ States extends StateSchemas,
4505
+ Owner extends ValuedStateIdentifier<States>
4506
+ > {
4507
+ readonly [Topology.CombinedTargetTypeId]: {
4508
+ readonly result: Types.Covariant<Result>
4509
+ readonly states: Types.Covariant<States>
4510
+ readonly owner: Types.Covariant<Owner>
4511
+ }
4479
4512
  }
4480
4513
 
4481
4514
  /** @internal */
4482
4515
  type StateUpdateBuilder<
4483
4516
  States extends StateSchemas,
4484
4517
  StateId extends ValuedStateIdentifier<States>
4485
- > =
4486
- & ((value: StateByIdentifier<States, StateId>) => StateUpdate<States, StateId>)
4487
- & FromMethod<
4518
+ > = {
4519
+ readonly decoded: (value: StateByIdentifier<States, StateId>) => StateUpdate<States, StateId>
4520
+ readonly from: FromCallable<
4488
4521
  readonly [input: SchemaByIdentifier<States, StateId>["~type.make.in"]],
4489
4522
  StateUpdate<States, StateId>
4490
4523
  >
4524
+ }
4491
4525
 
4492
4526
  /**
4493
4527
  * Opaque result returned by an explicitly targetless transition.
@@ -4720,23 +4754,36 @@ export declare namespace Machine {
4720
4754
  export interface TargetSelection<
4721
4755
  out Result,
4722
4756
  out Path extends string | undefined = string | undefined,
4723
- out Kind extends Topology.TargetSelectionKind = Topology.TargetSelectionKind
4757
+ out Kind extends Topology.TargetSelectionKind = Topology.TargetSelectionKind,
4758
+ out Scope extends Topology.TargetSelectionScope | undefined = Topology.TargetSelectionScope | undefined
4724
4759
  > {
4725
4760
  readonly [Topology.TargetSelectionTypeId]: typeof Topology.TargetSelectionTypeId
4726
4761
  readonly kind: Kind
4727
- readonly scope: Topology.TargetSelectionScope | undefined
4762
+ readonly scope: Scope
4728
4763
  readonly path: Path
4729
4764
  readonly "~effect/Machine/TargetSelectionResult"?: Types.Covariant<Result>
4730
4765
  }
4731
4766
 
4732
- type SelectionValue<Builder, Path extends string, Kind extends Topology.TargetSelectionKind = "state"> =
4733
- TargetSelection<Builder, Path, Kind>
4767
+ type SelectionValue<
4768
+ Builder,
4769
+ Path extends string,
4770
+ Kind extends Topology.TargetSelectionKind = "state",
4771
+ Scope extends Topology.TargetSelectionScope | undefined = Topology.TargetSelectionScope | undefined
4772
+ > = TargetSelection<Builder, Path, Kind, Scope>
4734
4773
 
4735
- type SelectionMethod<Builder, Path extends string, Kind extends Topology.TargetSelectionKind = "state"> = () =>
4736
- SelectionValue<Builder, Path, Kind>
4774
+ type SelectionMethod<
4775
+ Builder,
4776
+ Path extends string,
4777
+ Kind extends Topology.TargetSelectionKind = "state",
4778
+ Scope extends Topology.TargetSelectionScope | undefined = Topology.TargetSelectionScope | undefined
4779
+ > = () => SelectionValue<Builder, Path, Kind, Scope>
4737
4780
 
4738
- type InitialSelectionMethod<Builder, Path extends string> = Builder extends { readonly initial: infer Initial } ? {
4739
- readonly initial: SelectionValue<Initial, Path, "initial">
4781
+ type InitialSelectionMethod<
4782
+ Builder,
4783
+ Path extends string,
4784
+ Scope extends Topology.TargetSelectionScope
4785
+ > = Builder extends { readonly initial: infer Initial } ? {
4786
+ readonly initial: SelectionValue<Initial, Path, "initial", Scope>
4740
4787
  }
4741
4788
  : {}
4742
4789
 
@@ -4765,25 +4812,28 @@ export declare namespace Machine {
4765
4812
  > = Node extends ChoiceStateNodeConfig ? SelectionMethod<
4766
4813
  Builder,
4767
4814
  Path,
4768
- "choice"
4815
+ "choice",
4816
+ Scope
4769
4817
  >
4770
4818
  : Node extends { readonly states: infer Children extends StateSchemas } ?
4771
- & SelectionMethod<Builder, Path>
4772
- & InitialSelectionMethod<Builder, Path>
4819
+ & SelectionMethod<Builder, Path, "state", Scope>
4820
+ & InitialSelectionMethod<Builder, Path, Scope>
4773
4821
  & SelectionTreeWithPrefix<AllStates, Children, Path, Scope, Builder>
4774
- : SelectionMethod<Builder, Path>
4822
+ : SelectionMethod<Builder, Path, "state", Scope>
4775
4823
 
4776
4824
  /** @internal */
4777
4825
  type StateUpdateSelectionForNode<
4778
4826
  AllStates extends StateSchemas,
4779
4827
  Node,
4780
- Path extends string
4828
+ Path extends string,
4829
+ Scope extends "local" | "branch"
4781
4830
  > = Node extends { readonly states: StateSchemas } ? NodeSchema<Node> extends never ? {}
4782
4831
  : {
4783
4832
  readonly update: SelectionValue<
4784
4833
  StateUpdateBuilder<AllStates, Extract<Path, ValuedStateIdentifier<AllStates>>>,
4785
4834
  Path,
4786
- "update"
4835
+ "update",
4836
+ Scope
4787
4837
  >
4788
4838
  }
4789
4839
  : {}
@@ -4793,21 +4843,28 @@ export declare namespace Machine {
4793
4843
  AllStates extends StateSchemas,
4794
4844
  Node,
4795
4845
  Path extends string,
4796
- Rest extends string
4846
+ Rest extends string,
4847
+ Scope extends "local" | "branch" = "branch"
4797
4848
  > =
4798
- & StateUpdateSelectionForNode<AllStates, Node, Path>
4849
+ & StateUpdateSelectionForNode<AllStates, Node, Path, Scope>
4799
4850
  & (Node extends { readonly states: infer Children extends StateSchemas } ?
4800
4851
  Rest extends `${infer Head}.${infer Tail}` ? Head extends keyof Children ? {
4801
4852
  readonly [Key in Head]: BranchUpdateSelectionPath<
4802
4853
  AllStates,
4803
4854
  Children[Head],
4804
4855
  JoinPath<Path, Head>,
4805
- Tail
4856
+ Tail,
4857
+ Scope
4806
4858
  >
4807
4859
  }
4808
4860
  : {}
4809
4861
  : Rest extends keyof Children ? {
4810
- readonly [Key in Rest]: StateUpdateSelectionForNode<AllStates, Children[Rest], JoinPath<Path, Rest>>
4862
+ readonly [Key in Rest]: StateUpdateSelectionForNode<
4863
+ AllStates,
4864
+ Children[Rest],
4865
+ JoinPath<Path, Rest>,
4866
+ Scope
4867
+ >
4811
4868
  }
4812
4869
  : {}
4813
4870
  : {})
@@ -4818,9 +4875,9 @@ export declare namespace Machine {
4818
4875
  Path extends StateIdentifier<AllStates>,
4819
4876
  Builder
4820
4877
  > = Node extends { readonly states: StateSchemas } ?
4821
- & SelectionMethod<Builder, Path>
4822
- & InitialSelectionMethod<Builder, Path>
4823
- : SelectionMethod<Builder, Path>
4878
+ & SelectionMethod<Builder, Path, "state", "full">
4879
+ & InitialSelectionMethod<Builder, Path, "full">
4880
+ : SelectionMethod<Builder, Path, "state", "full">
4824
4881
 
4825
4882
  type FullTargetSelector<States extends StateSchemas> = {
4826
4883
  readonly [Key in Extract<ActiveStateKey<States>, keyof FullTargetBuilder<States>>]: FullSelectionNode<
@@ -4846,7 +4903,7 @@ export declare namespace Machine {
4846
4903
  >
4847
4904
  & (Source extends ChoiceIdentifier<States> ? {}
4848
4905
  : Source extends `${Key}.${infer Rest}` ? BranchUpdateSelectionPath<States, States[Key], Key, Rest>
4849
- : StateUpdateSelectionForNode<States, States[Key], Key>)
4906
+ : StateUpdateSelectionForNode<States, States[Key], Key, "branch">)
4850
4907
  }
4851
4908
  : {}
4852
4909
  : {}
@@ -4860,12 +4917,12 @@ export declare namespace Machine {
4860
4917
  LocalTargetBuilder<States, Source> extends infer Builder ?
4861
4918
  & SelectionTreeWithPrefix<States, Children, Scope, "local", Builder>
4862
4919
  & ("with" extends keyof Builder ? {
4863
- readonly with: SelectionValue<Builder["with"], Scope>
4920
+ readonly with: SelectionValue<Builder["with"], Scope, "state", "local">
4864
4921
  }
4865
4922
  : {})
4866
4923
  & (Source extends ChoiceIdentifier<States> ? {}
4867
4924
  : Scope extends ValuedStateIdentifier<States> ? {
4868
- readonly update: SelectionValue<StateUpdateBuilder<States, Scope>, Scope, "update">
4925
+ readonly update: SelectionValue<StateUpdateBuilder<States, Scope>, Scope, "update", "local">
4869
4926
  }
4870
4927
  : {})
4871
4928
  : {}
@@ -4883,7 +4940,8 @@ export declare namespace Machine {
4883
4940
  SelectionValue<
4884
4941
  Builder[Key],
4885
4942
  JoinPath<Prefix, Key>,
4886
- "history"
4943
+ "history",
4944
+ "full"
4887
4945
  >
4888
4946
  : States[Key] extends { readonly states: infer Children extends StateSchemas } ? HistorySelectionTree<
4889
4947
  AllStates,
@@ -4908,7 +4966,7 @@ export declare namespace Machine {
4908
4966
  Source extends StateNodeIdentifier<States>
4909
4967
  > {
4910
4968
  /** Handles the trigger without selecting a destination. */
4911
- readonly none: SelectionValue<TargetBuilder<States, Source>["none"], never, "none">
4969
+ readonly none: SelectionValue<TargetBuilder<States, Source>["none"], never, "none", "local">
4912
4970
  /** Selects a destination or updates the nearest active compound scope. */
4913
4971
  readonly local: LocalTargetSelector<States, Source>
4914
4972
  /** Selects a destination or updates a valued active ancestor under the current root. */
@@ -4923,9 +4981,9 @@ export declare namespace Machine {
4923
4981
  type InitialTargetSelector<States extends StateSchemas> = {
4924
4982
  readonly [Key in Extract<ActiveStateKey<States>, keyof InitialBuilder<States>>]: States[Key] extends
4925
4983
  { readonly states: StateSchemas } ? {
4926
- readonly initial: SelectionValue<InitialBuilder<States>[Key], Key, "initial">
4984
+ readonly initial: SelectionValue<InitialBuilder<States>[Key], Key, "initial", "initial">
4927
4985
  }
4928
- : SelectionMethod<InitialBuilder<States>[Key], Key>
4986
+ : SelectionMethod<InitialBuilder<States>[Key], Key, "state", "initial">
4929
4987
  }
4930
4988
 
4931
4989
  /**
@@ -5334,6 +5392,11 @@ export declare namespace Machine {
5334
5392
  | HistoryTarget<States, HistoryIdentifier<States>>
5335
5393
  | ChoiceTarget<States, ChoiceIdentifier<States>>
5336
5394
  | StateUpdate<States, ValuedStateIdentifier<States>>
5395
+ | CombinedTarget<
5396
+ Target<States, StateIdentifier<States>> | Snapshot<States>,
5397
+ States,
5398
+ ValuedStateIdentifier<States>
5399
+ >
5337
5400
  | StateConstruction<
5338
5401
  | Snapshot<States>
5339
5402
  | Target<States, StateIdentifier<States>>
@@ -5667,21 +5730,75 @@ export declare namespace Machine {
5667
5730
  Acceptance extends TransitionAcceptance = "required"
5668
5731
  > = TransitionBuilderInput<States, Events, Emits, StateId, Context, Reenter, Acceptance>
5669
5732
 
5670
- export type SelectionBuilder<Selection> = Selection extends TargetSelection<infer Builder, any, any> ? Builder : never
5671
- export type SelectionKind<Selection> = Selection extends TargetSelection<any, any, infer Kind> ? Kind : never
5672
- export type SelectionPath<Selection> = Selection extends TargetSelection<any, infer Path, any> ? Path : never
5733
+ export type SelectionBuilder<Selection> = Selection extends TargetSelection<infer Builder, any, any, any> ? Builder
5734
+ : never
5735
+ export type SelectionKind<Selection> = Selection extends TargetSelection<any, any, infer Kind, any> ? Kind : never
5736
+ export type SelectionPath<Selection> = Selection extends TargetSelection<any, infer Path, any, any> ? Path : never
5737
+ type SelectionScope<Selection> = Selection extends TargetSelection<any, any, any, infer Scope> ? Scope : never
5673
5738
  export type TargetBuilderResult<Builder> =
5674
5739
  | (Builder extends (...args: any) => infer Result ? Result : never)
5740
+ | (Builder extends { readonly decoded: (...args: any) => infer Result } ? Result : never)
5675
5741
  | (Builder extends { readonly from: (...args: any) => infer Result } ? Result : never)
5676
5742
  export type SelectedTargetResult<Selection> = SelectionBuilder<Selection> extends infer Builder ?
5677
5743
  TargetBuilderResult<Builder>
5678
5744
  : never
5679
5745
 
5746
+ type RetainedUpdateOwner<
5747
+ States extends StateSchemas,
5748
+ Source extends StateNodeIdentifier<States>,
5749
+ Selection
5750
+ > = Extract<
5751
+ ParentStateIdentifier<Source>,
5752
+ ParentStateIdentifier<Extract<SelectionPath<Selection>, string>> & ValuedStateIdentifier<States>
5753
+ >
5754
+
5755
+ type RetainedOwnerSelector<Owner extends string> = () => TargetSelection<any, Owner, "state", "branch">
5756
+
5757
+ /**
5758
+ * Destination construction returned when a transition declares one retained
5759
+ * valued owner with `.updating(...)`.
5760
+ *
5761
+ * @category models
5762
+ * @since 0.22.0
5763
+ */
5764
+ export interface UpdatingStateConstruction<
5765
+ Result,
5766
+ States extends StateSchemas,
5767
+ Owner extends ValuedStateIdentifier<States>
5768
+ > {
5769
+ /** Combines the selected topology with the required owner replacement. */
5770
+ readonly update: (
5771
+ update: StateUpdate<States, Owner>
5772
+ ) => CombinedTarget<UnwrapConstruction<Result>, States, Owner>
5773
+ }
5774
+
5775
+ type UpdatingCallable<
5776
+ Callable,
5777
+ States extends StateSchemas,
5778
+ Owner extends ValuedStateIdentifier<States>
5779
+ > = Callable extends {
5780
+ (...args: infer Arguments1): infer Result1
5781
+ (...args: infer Arguments2): infer Result2
5782
+ } ? {
5783
+ (...args: Arguments1): UpdatingStateConstruction<Result1, States, Owner>
5784
+ (...args: Arguments2): UpdatingStateConstruction<Result2, States, Owner>
5785
+ }
5786
+ : Callable extends (...args: infer Arguments) => infer Result ?
5787
+ (...args: Arguments) => UpdatingStateConstruction<Result, States, Owner>
5788
+ : never
5789
+
5790
+ type UpdatingTargetBuilder<
5791
+ Builder,
5792
+ States extends StateSchemas,
5793
+ Owner extends ValuedStateIdentifier<States>
5794
+ > = {
5795
+ readonly [Key in keyof Builder]: Key extends "from" | "decoded" ? UpdatingCallable<Builder[Key], States, Owner>
5796
+ : Builder[Key]
5797
+ }
5798
+
5680
5799
  type SelectionSupportsDefaultConstruction<Selection> = SelectionKind<Selection> extends "none" ? true
5681
5800
  : SelectionBuilder<Selection> extends { readonly from: (...args: infer Args) => any } ? [] extends Args ? true
5682
5801
  : false
5683
- : SelectionBuilder<Selection> extends (...args: infer Args) => any ? [] extends Args ? true
5684
- : false
5685
5802
  : false
5686
5803
 
5687
5804
  export type TransitionResolveContext<
@@ -5691,6 +5808,31 @@ export declare namespace Machine {
5691
5808
  & Omit<Context, "target">
5692
5809
  & (SelectionKind<Selection> extends "none" ? {} : { readonly target: SelectionBuilder<Selection> })
5693
5810
 
5811
+ type StateUpdateResolveContext<
5812
+ States extends StateSchemas,
5813
+ Context,
5814
+ Owner extends ValuedStateIdentifier<States>
5815
+ > = Omit<Context, "target"> & {
5816
+ /** Decoded owner value from the pre-transition snapshot. */
5817
+ readonly current: StateByIdentifier<States, Owner>
5818
+ /** Constructs the complete replacement for the selected owner. */
5819
+ readonly owner: StateUpdateBuilder<States, Owner>
5820
+ }
5821
+
5822
+ type UpdatingTransitionResolveContext<
5823
+ States extends StateSchemas,
5824
+ Context,
5825
+ Selection,
5826
+ Owner extends ValuedStateIdentifier<States>
5827
+ > = Omit<Context, "target"> & {
5828
+ /** Decoded owner value from the pre-transition snapshot. */
5829
+ readonly current: StateByIdentifier<States, Owner>
5830
+ /** Constructs the selected topology and requires `.update(...)`. */
5831
+ readonly target: UpdatingTargetBuilder<SelectionBuilder<Selection>, States, Owner>
5832
+ /** Constructs the complete replacement for the retained owner. */
5833
+ readonly owner: StateUpdateBuilder<States, Owner>
5834
+ }
5835
+
5694
5836
  /** Context capability available only to explicitly declinable resolvers. */
5695
5837
  export interface DeclineCapability {
5696
5838
  /** Declines this candidate and continues hierarchical transition selection. */
@@ -5721,25 +5863,27 @@ export declare namespace Machine {
5721
5863
 
5722
5864
  /** @internal */
5723
5865
  type StateUpdateResolver<
5866
+ States extends StateSchemas,
5724
5867
  Events extends ReadonlyArray<TaggedSchema>,
5725
5868
  Emits extends ReadonlyArray<TaggedSchema>,
5726
5869
  Context,
5727
- Selection
5870
+ Owner extends ValuedStateIdentifier<States>
5728
5871
  > = (
5729
- context: TransitionResolveContext<Context, Selection>,
5872
+ context: StateUpdateResolveContext<States, Context, Owner>,
5730
5873
  enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>
5731
- ) => SelectedTargetResult<Selection>
5874
+ ) => StateUpdate<States, Owner>
5732
5875
 
5733
5876
  /** @internal */
5734
5877
  type DeclinableStateUpdateResolver<
5878
+ States extends StateSchemas,
5735
5879
  Events extends ReadonlyArray<TaggedSchema>,
5736
5880
  Emits extends ReadonlyArray<TaggedSchema>,
5737
5881
  Context,
5738
- Selection
5882
+ Owner extends ValuedStateIdentifier<States>
5739
5883
  > = (
5740
- context: TransitionResolveContext<Context, Selection> & DeclineCapability,
5884
+ context: StateUpdateResolveContext<States, Context, Owner> & DeclineCapability,
5741
5885
  enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>
5742
- ) => SelectedTargetResult<Selection> | Declined
5886
+ ) => StateUpdate<States, Owner> | Declined
5743
5887
 
5744
5888
  /** One named destination declared by a branching transition. */
5745
5889
  export interface TransitionBranchInput<
@@ -5949,10 +6093,7 @@ export declare namespace Machine {
5949
6093
  >
5950
6094
  : {})
5951
6095
  & {
5952
- /**
5953
- * Evaluates state construction and queued commands only after this
5954
- * transition has been selected.
5955
- */
6096
+ /** Evaluates state construction after this transition is selected. */
5956
6097
  readonly resolve:
5957
6098
  & TransitionResolveRequired<States, Events, Emits, StateId, Context, Reenter, Selection>
5958
6099
  & ("declinable" extends Acceptance ? TransitionResolveDeclinable<
@@ -5981,6 +6122,79 @@ export declare namespace Machine {
5981
6122
  }
5982
6123
  : {}
5983
6124
  : {})
6125
+ & (SelectionKind<Selection> extends "state" ?
6126
+ SelectionScope<Selection> extends "local" | "branch" ?
6127
+ RetainedUpdateOwner<States, StateId, Selection> extends infer Owner extends ValuedStateIdentifier<States> ?
6128
+ [Owner] extends [never] ? {}
6129
+ : {
6130
+ /** Declares one valued owner retained by the selected topology. */
6131
+ readonly updating: <SelectedOwner extends Owner>(
6132
+ owner: RetainedOwnerSelector<SelectedOwner>
6133
+ ) => UpdatingTransitionTarget<
6134
+ States,
6135
+ Events,
6136
+ Emits,
6137
+ StateId,
6138
+ Context,
6139
+ Reenter,
6140
+ Acceptance,
6141
+ Selection,
6142
+ SelectedOwner
6143
+ >
6144
+ }
6145
+ : {}
6146
+ : {}
6147
+ : {})
6148
+
6149
+ /** A topology selection that requires one retained owner replacement. */
6150
+ export type UpdatingTransitionTarget<
6151
+ States extends StateSchemas,
6152
+ Events extends ReadonlyArray<TaggedSchema>,
6153
+ Emits extends ReadonlyArray<TaggedSchema>,
6154
+ StateId extends StateNodeIdentifier<States>,
6155
+ Context,
6156
+ Reenter extends boolean,
6157
+ Acceptance extends TransitionAcceptance,
6158
+ Selection extends TargetSelection<any, any, "state">,
6159
+ Owner extends ValuedStateIdentifier<States>
6160
+ > = Selection & {
6161
+ /** @internal */
6162
+ readonly "~effect/Machine/UpdatingTransitionTarget": Owner
6163
+ readonly resolve:
6164
+ & ((
6165
+ resolve: (
6166
+ context: UpdatingTransitionResolveContext<States, Context, Selection, Owner>,
6167
+ enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>
6168
+ ) => CombinedTarget<UnwrapConstruction<SelectedTargetResult<Selection>>, States, Owner>,
6169
+ options?: TransitionRequiredOptions<Reenter>
6170
+ ) => BuiltTransition<
6171
+ States,
6172
+ Events,
6173
+ Emits,
6174
+ StateId,
6175
+ Context,
6176
+ Reenter,
6177
+ CombinedTarget<UnwrapConstruction<SelectedTargetResult<Selection>>, States, Owner>,
6178
+ "required"
6179
+ >)
6180
+ & ("declinable" extends Acceptance ? (
6181
+ resolve: (
6182
+ context: UpdatingTransitionResolveContext<States, Context, Selection, Owner> & DeclineCapability,
6183
+ enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>
6184
+ ) => CombinedTarget<UnwrapConstruction<SelectedTargetResult<Selection>>, States, Owner> | Declined,
6185
+ options: TransitionDeclinableOptions<Reenter>
6186
+ ) => BuiltTransition<
6187
+ States,
6188
+ Events,
6189
+ Emits,
6190
+ StateId,
6191
+ Context,
6192
+ Reenter,
6193
+ CombinedTarget<UnwrapConstruction<SelectedTargetResult<Selection>>, States, Owner> | Declined,
6194
+ "declinable"
6195
+ >
6196
+ : {})
6197
+ }
5984
6198
 
5985
6199
  /** @internal */
5986
6200
  interface StateUpdateTransitionRequired<
@@ -5993,7 +6207,13 @@ export declare namespace Machine {
5993
6207
  Selection extends TargetSelection<any, any, "update">
5994
6208
  > {
5995
6209
  (
5996
- resolve: StateUpdateResolver<Events, Emits, Context, Selection>,
6210
+ resolve: StateUpdateResolver<
6211
+ States,
6212
+ Events,
6213
+ Emits,
6214
+ Context,
6215
+ Extract<SelectionPath<Selection>, ValuedStateIdentifier<States>>
6216
+ >,
5997
6217
  options?: TransitionRequiredOptions<Reenter>
5998
6218
  ): BuiltTransition<
5999
6219
  States,
@@ -6018,7 +6238,13 @@ export declare namespace Machine {
6018
6238
  Selection extends TargetSelection<any, any, "update">
6019
6239
  > {
6020
6240
  (
6021
- resolve: DeclinableStateUpdateResolver<Events, Emits, Context, Selection>,
6241
+ resolve: DeclinableStateUpdateResolver<
6242
+ States,
6243
+ Events,
6244
+ Emits,
6245
+ Context,
6246
+ Extract<SelectionPath<Selection>, ValuedStateIdentifier<States>>
6247
+ >,
6022
6248
  options: TransitionDeclinableOptions<Reenter>
6023
6249
  ): BuiltTransition<
6024
6250
  States,
@@ -8447,13 +8673,13 @@ interface Make {
8447
8673
  * const counter = Machine.make({
8448
8674
  * states: States.states,
8449
8675
  * events: Events,
8450
- * initial: (to) => to.Count().resolve(({ target }) => target(new Count({ value: 0 })))
8676
+ * initial: (to) => to.Count().resolve(({ target }) => target.decoded(new Count({ value: 0 })))
8451
8677
  * }).handle({
8452
8678
  * Count: {
8453
8679
  * on: {
8454
8680
  * Increment: (to) =>
8455
8681
  * to.full.Count().resolve(({ event, state, target }) =>
8456
- * target(new Count({ value: state.value + event.by })))
8682
+ * target.decoded(new Count({ value: state.value + event.by })))
8457
8683
  * }
8458
8684
  * }
8459
8685
  * })
@@ -8780,9 +9006,21 @@ type TransitionBranchRecordError<Message extends string, Key extends PropertyKey
8780
9006
 
8781
9007
  type InvalidStaticTransitionBranchKey<Branches> = Extract<keyof Branches, "" | number | symbol>
8782
9008
 
9009
+ type InvalidUpdatingTransitionBranchKey<Branches> = {
9010
+ readonly [Key in keyof Branches]: Branches[Key] extends {
9011
+ readonly target: { readonly "~effect/Machine/UpdatingTransitionTarget": string }
9012
+ } ? Key
9013
+ : never
9014
+ }[keyof Branches]
9015
+
8783
9016
  type ValidateTransitionBranchRecord<Branches> = [keyof Branches] extends [never] ?
8784
9017
  TransitionBranchRecordError<"Branch records must contain at least one branch">
8785
- : [InvalidStaticTransitionBranchKey<Branches>] extends [never] ? unknown
9018
+ : [InvalidStaticTransitionBranchKey<Branches>] extends [never] ?
9019
+ [InvalidUpdatingTransitionBranchKey<Branches>] extends [never] ? unknown
9020
+ : TransitionBranchRecordError<
9021
+ "Updating targets require a direct resolver",
9022
+ InvalidUpdatingTransitionBranchKey<Branches>
9023
+ >
8786
9024
  : TransitionBranchRecordError<
8787
9025
  "Branch keys must be non-empty, non-index strings",
8788
9026
  InvalidStaticTransitionBranchKey<Branches>