@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.
- package/README.md +79 -64
- package/dist/Machine.d.ts +139 -272
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +3 -49
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/invocation.d.ts.map +1 -1
- package/dist/internal/machine/invocation.js +1 -1
- package/dist/internal/machine/invocation.js.map +1 -1
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +48 -10
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/testing/MachineTest.d.ts +4 -4
- package/dist/testing/MachineTest.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/docs/agent-guide.md +106 -67
- package/package.json +1 -1
- package/src/Machine.ts +552 -1040
- package/src/internal/machine/invocation.ts +1 -1
- package/src/internal/machine/machine.ts +64 -8
- package/src/internal/testing/machine/exploration.ts +1 -1
- package/src/internal/testing/machine/trace.ts +1 -1
- package/src/internal/testing/machine/verification.ts +1 -1
- package/src/testing/MachineTest.ts +4 -4
- package/src/unstable/reactivity/AtomMachine.ts +1 -1
|
@@ -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.
|
|
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 (
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
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
|
-
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
585
|
+
...Machine.Machine.InputArgs<Machine.Machine.InputSchema<M>>
|
|
586
586
|
]
|
|
587
587
|
|
|
588
588
|
type MachineAtomOf<M extends Machine.Machine.Any, RuntimeError> = MachineAtom<
|