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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -54
  3. package/dist/actor.d.ts +8 -45
  4. package/dist/actor.js +157 -231
  5. package/dist/cluster/adapters/in-memory.d.ts +0 -1
  6. package/dist/cluster/adapters/in-memory.js +10 -5
  7. package/dist/cluster/entity-actor-ref.d.ts +2 -3
  8. package/dist/cluster/entity-actor-ref.js +14 -17
  9. package/dist/cluster/entity-machine.d.ts +2 -8
  10. package/dist/cluster/entity-machine.js +57 -34
  11. package/dist/cluster/index.js +2 -2
  12. package/dist/cluster/persistence.d.ts +0 -1
  13. package/dist/cluster/to-entity.d.ts +19 -21
  14. package/dist/cluster/to-entity.js +18 -19
  15. package/dist/errors.d.ts +11 -37
  16. package/dist/errors.js +12 -30
  17. package/dist/index.d.ts +4 -5
  18. package/dist/index.js +4 -5
  19. package/dist/inspection.d.ts +0 -1
  20. package/dist/inspection.js +24 -13
  21. package/dist/internal/brands.d.ts +0 -1
  22. package/dist/internal/event-advancement.d.ts +50 -0
  23. package/dist/internal/event-advancement.js +79 -0
  24. package/dist/internal/inspection.d.ts +5 -9
  25. package/dist/internal/inspection.js +31 -10
  26. package/dist/internal/machine-definition.d.ts +16 -0
  27. package/dist/internal/runtime.d.ts +1 -161
  28. package/dist/internal/runtime.js +191 -150
  29. package/dist/internal/transition.d.ts +4 -135
  30. package/dist/internal/transition.js +82 -157
  31. package/dist/internal/utils.d.ts +3 -40
  32. package/dist/internal/utils.js +2 -2
  33. package/dist/machine.d.ts +47 -137
  34. package/dist/machine.js +147 -215
  35. package/dist/schema.d.ts +42 -21
  36. package/dist/schema.js +28 -18
  37. package/dist/supervision.d.ts +1 -24
  38. package/dist/supervision.js +2 -3
  39. package/dist/testing.d.ts +15 -29
  40. package/dist/testing.js +76 -95
  41. package/package.json +19 -38
  42. package/dist/slot.d.ts +0 -159
  43. package/dist/slot.js +0 -165
  44. package/v3/dist/_virtual/_rolldown/runtime.js +0 -13
  45. package/v3/dist/actor.d.ts +0 -250
  46. package/v3/dist/actor.js +0 -577
  47. package/v3/dist/cluster/adapters/in-memory.d.ts +0 -15
  48. package/v3/dist/cluster/adapters/in-memory.js +0 -62
  49. package/v3/dist/cluster/entity-actor-ref.d.ts +0 -49
  50. package/v3/dist/cluster/entity-actor-ref.js +0 -19
  51. package/v3/dist/cluster/entity-machine.d.ts +0 -74
  52. package/v3/dist/cluster/entity-machine.js +0 -166
  53. package/v3/dist/cluster/index.d.ts +0 -6
  54. package/v3/dist/cluster/index.js +0 -6
  55. package/v3/dist/cluster/persistence.d.ts +0 -48
  56. package/v3/dist/cluster/persistence.js +0 -14
  57. package/v3/dist/cluster/to-entity.d.ts +0 -69
  58. package/v3/dist/cluster/to-entity.js +0 -59
  59. package/v3/dist/errors.d.ts +0 -95
  60. package/v3/dist/errors.js +0 -54
  61. package/v3/dist/index.d.ts +0 -11
  62. package/v3/dist/index.js +0 -9
  63. package/v3/dist/inspection.d.ts +0 -151
  64. package/v3/dist/inspection.js +0 -128
  65. package/v3/dist/internal/brands.d.ts +0 -50
  66. package/v3/dist/internal/inspection.d.ts +0 -11
  67. package/v3/dist/internal/inspection.js +0 -20
  68. package/v3/dist/internal/runtime.d.ts +0 -161
  69. package/v3/dist/internal/runtime.js +0 -360
  70. package/v3/dist/internal/transition.d.ts +0 -190
  71. package/v3/dist/internal/transition.js +0 -278
  72. package/v3/dist/internal/utils.d.ts +0 -101
  73. package/v3/dist/internal/utils.js +0 -75
  74. package/v3/dist/machine.d.ts +0 -398
  75. package/v3/dist/machine.js +0 -487
  76. package/v3/dist/schema.d.ts +0 -174
  77. package/v3/dist/schema.js +0 -206
  78. package/v3/dist/slot.d.ts +0 -158
  79. package/v3/dist/slot.js +0 -165
  80. package/v3/dist/supervision.d.ts +0 -97
  81. package/v3/dist/supervision.js +0 -42
  82. package/v3/dist/testing.d.ts +0 -151
  83. package/v3/dist/testing.js +0 -189
  84. /package/{v3/dist/internal/brands.js → dist/internal/machine-definition.js} +0 -0
