effect-machine 0.19.0 → 0.21.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/dist/actor.d.ts CHANGED
@@ -5,17 +5,31 @@ import { Lifecycle, Machine } from "./machine.js";
5
5
  import { ProcessEventResult } from "./internal/transition.js";
6
6
  import { Context, Effect, Layer, Option, Scope, Stream, SubscriptionRef } from "effect";
7
7
  //#region src/actor.d.ts
8
- /**
9
- * Sync projection of ActorRef for non-Effect boundaries (React hooks, framework callbacks).
10
- */
8
+ /** JavaScript client for code that does not run inside Effect. */
9
+ interface ActorClient<State extends {
10
+ readonly _tag: string;
11
+ }, Event, Output = State> {
12
+ readonly send: (event: Event) => void;
13
+ readonly stop: () => void;
14
+ readonly getSnapshot: () => State;
15
+ readonly matches: (tag: State["_tag"]) => boolean;
16
+ readonly canSync: (event: Event) => boolean;
17
+ readonly can: (event: Event) => Promise<boolean>;
18
+ readonly getLifecycle: () => ActorLifecycle<State, Output>;
19
+ readonly getLatestTransition: () => TransitionInfo<State, Event> | undefined;
20
+ readonly subscribe: (listener: (state: State) => void) => () => void;
21
+ }
22
+ /** @deprecated Use `ActorClient`. */
11
23
  interface ActorRefSync<State extends {
12
24
  readonly _tag: string;
13
- }, Event> {
25
+ }, Event, Output = State> {
14
26
  readonly send: (event: Event) => void;
15
27
  readonly stop: () => void;
16
28
  readonly snapshot: () => State;
17
29
  readonly matches: (tag: State["_tag"]) => boolean;
18
30
  readonly can: (event: Event) => boolean;
31
+ readonly lifecycle: () => ActorLifecycle<State, Output>;
32
+ readonly latestTransition: () => TransitionInfo<State, Event> | undefined;
19
33
  }
