effect-machine 0.9.0 → 0.10.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 +76 -16
- package/dist/actor.d.ts +55 -89
- package/dist/actor.js +135 -30
- package/dist/cluster/entity-machine.js +5 -3
- package/dist/errors.d.ts +12 -1
- package/dist/errors.js +8 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/internal/transition.d.ts +26 -2
- package/dist/internal/transition.js +37 -8
- package/dist/internal/utils.d.ts +7 -2
- package/dist/machine.d.ts +66 -3
- package/dist/machine.js +65 -0
- package/dist/persistence/persistent-actor.js +52 -16
- package/dist/testing.js +57 -3
- package/package.json +9 -8
- package/{dist-v3 → v3/dist}/actor.d.ts +65 -78
- package/{dist-v3 → v3/dist}/actor.js +173 -35
- package/{dist-v3 → v3/dist}/cluster/entity-machine.d.ts +1 -1
- package/{dist-v3 → v3/dist}/cluster/entity-machine.js +8 -6
- package/{dist-v3 → v3/dist}/cluster/to-entity.d.ts +1 -1
- package/{dist-v3 → v3/dist}/cluster/to-entity.js +1 -1
- package/v3/dist/errors.d.ts +76 -0
- package/{dist-v3 → v3/dist}/errors.js +9 -2
- package/v3/dist/index.d.ts +13 -0
- package/v3/dist/index.js +13 -0
- package/{dist-v3 → v3/dist}/inspection.d.ts +53 -8
- package/v3/dist/inspection.js +156 -0
- package/{dist-v3 → v3/dist}/internal/brands.d.ts +1 -1
- package/{dist-v3 → v3/dist}/internal/inspection.d.ts +1 -1
- package/v3/dist/internal/inspection.js +20 -0
- package/{dist-v3 → v3/dist}/internal/transition.d.ts +35 -11
- package/{dist-v3 → v3/dist}/internal/transition.js +47 -15
- package/{dist-v3 → v3/dist}/internal/utils.d.ts +9 -4
- package/{dist-v3 → v3/dist}/internal/utils.js +1 -1
- package/{dist-v3 → v3/dist}/machine.d.ts +86 -9
- package/{dist-v3 → v3/dist}/machine.js +128 -2
- package/{dist-v3 → v3/dist}/persistence/adapter.d.ts +18 -5
- package/{dist-v3 → v3/dist}/persistence/adapter.js +1 -1
- package/{dist-v3 → v3/dist}/persistence/adapters/in-memory.d.ts +1 -1
- package/{dist-v3 → v3/dist}/persistence/adapters/in-memory.js +1 -1
- package/{dist-v3 → v3/dist}/persistence/persistent-actor.d.ts +7 -6
- package/{dist-v3 → v3/dist}/persistence/persistent-actor.js +58 -19
- package/{dist-v3 → v3/dist}/persistence/persistent-machine.d.ts +1 -1
- package/{dist-v3 → v3/dist}/persistence/persistent-machine.js +1 -1
- package/{dist-v3 → v3/dist}/schema.d.ts +1 -1
- package/{dist-v3 → v3/dist}/schema.js +5 -2
- package/{dist-v3 → v3/dist}/slot.d.ts +4 -3
- package/{dist-v3 → v3/dist}/slot.js +1 -1
- package/{dist-v3 → v3/dist}/testing.d.ts +14 -8
- package/{dist-v3 → v3/dist}/testing.js +60 -6
- package/dist-v3/errors.d.ts +0 -27
- package/dist-v3/index.d.ts +0 -12
- package/dist-v3/index.js +0 -13
- package/dist-v3/inspection.js +0 -48
- package/dist-v3/internal/inspection.js +0 -13
- /package/{dist-v3 → v3/dist}/_virtual/_rolldown/runtime.js +0 -0
- /package/{dist-v3 → v3/dist}/cluster/index.d.ts +0 -0
- /package/{dist-v3 → v3/dist}/cluster/index.js +0 -0
- /package/{dist-v3 → v3/dist}/internal/brands.js +0 -0
- /package/{dist-v3 → v3/dist}/persistence/index.d.ts +0 -0
- /package/{dist-v3 → v3/dist}/persistence/index.js +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { Context, Effect, Option } from "effect";
|
|
2
|
+
//#region src/inspection.ts
|
|
3
|
+
/**
|
|
4
|
+
* Inspector service tag - optional service for machine introspection
|
|
5
|
+
* Uses `any` types to allow variance flexibility when providing the service
|
|
6
|
+
*/
|
|
7
|
+
const Inspector = Context.GenericTag("@effect/machine/Inspector");
|
|
8
|
+
/**
|
|
9
|
+
* Create an inspector from a sync callback function.
|
|
10
|
+
*
|
|
11
|
+
* Type params accept either raw tagged types or Schema constructors:
|
|
12
|
+
* - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
|
|
13
|
+
* - `makeInspector<MyState, MyEvent>(cb)` — explicit tagged types
|
|
14
|
+
* - `makeInspector<typeof MyState, typeof MyEvent>(cb)` — schema constructors (auto-extracts `.Type`)
|
|
15
|
+
*/
|
|
16
|
+
const makeInspector = (onInspect) => ({ onInspect });
|
|
17
|
+
/**
|
|
18
|
+
* Create an inspector from an Effect-returning callback function.
|
|
19
|
+
*/
|
|
20
|
+
const makeInspectorEffect = (onInspect) => ({ onInspect });
|
|
21
|
+
/**
|
|
22
|
+
* Run an inspector handler, handling both sync and Effect returns.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
const inspectionEffect = (inspector, event) => {
|
|
26
|
+
const result = inspector.onInspect(event);
|
|
27
|
+
return Effect.isEffect(result) ? result : Effect.void;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Combine multiple inspectors into one. All run concurrently per event.
|
|
31
|
+
* Individual inspector failures are swallowed.
|
|
32
|
+
*/
|
|
33
|
+
const combineInspectors = (...inspectors) => ({ onInspect: (event) => Effect.forEach(inspectors, (inspector) => inspectionEffect(inspector, event).pipe(Effect.catchAllCause(() => Effect.void)), {
|
|
34
|
+
concurrency: "unbounded",
|
|
35
|
+
discard: true
|
|
36
|
+
}) });
|
|
37
|
+
const inspectionSpanName = (event) => {
|
|
38
|
+
switch (event.type) {
|
|
39
|
+
case "@machine.spawn": return `Machine.inspect ${event.initialState._tag}`;
|
|
40
|
+
case "@machine.event": return `Machine.inspect ${event.event._tag}`;
|
|
41
|
+
case "@machine.transition": return `Machine.inspect ${event.fromState._tag}->${event.toState._tag}`;
|
|
42
|
+
case "@machine.effect": return `Machine.inspect ${event.effectType}`;
|
|
43
|
+
case "@machine.task": return `Machine.inspect task:${event.phase}`;
|
|
44
|
+
case "@machine.error": return `Machine.inspect ${event.phase}`;
|
|
45
|
+
case "@machine.stop": return `Machine.inspect ${event.finalState._tag}`;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const inspectionTraceName = (event) => {
|
|
49
|
+
switch (event.type) {
|
|
50
|
+
case "@machine.spawn": return `machine.spawn ${event.initialState._tag}`;
|
|
51
|
+
case "@machine.event": return `machine.event ${event.event._tag}`;
|
|
52
|
+
case "@machine.transition": return `machine.transition ${event.fromState._tag}->${event.toState._tag}`;
|
|
53
|
+
case "@machine.effect": return `machine.effect ${event.effectType}`;
|
|
54
|
+
case "@machine.task": return `machine.task ${event.phase}${event.taskName === void 0 ? "" : ` ${event.taskName}`}`;
|
|
55
|
+
case "@machine.error": return `machine.error ${event.phase}`;
|
|
56
|
+
case "@machine.stop": return `machine.stop ${event.finalState._tag}`;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const inspectionAttributes = (event) => {
|
|
60
|
+
const shared = {
|
|
61
|
+
"machine.actor.id": event.actorId,
|
|
62
|
+
"machine.inspection.type": event.type
|
|
63
|
+
};
|
|
64
|
+
switch (event.type) {
|
|
65
|
+
case "@machine.spawn": return {
|
|
66
|
+
...shared,
|
|
67
|
+
"machine.state.initial": event.initialState._tag
|
|
68
|
+
};
|
|
69
|
+
case "@machine.event": return {
|
|
70
|
+
...shared,
|
|
71
|
+
"machine.state.current": event.state._tag,
|
|
72
|
+
"machine.event.tag": event.event._tag
|
|
73
|
+
};
|
|
74
|
+
case "@machine.transition": return {
|
|
75
|
+
...shared,
|
|
76
|
+
"machine.state.from": event.fromState._tag,
|
|
77
|
+
"machine.state.to": event.toState._tag,
|
|
78
|
+
"machine.event.tag": event.event._tag
|
|
79
|
+
};
|
|
80
|
+
case "@machine.effect": return {
|
|
81
|
+
...shared,
|
|
82
|
+
"machine.state.current": event.state._tag,
|
|
83
|
+
"machine.effect.kind": event.effectType
|
|
84
|
+
};
|
|
85
|
+
case "@machine.task": return {
|
|
86
|
+
...shared,
|
|
87
|
+
"machine.state.current": event.state._tag,
|
|
88
|
+
"machine.task.phase": event.phase,
|
|
89
|
+
...event.taskName === void 0 ? {} : { "machine.task.name": event.taskName }
|
|
90
|
+
};
|
|
91
|
+
case "@machine.error": return {
|
|
92
|
+
...shared,
|
|
93
|
+
"machine.phase": event.phase,
|
|
94
|
+
"machine.state.current": event.state._tag
|
|
95
|
+
};
|
|
96
|
+
case "@machine.stop": return {
|
|
97
|
+
...shared,
|
|
98
|
+
"machine.state.final": event.finalState._tag
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Inspector that emits OpenTelemetry spans and events for each inspection event.
|
|
104
|
+
*/
|
|
105
|
+
const tracingInspector = (options) => ({ onInspect: (event) => {
|
|
106
|
+
const spanName = typeof options?.spanName === "function" ? options.spanName(event) : options?.spanName;
|
|
107
|
+
const traceName = options?.eventName?.(event) ?? inspectionTraceName(event);
|
|
108
|
+
const attributes = {
|
|
109
|
+
...inspectionAttributes(event),
|
|
110
|
+
...options?.attributes?.(event) ?? {}
|
|
111
|
+
};
|
|
112
|
+
return Effect.gen(function* () {
|
|
113
|
+
const currentSpan = yield* Effect.option(Effect.currentSpan);
|
|
114
|
+
if (Option.isSome(currentSpan)) currentSpan.value.event(traceName, BigInt(event.timestamp) * 1000000n, {
|
|
115
|
+
actorId: event.actorId,
|
|
116
|
+
inspectionType: event.type
|
|
117
|
+
});
|
|
118
|
+
}).pipe(Effect.withSpan(spanName ?? inspectionSpanName(event), { attributes }));
|
|
119
|
+
} });
|
|
120
|
+
/**
|
|
121
|
+
* Console inspector that logs events in a readable format
|
|
122
|
+
*/
|
|
123
|
+
const consoleInspector = () => makeInspector((event) => {
|
|
124
|
+
const prefix = `[${event.actorId}]`;
|
|
125
|
+
switch (event.type) {
|
|
126
|
+
case "@machine.spawn":
|
|
127
|
+
console.log(prefix, "spawned →", event.initialState._tag);
|
|
128
|
+
break;
|
|
129
|
+
case "@machine.event":
|
|
130
|
+
console.log(prefix, "received", event.event._tag, "in", event.state._tag);
|
|
131
|
+
break;
|
|
132
|
+
case "@machine.transition":
|
|
133
|
+
console.log(prefix, event.fromState._tag, "→", event.toState._tag);
|
|
134
|
+
break;
|
|
135
|
+
case "@machine.effect":
|
|
136
|
+
console.log(prefix, event.effectType, "effect in", event.state._tag);
|
|
137
|
+
break;
|
|
138
|
+
case "@machine.task":
|
|
139
|
+
console.log(prefix, "task", event.phase, event.taskName ?? "<unnamed>", "in", event.state._tag);
|
|
140
|
+
break;
|
|
141
|
+
case "@machine.error":
|
|
142
|
+
console.log(prefix, "error in", event.phase, event.state._tag, "-", event.error);
|
|
143
|
+
break;
|
|
144
|
+
case "@machine.stop":
|
|
145
|
+
console.log(prefix, "stopped in", event.finalState._tag);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
/**
|
|
150
|
+
* Collecting inspector that stores events in an array for testing
|
|
151
|
+
*/
|
|
152
|
+
const collectingInspector = (events) => ({ onInspect: (event) => {
|
|
153
|
+
events.push(event);
|
|
154
|
+
} });
|
|
155
|
+
//#endregion
|
|
156
|
+
export { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Clock, Effect } from "effect";
|
|
2
|
+
//#region src/internal/inspection.ts
|
|
3
|
+
/**
|
|
4
|
+
* Emit an inspection event with timestamp from Clock.
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
const emitWithTimestamp = Effect.fn("effect-machine.emitWithTimestamp")(function* (inspector, makeEvent) {
|
|
8
|
+
if (inspector === void 0) return;
|
|
9
|
+
const event = makeEvent(yield* Clock.currentTimeMillis);
|
|
10
|
+
const result = yield* Effect.sync(() => {
|
|
11
|
+
try {
|
|
12
|
+
return inspector.onInspect(event);
|
|
13
|
+
} catch {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
if (result !== void 0 && Effect.isEffect(result)) yield* result.pipe(Effect.catchAllCause(() => Effect.void));
|
|
18
|
+
});
|
|
19
|
+
//#endregion
|
|
20
|
+
export { emitWithTimestamp };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { EffectsDef, GuardsDef } from "../slot.js";
|
|
1
|
+
import { EffectsDef, GuardsDef, MachineContext } from "../slot.js";
|
|
2
2
|
import { BuiltMachine, Machine, MachineRef, SpawnEffect, Transition } from "../machine.js";
|
|
3
3
|
import { ActorSystem } from "../actor.js";
|
|
4
4
|
import { Cause, Effect, Scope } from "effect";
|
|
5
5
|
|
|
6
|
-
//#region src
|
|
6
|
+
//#region src/internal/transition.d.ts
|
|
7
7
|
/**
|
|
8
8
|
* Result of executing a transition.
|
|
9
9
|
*/
|
|
@@ -29,7 +29,11 @@ declare const runTransitionHandler: <S extends {
|
|
|
29
29
|
readonly _tag: string;
|
|
30
30
|
}, E extends {
|
|
31
31
|
readonly _tag: string;
|
|
32
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, transition: Transition<S, E, GD, EFD, R>, state: S, event: E, self: MachineRef<E>, system: ActorSystem) => Effect.Effect<
|
|
32
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, transition: Transition<S, E, GD, EFD, R>, state: S, event: E, self: MachineRef<E>, system: ActorSystem, actorId: string) => Effect.Effect<{
|
|
33
|
+
newState: S;
|
|
34
|
+
hasReply: boolean;
|
|
35
|
+
reply: unknown;
|
|
36
|
+
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>>>;
|
|
33
37
|
/**
|
|
34
38
|
* Execute a transition for a given state and event.
|
|
35
39
|
* Handles transition resolution, handler invocation, and guard/effect slot creation.
|
|
@@ -45,11 +49,13 @@ declare const executeTransition: <S extends {
|
|
|
45
49
|
readonly _tag: string;
|
|
46
50
|
}, E extends {
|
|
47
51
|
readonly _tag: string;
|
|
48
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, currentState: S, event: E, self: MachineRef<E>, system: ActorSystem) => Effect.Effect<{
|
|
52
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, currentState: S, event: E, self: MachineRef<E>, system: ActorSystem, actorId: string) => Effect.Effect<{
|
|
49
53
|
newState: S;
|
|
50
54
|
transitioned: boolean;
|
|
51
55
|
reenter: boolean;
|
|
52
|
-
|
|
56
|
+
hasReply: boolean;
|
|
57
|
+
reply: unknown;
|
|
58
|
+
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>>>;
|
|
53
59
|
/**
|
|
54
60
|
* Optional hooks for event processing inspection/tracing.
|
|
55
61
|
*/
|
|
@@ -84,7 +90,22 @@ interface ProcessEventResult<S> {
|
|
|
84
90
|
readonly lifecycleRan: boolean;
|
|
85
91
|
/** Whether new state is final */
|
|
86
92
|
readonly isFinal: boolean;
|
|
93
|
+
/** Whether the handler provided a reply (structural, not value-based) */
|
|
94
|
+
readonly hasReply: boolean;
|
|
95
|
+
/** Domain reply value from handler (used by ask). Only meaningful when hasReply is true. */
|
|
96
|
+
readonly reply?: unknown;
|
|
97
|
+
/** Whether the event was postponed (buffered for retry after next state change) */
|
|
98
|
+
readonly postponed: boolean;
|
|
87
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Check if an event should be postponed in the current state.
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
declare const shouldPostpone: <S extends {
|
|
105
|
+
readonly _tag: string;
|
|
106
|
+
}, E extends {
|
|
107
|
+
readonly _tag: string;
|
|
108
|
+
}, R>(machine: Machine<S, E, R, any, any, any, any>, stateTag: string, eventTag: string) => boolean;
|
|
88
109
|
/**
|
|
89
110
|
* Process a single event through the machine.
|
|
90
111
|
*
|
|
@@ -103,13 +124,16 @@ declare const processEventCore: <S extends {
|
|
|
103
124
|
readonly _tag: string;
|
|
104
125
|
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, currentState: S, event: E, self: MachineRef<E>, stateScopeRef: {
|
|
105
126
|
current: Scope.CloseableScope;
|
|
106
|
-
}, system: ActorSystem, hooks?: ProcessEventHooks<S, E> | undefined) => Effect.Effect<{
|
|
107
|
-
newState:
|
|
127
|
+
}, system: ActorSystem, actorId: string, hooks?: ProcessEventHooks<S, E> | undefined) => Effect.Effect<{
|
|
128
|
+
newState: S;
|
|
108
129
|
previousState: S;
|
|
109
130
|
transitioned: boolean;
|
|
110
|
-
lifecycleRan:
|
|
131
|
+
lifecycleRan: boolean;
|
|
111
132
|
isFinal: boolean;
|
|
112
|
-
|
|
133
|
+
hasReply: boolean;
|
|
134
|
+
reply: unknown;
|
|
135
|
+
postponed: boolean;
|
|
136
|
+
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
|
|
113
137
|
/**
|
|
114
138
|
* Run spawn effects for a state (forked into state scope, auto-cancelled on state exit).
|
|
115
139
|
*
|
|
@@ -119,7 +143,7 @@ declare const runSpawnEffects: <S extends {
|
|
|
119
143
|
readonly _tag: string;
|
|
120
144
|
}, E extends {
|
|
121
145
|
readonly _tag: string;
|
|
122
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, state: S, event: E, self: MachineRef<E>, stateScope: Scope.CloseableScope, system: ActorSystem, onError?: ((info: ProcessEventError<S, E>) => Effect.Effect<void>) | undefined) => Effect.Effect<void, never,
|
|
146
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, state: S, event: E, self: MachineRef<E>, stateScope: Scope.CloseableScope, system: ActorSystem, actorId: string, onError?: ((info: ProcessEventError<S, E>) => Effect.Effect<void>) | undefined) => Effect.Effect<void, never, Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
|
|
123
147
|
/**
|
|
124
148
|
* Resolve which transition should fire for a given state and event.
|
|
125
149
|
* Uses indexed O(1) lookup. First matching transition wins.
|
|
@@ -157,4 +181,4 @@ declare const findSpawnEffects: <S extends {
|
|
|
157
181
|
readonly _tag: string;
|
|
158
182
|
}, R, GD extends GuardsDef = Record<string, never>, EFD extends EffectsDef = Record<string, never>>(machine: Machine<S, E, R, any, any, GD, EFD>, stateTag: string) => ReadonlyArray<SpawnEffect<S, E, EFD, R>>;
|
|
159
183
|
//#endregion
|
|
160
|
-
export { ProcessEventError, ProcessEventHooks, ProcessEventResult, TransitionExecutionResult, executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler };
|
|
184
|
+
export { ProcessEventError, ProcessEventHooks, ProcessEventResult, TransitionExecutionResult, executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler, shouldPostpone };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { INTERNAL_ENTER_EVENT, isEffect } from "./utils.js";
|
|
2
2
|
import { BuiltMachine } from "../machine.js";
|
|
3
3
|
import { Cause, Effect, Exit, Scope } from "effect";
|
|
4
|
-
//#region src
|
|
4
|
+
//#region src/internal/transition.ts
|
|
5
5
|
/**
|
|
6
6
|
* Transition execution and indexing.
|
|
7
7
|
*
|
|
@@ -22,8 +22,9 @@ import { Cause, Effect, Exit, Scope } from "effect";
|
|
|
22
22
|
*
|
|
23
23
|
* @internal
|
|
24
24
|
*/
|
|
25
|
-
const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(function* (machine, transition, state, event, self, system) {
|
|
25
|
+
const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(function* (machine, transition, state, event, self, system, actorId) {
|
|
26
26
|
const ctx = {
|
|
27
|
+
actorId,
|
|
27
28
|
state,
|
|
28
29
|
event,
|
|
29
30
|
self,
|
|
@@ -36,8 +37,18 @@ const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(fu
|
|
|
36
37
|
guards,
|
|
37
38
|
effects
|
|
38
39
|
};
|
|
39
|
-
const
|
|
40
|
-
|
|
40
|
+
const raw = transition.handler(handlerCtx);
|
|
41
|
+
const resolved = isEffect(raw) ? yield* raw.pipe(Effect.provideService(machine.Context, ctx)) : raw;
|
|
42
|
+
if (resolved !== null && typeof resolved === "object" && "state" in resolved && "reply" in resolved && !("_tag" in resolved)) return {
|
|
43
|
+
newState: resolved.state,
|
|
44
|
+
hasReply: true,
|
|
45
|
+
reply: resolved.reply
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
newState: resolved,
|
|
49
|
+
hasReply: false,
|
|
50
|
+
reply: void 0
|
|
51
|
+
};
|
|
41
52
|
});
|
|
42
53
|
/**
|
|
43
54
|
* Execute a transition for a given state and event.
|
|
@@ -50,20 +61,33 @@ const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(fu
|
|
|
50
61
|
*
|
|
51
62
|
* @internal
|
|
52
63
|
*/
|
|
53
|
-
const executeTransition = Effect.fn("effect-machine.executeTransition")(function* (machine, currentState, event, self, system) {
|
|
64
|
+
const executeTransition = Effect.fn("effect-machine.executeTransition")(function* (machine, currentState, event, self, system, actorId) {
|
|
54
65
|
const transition = resolveTransition(machine, currentState, event);
|
|
55
66
|
if (transition === void 0) return {
|
|
56
67
|
newState: currentState,
|
|
57
68
|
transitioned: false,
|
|
58
|
-
reenter: false
|
|
69
|
+
reenter: false,
|
|
70
|
+
hasReply: false,
|
|
71
|
+
reply: void 0
|
|
59
72
|
};
|
|
73
|
+
const { newState, hasReply, reply } = yield* runTransitionHandler(machine, transition, currentState, event, self, system, actorId);
|
|
60
74
|
return {
|
|
61
|
-
newState
|
|
75
|
+
newState,
|
|
62
76
|
transitioned: true,
|
|
63
|
-
reenter: transition.reenter === true
|
|
77
|
+
reenter: transition.reenter === true,
|
|
78
|
+
hasReply,
|
|
79
|
+
reply
|
|
64
80
|
};
|
|
65
81
|
});
|
|
66
82
|
/**
|
|
83
|
+
* Check if an event should be postponed in the current state.
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
const shouldPostpone = (machine, stateTag, eventTag) => {
|
|
87
|
+
for (const rule of machine.postponeRules) if (rule.stateTag === stateTag && rule.eventTag === eventTag) return true;
|
|
88
|
+
return false;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
67
91
|
* Process a single event through the machine.
|
|
68
92
|
*
|
|
69
93
|
* Handles:
|
|
@@ -75,8 +99,8 @@ const executeTransition = Effect.fn("effect-machine.executeTransition")(function
|
|
|
75
99
|
*
|
|
76
100
|
* @internal
|
|
77
101
|
*/
|
|
78
|
-
const processEventCore = Effect.fn("effect-machine.processEventCore")(function* (machine, currentState, event, self, stateScopeRef, system, hooks) {
|
|
79
|
-
const result = yield* executeTransition(machine, currentState, event, self, system).pipe(Effect.catchAllCause((cause) => {
|
|
102
|
+
const processEventCore = Effect.fn("effect-machine.processEventCore")(function* (machine, currentState, event, self, stateScopeRef, system, actorId, hooks) {
|
|
103
|
+
const result = yield* executeTransition(machine, currentState, event, self, system, actorId).pipe(Effect.catchAllCause((cause) => {
|
|
80
104
|
if (Cause.isInterruptedOnly(cause)) return Effect.interrupt;
|
|
81
105
|
const onError = hooks?.onError;
|
|
82
106
|
if (onError === void 0) return Effect.failCause(cause).pipe(Effect.orDie);
|
|
@@ -92,7 +116,10 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
|
|
|
92
116
|
previousState: currentState,
|
|
93
117
|
transitioned: false,
|
|
94
118
|
lifecycleRan: false,
|
|
95
|
-
isFinal: false
|
|
119
|
+
isFinal: false,
|
|
120
|
+
hasReply: false,
|
|
121
|
+
reply: void 0,
|
|
122
|
+
postponed: false
|
|
96
123
|
};
|
|
97
124
|
const newState = result.newState;
|
|
98
125
|
const runLifecycle = newState._tag !== currentState._tag || result.reenter;
|
|
@@ -101,14 +128,17 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
|
|
|
101
128
|
stateScopeRef.current = yield* Scope.make();
|
|
102
129
|
if (hooks?.onTransition !== void 0) yield* hooks.onTransition(currentState, newState, event);
|
|
103
130
|
if (hooks?.onSpawnEffect !== void 0) yield* hooks.onSpawnEffect(newState);
|
|
104
|
-
yield* runSpawnEffects(machine, newState, { _tag: INTERNAL_ENTER_EVENT }, self, stateScopeRef.current, system, hooks?.onError);
|
|
131
|
+
yield* runSpawnEffects(machine, newState, { _tag: INTERNAL_ENTER_EVENT }, self, stateScopeRef.current, system, actorId, hooks?.onError);
|
|
105
132
|
}
|
|
106
133
|
return {
|
|
107
134
|
newState,
|
|
108
135
|
previousState: currentState,
|
|
109
136
|
transitioned: true,
|
|
110
137
|
lifecycleRan: runLifecycle,
|
|
111
|
-
isFinal: machine.finalStates.has(newState._tag)
|
|
138
|
+
isFinal: machine.finalStates.has(newState._tag),
|
|
139
|
+
hasReply: result.hasReply,
|
|
140
|
+
reply: result.reply,
|
|
141
|
+
postponed: false
|
|
112
142
|
};
|
|
113
143
|
});
|
|
114
144
|
/**
|
|
@@ -116,9 +146,10 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
|
|
|
116
146
|
*
|
|
117
147
|
* @internal
|
|
118
148
|
*/
|
|
119
|
-
const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (machine, state, event, self, stateScope, system, onError) {
|
|
149
|
+
const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (machine, state, event, self, stateScope, system, actorId, onError) {
|
|
120
150
|
const spawnEffects = findSpawnEffects(machine, state._tag);
|
|
121
151
|
const ctx = {
|
|
152
|
+
actorId,
|
|
122
153
|
state,
|
|
123
154
|
event,
|
|
124
155
|
self,
|
|
@@ -128,6 +159,7 @@ const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (m
|
|
|
128
159
|
const reportError = onError;
|
|
129
160
|
for (const spawnEffect of spawnEffects) {
|
|
130
161
|
const effect = spawnEffect.handler({
|
|
162
|
+
actorId,
|
|
131
163
|
state,
|
|
132
164
|
event,
|
|
133
165
|
self,
|
|
@@ -233,4 +265,4 @@ const findSpawnEffects = (machine, stateTag) => {
|
|
|
233
265
|
return getIndex(machine).spawn.get(stateTag) ?? [];
|
|
234
266
|
};
|
|
235
267
|
//#endregion
|
|
236
|
-
export { executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler };
|
|
268
|
+
export { executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler, shouldPostpone };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ActorSystem } from "../actor.js";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
|
|
4
|
-
//#region src
|
|
4
|
+
//#region src/internal/utils.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* Extracts _tag from a tagged union member
|
|
7
7
|
*/
|
|
@@ -23,10 +23,15 @@ type InstanceOf<C> = C extends ((...args: unknown[]) => infer R) ? R : never;
|
|
|
23
23
|
type TaggedConstructor<T extends {
|
|
24
24
|
readonly _tag: string;
|
|
25
25
|
}> = (args: Omit<T, "_tag">) => T;
|
|
26
|
+
/** Reply tuple returned from transition handlers for ask support */
|
|
27
|
+
interface TransitionReply<State> {
|
|
28
|
+
readonly state: State;
|
|
29
|
+
readonly reply: unknown;
|
|
30
|
+
}
|
|
26
31
|
/**
|
|
27
|
-
* Transition handler result - either a new state or Effect producing one
|
|
32
|
+
* Transition handler result - either a new state, reply tuple, or Effect producing one
|
|
28
33
|
*/
|
|
29
|
-
type TransitionResult<State, R> = State | Effect.Effect<State
|
|
34
|
+
type TransitionResult<State, R> = State | TransitionReply<State> | Effect.Effect<State | TransitionReply<State>, never, R>;
|
|
30
35
|
/**
|
|
31
36
|
* Internal event tags used for lifecycle effect contexts.
|
|
32
37
|
* Prefixed with $ to distinguish from user events.
|
|
@@ -57,4 +62,4 @@ declare const isEffect: (value: unknown) => value is Effect.Effect<unknown, unkn
|
|
|
57
62
|
*/
|
|
58
63
|
declare const stubSystem: ActorSystem;
|
|
59
64
|
//#endregion
|
|
60
|
-
export { ArgsOf, INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, InstanceOf, TagOf, TaggedConstructor, TransitionResult, getTag, isEffect, stubSystem };
|
|
65
|
+
export { ArgsOf, INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, InstanceOf, TagOf, TaggedConstructor, TransitionReply, TransitionResult, getTag, isEffect, stubSystem };
|
|
@@ -1,22 +1,24 @@
|
|
|
1
|
+
import { EffectHandlers, EffectSlots, EffectsDef, EffectsSchema, GuardHandlers, GuardSlots, GuardsDef, GuardsSchema, MachineContext } from "./slot.js";
|
|
1
2
|
import { TransitionResult } from "./internal/utils.js";
|
|
2
3
|
import { BrandedEvent, BrandedState, TaggedOrConstructor } from "./internal/brands.js";
|
|
3
4
|
import { MachineEventSchema, MachineStateSchema, VariantsUnion } from "./schema.js";
|
|
4
5
|
import { PersistenceConfig, PersistentMachine } from "./persistence/persistent-machine.js";
|
|
5
6
|
import { DuplicateActorError } from "./errors.js";
|
|
6
|
-
import { EffectHandlers, EffectSlots, EffectsDef, EffectsSchema, GuardHandlers, GuardSlots, GuardsDef, GuardsSchema, MachineContext } from "./slot.js";
|
|
7
7
|
import { findTransitions } from "./internal/transition.js";
|
|
8
8
|
import { ActorRef, ActorSystem } from "./actor.js";
|
|
9
|
-
import { Cause, Context, Effect, Schedule, Schema, Scope } from "effect";
|
|
9
|
+
import { Cause, Context, Duration, Effect, Schedule, Schema, Scope } from "effect";
|
|
10
10
|
|
|
11
|
-
//#region src
|
|
11
|
+
//#region src/machine.d.ts
|
|
12
12
|
declare namespace machine_d_exports {
|
|
13
|
-
export { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, PersistenceConfig, PersistentMachine, ProvideHandlers, SlotContext, SpawnEffect, StateEffectHandler, StateHandlerContext, Transition, TransitionHandler, findTransitions, make, spawn };
|
|
13
|
+
export { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, PersistenceConfig, PersistentMachine, ProvideHandlers, SlotContext, SpawnEffect, StateEffectHandler, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, TransitionHandler, findTransitions, make, spawn };
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Self reference for sending events back to the machine
|
|
17
17
|
*/
|
|
18
18
|
interface MachineRef<Event> {
|
|
19
19
|
readonly send: (event: Event) => Effect.Effect<void>;
|
|
20
|
+
/** Fire-and-forget alias for send (OTP gen_server:cast). */
|
|
21
|
+
readonly cast: (event: Event) => Effect.Effect<void>;
|
|
20
22
|
readonly spawn: <S2 extends {
|
|
21
23
|
readonly _tag: string;
|
|
22
24
|
}, E2 extends {
|
|
@@ -36,6 +38,7 @@ interface HandlerContext<State, Event, GD extends GuardsDef, ED extends EffectsD
|
|
|
36
38
|
* Handler context passed to state effect handlers (onEnter, spawn, background)
|
|
37
39
|
*/
|
|
38
40
|
interface StateHandlerContext<State, Event, ED extends EffectsDef> {
|
|
41
|
+
readonly actorId: string;
|
|
39
42
|
readonly state: State;
|
|
40
43
|
readonly event: Event;
|
|
41
44
|
readonly self: MachineRef<Event>;
|
|
@@ -80,6 +83,23 @@ interface PersistOptions {
|
|
|
80
83
|
readonly journalEvents: boolean;
|
|
81
84
|
readonly machineType?: string;
|
|
82
85
|
}
|
|
86
|
+
interface TaskOptions<State, Event, ED extends EffectsDef, A, E1, ES, EF> {
|
|
87
|
+
readonly onSuccess: (value: A, ctx: StateHandlerContext<State, Event, ED>) => ES;
|
|
88
|
+
readonly onFailure?: (cause: Cause.Cause<E1>, ctx: StateHandlerContext<State, Event, ED>) => EF;
|
|
89
|
+
readonly name?: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Configuration for `.timeout()` — gen_statem-style state timeouts.
|
|
93
|
+
*
|
|
94
|
+
* Entering the state starts a timer. Leaving cancels it.
|
|
95
|
+
* `.reenter()` restarts the timer with fresh state values.
|
|
96
|
+
*/
|
|
97
|
+
interface TimeoutConfig<State, Event> {
|
|
98
|
+
/** Duration before firing. Static or derived from current state. */
|
|
99
|
+
readonly duration: Duration.DurationInput | ((state: State) => Duration.DurationInput);
|
|
100
|
+
/** Event to send when the timer fires. Static or derived from current state. */
|
|
101
|
+
readonly event: Event | ((state: State) => Event);
|
|
102
|
+
}
|
|
83
103
|
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
84
104
|
type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false;
|
|
85
105
|
type NormalizeR<T> = IsAny<T> extends true ? T : IsUnknown<T> extends true ? never : T;
|
|
@@ -146,6 +166,11 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
|
|
|
146
166
|
/** @internal */
|
|
147
167
|
readonly _finalStates: Set<string>;
|
|
148
168
|
/** @internal */
|
|
169
|
+
readonly _postponeRules: Array<{
|
|
170
|
+
readonly stateTag: string;
|
|
171
|
+
readonly eventTag: string;
|
|
172
|
+
}>;
|
|
173
|
+
/** @internal */
|
|
149
174
|
readonly _guardsSchema?: GuardsSchema<GD>;
|
|
150
175
|
/** @internal */
|
|
151
176
|
readonly _effectsSchema?: EffectsSchema<EFD>;
|
|
@@ -169,10 +194,18 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
|
|
|
169
194
|
get spawnEffects(): ReadonlyArray<SpawnEffect<State, Event, EFD, R>>;
|
|
170
195
|
get backgroundEffects(): ReadonlyArray<BackgroundEffect<State, Event, EFD, R>>;
|
|
171
196
|
get finalStates(): ReadonlySet<string>;
|
|
197
|
+
get postponeRules(): ReadonlyArray<{
|
|
198
|
+
readonly stateTag: string;
|
|
199
|
+
readonly eventTag: string;
|
|
200
|
+
}>;
|
|
172
201
|
get guardsSchema(): GuardsSchema<GD> | undefined;
|
|
173
202
|
get effectsSchema(): EffectsSchema<EFD> | undefined;
|
|
174
203
|
/** @internal */
|
|
175
204
|
constructor(initial: State, stateSchema?: Schema.Schema<State, unknown, never>, eventSchema?: Schema.Schema<Event, unknown, never>, guardsSchema?: GuardsSchema<GD>, effectsSchema?: EffectsSchema<EFD>);
|
|
205
|
+
from<NS extends VariantsUnion<_SD> & BrandedState, R1>(state: TaggedOrConstructor<NS>, build: (scope: TransitionScope<State, Event, R, _SD, _ED, GD, EFD, NS>) => R1): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
206
|
+
from<NS extends ReadonlyArray<TaggedOrConstructor<VariantsUnion<_SD> & BrandedState>>, R1>(states: NS, build: (scope: TransitionScope<State, Event, R, _SD, _ED, GD, EFD, NS[number] extends TaggedOrConstructor<infer S extends VariantsUnion<_SD> & BrandedState> ? S : never>) => R1): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
207
|
+
/** @internal */
|
|
208
|
+
scopeTransition<NS extends VariantsUnion<_SD> & BrandedState, NE extends VariantsUnion<_ED> & BrandedEvent, RS extends VariantsUnion<_SD> & BrandedState>(states: ReadonlyArray<TaggedOrConstructor<NS>>, event: TaggedOrConstructor<NE>, handler: TransitionHandler<NS, NE, RS, GD, EFD, never>, reenter: boolean): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
176
209
|
/** Register transition for a single state */
|
|
177
210
|
on<NS extends VariantsUnion<_SD> & BrandedState, NE extends VariantsUnion<_ED> & BrandedEvent, RS extends VariantsUnion<_SD> & BrandedState>(state: TaggedOrConstructor<NS>, event: TaggedOrConstructor<NE>, handler: TransitionHandler<NS, NE, RS, GD, EFD, never>): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
178
211
|
/** Register transition for multiple states (handler receives union of state types) */
|
|
@@ -219,10 +252,29 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
|
|
|
219
252
|
* State-scoped task that runs on entry and sends success/failure events.
|
|
220
253
|
* Interrupts do not emit failure events.
|
|
221
254
|
*/
|
|
222
|
-
task<NS extends VariantsUnion<_SD> & BrandedState, A, E1, ES extends VariantsUnion<_ED> & BrandedEvent, EF extends VariantsUnion<_ED> & BrandedEvent>(state: TaggedOrConstructor<NS>, run: (ctx: StateHandlerContext<NS, VariantsUnion<_ED> & BrandedEvent, EFD>) => Effect.Effect<A, E1, Scope.Scope>, options:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
255
|
+
task<NS extends VariantsUnion<_SD> & BrandedState, A, E1, ES extends VariantsUnion<_ED> & BrandedEvent, EF extends VariantsUnion<_ED> & BrandedEvent>(state: TaggedOrConstructor<NS>, run: (ctx: StateHandlerContext<NS, VariantsUnion<_ED> & BrandedEvent, EFD>) => Effect.Effect<A, E1, Scope.Scope>, options: TaskOptions<NS, VariantsUnion<_ED> & BrandedEvent, EFD, A, E1, ES, EF>): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
256
|
+
/**
|
|
257
|
+
* State timeout — gen_statem's `state_timeout`.
|
|
258
|
+
*
|
|
259
|
+
* Entering the state starts a timer. Leaving cancels it (via state scope).
|
|
260
|
+
* `.reenter()` restarts the timer with fresh state values.
|
|
261
|
+
* Compiles to `.task()` internally — preserves `@machine.task` inspection events.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```ts
|
|
265
|
+
* machine
|
|
266
|
+
* .timeout(State.Loading, {
|
|
267
|
+
* duration: Duration.seconds(30),
|
|
268
|
+
* event: Event.Timeout,
|
|
269
|
+
* })
|
|
270
|
+
* // Dynamic duration from state
|
|
271
|
+
* .timeout(State.Retrying, {
|
|
272
|
+
* duration: (state) => Duration.seconds(state.backoff),
|
|
273
|
+
* event: Event.GiveUp,
|
|
274
|
+
* })
|
|
275
|
+
* ```
|
|
276
|
+
*/
|
|
277
|
+
timeout<NS extends VariantsUnion<_SD> & BrandedState>(state: TaggedOrConstructor<NS>, config: TimeoutConfig<NS, VariantsUnion<_ED> & BrandedEvent>): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
226
278
|
/**
|
|
227
279
|
* Machine-lifetime effect that is forked on actor spawn and runs until the actor stops.
|
|
228
280
|
* Use effect slots defined via `Slot.Effects` for the actual work.
|
|
@@ -244,6 +296,24 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
|
|
|
244
296
|
* ```
|
|
245
297
|
*/
|
|
246
298
|
background(handler: StateEffectHandler<State, Event, EFD, Scope.Scope>): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
299
|
+
/**
|
|
300
|
+
* Postpone events — gen_statem's event postpone.
|
|
301
|
+
*
|
|
302
|
+
* When a matching event arrives in the given state, it is buffered instead of
|
|
303
|
+
* processed. After the next state transition (tag change), all buffered events
|
|
304
|
+
* are drained through the loop in FIFO order.
|
|
305
|
+
*
|
|
306
|
+
* Reply-bearing events (from `call`/`ask`) in the postpone buffer are settled
|
|
307
|
+
* with `ActorStoppedError` on stop/interrupt/final-state.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```ts
|
|
311
|
+
* machine
|
|
312
|
+
* .postpone(State.Connecting, Event.Data) // single event
|
|
313
|
+
* .postpone(State.Connecting, [Event.Data, Event.Cmd]) // multiple events
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
postpone<NS extends VariantsUnion<_SD> & BrandedState>(state: TaggedOrConstructor<NS>, events: TaggedOrConstructor<VariantsUnion<_ED> & BrandedEvent> | ReadonlyArray<TaggedOrConstructor<VariantsUnion<_ED> & BrandedEvent>>): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
247
317
|
final<NS extends VariantsUnion<_SD> & BrandedState>(state: TaggedOrConstructor<NS>): Machine<State, Event, R, _SD, _ED, GD, EFD>;
|
|
248
318
|
/**
|
|
249
319
|
* Finalize the machine. Returns a `BuiltMachine` — the only type accepted by `Machine.spawn`.
|
|
@@ -260,6 +330,13 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
|
|
|
260
330
|
}, R>;
|
|
261
331
|
static make<SD extends Record<string, Schema.Struct.Fields>, ED extends Record<string, Schema.Struct.Fields>, S extends BrandedState, E extends BrandedEvent, GD extends GuardsDef = Record<string, never>, EFD extends EffectsDef = Record<string, never>>(config: MakeConfig<SD, ED, S, E, GD, EFD>): Machine<S, E, never, SD, ED, GD, EFD>;
|
|
262
332
|
}
|
|
333
|
+
declare class TransitionScope<State, Event, R, _SD extends Record<string, Schema.Struct.Fields>, _ED extends Record<string, Schema.Struct.Fields>, GD extends GuardsDef, EFD extends EffectsDef, SelectedState extends VariantsUnion<_SD> & BrandedState> {
|
|
334
|
+
private readonly machine;
|
|
335
|
+
private readonly states;
|
|
336
|
+
constructor(machine: Machine<State, Event, R, _SD, _ED, GD, EFD>, states: ReadonlyArray<TaggedOrConstructor<SelectedState>>);
|
|
337
|
+
on<NE extends VariantsUnion<_ED> & BrandedEvent, RS extends VariantsUnion<_SD> & BrandedState>(event: TaggedOrConstructor<NE>, handler: TransitionHandler<SelectedState, NE, RS, GD, EFD, never>): TransitionScope<State, Event, R, _SD, _ED, GD, EFD, SelectedState>;
|
|
338
|
+
reenter<NE extends VariantsUnion<_ED> & BrandedEvent, RS extends VariantsUnion<_SD> & BrandedState>(event: TaggedOrConstructor<NE>, handler: TransitionHandler<SelectedState, NE, RS, GD, EFD, never>): TransitionScope<State, Event, R, _SD, _ED, GD, EFD, SelectedState>;
|
|
339
|
+
}
|
|
263
340
|
declare const make: typeof Machine.make;
|
|
264
341
|
declare const spawn: {
|
|
265
342
|
<S extends {
|
|
@@ -274,4 +351,4 @@ declare const spawn: {
|
|
|
274
351
|
}, R>(machine: BuiltMachine<S, E, R>, id: string): Effect.Effect<ActorRef<S, E>, never, R>;
|
|
275
352
|
};
|
|
276
353
|
//#endregion
|
|
277
|
-
export { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, type PersistenceConfig, type PersistentMachine, ProvideHandlers, SlotContext, SpawnEffect, StateEffectHandler, StateHandlerContext, Transition, TransitionHandler, findTransitions, machine_d_exports, make, spawn };
|
|
354
|
+
export { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, type PersistenceConfig, type PersistentMachine, ProvideHandlers, SlotContext, SpawnEffect, StateEffectHandler, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, TransitionHandler, findTransitions, machine_d_exports, make, spawn };
|