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
package/dist/slot.d.ts DELETED
@@ -1,159 +0,0 @@
1
- import { ActorSystemService } from "./actor.js";
2
- import { Context, Effect, Schema } from "effect";
3
-
4
- //#region src/slot.d.ts
5
- /** Schema fields definition (like Schema.Struct.Fields) */
6
- type Fields = Record<string, Schema.Top>;
7
- /** Extract the type from schema fields (used for parameters) */
8
- type FieldsToParams<F extends Fields> = keyof F extends never ? void : Schema.Schema.Type<Schema.Struct<F>>;
9
- /**
10
- * Definition of a single slot function.
11
- * Created via `Slot.fn(params, returnSchema?)`.
12
- *
13
- * Carries both type-level information and materialized schemas
14
- * for runtime validation and serialization.
15
- */
16
- interface SlotFnDef<F extends Fields = Fields, Return = void> {
17
- readonly _tag: "SlotFnDef";
18
- readonly fields: F;
19
- /** Return schema — undefined means void */
20
- readonly returnSchema: Schema.Schema<Return> | undefined;
21
- /** Materialized input schema (Schema.Struct of fields, or Schema.Void for empty) */
22
- readonly inputSchema: Schema.Codec<FieldsToParams<F>>;
23
- /** Materialized output schema (returnSchema or Schema.Void) */
24
- readonly outputSchema: Schema.Codec<Return>;
25
- }
26
- /**
27
- * Define a single slot function with parameter schema and optional return schema.
28
- *
29
- * @example
30
- * ```ts
31
- * // Guard-like: returns boolean
32
- * Slot.fn({ max: Schema.Number }, Schema.Boolean)
33
- *
34
- * // Effect-like: returns void (default)
35
- * Slot.fn({ url: Schema.String })
36
- *
37
- * // No params, returns boolean
38
- * Slot.fn({}, Schema.Boolean)
39
- * ```
40
- */
41
- declare const fn: {
42
- <F extends Fields, Return>(fields: F, returnSchema: Schema.Schema<Return>): SlotFnDef<F, Return>;
43
- <F extends Fields>(fields: F): SlotFnDef<F>;
44
- };
45
- /**
46
- * Record of slot definitions. Keys are slot names, values are SlotFnDef.
47
- */
48
- type SlotsDef = Record<string, SlotFnDef<Fields, unknown>>;
49
- /**
50
- * Slots schema — returned by `Slot.define()`. Passed to `Machine.make({ slots })`.
51
- */
52
- interface SlotsSchema<D extends SlotsDef> {
53
- readonly _tag: "SlotsSchema";
54
- readonly definitions: D;
55
- /** Schema for slot requests `{ _tag: "SlotRequest", name, params }`. For RPC request payloads. */
56
- readonly requestSchema: Schema.Codec<SlotRequest<D>>;
57
- /** Schema for slot results `{ _tag: "SlotResult", name, result }`. For RPC response payloads. */
58
- readonly resultSchema: Schema.Codec<SlotResult<D>>;
59
- /** Schema for slot invocations `{ _tag: "SlotInvocation", name, params, result }`. For persistence/logging. */
60
- readonly invocationSchema: Schema.Codec<SlotInvocation<D>>;
61
- /** Create callable slot proxies (used by Machine internally) */
62
- readonly _createSlots: (resolve: <N extends keyof D & string>(name: N, params: SlotParams<D[N]>) => Effect.Effect<SlotReturn<D[N]>>) => SlotCalls<D>;
63
- }
64
- /**
65
- * A serialized slot request — captures name and params (no result).
66
- * Used for RPC request payloads.
67
- */
68
- type SlotRequest<D extends SlotsDef> = { readonly [K in keyof D & string]: {
69
- readonly _tag: "SlotRequest";
70
- readonly name: K;
71
- readonly params: SlotParams<D[K]>;
72
- } }[keyof D & string];
73
- /**
74
- * A serialized slot result — captures name and result (no params).
75
- * Used for RPC response payloads.
76
- */
77
- type SlotResult<D extends SlotsDef> = { readonly [K in keyof D & string]: {
78
- readonly _tag: "SlotResult";
79
- readonly name: K;
80
- readonly result: SlotReturn<D[K]>;
81
- } }[keyof D & string];
82
- /**
83
- * A serialized slot invocation — captures name, params, and result.
84
- * Used for persistence, logging, and audit trails.
85
- */
86
- type SlotInvocation<D extends SlotsDef> = { readonly [K in keyof D & string]: {
87
- readonly _tag: "SlotInvocation";
88
- readonly name: K;
89
- readonly params: SlotParams<D[K]>;
90
- readonly result: SlotReturn<D[K]>;
91
- } }[keyof D & string];
92
- /** Extract params type from a SlotFnDef */
93
- type SlotParams<D extends SlotFnDef<Fields, unknown>> = D extends SlotFnDef<infer F, unknown> ? FieldsToParams<F> : never;
94
- /** Extract return type from a SlotFnDef */
95
- type SlotReturn<D extends SlotFnDef<Fields, unknown>> = D extends SlotFnDef<Fields, infer R> ? R : never;
96
- /**
97
- * A callable slot — function that takes params and returns Effect<Return>.
98
- */
99
- interface SlotCall<Name extends string, Params, Return> {
100
- readonly _tag: "Slot";
101
- readonly name: Name;
102
- (params: Params): Effect.Effect<Return>;
103
- }
104
- /**
105
- * Convert slot definitions to callable slot proxies.
106
- */
107
- type SlotCalls<D extends SlotsDef> = { readonly [K in keyof D & string]: SlotCall<K, SlotParams<D[K]>, SlotReturn<D[K]>> };
108
- /**
109
- * Slot handler implementation.
110
- * Receives only params — use `yield* machine.Context` for machine context.
111
- */
112
- type SlotHandler<Params, Return, R = never> = (params: Params) => Return | Effect.Effect<Return, never, R>;
113
- /**
114
- * Handler implementations for all slots in a definition.
115
- */
116
- type ProvideSlots<D extends SlotsDef, R = never> = { readonly [K in keyof D & string]: SlotHandler<SlotParams<D[K]>, SlotReturn<D[K]>, R> };
117
- /** Check if a SlotsDef has any actual keys */
118
- type HasSlotKeys<SD extends SlotsDef> = [keyof SD] extends [never] ? false : SD extends Record<string, never> ? false : true;
119
- /**
120
- * Type for machine context — state, event, and self reference.
121
- * Shared across all machines via MachineContextTag.
122
- */
123
- interface MachineContext<State, Event, Self> {
124
- readonly actorId: string;
125
- readonly state: State;
126
- readonly event: Event;
127
- readonly self: Self;
128
- readonly system: ActorSystemService;
129
- }
130
- declare const MachineContextTag_base: Context.ServiceClass<MachineContextTag, "effect-machine/slot/MachineContextTag", MachineContext<any, any, any>>;
131
- /**
132
- * Shared Context tag for all machines.
133
- * Single module-level tag instead of per-machine allocation.
134
- * @internal
135
- */
136
- declare class MachineContextTag extends MachineContextTag_base {}
137
- /**
138
- * Define a set of slots with parameter and return schemas.
139
- *
140
- * @example
141
- * ```ts
142
- * const MySlots = Slot.define({
143
- * canRetry: Slot.fn({ max: Schema.Number }, Schema.Boolean),
144
- * fetchData: Slot.fn({ url: Schema.String }),
145
- * notify: Slot.fn({ message: Schema.String }),
146
- * })
147
- * ```
148
- */
149
- declare const define: <D extends SlotsDef>(definitions: D) => SlotsSchema<D>;
150
- declare const Slot: {
151
- readonly fn: {
152
- <F extends Fields, Return>(fields: F, returnSchema: Schema.Schema<Return>): SlotFnDef<F, Return>;
153
- <F extends Fields>(fields: F): SlotFnDef<F>;
154
- };
155
- readonly define: <D extends SlotsDef>(definitions: D) => SlotsSchema<D>;
156
- readonly of: <D extends SlotsDef>(slotsSchema: SlotsSchema<D>, provided: ProvideSlots<D>) => SlotCalls<D>;
157
- };
158
- //#endregion
159
- export { HasSlotKeys, MachineContext, MachineContextTag, ProvideSlots, Slot, SlotCall, SlotCalls, SlotFnDef, SlotHandler, SlotInvocation, SlotRequest, SlotResult, SlotsDef, SlotsSchema, define, fn };
package/dist/slot.js DELETED
@@ -1,165 +0,0 @@
1
- import { Context, Effect, Schema } from "effect";
2
- //#region src/slot.ts
3
- /**
4
- * Slot module — unified, schema-based parameterized slots.
5
- *
6
- * Replaces the split Guards/Effects API with a single `Slot.define` + `Slot.fn`.
7
- * Each slot declares its parameter schema and (optional) return schema.
8
- * Handlers receive only params — machine context is accessed via `yield* machine.Context`.
9
- *
10
- * @example
11
- * ```ts
12
- * import { Slot } from "effect-machine"
13
- * import { Schema } from "effect"
14
- *
15
- * const MySlots = Slot.define({
16
- * canRetry: Slot.fn({ max: Schema.Number }, Schema.Boolean),
17
- * isValid: Slot.fn({}, Schema.Boolean),
18
- * fetchData: Slot.fn({ url: Schema.String }),
19
- * notify: Slot.fn({ message: Schema.String }),
20
- * })
21
- *
22
- * // Used in handlers:
23
- * .on(State.X, Event.Y, ({ slots }) =>
24
- * Effect.gen(function* () {
25
- * if (yield* slots.canRetry({ max: 3 })) {
26
- * yield* slots.fetchData({ url: "/api" })
27
- * return State.Next
28
- * }
29
- * return state
30
- * })
31
- * )
32
- * ```
33
- *
34
- * @module
35
- */
36
- /**
37
- * Define a single slot function with parameter schema and optional return schema.
38
- *
39
- * @example
40
- * ```ts
41
- * // Guard-like: returns boolean
42
- * Slot.fn({ max: Schema.Number }, Schema.Boolean)
43
- *
44
- * // Effect-like: returns void (default)
45
- * Slot.fn({ url: Schema.String })
46
- *
47
- * // No params, returns boolean
48
- * Slot.fn({}, Schema.Boolean)
49
- * ```
50
- */
51
- const fn = (fields, returnSchema) => {
52
- return {
53
- _tag: "SlotFnDef",
54
- fields,
55
- returnSchema,
56
- inputSchema: Object.keys(fields).length > 0 ? Schema.Struct(fields) : Schema.Void,
57
- outputSchema: returnSchema ?? Schema.Void
58
- };
59
- };
60
- /**
61
- * Shared Context tag for all machines.
62
- * Single module-level tag instead of per-machine allocation.
63
- * @internal
64
- */
65
- var MachineContextTag = class extends Context.Service()("effect-machine/slot/MachineContextTag") {};
66
- /**
67
- * Define a set of slots with parameter and return schemas.
68
- *
69
- * @example
70
- * ```ts
71
- * const MySlots = Slot.define({
72
- * canRetry: Slot.fn({ max: Schema.Number }, Schema.Boolean),
73
- * fetchData: Slot.fn({ url: Schema.String }),
74
- * notify: Slot.fn({ message: Schema.String }),
75
- * })
76
- * ```
77
- */
78
- const define = (definitions) => {
79
- const names = Object.keys(definitions);
80
- const requestSchemas = [];
81
- const resultSchemas = [];
82
- const invocationSchemas = [];
83
- for (const name of names) {
84
- const def = definitions[name];
85
- if (def === void 0) continue;
86
- requestSchemas.push(Schema.TaggedStruct("SlotRequest", {
87
- name: Schema.Literal(name),
88
- params: def.inputSchema
89
- }));
90
- resultSchemas.push(Schema.TaggedStruct("SlotResult", {
91
- name: Schema.Literal(name),
92
- result: def.outputSchema
93
- }));
94
- invocationSchemas.push(Schema.TaggedStruct("SlotInvocation", {
95
- name: Schema.Literal(name),
96
- params: def.inputSchema,
97
- result: def.outputSchema
98
- }));
99
- }
100
- const buildUnion = (schemas) => schemas.length === 0 ? Schema.Never : Schema.Union(schemas);
101
- return {
102
- _tag: "SlotsSchema",
103
- definitions,
104
- requestSchema: buildUnion(requestSchemas),
105
- resultSchema: buildUnion(resultSchemas),
106
- invocationSchema: buildUnion(invocationSchemas),
107
- _createSlots: (resolve) => {
108
- const slots = {};
109
- for (const name of names) {
110
- const slot = (params) => resolve(name, params);
111
- Object.defineProperty(slot, "_tag", {
112
- value: "Slot",
113
- enumerable: true
114
- });
115
- Object.defineProperty(slot, "name", {
116
- value: name,
117
- enumerable: true
118
- });
119
- slots[name] = slot;
120
- }
121
- return slots;
122
- }
123
- };
124
- };
125
- /**
126
- * Convert raw slot handler implementations into the callable `SlotCalls` form.
127
- *
128
- * Handlers that return plain values are wrapped in `Effect.succeed`.
129
- * Handlers that return Effects are called directly inside `Effect.suspend`.
130
- *
131
- * @example
132
- * ```ts
133
- * const provided = yield* myExtension.slots(ctx)
134
- * const slots = Slot.of(slotsSchema, provided)
135
- * // slots.mySlot({ param: 1 }) returns Effect<ReturnType>
136
- * ```
137
- */
138
- const of = (slotsSchema, provided) => {
139
- const slots = {};
140
- for (const name of Object.keys(slotsSchema.definitions)) {
141
- const handler = provided[name];
142
- if (handler === void 0) continue;
143
- const call = (params) => Effect.suspend(() => {
144
- const result = handler(params);
145
- return Effect.isEffect(result) ? result : Effect.succeed(result);
146
- });
147
- Object.defineProperty(call, "_tag", {
148
- value: "Slot",
149
- enumerable: true
150
- });
151
- Object.defineProperty(call, "name", {
152
- value: name,
153
- enumerable: true
154
- });
155
- slots[name] = call;
156
- }
157
- return slots;
158
- };
159
- const Slot = {
160
- fn,
161
- define,
162
- of
163
- };
164
- //#endregion
165
- export { MachineContextTag, Slot, define, fn };
@@ -1,13 +0,0 @@
1
- //#region \0rolldown/runtime.js
2
- var __defProp = Object.defineProperty;
3
- var __exportAll = (all, no_symbols) => {
4
- let target = {};
5
- for (var name in all) __defProp(target, name, {
6
- get: all[name],
7
- enumerable: true
8
- });
9
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
- return target;
11
- };
12
- //#endregion
13
- export { __exportAll };
@@ -1,250 +0,0 @@
1
- import { ExtractReply, ReplyTypeBrand } from "./internal/brands.js";
2
- import { ActorStoppedError, DuplicateActorError, NoReplyError } from "./errors.js";
3
- import { ProvideSlots, SlotsDef } from "./slot.js";
4
- import { ActorExit, Supervision } from "./supervision.js";
5
- import { ProcessEventError, ProcessEventHooks, ProcessEventResult, processEventCore, resolveTransition, runSpawnEffects } from "./internal/transition.js";
6
- import { Lifecycle, Machine } from "./machine.js";
7
- import { RuntimeQueuedEvent } from "./internal/runtime.js";
8
- import { Context, Deferred, Effect, Layer, Option, PubSub, Queue, Ref, Scope, Stream, SubscriptionRef } from "effect";
9
-
10
- //#region src/actor.d.ts
11
- /** Discriminated mailbox request — alias for RuntimeQueuedEvent */
12
- type QueuedEvent<E> = RuntimeQueuedEvent<E>;
13
- /**
14
- * Sync projection of ActorRef for non-Effect boundaries (React hooks, framework callbacks).
15
- */
16
- interface ActorRefSync<State extends {
17
- readonly _tag: string;
18
- }, Event> {
19
- readonly send: (event: Event) => void;
20
- readonly stop: () => void;
21
- readonly snapshot: () => State;
22
- readonly matches: (tag: State["_tag"]) => boolean;
23
- readonly can: (event: Event) => boolean;
24
- }
25
- /**
26
- * Information about a successful transition.
27
- * Emitted on the `transitions` stream after each accepted event.
28
- */
29
- interface TransitionInfo<State, Event> {
30
- readonly fromState: State;
31
- readonly toState: State;
32
- readonly event: Event;
33
- }
34
- interface ActorRef<State extends {
35
- readonly _tag: string;
36
- }, Event> {
37
- readonly id: string;
38
- /** Send an event (fire-and-forget). */
39
- readonly send: (event: Event) => Effect.Effect<void>;
40
- /** Fire-and-forget alias for send (OTP gen_server:cast). */
41
- readonly cast: (event: Event) => Effect.Effect<void>;
42
- /**
43
- * Serialized request-reply (OTP gen_server:call).
44
- * Event is processed through the queue; caller gets ProcessEventResult back.
45
- */
46
- readonly call: (event: Event) => Effect.Effect<ProcessEventResult<State>>;
47
- /**
48
- * Typed request-reply. Accepts only events with a reply schema
49
- * (defined via `Event.reply()`). Return type is inferred from the schema.
50
- * Fails with NoReplyError if the handler doesn't provide a reply.
51
- */
52
- readonly ask: <E extends Event & ReplyTypeBrand<unknown>>(event: E) => Effect.Effect<ExtractReply<E>, NoReplyError | ActorStoppedError>;
53
- /** Observable state. */
54
- readonly state: SubscriptionRef.SubscriptionRef<State>;
55
- /** Stop the actor gracefully. */
56
- readonly stop: Effect.Effect<void>;
57
- /**
58
- * Start the actor — fork event loop, background effects, spawn effects.
59
- * Called automatically by `system.spawn`. For `Machine.spawn`, the caller
60
- * must call `start` explicitly. Events sent before start() are queued.
61
- */
62
- readonly start: Effect.Effect<void>;
63
- /** Get current state snapshot. */
64
- readonly snapshot: Effect.Effect<State>;
65
- /** Check if current state matches tag. */
66
- readonly matches: (tag: State["_tag"]) => Effect.Effect<boolean>;
67
- /** Check if event can be handled in current state. */
68
- readonly can: (event: Event) => Effect.Effect<boolean>;
69
- /** Stream of state changes. */
70
- readonly changes: Stream.Stream<State>;
71
- /**
72
- * Stream of accepted transitions (edge stream).
73
- *
74
- * Emits `{ fromState, toState, event }` on every successful transition,
75
- * including same-state reenters. PubSub-backed — late subscribers miss
76
- * past edges. This is observational, not a durability guarantee.
77
- */
78
- readonly transitions: Stream.Stream<TransitionInfo<State, Event>>;
79
- /** Wait for a state matching predicate or variant (includes current snapshot). */
80
- readonly waitFor: {
81
- (predicate: (state: State) => boolean): Effect.Effect<State>;
82
- (state: {
83
- readonly _tag: State["_tag"];
84
- }): Effect.Effect<State>;
85
- };
86
- /** Wait for a final state (includes current snapshot). */
87
- readonly awaitFinal: Effect.Effect<State>;
88
- /** Send event and wait for predicate, state variant, or final state. */
89
- readonly sendAndWait: {
90
- (event: Event, predicate: (state: State) => boolean): Effect.Effect<State>;
91
- (event: Event, state: {
92
- readonly _tag: State["_tag"];
93
- }): Effect.Effect<State>;
94
- (event: Event): Effect.Effect<State>;
95
- };
96
- /** Subscribe to state changes (sync callback). Returns unsubscribe function. */
97
- readonly subscribe: (fn: (state: State) => void) => () => void;
98
- /**
99
- * Wait for this actor's terminal exit. Resolves with the exit reason.
100
- * Set exactly once when the actor terminates (final, stop, drain, or defect).
101
- */
102
- readonly awaitExit: Effect.Effect<ActorExit<State>>;
103
- /**
104
- * Watch another actor. Returns an Effect that resolves with the exit reason
105
- * when the watched actor terminally stops. Ignores restarts (Step 3).
106
- * Built on the other actor's exitDeferred — authoritative, not system events.
107
- */
108
- readonly watch: (other: {
109
- readonly id: string;
110
- readonly awaitExit: Effect.Effect<ActorExit<unknown>>;
111
- }) => Effect.Effect<ActorExit<unknown>>;
112
- /**
113
- * Drain: process all remaining events in the queue, then stop.
114
- * Unlike `stop` (which interrupts immediately), `drain` lets the actor finish its work.
115
- */
116
- readonly drain: Effect.Effect<void>;
117
- /** Sync helpers for non-Effect boundaries. */
118
- readonly sync: ActorRefSync<State, Event>;
119
- /** The actor system this actor belongs to. */
120
- readonly system: ActorSystem;
121
- /** Child actors spawned via `self.spawn` in this actor's handlers. */
122
- readonly children: ReadonlyMap<string, ActorRef<AnyState, unknown>>;
123
- }
124
- /** Base type for stored actors (internal) */
125
- type AnyState = {
126
- readonly _tag: string;
127
- };
128
- /**
129
- * Events emitted by the ActorSystem when actors are spawned or stopped.
130
- */
131
- type SystemEvent = {
132
- readonly _tag: "ActorSpawned";
133
- readonly id: string;
134
- readonly actor: ActorRef<AnyState, unknown>;
135
- } | {
136
- readonly _tag: "ActorRestarted";
137
- readonly id: string;
138
- readonly actor: ActorRef<AnyState, unknown>;
139
- readonly generation: number;
140
- readonly exit: ActorExit<unknown>;
141
- } | {
142
- readonly _tag: "ActorStopped";
143
- readonly id: string;
144
- readonly actor: ActorRef<AnyState, unknown>;
145
- readonly exit: ActorExit<unknown>;
146
- };
147
- /**
148
- * Listener callback for system events.
149
- */
150
- type SystemEventListener = (event: SystemEvent) => void;
151
- /**
152
- * Actor system for managing actor lifecycles
153
- */
154
- interface ActorSystem {
155
- /**
156
- * Spawn a new actor with the given machine.
157
- *
158
- * @example
159
- * ```ts
160
- * const actor = yield* system.spawn("my-actor", machine);
161
- * ```
162
- */
163
- readonly spawn: <S extends {
164
- readonly _tag: string;
165
- }, E extends {
166
- readonly _tag: string;
167
- }, R, SD extends SlotsDef = Record<string, never>>(id: string, machine: Machine<S, E, R, any, any, SD>, options?: {
168
- readonly supervision?: Supervision.Policy;
169
- readonly slots?: ProvideSlots<SD, any>;
170
- readonly lifecycle?: Lifecycle<S, E>;
171
- }) => Effect.Effect<ActorRef<S, E>, DuplicateActorError, R>;
172
- /**
173
- * Get an existing actor by ID
174
- */
175
- readonly get: (id: string) => Effect.Effect<Option.Option<ActorRef<AnyState, unknown>>>;
176
- /**
177
- * Stop an actor by ID
178
- */
179
- readonly stop: (id: string) => Effect.Effect<boolean>;
180
- /**
181
- * Async stream of system events (actor spawned/stopped).
182
- * Each subscriber gets their own queue — late subscribers miss prior events.
183
- */
184
- readonly events: Stream.Stream<SystemEvent>;
185
- /**
186
- * Sync snapshot of all currently registered actors.
187
- * Returns a new Map on each access (not live).
188
- */
189
- readonly actors: ReadonlyMap<string, ActorRef<AnyState, unknown>>;
190
- /**
191
- * Subscribe to system events synchronously.
192
- * Returns an unsubscribe function.
193
- */
194
- readonly subscribe: (fn: SystemEventListener) => () => void;
195
- }
196
- /**
197
- * ActorSystem service tag
198
- */
199
- declare const ActorSystem: Context.Tag<ActorSystem, ActorSystem>;
200
- /**
201
- * Explicit scope for actor lifecycle management.
202
- *
203
- * When present in context, actors attach cleanup finalizers to this scope.
204
- * This replaces ambient `Scope.Scope` detection which caused bugs where
205
- * unrelated scopes would tear down actors unexpectedly.
206
- *
207
- * Provide via `Machine.scoped` or `Effect.provideService(ActorScope, scope)`.
208
- */
209
- declare const ActorScope: Context.Tag<Scope.Scope, Scope.Scope>;
210
- /** Listener set for sync subscriptions */
211
- type Listeners<S> = Set<(state: S) => void>;
212
- /**
213
- * Notify all listeners of state change.
214
- */
215
- declare const notifyListeners: <S>(listeners: Listeners<S>, state: S) => void;
216
- /**
217
- * Build core ActorRef methods.
218
- */
219
- declare const buildActorRefCore: <S extends {
220
- readonly _tag: string;
221
- }, E extends {
222
- readonly _tag: string;
223
- }, R, SD extends SlotsDef>(id: string, machine: Machine<S, E, R, any, any, SD>, stateRef: SubscriptionRef.SubscriptionRef<S>, eventQueueRef: Ref.Ref<Queue.Queue<QueuedEvent<E>>>, stoppedRef: Ref.Ref<boolean>, listeners: Listeners<S>, stop: Effect.Effect<void>, start: Effect.Effect<void>, system: ActorSystem, childrenMap: ReadonlyMap<string, ActorRef<AnyState, unknown>>, pendingReplies: Set<Deferred.Deferred<unknown, unknown>>, transitionsPubSub: PubSub.PubSub<TransitionInfo<S, E>> | undefined, exitDeferred: Deferred.Deferred<ActorExit<S>>) => ActorRef<S, E>;
224
- /**
225
- * Create and start an actor for a machine.
226
- * Delegates to the shared runtime kernel with actor-specific lifecycle hooks.
227
- */
228
- declare const createActor: <S extends {
229
- readonly _tag: string;
230
- }, E extends {
231
- readonly _tag: string;
232
- }, R, SD extends SlotsDef>(id: string, machine: Machine<S, E, R, any, any, SD>, options?: {
233
- initialState?: S;
234
- supervision?: Supervision.Policy;
235
- lifecycle?: Lifecycle<S, E>; /** @internal Called by system after each restart — emits ActorRestarted system event */
236
- onRestart?: (generation: number, exit: ActorExit<unknown>) => Effect.Effect<void>;
237
- } | undefined) => Effect.Effect<ActorRef<S, E>, never, never>;
238
- /** Fail all pending call/ask Deferreds with ActorStoppedError. Safe to call multiple times. */
239
- declare const settlePendingReplies: (pendingReplies: Set<Deferred.Deferred<unknown, unknown>>, actorId: string) => Effect.Effect<void, never, never>;
240
- /**
241
- * Create an ActorSystem instance. Must be run in a Scope.
242
- * @internal — use Default layer for normal usage
243
- */
244
- declare const makeSystem: () => Effect.Effect<ActorSystem, never, Scope.Scope>;
245
- /**
246
- * Default ActorSystem layer
247
- */
248
- declare const Default: Layer.Layer<ActorSystem, never, never>;
249
- //#endregion
250
- export { ActorRef, ActorRefSync, ActorScope, ActorSystem, Default, Listeners, type ProcessEventError, type ProcessEventHooks, type ProcessEventResult, QueuedEvent, SystemEvent, SystemEventListener, TransitionInfo, buildActorRefCore, createActor, makeSystem, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };