effect-machine 0.13.0 → 0.14.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 (48) hide show
  1. package/README.md +14 -9
  2. package/dist/actor.d.ts +9 -6
  3. package/dist/actor.js +97 -43
  4. package/dist/cluster/entity-machine.d.ts +1 -1
  5. package/dist/cluster/entity-machine.js +1 -1
  6. package/dist/cluster/to-entity.d.ts +1 -1
  7. package/dist/errors.d.ts +9 -2
  8. package/dist/errors.js +8 -2
  9. package/dist/index.d.ts +4 -4
  10. package/dist/index.js +4 -4
  11. package/dist/internal/runtime.d.ts +2 -2
  12. package/dist/internal/runtime.js +5 -10
  13. package/dist/internal/transition.d.ts +9 -9
  14. package/dist/internal/transition.js +3 -5
  15. package/dist/machine.d.ts +122 -135
  16. package/dist/machine.js +97 -112
  17. package/dist/schema.d.ts +14 -0
  18. package/dist/schema.js +9 -0
  19. package/dist/slot.d.ts +112 -86
  20. package/dist/slot.js +92 -59
  21. package/dist/testing.d.ts +16 -16
  22. package/dist/testing.js +3 -3
  23. package/package.json +3 -3
  24. package/v3/dist/actor.d.ts +19 -12
  25. package/v3/dist/actor.js +130 -75
  26. package/v3/dist/cluster/entity-machine.d.ts +1 -1
  27. package/v3/dist/cluster/to-entity.d.ts +1 -1
  28. package/v3/dist/errors.d.ts +12 -3
  29. package/v3/dist/errors.js +10 -4
  30. package/v3/dist/index.d.ts +6 -6
  31. package/v3/dist/index.js +2 -2
  32. package/v3/dist/inspection.d.ts +3 -22
  33. package/v3/dist/inspection.js +1 -15
  34. package/v3/dist/internal/brands.d.ts +4 -8
  35. package/v3/dist/internal/inspection.js +1 -1
  36. package/v3/dist/internal/runtime.d.ts +8 -8
  37. package/v3/dist/internal/runtime.js +45 -28
  38. package/v3/dist/internal/transition.d.ts +10 -10
  39. package/v3/dist/internal/transition.js +8 -10
  40. package/v3/dist/internal/utils.js +5 -1
  41. package/v3/dist/machine.d.ts +153 -120
  42. package/v3/dist/machine.js +118 -115
  43. package/v3/dist/schema.d.ts +25 -11
  44. package/v3/dist/schema.js +18 -5
  45. package/v3/dist/slot.d.ts +112 -86
  46. package/v3/dist/slot.js +92 -59
  47. package/v3/dist/testing.d.ts +16 -16
  48. package/v3/dist/testing.js +7 -7