20
34
  /**
21
35
  * Information about a successful transition.
@@ -26,9 +40,19 @@ interface TransitionInfo<State, Event> {
26
40
  readonly toState: State;
27
41
  readonly event: Event;
28
42
  }
43
+ /** Observable actor lifecycle. Domain state remains available through `actor.state`. */
44
+ type ActorLifecycle<State, Output = State> = {
45
+ readonly _tag: "Created";
46
+ } | {
47
+ readonly _tag: "Starting";
48
+ readonly generation: number;
49
+ } | {
50
+ readonly _tag: "Active";
51
+ readonly generation: number;
52
+ } | ActorExit<State, Output>;
29
53
  interface ActorRef<State extends {
30
54
  readonly _tag: string;
31
- }, Event> {
55
+ }, Event, Output = State> {
32
56
  readonly id: string;
33
57
  /** Send an event (fire-and-forget). */
34
58
  readonly send: (event: Event) => Effect.Effect<void>;
@@ -36,7 +60,7 @@ interface ActorRef<State extends {
36
60
  * Serialized request-reply (OTP gen_server:call).
37
61
  * Event is processed through the queue; caller gets ProcessEventResult back.
38
62
  */
39
- readonly call: (event: Event) => Effect.Effect<ProcessEventResult<State>>;
63
+ readonly call: (event: Event) => Effect.Effect<ProcessEventResult<State, Event>>;
40
64
  /**
41
65
  * Typed request-reply. Accepts only events with a reply schema
42
66
  * (defined via `Event.reply()`). Return type is inferred from the schema.
@@ -45,6 +69,10 @@ interface ActorRef<State extends {
45
69
  readonly ask: <E extends Event & ReplyTypeBrand<unknown>>(event: E) => Effect.Effect<ExtractReply<E>, NoReplyError | ActorStoppedError>;
46
70
  /** Observable state. */
47
71
  readonly state: SubscriptionRef.SubscriptionRef<State>;
72
+ /** Observable actor lifecycle. */
73
+ readonly lifecycle: SubscriptionRef.SubscriptionRef<ActorLifecycle<State, Output>>;
74
+ /** The latest accepted edge. This value remains available after actor exit. */
75
+ readonly latestTransition: SubscriptionRef.SubscriptionRef<TransitionInfo<State, Event> | undefined>;
48
76
  /** Stop the actor gracefully. */
49
77
  readonly stop: Effect.Effect<void>;
50
78
  /**
@@ -60,7 +88,7 @@ interface ActorRef<State extends {
60
88
  readonly snapshot: Effect.Effect<State>;
61
89
  /** Check if current state matches tag. */
62
90
  readonly matches: (tag: State["_tag"]) => Effect.Effect<boolean>;
63
- /** Check if event can be handled in current state. */
91
+ /** Check if an event has an enabled transition. Supports Boolean and Effect predicates. */
64
92
  readonly can: (event: Event) => Effect.Effect<boolean>;
65
93
  /** Stream of state changes. */
66
94
  readonly changes: Stream.Stream<State>;
@@ -81,6 +109,8 @@ interface ActorRef<State extends {
81
109
  };
82
110
  /** Wait for a final state (includes current snapshot). */
83
111
  readonly awaitFinal: Effect.Effect<State>;
112
+ /** Wait for the domain output of a final state. */
113
+ readonly awaitOutput: Effect.Effect<Output, ActorStoppedError>;
84
114
  /** Send event and wait for predicate, state variant, or final state. */
85
115
  readonly sendAndWait: {
86
116
  (event: Event, predicate: (state: State) => boolean): Effect.Effect<State>;
@@ -91,18 +121,20 @@ interface ActorRef<State extends {
91
121
  };
92
122
  /** Subscribe to state changes (sync callback). Returns unsubscribe function. */
93
123
  readonly subscribe: (fn: (state: State) => void) => () => void;
124
+ /** JavaScript client for callbacks and applications outside Effect. */
125
+ readonly client: ActorClient<State, Event, Output>;
94
126
  /**
95
127
  * Wait for this actor's terminal exit. Resolves with the exit reason.
96
128
  * Set exactly once when the actor terminates (final, stop, drain, or defect).
97
129
  */
98
- readonly awaitExit: Effect.Effect<ActorExit<State>>;
130
+ readonly awaitExit: Effect.Effect<ActorExit<State, Output>>;
99
131
  /**
100
132
  * Drain: process all remaining events in the queue, then stop.
101
133
  * Unlike `stop` (which interrupts immediately), `drain` lets the actor finish its work.
102
134
  */
103
135
  readonly drain: Effect.Effect<void>;
104
- /** Sync helpers for non-Effect boundaries. */
105
- readonly sync: ActorRefSync<State, Event>;
136
+ /** @deprecated Use `client`. */
137
+ readonly sync: ActorRefSync<State, Event, Output>;
106
138
  /** The actor system this actor belongs to. */
107
139
  readonly system: ActorSystemService;
108
140
  /** Child actors spawned via `self.spawn` in this actor's handlers. */
@@ -112,6 +144,20 @@ interface ActorRef<State extends {
112
144
  type AnyState = {
113
145
  readonly _tag: string;
114
146
  };
147
+ declare const ActorSystemKeyTypeId: unique symbol;
148
+ /** A typed identity for an actor stored in an ActorSystem. */
149
+ declare class ActorSystemKey<State extends AnyState, Event, Output = State> {
150
+ readonly id: string;
151
+ readonly [ActorSystemKeyTypeId]: {
152
+ readonly state: State;
153
+ readonly event: Event;
154
+ readonly output: Output;
155
+ };
156
+ constructor(id: string);
157
+ }
158
+ /** Create a typed ActorSystem identity. */
159
+ declare const actorSystemKey: <State extends AnyState, Event, Output = State>(id: string) => ActorSystemKey<State, Event, Output>;
160
+ type AnyActorSystemKey = ActorSystemKey<AnyState, unknown, unknown>;
115
161
  /**
116
162
  * Events emitted by the ActorSystem when actors are spawned or stopped.
117
163
  */
@@ -147,22 +193,36 @@ interface ActorSystemService {
147
193
  * const actor = yield* system.spawn("my-actor", machine);
148
194
  * ```
149
195
  */
150
- readonly spawn: <S extends {
151
- readonly _tag: string;
152
- }, E extends {
153
- readonly _tag: string;
154
- }, R>(id: string, machine: Machine<S, E, R, any, any>, options?: {
155
- readonly supervision?: Supervision.Policy;
156
- readonly lifecycle?: Lifecycle<S, E>;
157
- }) => Effect.Effect<ActorRef<S, E>, DuplicateActorError, R>;
196
+ readonly spawn: {
197
+ <S extends AnyState, E extends {
198
+ readonly _tag: string;
199
+ }, R, Output>(key: ActorSystemKey<S, E, Output>, machine: Machine<S, E, R, any, any, void, Output>, options?: SystemSpawnOptions<S, E, void>): Effect.Effect<ActorRef<S, E, Output>, DuplicateActorError, R>;
200
+ <S extends AnyState, E extends {
201
+ readonly _tag: string;
202
+ }, R, Output>(id: string, machine: Machine<S, E, R, any, any, void, Output>, options?: SystemSpawnOptions<S, E, void>): Effect.Effect<ActorRef<S, E, Output>, DuplicateActorError, R>;
203
+ <S extends AnyState, E extends {
204
+ readonly _tag: string;
205
+ }, R, Input, Output>(key: ActorSystemKey<S, E, Output>, machine: Machine<S, E, R, any, any, Input, Output>, options: SystemSpawnOptions<S, E, Input>): Effect.Effect<ActorRef<S, E, Output>, DuplicateActorError, R>;
206
+ <S extends AnyState, E extends {
207
+ readonly _tag: string;
208
+ }, R, Input, Output>(id: string, machine: Machine<S, E, R, any, any, Input, Output>, options: SystemSpawnOptions<S, E, Input>): Effect.Effect<ActorRef<S, E, Output>, DuplicateActorError, R>;
209
+ };
158
210
  /**
159
211
  * Get an existing actor by ID
160
212
  */
161
- readonly get: (id: string) => Effect.Effect<Option.Option<ActorRef<AnyState, unknown>>>;
213
+ readonly get: {
214
+ <S extends AnyState, E, Output>(key: ActorSystemKey<S, E, Output>): Effect.Effect<Option.Option<ActorRef<S, E, Output>>>;
215
+ (id: string): Effect.Effect<Option.Option<ActorRef<AnyState, unknown>>>;
216
+ };
217
+ /** Observe the current actor for one ID across actor generations. */
218
+ readonly watch: {
219
+ <S extends AnyState, E, Output>(key: ActorSystemKey<S, E, Output>): Stream.Stream<Option.Option<ActorRef<S, E, Output>>>;
220
+ (id: string): Stream.Stream<Option.Option<ActorRef<AnyState, unknown>>>;
221
+ };
162
222
  /**
163
223
  * Stop an actor by ID
164
224
  */
165
- readonly stop: (id: string) => Effect.Effect<boolean>;
225
+ readonly stop: (id: string | AnyActorSystemKey) => Effect.Effect<boolean>;
166
226
  /**
167
227
  * Async stream of system events (actor spawned/stopped).
168
228
  * Each subscriber gets their own queue — late subscribers miss prior events.
@@ -179,6 +239,15 @@ interface ActorSystemService {
179
239
  */
180
240
  readonly subscribe: (fn: SystemEventListener) => () => void;
181
241
  }
242
+ type SystemSpawnOptions<S, E, Input> = {
243
+ readonly supervision?: Supervision.Policy;
244
+ readonly lifecycle?: Lifecycle<S, E>;
245
+ readonly hydrate?: S;
246
+ } & ([Input] extends [void] ? {
247
+ readonly input?: never;
248
+ } : {
249
+ readonly input: Input;
250
+ });
182
251
  declare const ActorSystem_base: Context.ServiceClass<ActorSystem, "effect-machine/actor/ActorSystem", ActorSystemService>;
183
252
  /**
184
253
  * ActorSystem service tag
@@ -203,16 +272,18 @@ declare const createActor: <S extends {
203
272
  readonly _tag: string;
204
273
  }, E extends {
205
274
  readonly _tag: string;
206
- }, R>(id: string, machine: Machine<S, E, R, any, any>, options?: {
207
- initialState?: S;
275
+ }, R, O>(id: string, machine: Machine<S, E, R, any, any, any, O>, options: {
276
+ initialState: S;
277
+ machineInitial: S;
278
+ hydrated?: boolean;
208
279
  supervision?: Supervision.Policy;
209
280
  lifecycle?: Lifecycle<S, E>;
210
281
  /** @internal Called by system after each restart — emits ActorRestarted system event */
211
282
  onRestart?: (generation: number, exit: ActorExit<unknown>) => Effect.Effect<void>;
212
- } | undefined) => Effect.Effect<ActorRef<S, E>, never, R>;
283
+ }) => Effect.Effect<ActorRef<S, E, O>, never, R>;
213
284
  /**
214
285
  * Default ActorSystem layer
215
286
  */
216
287
  declare const Default: Layer.Layer<ActorSystem, never, never>;
217
288
  //#endregion
218
- export { ActorRef, ActorRefSync, ActorScope, ActorSystem, ActorSystemService, Default, type ProcessEventResult, SystemEvent, SystemEventListener, TransitionInfo, createActor };
289
+ export { ActorClient, ActorLifecycle, ActorRef, ActorRefSync, ActorScope, ActorSystem, ActorSystemKey, ActorSystemService, Default, type ProcessEventResult, SystemEvent, SystemEventListener, SystemSpawnOptions, TransitionInfo, actorSystemKey, createActor };