@typeonce/effect-machine 0.17.0 → 0.18.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.
@@ -31,7 +31,7 @@ export interface AnyConfig {
31
31
  export const makeKey = (path: string, id: string): string => `${path.length}:${path}${id}`
32
32
 
33
33
  /** @internal */
34
- export const makeChildId = (path: string, id: string): string => `Machine.invoke:${makeKey(path, id)}`
34
+ export const makeChildId = (path: string, id: string): string => `Machine.invocation:${makeKey(path, id)}`
35
35
 
36
36
  const oneShot = (effect: Effect.Effect<any, any, any>): Logic<void, never, any, any, any> => ({
37
37
  initial: () => Effect.void,
@@ -54,6 +54,7 @@ const TypeId = "~effect/Machine"
54
54
  const ParentTypeId = "~effect/Machine/Parent"
55
55
  export const InvokeTypeId: unique symbol = Symbol.for("effect/Machine/Invoke")
56
56
  export const TransitionTypeId: unique symbol = Symbol.for("effect/Machine/Transition")
57
+ const InvokeBuilderDescriptorTypeId: unique symbol = Symbol("effect/Machine/InvokeBuilderDescriptor")
57
58
  const ChildMachineTypeId = "~effect/Machine/ChildMachine"
58
59
  type IsAny<A> = 0 extends 1 & A ? true : false
59
60
  type MachineRuntimeRequirement = internalRuntime.MachineRuntime
@@ -788,20 +789,75 @@ const captureEventHandlers = (
788
789
  return captured
789
790
  }
790
791
 
792
+ interface InvokeBuilderDescriptor {
793
+ readonly [InvokeBuilderDescriptorTypeId]: typeof InvokeBuilderDescriptorTypeId
794
+ readonly config: Readonly<Record<PropertyKey, unknown>>
795
+ }
796
+
797
+ type InvokeBuilderChannel = "onDone" | "onFailure" | "onElement" | "onSnapshot"
798
+
799
+ const makeInvokeBuilder = (
800
+ config: Readonly<Record<PropertyKey, unknown>>,
801
+ channels: ReadonlyArray<InvokeBuilderChannel>
802
+ ): InvokeBuilderDescriptor => {
803
+ const builder: Record<PropertyKey, unknown> = {
804
+ [InvokeBuilderDescriptorTypeId]: InvokeBuilderDescriptorTypeId as typeof InvokeBuilderDescriptorTypeId,
805
+ config
806
+ }
807
+ for (const channel of channels) {
808
+ if (!hasProperty(config, channel)) {
809
+ builder[channel] = (handler: unknown) => makeInvokeBuilder({ ...config, [channel]: handler }, channels)
810
+ }
811
+ }
812
+ return Object.freeze(builder) as unknown as InvokeBuilderDescriptor
813
+ }
814
+
815
+ const invokeSelector = Object.freeze({
816
+ effect: (id: string, effect: unknown) => makeInvokeBuilder({ id, effect }, ["onDone", "onFailure"]),
817
+ stream: (id: string, stream: unknown) => makeInvokeBuilder({ id, stream }, ["onElement", "onDone", "onFailure"]),
818
+ timer: (id: string, after: unknown) => makeInvokeBuilder({ id, after }, ["onDone"]),
819
+ logic: (id: string, options: Readonly<Record<PropertyKey, unknown>>) =>
820
+ makeInvokeBuilder({ id, ...options }, ["onSnapshot", "onDone", "onFailure"]),
821
+ child: (child: unknown, options?: Readonly<Record<PropertyKey, unknown>>) =>
822
+ makeInvokeBuilder(options === undefined ? { child } : { child, ...options }, [
823
+ "onSnapshot",
824
+ "onDone",
825
+ "onFailure"
826
+ ])
827
+ })
828
+
829
+ const invokeBuilderConfig = (value: unknown, path: string): Readonly<Record<PropertyKey, unknown>> => {
830
+ if (
831
+ typeof value !== "object" || value === null ||
832
+ !hasProperty(value, InvokeBuilderDescriptorTypeId) ||
833
+ value[InvokeBuilderDescriptorTypeId] !== InvokeBuilderDescriptorTypeId
834
+ ) {
835
+ throw new Error(`Machine invocation for state "${path}" must be constructed from its source selector`)
836
+ }
837
+ return (value as unknown as InvokeBuilderDescriptor).config
838
+ }
839
+
791
840
  const captureInvokeDefinition = (
792
841
  invoke: unknown,
793
842
  stateNodes: Machine.StateNodes,
794
843
  path: string
795
844
  ): unknown => {
796
- if (Array.isArray(invoke)) return invoke.map((item) => captureInvokeDefinition(item, stateNodes, path))
797
- if (typeof invoke !== "object" || invoke === null) return invoke
798
- const captured = { ...(invoke as Record<PropertyKey, unknown>) }
799
- for (const key of ["onElement", "onDone", "onFailure", "onSnapshot"] as const) {
800
- if (captured[key] !== undefined) {
801
- captured[key] = captureTransition(captured[key], stateNodes, path, key)
845
+ if (typeof invoke !== "function") {
846
+ throw new Error(`Machine invocation for state "${path}" must be a source-first callback`)
847
+ }
848
+ const authored = invoke(invokeSelector)
849
+ const definitions = Array.isArray(authored) ? authored : [authored]
850
+ const capturedDefinitions = definitions.map((definition) => {
851
+ const captured = { ...invokeBuilderConfig(definition, path) }
852
+ for (const key of ["onElement", "onDone", "onFailure", "onSnapshot"] as const) {
853
+ if (captured[key] !== undefined) {
854
+ captured[key] = captureTransition(captured[key], stateNodes, path, key)
855
+ }
802
856
  }
803
- }
804
- return captured
857
+ return captured
858
+ })
859
+ if (Array.isArray(authored)) return capturedDefinitions
860
+ return capturedDefinitions[0]
805
861
  }
806
862
 
807
863
  const flattenHandlers = (
@@ -34,7 +34,7 @@ import { makeTransitionCoverageCollector } from "./transitionCoverage.js"
34
34
 
35
35
  type AnyMachine = Machine.Machine.Any
36
36
 
37
- type InputValue<M extends AnyMachine> = Machine.Machine.Input<M>["Type"]
37
+ type InputValue<M extends AnyMachine> = Machine.Machine.Input<M>
38
38
 
39
39
  type ReadyMachine<M extends AnyMachine> =
40
40
  & M
@@ -22,7 +22,7 @@ import type { EnsureExecutable } from "../../machine/readiness.js"
22
22
 
23
23
  type AnyMachine = Machine.Machine.Any
24
24
 
25
- type InputValue<M extends AnyMachine> = Machine.Machine.Input<M>["Type"]
25
+ type InputValue<M extends AnyMachine> = Machine.Machine.Input<M>
26
26
 
27
27
  type StatePath<M extends AnyMachine> = Machine.Machine.StateIdentifier<Machine.Machine.States<M>>
28
28
 
@@ -152,7 +152,7 @@ export const interpretModel = ReferenceModel.interpretModel
152
152
 
153
153
  type AnyMachine = Machine.Machine.Any
154
154
 
155
- type InputValue<M extends AnyMachine> = Machine.Machine.Input<M>["Type"]
155
+ type InputValue<M extends AnyMachine> = Machine.Machine.Input<M>
156
156
 
157
157
  type StatePath<M extends AnyMachine> = Machine.Machine.StateIdentifier<Machine.Machine.States<M>>
158
158
 
@@ -122,7 +122,7 @@ export const interpretModel: (model: FiniteModel, events: ReadonlyArray<string>)
122
122
 
123
123
  type AnyMachine = Machine.Machine.Any
124
124
 
125
- type InputValue<M extends AnyMachine> = Machine.Machine.Input<M>["Type"]
125
+ type InputValue<M extends AnyMachine> = Machine.Machine.Input<M>
126
126
 
127
127
  type StatePath<M extends AnyMachine> = Machine.Machine.StateIdentifier<Machine.Machine.States<M>>
128
128
 
@@ -151,7 +151,7 @@ type RootReadyMachine<M extends AnyMachine> =
151
151
  * @category models
152
152
  * @since 0.4.0
153
153
  */
154
- export type Scenario<M extends AnyMachine> = Machine.Machine.Input<M> extends typeof Schema.Void ? {
154
+ export type Scenario<M extends AnyMachine> = Machine.Machine.InputSchema<M> extends typeof Schema.Void ? {
155
155
  readonly events: ReadonlyArray<Machine.Machine.InputEvent<M>>
156
156
  }
157
157
  : {
@@ -174,7 +174,7 @@ export type ScenarioOptions<M extends AnyMachine> =
174
174
  readonly maxEvents?: number
175
175
  readonly eventsArbitrary?: FastCheck.Arbitrary<ReadonlyArray<Machine.Machine.InputEvent<M>>>
176
176
  }
177
- & (Machine.Machine.Input<M> extends typeof Schema.Void ? {
177
+ & (Machine.Machine.InputSchema<M> extends typeof Schema.Void ? {
178
178
  readonly inputArbitrary?: never
179
179
  }
180
180
  : {
@@ -1410,7 +1410,7 @@ interface ExploreOptionsBase<M extends AnyMachine, Key extends ExplorationKey> {
1410
1410
  */
1411
1411
  export type ExploreOptions<M extends AnyMachine, Key extends ExplorationKey = ExplorationKey> =
1412
1412
  & ExploreOptionsBase<M, Key>
1413
- & (Machine.Machine.Input<M> extends typeof Schema.Void ? {
1413
+ & (Machine.Machine.InputSchema<M> extends typeof Schema.Void ? {
1414
1414
  readonly input?: never
1415
1415
  }
1416
1416
  : {
@@ -582,7 +582,7 @@ type EnsureMachineExecutable<M extends Machine.Machine.Any> = IsAny<Machine.Mach
582
582
  >
583
583
 
584
584
  type MachineInputArgsOf<M extends Machine.Machine.Any> = [
585
- ...Machine.Machine.InputArgs<Machine.Machine.Input<M>>
585
+ ...Machine.Machine.InputArgs<Machine.Machine.InputSchema<M>>
586
586
  ]
587
587
 
588
588
  type MachineAtomOf<M extends Machine.Machine.Any, RuntimeError> = MachineAtom<