package/v3/dist/actor.js CHANGED
@@ -12,7 +12,7 @@ import { Cause, Context, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, O
12
12
  * Combines:
13
13
  * - ActorRef interface (running actor handle)
14
14
  * - ActorSystem service (spawn/stop/get actors)
15
- * - Actor creation (delegates to runtime kernel)
15
+ * - Actor creation and event loop
16
16
  */
17
17
  /**
18
18
  * ActorSystem service tag
@@ -163,23 +163,113 @@ const buildActorRefCore = (id, machine, stateRef, eventQueueRef, stoppedRef, lis
163
163
  children: childrenMap
164
164
  };
165
165
  };
166
+ /** Build ProcessEventHooks from an inspector */
167
+ const buildInspectionHooks = (actorId, inspector) => ({
168
+ onSpawnEffect: (state) => emitWithTimestamp(inspector, (timestamp) => ({
169
+ type: "@machine.effect",
170
+ actorId,
171
+ effectType: "spawn",
172
+ state,
173
+ timestamp
174
+ })),
175
+ onTransition: (from, to, ev) => emitWithTimestamp(inspector, (timestamp) => ({
176
+ type: "@machine.transition",
177
+ actorId,
178
+ fromState: from,
179
+ toState: to,
180
+ event: ev,
181
+ timestamp
182
+ })),
183
+ onError: (info) => emitWithTimestamp(inspector, (timestamp) => ({
184
+ type: "@machine.error",
185
+ actorId,
186
+ phase: info.phase,
187
+ state: info.state,
188
+ event: info.event,
189
+ error: Cause.pretty(info.cause),
190
+ timestamp
191
+ }))
192
+ });
193
+ /**
194
+ * Load persisted state and run onRestore hook if present.
195
+ * Returns the resolved initial state (loaded, restored, or fallback to machineInitial).
196
+ * @internal
197
+ */
198
+ const loadAndRestore = (persist, machineInitial) => Effect.gen(function* () {
199
+ const loaded = yield* persist.load();
200
+ if (Option.isNone(loaded)) return machineInitial;
201
+ if (persist.onRestore === void 0) return loaded.value;
202
+ const restored = yield* persist.onRestore(loaded.value, { initial: machineInitial });
203
+ return Option.getOrElse(restored, () => machineInitial);
204
+ });
205
+ /**
206
+ * Resolve actor system from context, creating an implicit one if none exists.
207
+ * @internal
208
+ */
209
+ const resolveActorSystem = Effect.fn("effect-machine.resolveActorSystem")(function* () {
210
+ const existingSystem = yield* Effect.serviceOption(ActorSystem);
211
+ if (Option.isSome(existingSystem)) return {
212
+ system: existingSystem.value,
213
+ implicitSystemScope: void 0
214
+ };
215
+ const scope = yield* Scope.make();
216
+ return {
217
+ system: yield* make().pipe(Effect.provideService(Scope.Scope, scope)),
218
+ implicitSystemScope: scope
219
+ };
220
+ });
221
+ /**
222
+ * Run the supervision loop for a supervised actor.
223
+ * Observes exit deferred, applies restart policy, resets cell resources on restart.
224
+ * @internal
225
+ */
226
+ const runSupervisionLoop = (params) => Effect.gen(function* () {
227
+ const driver = yield* Schedule.driver(params.supervision.schedule);
228
+ let generation = 0;
229
+ while (true) {
230
+ const currentRuntime = params.runtimeRef.current;
231
+ if (currentRuntime === void 0) return;
232
+ const generationExit = yield* Deferred.await(currentRuntime.exitDeferred);
233
+ if (generationExit._tag !== "Defect") {
234
+ yield* Deferred.succeed(params.terminalExitDeferred, generationExit);
235
+ return;
236
+ }
237
+ if (params.supervision.shouldRestart !== void 0 && !params.supervision.shouldRestart(generationExit)) {
238
+ yield* Deferred.succeed(params.terminalExitDeferred, generationExit);
239
+ return;
240
+ }
241
+ if ((yield* driver.next(generationExit).pipe(Effect.exit))._tag === "Failure") {
242
+ yield* Deferred.succeed(params.terminalExitDeferred, generationExit);
243
+ return;
244
+ }
245
+ const restartState = params.persist !== void 0 ? yield* loadAndRestore(params.persist, params.machine.initial) : params.machine.initial;
246
+ yield* settlePendingReplies(params.pendingReplies, params.id);
247
+ const freshQueue = yield* Queue.unbounded();
248
+ yield* Ref.set(params.eventQueueRef, freshQueue);
249
+ yield* SubscriptionRef.set(params.stateRef, restartState);
250
+ yield* Ref.set(params.stoppedRef, false);
251
+ params.childrenMap.clear();
252
+ const machineForRestart = restartState !== params.machine.initial ? Object.create(params.machine, { initial: {
253
+ value: restartState,
254
+ enumerable: true
255
+ } }) : params.machine;
256
+ const newRuntime = yield* params.spawnGeneration(machineForRestart);
257
+ params.runtimeRef.current = newRuntime;
258
+ generation++;
259
+ if (params.onRestart !== void 0) yield* params.onRestart(generation, generationExit);
260
+ notifyListeners(params.listeners, restartState);
261
+ }
262
+ });
166
263
  /**
167
264
  * Create and start an actor for a machine.
168
- * Uses the shared runtime kernel with lifecycle hooks for actor-specific concerns.
265
+ * Delegates to the shared runtime kernel with actor-specific lifecycle hooks.
169
266
  */
170
267
  const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machine, options) {
171
- const initial = options?.initialState ?? machine.initial;
268
+ const persist = options?.persist;
269
+ const initial = options?.initialState ?? (persist !== void 0 ? yield* loadAndRestore(persist, machine.initial) : machine.initial);
172
270
  yield* Effect.annotateCurrentSpan("effect_machine.actor.id", id);
173
271
  yield* Effect.annotateCurrentSpan("effect_machine.actor.initial_state", initial._tag);
174
- const existingSystem = yield* Effect.serviceOption(ActorSystem);
175
- let system;
176
- let implicitSystemScope;
177
- if (Option.isSome(existingSystem)) system = existingSystem.value;
178
- else {
179
- const scope = yield* Scope.make();
180
- system = yield* make().pipe(Effect.provideService(Scope.Scope, scope));
181
- implicitSystemScope = scope;
182
- }
272
+ const { system, implicitSystemScope } = yield* resolveActorSystem();
183
273
  const inspectorValue = Option.getOrUndefined(yield* Effect.serviceOption(Inspector));
184
274
  const childrenMap = /* @__PURE__ */ new Map();
185
275
  const pendingReplies = /* @__PURE__ */ new Set();
@@ -191,32 +281,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
191
281
  initialState: initial,
192
282
  timestamp
193
283
  }));