@@ -1,151 +0,0 @@
1
- import { Context, Effect, Schema } from "effect";
2
-
3
- //#region src/inspection.d.ts
4
- /**
5
- * Resolve a type param: if it's a Schema, extract `.Type`; otherwise use as-is.
6
- */
7
- type ResolveType<T> = T extends Schema.Schema<infer A> ? A : T;
8
- /**
9
- * Event emitted when an actor is spawned
10
- */
11
- interface SpawnEvent<S> {
12
- readonly type: "@machine.spawn";
13
- readonly actorId: string;
14
- readonly initialState: S;
15
- readonly timestamp: number;
16
- }
17
- /**
18
- * Event emitted when an actor receives an event
19
- */
20
- interface EventReceivedEvent<S, E> {
21
- readonly type: "@machine.event";
22
- readonly actorId: string;
23
- readonly state: S;
24
- readonly event: E;
25
- readonly timestamp: number;
26
- }
27
- /**
28
- * Event emitted when a transition occurs
29
- */
30
- interface TransitionEvent<S, E> {
31
- readonly type: "@machine.transition";
32
- readonly actorId: string;
33
- readonly fromState: S;
34
- readonly toState: S;
35
- readonly event: E;
36
- readonly timestamp: number;
37
- }
38
- /**
39
- * Event emitted when a spawn effect runs
40
- */
41
- interface EffectEvent<S> {
42
- readonly type: "@machine.effect";
43
- readonly actorId: string;
44
- readonly effectType: "spawn";
45
- readonly state: S;
46
- readonly timestamp: number;
47
- }
48
- interface TaskEvent<S> {
49
- readonly type: "@machine.task";
50
- readonly actorId: string;
51
- readonly state: S;
52
- readonly taskName?: string;
53
- readonly phase: "start" | "success" | "failure" | "interrupt";
54
- readonly error?: string;
55
- readonly timestamp: number;
56
- }
57
- /**
58
- * Event emitted when a transition handler or spawn effect fails with a defect
59
- */
60
- interface ErrorEvent<S, E> {
61
- readonly type: "@machine.error";
62
- readonly actorId: string;
63
- readonly phase: "transition" | "spawn";
64
- readonly state: S;
65
- readonly event: E;
66
- readonly error: string;
67
- readonly timestamp: number;
68
- }
69
- /**
70
- * Event emitted when an actor stops
71
- */
72
- interface StopEvent<S> {
73
- readonly type: "@machine.stop";
74
- readonly actorId: string;
75
- readonly finalState: S;
76
- readonly timestamp: number;
77
- }
78
- /**
79
- * Union of all inspection events
80
- */
81
- type InspectionEvent<S, E> = SpawnEvent<S> | EventReceivedEvent<S, E> | TransitionEvent<S, E> | EffectEvent<S> | TaskEvent<S> | ErrorEvent<S, E> | StopEvent<S>;
82
- /**
83
- * Convenience alias for untyped inspection events.
84
- * Useful for general-purpose inspectors that don't need specific state/event types.
85
- * State and event fields are typed as `{ readonly _tag: string }` so discriminated
86
- * access to `_tag` works without casting.
87
- */
88
- type AnyInspectionEvent = InspectionEvent<{
89
- readonly _tag: string;
90
- }, {
91
- readonly _tag: string;
92
- }>;
93
- /**
94
- * Inspector interface for observing machine behavior
95
- */
96
- type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void>;
97
- interface Inspector<S, E> {
98
- readonly onInspect: InspectorHandler<S, E>;
99
- }
100
- /**
101
- * Inspector service tag - optional service for machine introspection
102
- * Uses `any` types to allow variance flexibility when providing the service
103
- */
104
- declare const Inspector: Context.Tag<Inspector<any, any>, Inspector<any, any>>;
105
- /**
106
- * Create an inspector from a callback function.
107
- *
108
- * Type params accept either raw tagged types or Schema constructors:
109
- * - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
110
- * - `makeInspector<MyState, MyEvent>(cb)` — explicit tagged types
111
- * - `makeInspector<typeof MyState, typeof MyEvent>(cb)` — schema constructors (auto-extracts `.Type`)
112
- */
113
- declare const makeInspector: <S = {
114
- readonly _tag: string;
115
- }, E = {
116
- readonly _tag: string;
117
- }>(onInspect: InspectorHandler<ResolveType<S>, ResolveType<E>>) => Inspector<ResolveType<S>, ResolveType<E>>;
118
- declare const makeInspectorEffect: <S = {
119
- readonly _tag: string;
120
- }, E = {
121
- readonly _tag: string;
122
- }>(onInspect: (event: InspectionEvent<ResolveType<S>, ResolveType<E>>) => Effect.Effect<void>) => Inspector<ResolveType<S>, ResolveType<E>>;
123
- declare const combineInspectors: <S, E>(...inspectors: ReadonlyArray<Inspector<S, E>>) => Inspector<S, E>;
124
- interface TracingInspectorOptions<S, E> {
125
- readonly spanName?: string | ((event: InspectionEvent<S, E>) => string);
126
- readonly attributes?: (event: InspectionEvent<S, E>) => Readonly<Record<string, string | number | boolean>>;
127
- readonly eventName?: (event: InspectionEvent<S, E>) => string;
128
- }
129
- declare const tracingInspector: <S extends {
130
- readonly _tag: string;
131
- }, E extends {
132
- readonly _tag: string;
133
- }>(options?: TracingInspectorOptions<S, E>) => Inspector<S, E>;
134
- /**
135
- * Console inspector that logs events in a readable format
136
- */
137
- declare const consoleInspector: () => Inspector<{
138
- readonly _tag: string;
139
- }, {
140
- readonly _tag: string;
141
- }>;
142
- /**
143
- * Collecting inspector that stores events in an array for testing
144
- */
145
- declare const collectingInspector: <S extends {
146
- readonly _tag: string;
147
- }, E extends {
148
- readonly _tag: string;
149
- }>(events: InspectionEvent<S, E>[]) => Inspector<S, E>;
150
- //#endregion
151
- export { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
@@ -1,128 +0,0 @@
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 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
- const makeInspectorEffect = (onInspect) => ({ onInspect });
18
- const inspectionEffect = (inspector, event) => {
19
- const result = inspector.onInspect(event);
20
- return Effect.isEffect(result) ? result : Effect.void;
21
- };
22
- const combineInspectors = (...inspectors) => ({ onInspect: (event) => Effect.forEach(inspectors, (inspector) => inspectionEffect(inspector, event).pipe(Effect.catchAllCause(() => Effect.void)), {
23
- concurrency: "unbounded",
24
- discard: true
25
- }) });
26
- const inspectionSpanName = (event) => {
27
- switch (event.type) {
28
- case "@machine.spawn": return `Machine.inspect ${event.initialState._tag}`;
29
- case "@machine.event": return `Machine.inspect ${event.event._tag}`;
30
- case "@machine.transition": return `Machine.inspect ${event.fromState._tag}->${event.toState._tag}`;
31
- case "@machine.effect": return `Machine.inspect ${event.effectType}`;
32
- case "@machine.task": return `Machine.inspect task:${event.phase}`;
33
- case "@machine.error": return `Machine.inspect ${event.phase}`;
34
- case "@machine.stop": return `Machine.inspect ${event.finalState._tag}`;
35
- }
36
- };
37
- const inspectionTraceName = (event) => {
38
- switch (event.type) {
39
- case "@machine.spawn": return `machine.spawn ${event.initialState._tag}`;
40
- case "@machine.event": return `machine.event ${event.event._tag}`;
41
- case "@machine.transition": return `machine.transition ${event.fromState._tag}->${event.toState._tag}`;
42
- case "@machine.effect": return `machine.effect ${event.effectType}`;
43
- case "@machine.task": return `machine.task ${event.phase}${event.taskName === void 0 ? "" : ` ${event.taskName}`}`;
44
- case "@machine.error": return `machine.error ${event.phase}`;
45
- case "@machine.stop": return `machine.stop ${event.finalState._tag}`;
46
- }
47
- };
48
- const inspectionAttributes = (event) => {
49
- const shared = {
50
- "machine.actor.id": event.actorId,
51
- "machine.inspection.type": event.type
52
- };
53
- switch (event.type) {
54
- case "@machine.spawn": return {
55
- ...shared,
56
- "machine.state.initial": event.initialState._tag
57
- };
58
- case "@machine.event": return {
59
- ...shared,
60
- "machine.state.current": event.state._tag,
61
- "machine.event.tag": event.event._tag
62
- };
63
- case "@machine.transition": return {
64
- ...shared,
65
- "machine.state.from": event.fromState._tag,
66
- "machine.state.to": event.toState._tag,
67
- "machine.event.tag": event.event._tag
68
- };
69
- case "@machine.effect": return {
70
- ...shared,
71
- "machine.state.current": event.state._tag,
72
- "machine.effect.kind": event.effectType
73
- };
74
- case "@machine.task": return {
75
- ...shared,
76
- "machine.state.current": event.state._tag,
77
- "machine.task.phase": event.phase,
78
- ...event.taskName === void 0 ? {} : { "machine.task.name": event.taskName }
79
- };
80
- case "@machine.error": return {
81
- ...shared,
82
- "machine.phase": event.phase,
83
- "machine.state.current": event.state._tag
84
- };
85
- case "@machine.stop": return {
86
- ...shared,
87
- "machine.state.final": event.finalState._tag
88
- };
89
- }
90
- };
91
- const tracingInspector = (options) => ({ onInspect: (event) => {
92
- const spanName = typeof options?.spanName === "function" ? options.spanName(event) : options?.spanName;
93
- const traceName = options?.eventName?.(event) ?? inspectionTraceName(event);
94
- const attributes = {
95
- ...inspectionAttributes(event),
96
- ...options?.attributes?.(event) ?? {}
97
- };
98
- return Effect.gen(function* () {
99
- const currentSpan = yield* Effect.option(Effect.currentSpan);
100
- if (Option.isSome(currentSpan)) currentSpan.value.event(traceName, BigInt(event.timestamp) * 1000000n, {
101
- actorId: event.actorId,
102
- inspectionType: event.type
103
- });
104
- }).pipe(Effect.withSpan(spanName ?? inspectionSpanName(event), { attributes }));
105
- } });
106
- /**
107
- * Console inspector that logs events in a readable format
108
- */
109
- const consoleInspector = () => makeInspectorEffect((event) => {
110
- const prefix = `[${event.actorId}]`;
111
- switch (event.type) {
112
- case "@machine.spawn": return Effect.log(`${prefix} spawned -> ${event.initialState._tag}`);
113
- case "@machine.event": return Effect.log(`${prefix} received ${event.event._tag} in ${event.state._tag}`);
114
- case "@machine.transition": return Effect.log(`${prefix} ${event.fromState._tag} -> ${event.toState._tag}`);
115
- case "@machine.effect": return Effect.log(`${prefix} ${event.effectType} effect in ${event.state._tag}`);
116
- case "@machine.task": return Effect.log(`${prefix} task ${event.phase} ${event.taskName ?? "<unnamed>"} in ${event.state._tag}`);
117
- case "@machine.error": return Effect.log(`${prefix} error in ${event.phase} ${event.state._tag} - ${String(event.error)}`);
118
- case "@machine.stop": return Effect.log(`${prefix} stopped in ${event.finalState._tag}`);
119
- }
120
- });
121
- /**
122
- * Collecting inspector that stores events in an array for testing
123
- */
124
- const collectingInspector = (events) => ({ onInspect: (event) => {
125
- events.push(event);
126
- } });
127
- //#endregion
128
- export { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
@@ -1,50 +0,0 @@
1
- import { Brand } from "effect";
2
-
3
- //#region src/internal/brands.d.ts
4
- type StateTypeId = "effect-machine/StateTypeId";
5
- type EventTypeId = "effect-machine/EventTypeId";
6
- interface StateBrand extends Brand.Brand<StateTypeId> {}
7
- interface EventBrand extends Brand.Brand<EventTypeId> {}
8
- type BrandedState = {
9
- readonly _tag: string;
10
- } & StateBrand;
11
- type BrandedEvent = {
12
- readonly _tag: string;
13
- } & EventBrand;
14
- type SchemaIdTypeId = "effect-machine/SchemaIdTypeId";
15
- /**
16
- * Brand that captures the schema definition type D.
17
- * Two schemas with identical definition shapes will have compatible brands.
18
- * Different definitions = incompatible brands.
19
- */
20
- interface SchemaIdBrand<_D extends Record<string, unknown>> extends Brand.Brand<SchemaIdTypeId> {}
21
- /**
22
- * Full state brand: combines base state brand with schema-specific brand
23
- */
24
- type FullStateBrand<D extends Record<string, unknown>> = StateBrand & SchemaIdBrand<D>;
25
- /**
26
- * Full event brand: combines base event brand with schema-specific brand
27
- */
28
- type FullEventBrand<D extends Record<string, unknown>> = EventBrand & SchemaIdBrand<D>;
29
- /**
30
- * Brand that carries the reply type for an event variant.
31
- * Present only on events defined with Event.reply().
32
- */
33
- type ReplyTypeId = "effect-machine/ReplyTypeId";
34
- interface ReplyTypeBrand<R> extends Brand.Brand<ReplyTypeId> {
35
- readonly _ReplyType: R;
36
- }
37
- /**
38
- * Extract the reply type from a branded event value.
39
- * Returns `never` if the event has no reply schema.
40
- */
41
- type ExtractReply<E> = E extends ReplyTypeBrand<infer R> ? R : never;
42
- /**
43
- * Value or constructor for a tagged type.
44
- * Accepts both plain values (empty structs) and constructor functions (non-empty structs).
45
- */
46
- type TaggedOrConstructor<T extends {
47
- readonly _tag: string;
48
- }> = T | ((...args: never[]) => T);
49
- //#endregion
50
- export { BrandedEvent, BrandedState, EventBrand, EventTypeId, ExtractReply, FullEventBrand, FullStateBrand, ReplyTypeBrand, ReplyTypeId, SchemaIdBrand, StateBrand, StateTypeId, TaggedOrConstructor };
@@ -1,11 +0,0 @@
1
- import { InspectionEvent, Inspector } from "../inspection.js";
2
- import { Effect } from "effect";
3
-
4
- //#region src/internal/inspection.d.ts
5
- /**
6
- * Emit an inspection event with timestamp from Clock.
7
- * @internal
8
- */
9
- declare const emitWithTimestamp: <S, E>(inspector: Inspector<S, E> | undefined, makeEvent: (timestamp: number) => InspectionEvent<S, E>) => Effect.Effect<void, never, never>;
10
- //#endregion
11
- export { emitWithTimestamp };
@@ -1,20 +0,0 @@
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 (Effect.isEffect(result)) yield* result.pipe(Effect.catchAllCause(() => Effect.void));
18
- });
19
- //#endregion
20
- export { emitWithTimestamp };
@@ -1,161 +0,0 @@
1
- import { NoReplyError } from "../errors.js";
2
- import { SlotsDef } from "../slot.js";
3
- import { ActorExit } from "../supervision.js";
4
- import { ProcessEventHooks, ProcessEventResult } from "./transition.js";
5
- import { Machine } from "../machine.js";
6
- import { ActorSystem } from "../actor.js";
7
- import { Deferred, Effect, Queue, Ref, Scope, SubscriptionRef } from "effect";
8
-
9
- //#region src/internal/runtime.d.ts
10
- /** @internal */
11
- type RuntimeQueuedEvent<E> = {
12
- readonly _tag: "send";
13
- readonly event: E;
14
- } | {
15
- readonly _tag: "sendWait";
16
- readonly event: E;
17
- readonly done: Deferred.Deferred<void, unknown>;
18
- } | {
19
- readonly _tag: "call";
20
- readonly event: E;
21
- readonly reply: Deferred.Deferred<ProcessEventResult<{
22
- readonly _tag: string;
23
- }>, unknown>;
24
- } | {
25
- readonly _tag: "ask";
26
- readonly event: E;
27
- readonly reply: Deferred.Deferred<unknown, NoReplyError>;
28
- } | {
29
- readonly _tag: "drain";
30
- readonly done: Deferred.Deferred<void>;
31
- };
32
- /**
33
- * Resources owned by the actor cell (stable across generations).
34
- * When provided, createRuntime uses these instead of allocating its own.
35
- * @internal
36
- */
37
- interface RuntimeCellResources<S, E> {
38
- readonly stateRef: SubscriptionRef.SubscriptionRef<S>;
39
- readonly eventQueue: Queue.Queue<RuntimeQueuedEvent<E>>;
40
- readonly stoppedRef: Ref.Ref<boolean>;
41
- }
42
- /** @internal */
43
- interface RuntimeHandle<S, E> {
44
- /** Enqueue a fire-and-forget event */
45
- readonly send: (event: E) => Effect.Effect<void>;
46
- /** Enqueue event and wait for processing to complete (for RPC Send). Fails on defect. */
47
- readonly sendWait: (event: E) => Effect.Effect<void, unknown>;
48
- /** Enqueue an ask event, returns the reply value */
49
- readonly ask: (event: E) => Effect.Effect<unknown, NoReplyError>;
50
- /** Get current state */
51
- readonly getState: Effect.Effect<S>;
52
- /** SubscriptionRef for state observation (WatchState streaming) */
53
- readonly stateRef: SubscriptionRef.SubscriptionRef<S>;
54
- /** Whether the runtime has stopped (final state reached) */
55
- readonly isStopped: Effect.Effect<boolean>;
56
- /** Stop the runtime (interrupt event loop, clean up) */
57
- readonly stop: Effect.Effect<void>;
58
- /**
59
- * Start the runtime — fork event loop, background effects, spawn effects.
60
- * Idempotent: first caller runs initialization, subsequent callers await completion.
61
- * Events sent before start() are queued and processed when start() runs.
62
- */
63
- readonly start: Effect.Effect<void>;
64
- /** @internal — raw event queue for direct enqueue (actor.ts uses this for pendingReplies tracking) */
65
- readonly _queue: Queue.Queue<RuntimeQueuedEvent<E>>;
66
- /** @internal — stopped ref for direct access */
67
- readonly _stoppedRef: Ref.Ref<boolean>;
68
- /**
69
- * Exit deferred — set exactly once with the exit reason when the runtime stops.
70
- * Final state → ActorExit.Final, explicit stop → ActorExit.Stopped, defect → ActorExit.Defect.
71
- */
72
- readonly exitDeferred: Deferred.Deferred<ActorExit<S>>;
73
- /**
74
- * Actor scope — owns background fibers for this generation.
75
- * Closing this scope interrupts all background fibers.
76
- */
77
- readonly actorScope: Scope.CloseableScope;
78
- }
79
- /** @internal */
80
- interface RuntimeLifecycleHooks<S, E> {
81
- /** Before processEventCore — actor emits @machine.event inspection */
82
- readonly onEvent?: (state: S, event: E) => Effect.Effect<void>;
83
- /** After SubscriptionRef.set on transition — actor notifies listeners, annotates spans */
84
- readonly onStateChange?: (result: ProcessEventResult<S>, event: E) => Effect.Effect<void>;
85
- /** After reply settlement when transition occurred — actor publishes to transitionsPubSub */
86
- readonly onProcessed?: (result: ProcessEventResult<S>, event: E) => Effect.Effect<void>;
87
- /** When final state detected in event loop — actor emits @machine.stop */
88
- readonly onFinal?: (state: S) => Effect.Effect<void>;
89
- /** Before stop resource cleanup — actor emits @machine.stop, settles pending replies */
90
- readonly onShutdown?: () => Effect.Effect<void>;
91
- /** Before initial spawn effects — actor emits @machine.effect inspection */
92
- readonly onInitialSpawnEffects?: (state: S) => Effect.Effect<void>;
93
- }
94
- /** @internal */
95
- interface RuntimeConfig<S, E> {
96
- readonly actorId: string;
97
- readonly hooks?: ProcessEventHooks<S, E>;
98
- /**
99
- * Cell-owned resources. When provided, the runtime uses the cell's stateRef,
100
- * eventQueue, and stoppedRef instead of creating its own.
101
- * Used by actor.ts for supervision (cell owns stable resources across generations).
102
- */
103
- readonly cellResources?: RuntimeCellResources<S, E>;
104
- /**
105
- * Custom queue factory. Default: `Queue.unbounded()`.
106
- * Use `Queue.sliding(n)` or `Queue.dropping(n)` for bounded queues.
107
- * Ignored when cellResources is provided.
108
- */
109
- readonly queueFactory?: Effect.Effect<Queue.Queue<RuntimeQueuedEvent<E>>>;
110
- /** Lifecycle callbacks for actor-specific concerns */
111
- readonly lifecycle?: RuntimeLifecycleHooks<S, E>;
112
- /** Wrap each processQueued invocation — actor uses for span annotations */
113
- readonly wrapProcess?: (state: S, event: E, inner: Effect.Effect<ProcessQueuedResult<S>>) => Effect.Effect<ProcessQueuedResult<S>>;
114
- /** Called after self.spawn succeeds — actor tracks children */
115
- readonly onChildSpawned?: (childId: string, child: unknown) => Effect.Effect<void>;
116
- /** Skip registering stop as scope finalizer — actor manages its own lifecycle */
117
- readonly skipFinalizer?: boolean;
118
- /** Prefix for child actor IDs in self.spawn. Entity-machine uses `${actorId}/`. Default: no prefix. */
119
- readonly childIdPrefix?: string;
120
- }
121
- /** @internal */
122
- interface ProcessQueuedResult<S> {
123
- readonly shouldStop: boolean;
124
- readonly stateChanged: boolean;
125
- readonly result: ProcessEventResult<S>;
126
- }
127
- /**
128
- * Create a runtime for a machine. Returns a handle for sending events
129
- * and querying state. The runtime owns:
130
- * - Event loop fiber
131
- * - Postpone buffer
132
- * - Background effects (under actorScope)
133
- * - State scope (spawn effects)
134
- * - Final state detection
135
- * - Exit reason via exitDeferred
136
- *
137
- * Resources (stateRef, eventQueue, stoppedRef) are either cell-provided
138
- * or allocated fresh by the runtime.
139
- *
140
- * @internal
141
- */
142
- declare const createRuntime: <S extends {
143
- readonly _tag: string;
144
- }, E extends {
145
- readonly _tag: string;
146
- }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, system: ActorSystem, config: RuntimeConfig<S, E>) => Effect.Effect<{
147
- stop: Effect.Effect<void, never, never>;
148
- start: Effect.Effect<void, unknown, unknown>;
149
- send: (event: E) => Effect.Effect<void>;
150
- sendWait: (event: E) => Effect.Effect<void, unknown>;
151
- ask: (event: E) => Effect.Effect<unknown, NoReplyError>;
152
- getState: Effect.Effect<S, never, never>;
153
- stateRef: SubscriptionRef.SubscriptionRef<S>;
154
- isStopped: Effect.Effect<boolean>;
155
- _queue: Queue.Queue<RuntimeQueuedEvent<E>>;
156
- _stoppedRef: Ref.Ref<boolean>;
157
- exitDeferred: Deferred.Deferred<ActorExit<S>, never>;
158
- actorScope: Scope.CloseableScope;
159
- }, never, Scope.Scope>;
160
- //#endregion
161
- export { ProcessQueuedResult, RuntimeCellResources, RuntimeConfig, RuntimeHandle, RuntimeLifecycleHooks, RuntimeQueuedEvent, createRuntime };