194
- const hooks = inspectorValue === void 0 ? void 0 : {
195
- onSpawnEffect: (state) => emitWithTimestamp(inspectorValue, (timestamp) => ({
196
- type: "@machine.effect",
197
- actorId: id,
198
- effectType: "spawn",
199
- state,
200
- timestamp
201
- })),
202
- onTransition: (from, to, ev) => emitWithTimestamp(inspectorValue, (timestamp) => ({
203
- type: "@machine.transition",
204
- actorId: id,
205
- fromState: from,
206
- toState: to,
207
- event: ev,
208
- timestamp
209
- })),
210
- onError: (info) => emitWithTimestamp(inspectorValue, (timestamp) => ({
211
- type: "@machine.error",
212
- actorId: id,
213
- phase: info.phase,
214
- state: info.state,
215
- event: info.event,
216
- error: Cause.pretty(info.cause),
217
- timestamp
218
- }))
219
- };
284
+ const hooks = inspectorValue !== void 0 ? buildInspectionHooks(id, inspectorValue) : void 0;
220
285
  const machineWithState = initial !== machine.initial ? Object.create(machine, { initial: {
221
286
  value: initial,
222
287
  enumerable: true
@@ -241,6 +306,9 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
241
306
  })) : void 0,
242
307
  onStateChange: (result, _event) => Effect.gen(function* () {
243
308
  notifyListeners(listeners, result.newState);
309
+ if (persist !== void 0 && result.transitioned) {
310
+ if (persist.shouldSave === void 0 || persist.shouldSave(result.newState, result.previousState)) yield* persist.save(result.newState);
311
+ }
244
312
  yield* Effect.annotateCurrentSpan("effect_machine.transition.matched", true);
245
313
  if (result.lifecycleRan) {
246
314
  yield* Effect.annotateCurrentSpan("effect_machine.state.from", result.previousState._tag);
@@ -282,7 +350,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
282
350
  })) : void 0
283
351
  };
284
352
  };
285
- /** Create a single runtime generation */
353
+ /** Create a single runtime generation. machineForGen is machineWithState for initial, machine for restarts. */
286
354
  const spawnGeneration = (machineForGen) => Ref.get(eventQueueRef).pipe(Effect.flatMap((currentQueue) => createRuntime(machineForGen, system, {
287
355
  actorId: id,
288
356
  hooks,
@@ -306,42 +374,27 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
306
374
  }));
307
375
  })
308
376
  })));
309
- const supervision = options?.supervision;
310
377
  const runtime = yield* spawnGeneration(machineWithState);
311
378
  runtimeRef.current = runtime;
379
+ const supervision = options?.supervision;
312
380
  let supervisorFiber;
313
- if (supervision !== void 0) supervisorFiber = yield* Effect.forkDaemon(Effect.gen(function* () {
314
- const driver = yield* Schedule.driver(supervision.schedule);
315
- let generation = 0;
316
- while (true) {
317
- const currentRuntime = runtimeRef.current;
318
- if (currentRuntime === void 0) return;
319
- const generationExit = yield* Deferred.await(currentRuntime.exitDeferred);
320
- if (generationExit._tag !== "Defect") {
321
- yield* Deferred.succeed(terminalExitDeferred, generationExit);
322
- return;
323
- }
324
- if (supervision.shouldRestart !== void 0 && !supervision.shouldRestart(generationExit)) {
325
- yield* Deferred.succeed(terminalExitDeferred, generationExit);
326
- return;
327
- }
328
- if ((yield* driver.next(generationExit).pipe(Effect.exit))._tag === "Failure") {
329
- yield* Deferred.succeed(terminalExitDeferred, generationExit);
330
- return;
331
- }
332
- yield* settlePendingReplies(pendingReplies, id);
333
- const freshQueue = yield* Queue.unbounded();
334
- yield* Ref.set(eventQueueRef, freshQueue);
335
- yield* SubscriptionRef.set(stateRef, machine.initial);
336
- yield* Ref.set(stoppedRef, false);
337
- childrenMap.clear();
338
- runtimeRef.current = yield* spawnGeneration(machine);
339
- generation++;
340
- if (options?.onRestart !== void 0) yield* options.onRestart(generation, generationExit);
341
- notifyListeners(listeners, machine.initial);
342
- }
381
+ if (supervision !== void 0) supervisorFiber = yield* Effect.forkDaemon(runSupervisionLoop({
382
+ supervision,
383
+ machine,
384
+ id,
385
+ runtimeRef,
386
+ terminalExitDeferred,
387
+ pendingReplies,
388
+ eventQueueRef,
389
+ stateRef,
390
+ stoppedRef,
391
+ childrenMap,
392
+ listeners,
393
+ spawnGeneration,
394
+ persist,
395
+ onRestart: options?.onRestart
343
396
  }));
344
- else yield* Deferred.await(runtime.exitDeferred).pipe(Effect.tap((exit) => Deferred.succeed(terminalExitDeferred, exit)), Effect.catchAllCause(() => Effect.void), Effect.fork);
397
+ else yield* Effect.forkDaemon(Deferred.await(runtime.exitDeferred).pipe(Effect.tap((exit) => Deferred.succeed(terminalExitDeferred, exit))));
345
398
  return buildActorRefCore(id, machine, stateRef, eventQueueRef, stoppedRef, listeners, Effect.gen(function* () {
346
399
  if (supervisorFiber !== void 0) yield* Fiber.interrupt(supervisorFiber);
347
400
  const currentRuntime = runtimeRef.current;
@@ -367,14 +420,15 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
367
420
  const withSpawnGate = (yield* Effect.makeSemaphore(1)).withPermits(1);
368
421
  const eventPubSub = yield* PubSub.unbounded();
369
422
  const eventListeners = /* @__PURE__ */ new Set();
370
- const emitSystemEvent = (event) => Effect.sync(() => notifySystemListeners(eventListeners, event)).pipe(Effect.zipRight(PubSub.publish(eventPubSub, event)), Effect.catchAllCause(() => Effect.void), Effect.asVoid);
423
+ const emitSystemEvent = (event) => Effect.sync(() => notifySystemListeners(eventListeners, event)).pipe(Effect.andThen(PubSub.publish(eventPubSub, event)), Effect.catchAllCause(() => Effect.void), Effect.asVoid);
371
424
  yield* Effect.addFinalizer(() => {
372
425
  const stops = [];
373
426
  MutableHashMap.forEach(actorsMap, (actor) => {
374
427
  stops.push(actor.stop);
375
428
  });
376
- return Effect.all(stops, { concurrency: "unbounded" }).pipe(Effect.zipRight(PubSub.shutdown(eventPubSub)), Effect.asVoid);
429
+ return Effect.all(stops, { concurrency: "unbounded" }).pipe(Effect.andThen(PubSub.shutdown(eventPubSub)), Effect.asVoid);
377
430
  });
431
+ /** Check for duplicate ID, register actor, attach scope cleanup if available */
378
432
  const registerActor = Effect.fn("effect-machine.actorSystem.register")(function* (id, actor) {
379
433
  if (MutableHashMap.has(actorsMap, id)) {
380
434
  yield* actor.stop;
@@ -404,10 +458,11 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
404
458
  });
405
459
  const spawnRegular = Effect.fn("effect-machine.actorSystem.spawnRegular")(function* (id, machine, spawnOptions) {
406
460
  if (MutableHashMap.has(actorsMap, id)) return yield* new DuplicateActorError({ actorId: id });
407
- const materialized = materializeMachine(machine, spawnOptions?.slots);
461
+ const materialized = spawnOptions?.slots !== void 0 ? materializeMachine(machine, spawnOptions.slots) : machine;
408
462
  let actorRef;
409
463
  const actor = yield* createActor(id, materialized, {
410
464
  supervision: spawnOptions?.supervision,
465
+ persist: spawnOptions?.persist,
411
466
  onRestart: spawnOptions?.supervision !== void 0 ? (generation, exit) => actorRef !== void 0 ? emitSystemEvent({
412
467
  _tag: "ActorRestarted",
413
468
  id,
@@ -465,6 +520,6 @@ const makeSystem = make;
465
520
  /**
466
521
  * Default ActorSystem layer
467
522
  */
468
- const Default = Layer.effect(ActorSystem, make());
523
+ const Default = Layer.scoped(ActorSystem, make());
469
524
  //#endregion
470
525
  export { ActorSystem, Default, buildActorRefCore, createActor, makeSystem, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
@@ -68,7 +68,7 @@ declare const EntityMachine: {
68
68
  readonly _tag: string;
69
69
  }, E extends {
70
70
  readonly _tag: string;
71
- }, R, EntityType extends string, Rpcs extends Rpc.Any>(entity: Entity.Entity<EntityType, Rpcs>, machine: Machine<S, E, R, any, any, any, any>, options?: EntityMachineOptions<S, E>) => Layer.Layer<never, never, R>;
71
+ }, R, EntityType extends string, Rpcs extends Rpc.Any>(entity: Entity.Entity<EntityType, Rpcs>, machine: Machine<S, E, R, any, any, any>, options?: EntityMachineOptions<S, E>) => Layer.Layer<never, never, R>;
72
72
  };
73
73
  //#endregion
74
74
  export { EntityMachine, EntityMachineOptions };
@@ -59,6 +59,6 @@ declare const toEntity: <S extends {
59
59
  readonly _tag: string;
60
60
  }, E extends {
61
61
  readonly _tag: string;
62
- }, R>(machine: Machine<S, E, R, any, any, any, any>, options: ToEntityOptions) => any;
62
+ }, R>(machine: Machine<S, E, R, any, any, any>, options: ToEntityOptions) => any;
63
63
  //#endregion
64
64
  export { EntityRpcs, ToEntityOptions, toEntity };
@@ -33,7 +33,7 @@ declare const SlotProvisionError_base: Schema.TaggedErrorClass<SlotProvisionErro
33
33
  readonly _tag: Schema.tag<"SlotProvisionError">;
34
34
  } & {
35
35
  slotName: typeof Schema.String;
36
- slotType: Schema.Literal<["guard", "effect"]>;
36
+ slotType: Schema.Literal<["slot"]>;
37
37
  }>;
38
38
  /** Slot handler not found at runtime (internal error) */
39
39
  declare class SlotProvisionError extends SlotProvisionError_base {}
@@ -43,7 +43,7 @@ declare const ProvisionValidationError_base: Schema.TaggedErrorClass<ProvisionVa
43
43
  missing: Schema.Array$<typeof Schema.String>;
44
44
  extra: Schema.Array$<typeof Schema.String>;
45
45
  }>;
46
- /** Machine.build() validation failed - missing or extra handlers */
46
+ /** Slot provision validation failed missing or extra handlers */
47
47
  declare class ProvisionValidationError extends ProvisionValidationError_base {}
48
48
  declare const AssertionError_base: Schema.TaggedErrorClass<AssertionError, "AssertionError", {
49
49
  readonly _tag: Schema.tag<"AssertionError">;
@@ -74,6 +74,15 @@ declare const PersistenceError_base: Schema.TaggedErrorClass<PersistenceError, "
74
74
  }>;
75
75
  /** Persistence adapter operation failed */
76
76
  declare class PersistenceError extends PersistenceError_base {}
77
+ declare const SlotCodecError_base: Schema.TaggedErrorClass<SlotCodecError, "SlotCodecError", {
78
+ readonly _tag: Schema.tag<"SlotCodecError">;
79
+ } & {
80
+ slotName: typeof Schema.String;
81
+ phase: Schema.Literal<["input", "output"]>;
82
+ message: typeof Schema.String;
83
+ }>;
84
+ /** Slot input/output schema validation failed */
85
+ declare class SlotCodecError extends SlotCodecError_base {}
77
86
  declare const VersionConflictError_base: Schema.TaggedErrorClass<VersionConflictError, "VersionConflictError", {
78
87
  readonly _tag: Schema.tag<"VersionConflictError">;
79
88
  } & {
@@ -83,4 +92,4 @@ declare const VersionConflictError_base: Schema.TaggedErrorClass<VersionConflict
83
92
  /** Optimistic locking failure — stored version doesn't match expected */
84
93
  declare class VersionConflictError extends VersionConflictError_base {}
85
94
  //#endregion
86
- export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, VersionConflictError };
95
+ export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError };
package/v3/dist/errors.js CHANGED
@@ -3,7 +3,7 @@ import { Schema } from "effect";
3
3
  /**
4
4
  * Typed error classes for effect-machine.
5
5
  *
6
- * All errors extend Schema.TaggedError for:
6
+ * All errors extend Schema.TaggedErrorClass for:
7
7
  * - Type-safe catching via Effect.catchTag
8
8
  * - Serialization support
9
9
  * - Composable error handling
@@ -21,9 +21,9 @@ var MissingMatchHandlerError = class extends Schema.TaggedError()("MissingMatchH
21
21
  /** Slot handler not found at runtime (internal error) */
22
22
  var SlotProvisionError = class extends Schema.TaggedError()("SlotProvisionError", {
23
23
  slotName: Schema.String,
24
- slotType: Schema.Literal("guard", "effect")
24
+ slotType: Schema.Literal("slot")
25
25
  }) {};
26
- /** Machine.build() validation failed - missing or extra handlers */
26
+ /** Slot provision validation failed missing or extra handlers */
27
27
  var ProvisionValidationError = class extends Schema.TaggedError()("ProvisionValidationError", {
28
28
  missing: Schema.Array(Schema.String),
29
29
  extra: Schema.Array(Schema.String)
@@ -39,10 +39,16 @@ var NoReplyError = class extends Schema.TaggedError()("NoReplyError", {
39
39
  }) {};
40
40
  /** Persistence adapter operation failed */
41
41
  var PersistenceError = class extends Schema.TaggedError()("PersistenceError", { message: Schema.String }) {};
42
+ /** Slot input/output schema validation failed */
43
+ var SlotCodecError = class extends Schema.TaggedError()("SlotCodecError", {
44
+ slotName: Schema.String,
45
+ phase: Schema.Literal("input", "output"),
46
+ message: Schema.String
47
+ }) {};
42
48
  /** Optimistic locking failure — stored version doesn't match expected */
43
49
  var VersionConflictError = class extends Schema.TaggedError()("VersionConflictError", {
44
50
  expected: Schema.Number,
45
51
  actual: Schema.Number
46
52
  }) {};
47
53
  //#endregion
48
- export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, VersionConflictError };
54
+ export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError };
@@ -1,11 +1,11 @@
1
- import { ActorExit, CellPhase, DefectPhase, Supervision } from "./supervision.js";
2
- import { ReplyResult } from "./internal/utils.js";
1
+ import { DeferReplyResult, ReplyResult } from "./internal/utils.js";
3
2
  import { Event, MachineEventSchema, MachineStateSchema, ReplyFields, State } from "./schema.js";
4
- import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, VersionConflictError } from "./errors.js";
5
- import { EffectHandlers, EffectSlot, EffectSlots, EffectsDef, EffectsSchema, GuardHandlers, GuardSlot, GuardSlots, GuardsDef, GuardsSchema, MachineContext, Slot } from "./slot.js";
3
+ import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError } from "./errors.js";
4
+ import { HasSlotKeys, MachineContext, ProvideSlots, Slot, SlotCall, SlotCalls, SlotFnDef, SlotHandler, SlotInvocation, SlotRequest, SlotResult, SlotsDef, SlotsSchema } from "./slot.js";
5
+ import { ActorExit, CellPhase, DefectPhase, Supervision } from "./supervision.js";
6
6
  import { ProcessEventResult } from "./internal/transition.js";
7
- import { BackgroundEffect, HandlerContext, Machine, MachineRef, MakeConfig, ProvideHandlers, SlotContext, SpawnEffect, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, machine_d_exports } from "./machine.js";
7
+ import { BackgroundEffect, HandlerContext, Machine, MachineRef, MakeConfig, SpawnEffect, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, machine_d_exports } from "./machine.js";
8
8
  import { ActorRef, ActorRefSync, ActorSystem, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
9
9
  import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
10
10
  import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
11
- export { ActorExit, type ActorRef, type ActorRefSync, ActorStoppedError, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type CellPhase, type DefectPhase, DuplicateActorError, type EffectEvent, type EffectSlots, type EffectsDef, type EffectsSchema, type ErrorEvent, Event, type EventReceivedEvent, type GuardHandlers, type GuardSlot, type GuardSlots, type GuardsDef, type GuardsSchema, type HandlerContext, type InspectionEvent, type Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, machine_d_exports as Machine, type MachineContext, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, type ProcessEventResult, type ProvideHandlers, ProvisionValidationError, type ReplyFields, type ReplyResult, type SimulationResult, Slot, type SlotContext, type EffectHandlers as SlotEffectHandlers, type EffectSlot as SlotEffectSlot, SlotProvisionError, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, Supervision, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TimeoutConfig, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
11
+ export { ActorExit, type ActorRef, type ActorRefSync, ActorStoppedError, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type CellPhase, type DefectPhase, type DeferReplyResult, DuplicateActorError, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type HandlerContext, type HasSlotKeys, type InspectionEvent, type Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, machine_d_exports as Machine, type MachineContext, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, type ProcessEventResult, type ProvideSlots, ProvisionValidationError, type ReplyFields, type ReplyResult, type SimulationResult, Slot, type SlotCall, type SlotCalls, SlotCodecError, type SlotFnDef, type SlotHandler, type SlotInvocation, SlotProvisionError, type SlotRequest, type SlotResult, type SlotsDef, type SlotsSchema, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, Supervision, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TimeoutConfig, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
package/v3/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, VersionConflictError } from "./errors.js";
1
+ import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError } from "./errors.js";
2
2
  import { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
3
3
  import { Slot } from "./slot.js";
4
4
  import { machine_exports } from "./machine.js";
@@ -6,4 +6,4 @@ import { ActorExit, Supervision } from "./supervision.js";
6
6
  import { ActorSystem, Default } from "./actor.js";
7
7
  import { Event, State } from "./schema.js";
8
8
  import { assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
9
- export { ActorExit, ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, Slot, SlotProvisionError, State, Supervision, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
9
+ export { ActorExit, ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, Slot, SlotCodecError, SlotProvisionError, State, Supervision, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
@@ -4,7 +4,7 @@ import { Context, Effect, Schema } from "effect";
4
4
  /**
5
5
  * Resolve a type param: if it's a Schema, extract `.Type`; otherwise use as-is.
6
6
  */
7
- type ResolveType<T> = T extends Schema.Schema<infer A, infer _I, infer _R> ? A : T;
7
+ type ResolveType<T> = T extends Schema.Schema<infer A> ? A : T;
8
8
  /**
9
9
  * Event emitted when an actor is spawned
10
10
  */
@@ -45,9 +45,6 @@ interface EffectEvent<S> {
45
45
  readonly state: S;
46
46
  readonly timestamp: number;
47
47
  }
48
- /**
49
- * Event emitted when a task lifecycle phase occurs
50
- */
51
48
  interface TaskEvent<S> {
52
49
  readonly type: "@machine.task";
53
50
  readonly actorId: string;
@@ -93,13 +90,10 @@ type AnyInspectionEvent = InspectionEvent<{
93
90
  }, {
94
91
  readonly _tag: string;
95
92
  }>;
96
- /**
97
- * Inspector handler — sync callback or Effect-returning callback.
98
- */
99
- type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void, never, never>;
100
93
  /**
101
94
  * Inspector interface for observing machine behavior
102
95
  */
96
+ type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void, never, never>;
103
97
  interface Inspector<S, E> {
104
98
  readonly onInspect: InspectorHandler<S, E>;
105
99
  }
@@ -109,7 +103,7 @@ interface Inspector<S, E> {
109
103
  */
110
104
  declare const Inspector: Context.Tag<Inspector<any, any>, Inspector<any, any>>;
111
105
  /**
112
- * Create an inspector from a sync callback function.
106
+ * Create an inspector from a callback function.
113
107
  *
114
108
  * Type params accept either raw tagged types or Schema constructors:
115
109
  * - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
@@ -121,30 +115,17 @@ declare const makeInspector: <S = {
121
115
  }, E = {
122
116
  readonly _tag: string;
123
117
  }>(onInspect: InspectorHandler<ResolveType<S>, ResolveType<E>>) => Inspector<ResolveType<S>, ResolveType<E>>;
124
- /**
125
- * Create an inspector from an Effect-returning callback function.
126
- */
127
118
  declare const makeInspectorEffect: <S = {
128
119
  readonly _tag: string;
129
120
  }, E = {
130
121
  readonly _tag: string;
131
122
  }>(onInspect: (event: InspectionEvent<ResolveType<S>, ResolveType<E>>) => Effect.Effect<void, never, never>) => Inspector<ResolveType<S>, ResolveType<E>>;
132
- /**
133
- * Combine multiple inspectors into one. All run concurrently per event.
134
- * Individual inspector failures are swallowed.
135
- */
136
123
  declare const combineInspectors: <S, E>(...inspectors: ReadonlyArray<Inspector<S, E>>) => Inspector<S, E>;
137
- /**
138
- * Options for the tracing inspector.
139
- */
140
124
  interface TracingInspectorOptions<S, E> {
141
125
  readonly spanName?: string | ((event: InspectionEvent<S, E>) => string);
142
126
  readonly attributes?: (event: InspectionEvent<S, E>) => Readonly<Record<string, string | number | boolean>>;
143
127
  readonly eventName?: (event: InspectionEvent<S, E>) => string;
144
128
  }
145
- /**
146
- * Inspector that emits OpenTelemetry spans and events for each inspection event.
147
- */
148
129
  declare const tracingInspector: <S extends {
149
130
  readonly _tag: string;
150
131
  }, E extends {
@@ -6,7 +6,7 @@ import { Context, Effect, Option } from "effect";
6
6
  */
7
7
  const Inspector = Context.GenericTag("@effect/machine/Inspector");
8
8
  /**
9
- * Create an inspector from a sync callback function.
9
+ * Create an inspector from a callback function.
10
10
  *
11
11
  * Type params accept either raw tagged types or Schema constructors:
12
12
  * - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
@@ -14,22 +14,11 @@ const Inspector = Context.GenericTag("@effect/machine/Inspector");
14
14
  * - `makeInspector<typeof MyState, typeof MyEvent>(cb)` — schema constructors (auto-extracts `.Type`)
15
15
  */
16
16
  const makeInspector = (onInspect) => ({ onInspect });
17
- /**
18
- * Create an inspector from an Effect-returning callback function.
19
- */
20
17
  const makeInspectorEffect = (onInspect) => ({ onInspect });
21
- /**
22
- * Run an inspector handler, handling both sync and Effect returns.
23
- * @internal
24
- */
25
18
  const inspectionEffect = (inspector, event) => {
26
19
  const result = inspector.onInspect(event);
27
20
  return Effect.isEffect(result) ? result : Effect.void;
28
21
  };
29
- /**
30
- * Combine multiple inspectors into one. All run concurrently per event.
31
- * Individual inspector failures are swallowed.
32
- */
33
22
  const combineInspectors = (...inspectors) => ({ onInspect: (event) => Effect.forEach(inspectors, (inspector) => inspectionEffect(inspector, event).pipe(Effect.catchAllCause(() => Effect.void)), {
34
23
  concurrency: "unbounded",
35
24
  discard: true
@@ -99,9 +88,6 @@ const inspectionAttributes = (event) => {
99
88
  };
100
89
  }
101
90
  };
102
- /**
103
- * Inspector that emits OpenTelemetry spans and events for each inspection event.
104
- */
105
91
  const tracingInspector = (options) => ({ onInspect: (event) => {
106
92
  const spanName = typeof options?.spanName === "function" ? options.spanName(event) : options?.spanName;
107
93
  const traceName = options?.eventName?.(event) ?? inspectionTraceName(event);
@@ -1,10 +1,8 @@
1
1
  import { Brand } from "effect";
2
2
 
3
3
  //#region src/internal/brands.d.ts
4
- declare const StateTypeId: unique symbol;
5
- declare const EventTypeId: unique symbol;
6
- type StateTypeId = typeof StateTypeId;
7
- type EventTypeId = typeof EventTypeId;
4
+ type StateTypeId = "effect-machine/StateTypeId";
5
+ type EventTypeId = "effect-machine/EventTypeId";
8
6
  interface StateBrand extends Brand.Brand<StateTypeId> {}
9
7
  interface EventBrand extends Brand.Brand<EventTypeId> {}
10
8
  type BrandedState = {
@@ -13,8 +11,7 @@ type BrandedState = {
13
11
  type BrandedEvent = {
14
12
  readonly _tag: string;
15
13
  } & EventBrand;
16
- declare const SchemaIdTypeId: unique symbol;
17
- type SchemaIdTypeId = typeof SchemaIdTypeId;
14
+ type SchemaIdTypeId = "effect-machine/SchemaIdTypeId";
18
15
  /**
19
16
  * Brand that captures the schema definition type D.
20
17
  * Two schemas with identical definition shapes will have compatible brands.
@@ -33,8 +30,7 @@ type FullEventBrand<D extends Record<string, unknown>> = EventBrand & SchemaIdBr
33
30
  * Brand that carries the reply type for an event variant.
34
31
  * Present only on events defined with Event.reply().
35
32
  */
36
- declare const ReplyTypeId: unique symbol;
37
- type ReplyTypeId = typeof ReplyTypeId;
33
+ type ReplyTypeId = "effect-machine/ReplyTypeId";
38
34
  interface ReplyTypeBrand<R> extends Brand.Brand<ReplyTypeId> {
39
35
  readonly _ReplyType: R;
40
36
  }
@@ -14,7 +14,7 @@ const emitWithTimestamp = Effect.fn("effect-machine.emitWithTimestamp")(function
14
14
  return;
15
15
  }
16
16
  });
17
- if (result !== void 0 && Effect.isEffect(result)) yield* result.pipe(Effect.catchAllCause(() => Effect.void));
17
+ if (Effect.isEffect(result)) yield* result.pipe(Effect.catchAllCause(() => Effect.void));
18
18
  });
19
19
  //#endregion
20
20
  export { emitWithTimestamp };
@@ -1,6 +1,6 @@
1
- import { ActorExit } from "../supervision.js";
2
1
  import { NoReplyError } from "../errors.js";
3
- import { EffectsDef, GuardsDef, MachineContext } from "../slot.js";
2
+ import { MachineContext, SlotsDef } from "../slot.js";
3
+ import { ActorExit } from "../supervision.js";
4
4
  import { ProcessEventHooks, ProcessEventResult } from "./transition.js";
5
5
  import { Machine, MachineRef } from "../machine.js";
6
6
  import { ActorSystem } from "../actor.js";
@@ -14,7 +14,7 @@ type RuntimeQueuedEvent<E> = {
14
14
  } | {
15
15
  readonly _tag: "sendWait";
16
16
  readonly event: E;
17
- readonly done: Deferred.Deferred<void>;
17
+ readonly done: Deferred.Deferred<void, unknown>;
18
18
  } | {
19
19
  readonly _tag: "call";
20
20
  readonly event: E;
@@ -43,13 +43,13 @@ interface RuntimeCellResources<S, E> {
43
43
  interface RuntimeHandle<S, E> {
44
44
  /** Enqueue a fire-and-forget event */
45
45
  readonly send: (event: E) => Effect.Effect<void>;
46
- /** Enqueue event and wait for processing to complete (for RPC Send) */
47
- readonly sendWait: (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
48
  /** Enqueue an ask event, returns the reply value */
49
49
  readonly ask: (event: E) => Effect.Effect<unknown, NoReplyError>;
50
50
  /** Get current state */
51
51
  readonly getState: Effect.Effect<S>;
52
- /** SubscriptionRef for state observation */
52
+ /** SubscriptionRef for state observation (WatchState streaming) */
53
53
  readonly stateRef: SubscriptionRef.SubscriptionRef<S>;
54
54
  /** Whether the runtime has stopped (final state reached) */
55
55
  readonly isStopped: Effect.Effect<boolean>;
@@ -123,7 +123,7 @@ interface ProcessQueuedResult<S> {
123
123
  * and querying state. The runtime owns:
124
124
  * - Event loop fiber
125
125
  * - Postpone buffer
126
- * - Background effects
126
+ * - Background effects (under actorScope)
127
127
  * - State scope (spawn effects)
128
128
  * - Final state detection
129
129
  * - Exit reason via exitDeferred
@@ -137,6 +137,6 @@ declare const createRuntime: <S extends {
137
137
  readonly _tag: string;
138
138
  }, E extends {
139
139
  readonly _tag: string;
140
- }, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, any, any, GD, EFD>, system: ActorSystem, config: RuntimeConfig<S, E>) => Effect.Effect<RuntimeHandle<S, E>, never, Scope.Scope | Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
140
+ }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, system: ActorSystem, config: RuntimeConfig<S, E>) => Effect.Effect<RuntimeHandle<S, E>, never, Scope.Scope | Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
141
141
  //#endregion
142
142
  export { ProcessQueuedResult, RuntimeCellResources, RuntimeConfig, RuntimeHandle, RuntimeLifecycleHooks, RuntimeQueuedEvent, createRuntime };