effect-machine 0.15.2 → 0.17.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 (46) hide show
  1. package/README.md +4 -0
  2. package/dist/actor.d.ts +19 -7
  3. package/dist/actor.js +26 -4
  4. package/dist/cluster/adapters/in-memory.d.ts +4 -4
  5. package/dist/cluster/adapters/in-memory.js +2 -2
  6. package/dist/cluster/entity-machine.d.ts +2 -2
  7. package/dist/cluster/index.d.ts +2 -2
  8. package/dist/cluster/persistence.d.ts +5 -4
  9. package/dist/cluster/persistence.js +2 -2
  10. package/dist/cluster/to-entity.d.ts +2 -2
  11. package/dist/errors.d.ts +12 -12
  12. package/dist/index.d.ts +3 -3
  13. package/dist/index.js +2 -2
  14. package/dist/inspection.d.ts +12 -11
  15. package/dist/inspection.js +10 -24
  16. package/dist/internal/inspection.d.ts +2 -2
  17. package/dist/internal/runtime.d.ts +7 -7
  18. package/dist/internal/runtime.js +10 -15
  19. package/dist/internal/transition.d.ts +9 -9
  20. package/dist/internal/utils.d.ts +3 -3
  21. package/dist/internal/utils.js +1 -1
  22. package/dist/machine.d.ts +27 -7
  23. package/dist/machine.js +26 -4
  24. package/dist/schema.d.ts +24 -13
  25. package/dist/schema.js +8 -8
  26. package/dist/slot.d.ts +8 -6
  27. package/dist/slot.js +38 -3
  28. package/dist/testing.d.ts +7 -7
  29. package/package.json +22 -22
  30. package/v3/dist/actor.d.ts +12 -2
  31. package/v3/dist/actor.js +24 -2
  32. package/v3/dist/cluster/entity-machine.d.ts +1 -1
  33. package/v3/dist/cluster/entity-machine.js +4 -3
  34. package/v3/dist/cluster/to-entity.d.ts +8 -3
  35. package/v3/dist/index.d.ts +2 -2
  36. package/v3/dist/index.js +2 -2
  37. package/v3/dist/inspection.d.ts +2 -2
  38. package/v3/dist/inspection.js +8 -22
  39. package/v3/dist/internal/runtime.d.ts +5 -5
  40. package/v3/dist/internal/runtime.js +9 -14
  41. package/v3/dist/machine.d.ts +22 -2
  42. package/v3/dist/machine.js +26 -4
  43. package/v3/dist/schema.d.ts +25 -12
  44. package/v3/dist/schema.js +8 -7
  45. package/v3/dist/slot.d.ts +3 -2
  46. package/v3/dist/slot.js +37 -2
package/README.md CHANGED
@@ -17,6 +17,10 @@ Use it when a feature has:
17
17
  bun add effect-machine effect
18
18
  ```
19
19
 
20
+ `effect` is a peer dependency. The repository validates both the v4 entrypoint
21
+ and the `effect-machine/v3` mirror with `@effect/tsgo`, the latest Effect beta,
22
+ type-aware oxlint, and Bun tests.
23
+
20
24
  ## Core Pattern
21
25
 
22
26
  States and events are schemas. Types, validation, and serialization from one place.
package/dist/actor.d.ts CHANGED
@@ -5,7 +5,7 @@ import { ActorExit, Supervision } from "./supervision.js";
5
5
  import { ProcessEventError, ProcessEventHooks, ProcessEventResult, processEventCore, resolveTransition, runSpawnEffects } from "./internal/transition.js";
6
6
  import { Lifecycle, Machine } from "./machine.js";
7
7
  import { RuntimeQueuedEvent } from "./internal/runtime.js";
8
- import { Deferred, Effect, Layer, Option, PubSub, Queue, Ref, Scope, ServiceMap, Stream, SubscriptionRef } from "effect";
8
+ import { Context, Deferred, Effect, Layer, Option, PubSub, Queue, Ref, Scope, Stream, SubscriptionRef } from "effect";
9
9
 
10
10
  //#region src/actor.d.ts
11
11
  /** Discriminated mailbox request — alias for RuntimeQueuedEvent */
@@ -120,7 +120,7 @@ interface ActorRef<State extends {
120
120
  /** Sync helpers for non-Effect boundaries. */
121
121
  readonly sync: ActorRefSync<State, Event>;
122
122
  /** The actor system this actor belongs to. */
123
- readonly system: ActorSystem;
123
+ readonly system: ActorSystemService;
124
124
  /** Child actors spawned via `self.spawn` in this actor's handlers. */
125
125
  readonly children: ReadonlyMap<string, ActorRef<AnyState, unknown>>;
126
126
  }
@@ -154,7 +154,7 @@ type SystemEventListener = (event: SystemEvent) => void;
154
154
  /**
155
155
  * Actor system for managing actor lifecycles
156
156
  */
157
- interface ActorSystem {
157
+ interface ActorSystemService {
158
158
  /**
159
159
  * Spawn a new actor with the given machine.
160
160
  *
@@ -196,10 +196,22 @@ interface ActorSystem {
196
196
  */
197
197
  readonly subscribe: (fn: SystemEventListener) => () => void;
198
198
  }
199
+ declare const ActorSystem_base: Context.ServiceClass<ActorSystem, "effect-machine/actor/ActorSystem", ActorSystemService>;
199
200
  /**
200
201
  * ActorSystem service tag
201
202
  */
202
- declare const ActorSystem: ServiceMap.Service<ActorSystem, ActorSystem>;
203
+ declare class ActorSystem extends ActorSystem_base {}
204
+ declare const ActorScope_base: Context.ServiceClass<ActorScope, "effect-machine/actor/ActorScope", Scope.Scope>;
205
+ /**
206
+ * Explicit scope for actor lifecycle management.
207
+ *
208
+ * When present in context, actors attach cleanup finalizers to this scope.
209
+ * This replaces ambient `Scope.Scope` detection which caused bugs where
210
+ * unrelated scopes would tear down actors unexpectedly.
211
+ *
212
+ * Provide via `Machine.scoped` or `Effect.provideService(ActorScope, scope)`.
213
+ */
214
+ declare class ActorScope extends ActorScope_base {}
203
215
  /** Listener set for sync subscriptions */
204
216
  type Listeners<S> = Set<(state: S) => void>;
205
217
  /**
@@ -213,7 +225,7 @@ declare const buildActorRefCore: <S extends {
213
225
  readonly _tag: string;
214
226
  }, E extends {
215
227
  readonly _tag: string;
216
- }, 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>, never>) => ActorRef<S, E>;
228
+ }, 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: ActorSystemService, 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>;
217
229
  /**
218
230
  * Create and start an actor for a machine.
219
231
  * Delegates to the shared runtime kernel with actor-specific lifecycle hooks.
@@ -234,10 +246,10 @@ declare const settlePendingReplies: (pendingReplies: Set<Deferred.Deferred<unkno
234
246
  * Create an ActorSystem instance. Must be run in a Scope.
235
247
  * @internal — use Default layer for normal usage
236
248
  */
237
- declare const makeSystem: () => Effect.Effect<ActorSystem, never, Scope.Scope>;
249
+ declare const makeSystem: () => Effect.Effect<ActorSystemService, never, Scope.Scope>;
238
250
  /**
239
251
  * Default ActorSystem layer
240
252
  */
241
253
  declare const Default: Layer.Layer<ActorSystem, never, never>;
242
254
  //#endregion
243
- export { ActorRef, ActorRefSync, ActorSystem, Default, Listeners, type ProcessEventError, type ProcessEventHooks, type ProcessEventResult, QueuedEvent, SystemEvent, SystemEventListener, TransitionInfo, buildActorRefCore, createActor, makeSystem, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
255
+ export { ActorRef, ActorRefSync, ActorScope, ActorSystem, ActorSystemService, Default, Listeners, type ProcessEventError, type ProcessEventHooks, type ProcessEventResult, QueuedEvent, SystemEvent, SystemEventListener, TransitionInfo, buildActorRefCore, createActor, makeSystem, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
package/dist/actor.js CHANGED
@@ -4,7 +4,7 @@ import { emitWithTimestamp } from "./internal/inspection.js";
4
4
  import { Inspector } from "./inspection.js";
5
5
  import { materializeMachine } from "./machine.js";
6
6
  import { createRuntime } from "./internal/runtime.js";
7
- import { Cause, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, Option, PubSub, Queue, Ref, Schedule, Scope, Semaphore, ServiceMap, Stream, SubscriptionRef } from "effect";
7
+ import { Cause, Context, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, Option, PubSub, Queue, Ref, Schedule, Scope, Semaphore, Stream, SubscriptionRef } from "effect";
8
8
  //#region src/actor.ts
9
9
  /**
10
10
  * Actor system: spawning, lifecycle, and event processing.
@@ -17,7 +17,17 @@ import { Cause, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, Option, Pu
17
17
  /**
18
18
  * ActorSystem service tag
19
19
  */
20
- const ActorSystem = ServiceMap.Service("@effect/machine/ActorSystem");
20
+ var ActorSystem = class extends Context.Service()("effect-machine/actor/ActorSystem") {};
21
+ /**
22
+ * Explicit scope for actor lifecycle management.
23
+ *
24
+ * When present in context, actors attach cleanup finalizers to this scope.
25
+ * This replaces ambient `Scope.Scope` detection which caused bugs where
26
+ * unrelated scopes would tear down actors unexpectedly.
27
+ *
28
+ * Provide via `Machine.scoped` or `Effect.provideService(ActorScope, scope)`.
29
+ */
30
+ var ActorScope = class extends Context.Service()("effect-machine/actor/ActorScope") {};
21
31
  /**
22
32
  * Notify all listeners of state change.
23
33
  */
@@ -40,11 +50,19 @@ const buildActorRefCore = (id, machine, stateRef, eventQueueRef, stoppedRef, lis
40
50
  });
41
51
  const call = Effect.fn("effect-machine.actor.call")(function* (event) {
42
52
  if (yield* Ref.get(stoppedRef)) {
53
+ yield* Effect.logWarning("effect-machine.actor.call.stopped").pipe(Effect.annotateLogs({
54
+ actorId: id,
55
+ eventTag: event._tag
56
+ }));
43
57
  const currentState = yield* SubscriptionRef.get(stateRef);
44
58
  return {
45
59
  newState: currentState,
46
60
  previousState: currentState,
47
61
  transitioned: false,
62
+ hasReply: false,
63
+ deferReply: false,
64
+ reply: void 0,
65
+ postponed: false,
48
66
  lifecycleRan: false,
49
67
  isFinal: machine.finalStates.has(currentState._tag)
50
68
  };
@@ -61,6 +79,10 @@ const buildActorRefCore = (id, machine, stateRef, eventQueueRef, stoppedRef, lis
61
79
  newState: currentState,
62
80
  previousState: currentState,
63
81
  transitioned: false,
82
+ hasReply: false,
83
+ deferReply: false,
84
+ reply: void 0,
85
+ postponed: false,
64
86
  lifecycleRan: false,
65
87
  isFinal: machine.finalStates.has(currentState._tag)
66
88
  })))));
@@ -475,7 +497,7 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
475
497
  id,
476
498
  actor: actorRef
477
499
  });
478
- const maybeScope = yield* Effect.serviceOption(Scope.Scope);
500
+ const maybeScope = yield* Effect.serviceOption(ActorScope);
479
501
  if (Option.isSome(maybeScope)) yield* Scope.addFinalizer(maybeScope.value, Effect.gen(function* () {
480
502
  if (MutableHashMap.has(actorsMap, id)) {
481
503
  yield* emitSystemEvent({
@@ -558,4 +580,4 @@ const makeSystem = make;
558
580
  */
559
581
  const Default = Layer.effect(ActorSystem, make());
560
582
  //#endregion
561
- export { ActorSystem, Default, buildActorRefCore, createActor, makeSystem, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
583
+ export { ActorScope, ActorSystem, Default, buildActorRefCore, createActor, makeSystem, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
@@ -1,4 +1,4 @@
1
- import { PersistedEvent, PersistenceAdapter, Snapshot } from "../persistence.js";
1
+ import { PersistedEvent, PersistenceAdapter, PersistenceAdapterService, Snapshot } from "../persistence.js";
2
2
  import { Effect, Layer, Ref } from "effect";
3
3
 
4
4
  //#region src/cluster/adapters/in-memory.d.ts
@@ -9,18 +9,18 @@ interface EntityStore {
9
9
  /**
10
10
  * Create an in-memory persistence adapter.
11
11
  *
12
- * Returns a Layer providing `PersistenceAdapter` and a ref
12
+ * Returns a Layer providing `PersistenceAdapterService` and a ref
13
13
  * to the backing store for test assertions.
14
14
  *
15
15
  * @example
16
16
  * ```ts
17
17
  * const { layer, storeRef } = yield* makeInMemoryPersistenceAdapter
18
- * // Use layer to provide PersistenceAdapter
18
+ * // Use layer to provide PersistenceAdapterService
19
19
  * // Inspect storeRef for test assertions
20
20
  * ```
21
21
  */
22
22
  declare const makeInMemoryPersistenceAdapter: Effect.Effect<{
23
- adapter: PersistenceAdapter;
23
+ adapter: PersistenceAdapterService;
24
24
  storeRef: Ref.Ref<Map<string, EntityStore>>;
25
25
  layer: Layer.Layer<PersistenceAdapter, never, never>;
26
26
  }, never, never>;
@@ -26,13 +26,13 @@ const getOrCreate = (store, key) => {
26
26
  /**
27
27
  * Create an in-memory persistence adapter.
28
28
  *
29
- * Returns a Layer providing `PersistenceAdapter` and a ref
29
+ * Returns a Layer providing `PersistenceAdapterService` and a ref
30
30
  * to the backing store for test assertions.
31
31
  *
32
32
  * @example
33
33
  * ```ts
34
34
  * const { layer, storeRef } = yield* makeInMemoryPersistenceAdapter
35
- * // Use layer to provide PersistenceAdapter
35
+ * // Use layer to provide PersistenceAdapterService
36
36
  * // Inspect storeRef for test assertions
37
37
  * ```
38
38
  */
@@ -38,9 +38,9 @@ interface EntityMachineOptions<S, E> {
38
38
  * Retry policy for defects (schedule for restarting after defect).
39
39
  * Forwarded to Entity.toLayerQueue.
40
40
  */
41
- readonly defectRetryPolicy?: Schedule.Schedule<any, unknown>;
41
+ readonly defectRetryPolicy?: Schedule.Schedule<any>;
42
42
  /**
43
- * Persistence configuration. When set, requires PersistenceAdapter in R.
43
+ * Persistence configuration. When set, requires PersistenceAdapterService in R.
44
44
  */
45
45
  readonly persistence?: EntityPersistenceConfig;
46
46
  }
@@ -1,6 +1,6 @@
1
- import { EntityPersistenceConfig, PersistedEvent, PersistenceAdapter, PersistenceKey, Snapshot } from "./persistence.js";
1
+ import { EntityPersistenceConfig, PersistedEvent, PersistenceAdapter, PersistenceAdapterService, PersistenceKey, Snapshot } from "./persistence.js";
2
2
  import { makeInMemoryPersistenceAdapter } from "./adapters/in-memory.js";
3
3
  import { EntityRpcs, ToEntityOptions, toEntity } from "./to-entity.js";
4
4
  import { EntityActorRef, makeEntityActorRef } from "./entity-actor-ref.js";
5
5
  import { EntityMachine, EntityMachineOptions } from "./entity-machine.js";
6
- export { type EntityActorRef, EntityMachine, type EntityMachineOptions, type EntityPersistenceConfig, type EntityRpcs, type PersistedEvent, PersistenceAdapter, type PersistenceAdapter as PersistenceAdapterInterface, type PersistenceKey, type Snapshot, type ToEntityOptions, makeEntityActorRef, makeInMemoryPersistenceAdapter, toEntity };
6
+ export { type EntityActorRef, EntityMachine, type EntityMachineOptions, type EntityPersistenceConfig, type EntityRpcs, type PersistedEvent, PersistenceAdapter, type PersistenceAdapterService as PersistenceAdapterInterface, type PersistenceKey, type Snapshot, type ToEntityOptions, makeEntityActorRef, makeInMemoryPersistenceAdapter, toEntity };
@@ -1,5 +1,5 @@
1
1
  import { PersistenceError, VersionConflictError } from "../errors.js";
2
- import { Effect, Option, Schedule, ServiceMap } from "effect";
2
+ import { Context, Effect, Option, Schedule } from "effect";
3
3
 
4
4
  //#region src/cluster/persistence.d.ts
5
5
  /** Namespaced key preventing cross-type collisions (e.g. Order/123 vs User/123). */
@@ -33,7 +33,7 @@ interface EntityPersistenceConfig {
33
33
  readonly machineType?: string;
34
34
  }
35
35
  /** Storage backend for entity state persistence. */
36
- interface PersistenceAdapter {
36
+ interface PersistenceAdapterService {
37
37
  /** Save a state snapshot. Fails with VersionConflictError if version is stale. */
38
38
  readonly saveSnapshot: (key: PersistenceKey, snapshot: Snapshot<unknown>) => Effect.Effect<void, PersistenceError | VersionConflictError>;
39
39
  /** Load the latest snapshot, or None if no snapshot exists. */
@@ -43,7 +43,8 @@ interface PersistenceAdapter {
43
43
  /** Load events from the journal, optionally after a given version. */
44
44
  readonly loadEvents: (key: PersistenceKey, afterVersion?: number) => Effect.Effect<ReadonlyArray<PersistedEvent<unknown>>, PersistenceError>;
45
45
  }
46
+ declare const PersistenceAdapter_base: Context.ServiceClass<PersistenceAdapter, "effect-machine/cluster/persistence/PersistenceAdapter", PersistenceAdapterService>;
46
47
  /** Service tag for PersistenceAdapter — resolve from context for shared infra. */
47
- declare const PersistenceAdapter: ServiceMap.Service<PersistenceAdapter, PersistenceAdapter>;
48
+ declare class PersistenceAdapter extends PersistenceAdapter_base {}
48
49
  //#endregion
49
- export { EntityPersistenceConfig, PersistedEvent, PersistenceAdapter, PersistenceKey, Snapshot };
50
+ export { EntityPersistenceConfig, PersistedEvent, PersistenceAdapter, PersistenceAdapterService, PersistenceKey, Snapshot };
@@ -1,4 +1,4 @@
1
- import { ServiceMap } from "effect";
1
+ import { Context } from "effect";
2
2
  //#region src/cluster/persistence.ts
3
3
  /**
4
4
  * Entity persistence types and adapter interface.
@@ -13,6 +13,6 @@ import { ServiceMap } from "effect";
13
13
  * @module
14
14
  */
15
15
  /** Service tag for PersistenceAdapter — resolve from context for shared infra. */
16
- const PersistenceAdapter = ServiceMap.Service("@effect-machine/cluster/PersistenceAdapter");
16
+ var PersistenceAdapter = class extends Context.Service()("effect-machine/cluster/persistence/PersistenceAdapter") {};
17
17
  //#endregion
18
18
  export { PersistenceAdapter };
@@ -23,9 +23,9 @@ interface ToEntityOptions {
23
23
  */
24
24
  type EntityRpcs<StateSchema extends Schema.Top, EventSchema extends Schema.Top> = readonly [Rpc.Rpc<"Send", Schema.Struct<{
25
25
  readonly event: EventSchema;
26
- }>, StateSchema, typeof Schema.Never, never>, Rpc.Rpc<"Ask", Schema.Struct<{
26
+ }>, StateSchema>, Rpc.Rpc<"Ask", Schema.Struct<{
27
27
  readonly event: EventSchema;
28
- }>, typeof Schema.Unknown, typeof Schema.Never, never>, Rpc.Rpc<"GetState", typeof Schema.Void, StateSchema, typeof Schema.Never, never>];
28
+ }>, typeof Schema.Unknown>, Rpc.Rpc<"GetState", typeof Schema.Void, StateSchema>];
29
29
  /**
30
30
  * Generate an Entity definition from a machine.
31
31
  *
package/dist/errors.d.ts CHANGED
@@ -2,67 +2,67 @@ import { Schema } from "effect";
2
2
  import * as _$effect_Cause0 from "effect/Cause";
3
3
 
4
4
  //#region src/errors.d.ts
5
- declare const DuplicateActorError_base: Schema.ErrorClass<DuplicateActorError, Schema.TaggedStruct<"DuplicateActorError", {
5
+ declare const DuplicateActorError_base: Schema.Class<DuplicateActorError, Schema.TaggedStruct<"DuplicateActorError", {
6
6
  readonly actorId: Schema.String;
7
7
  }>, _$effect_Cause0.YieldableError>;
8
8
  /** Attempted to spawn/restore actor with ID already in use */
9
9
  declare class DuplicateActorError extends DuplicateActorError_base {}
10
- declare const MissingSchemaError_base: Schema.ErrorClass<MissingSchemaError, Schema.TaggedStruct<"MissingSchemaError", {
10
+ declare const MissingSchemaError_base: Schema.Class<MissingSchemaError, Schema.TaggedStruct<"MissingSchemaError", {
11
11
  readonly operation: Schema.String;
12
12
  }>, _$effect_Cause0.YieldableError>;
13
13
  /** Operation requires schemas attached to machine */
14
14
  declare class MissingSchemaError extends MissingSchemaError_base {}
15
- declare const InvalidSchemaError_base: Schema.ErrorClass<InvalidSchemaError, Schema.TaggedStruct<"InvalidSchemaError", {
15
+ declare const InvalidSchemaError_base: Schema.Class<InvalidSchemaError, Schema.TaggedStruct<"InvalidSchemaError", {
16
16
  readonly message: Schema.String;
17
17
  }>, _$effect_Cause0.YieldableError>;
18
18
  /** State/Event schema has no variants */
19
19
  declare class InvalidSchemaError extends InvalidSchemaError_base {}
20
- declare const MissingMatchHandlerError_base: Schema.ErrorClass<MissingMatchHandlerError, Schema.TaggedStruct<"MissingMatchHandlerError", {
20
+ declare const MissingMatchHandlerError_base: Schema.Class<MissingMatchHandlerError, Schema.TaggedStruct<"MissingMatchHandlerError", {
21
21
  readonly tag: Schema.String;
22
22
  }>, _$effect_Cause0.YieldableError>;
23
23
  /** $match called with missing handler for tag */
24
24
  declare class MissingMatchHandlerError extends MissingMatchHandlerError_base {}
25
- declare const SlotProvisionError_base: Schema.ErrorClass<SlotProvisionError, Schema.TaggedStruct<"SlotProvisionError", {
25
+ declare const SlotProvisionError_base: Schema.Class<SlotProvisionError, Schema.TaggedStruct<"SlotProvisionError", {
26
26
  readonly slotName: Schema.String;
27
27
  readonly slotType: Schema.Literal<"slot">;
28
28
  }>, _$effect_Cause0.YieldableError>;
29
29
  /** Slot handler not found at runtime (internal error) */
30
30
  declare class SlotProvisionError extends SlotProvisionError_base {}
31
- declare const ProvisionValidationError_base: Schema.ErrorClass<ProvisionValidationError, Schema.TaggedStruct<"ProvisionValidationError", {
31
+ declare const ProvisionValidationError_base: Schema.Class<ProvisionValidationError, Schema.TaggedStruct<"ProvisionValidationError", {
32
32
  readonly missing: Schema.$Array<Schema.String>;
33
33
  readonly extra: Schema.$Array<Schema.String>;
34
34
  }>, _$effect_Cause0.YieldableError>;
35
35
  /** Slot provision validation failed — missing or extra handlers */
36
36
  declare class ProvisionValidationError extends ProvisionValidationError_base {}
37
- declare const AssertionError_base: Schema.ErrorClass<AssertionError, Schema.TaggedStruct<"AssertionError", {
37
+ declare const AssertionError_base: Schema.Class<AssertionError, Schema.TaggedStruct<"AssertionError", {
38
38
  readonly message: Schema.String;
39
39
  }>, _$effect_Cause0.YieldableError>;
40
40
  /** Assertion failed in testing utilities */
41
41
  declare class AssertionError extends AssertionError_base {}
42
- declare const ActorStoppedError_base: Schema.ErrorClass<ActorStoppedError, Schema.TaggedStruct<"ActorStoppedError", {
42
+ declare const ActorStoppedError_base: Schema.Class<ActorStoppedError, Schema.TaggedStruct<"ActorStoppedError", {
43
43
  readonly actorId: Schema.String;
44
44
  }>, _$effect_Cause0.YieldableError>;
45
45
  /** Actor was stopped while a call/ask was pending */
46
46
  declare class ActorStoppedError extends ActorStoppedError_base {}
47
- declare const NoReplyError_base: Schema.ErrorClass<NoReplyError, Schema.TaggedStruct<"NoReplyError", {
47
+ declare const NoReplyError_base: Schema.Class<NoReplyError, Schema.TaggedStruct<"NoReplyError", {
48
48
  readonly actorId: Schema.String;
49
49
  readonly eventTag: Schema.String;
50
50
  }>, _$effect_Cause0.YieldableError>;
51
51
  /** ask() was used but the transition handler did not call reply */
52
52
  declare class NoReplyError extends NoReplyError_base {}
53
- declare const PersistenceError_base: Schema.ErrorClass<PersistenceError, Schema.TaggedStruct<"PersistenceError", {
53
+ declare const PersistenceError_base: Schema.Class<PersistenceError, Schema.TaggedStruct<"PersistenceError", {
54
54
  readonly message: Schema.String;
55
55
  }>, _$effect_Cause0.YieldableError>;
56
56
  /** Persistence adapter operation failed */
57
57
  declare class PersistenceError extends PersistenceError_base {}
58
- declare const SlotCodecError_base: Schema.ErrorClass<SlotCodecError, Schema.TaggedStruct<"SlotCodecError", {
58
+ declare const SlotCodecError_base: Schema.Class<SlotCodecError, Schema.TaggedStruct<"SlotCodecError", {
59
59
  readonly slotName: Schema.String;
60
60
  readonly phase: Schema.Literals<readonly ["input", "output"]>;
61
61
  readonly message: Schema.String;
62
62
  }>, _$effect_Cause0.YieldableError>;
63
63
  /** Slot input/output schema validation failed */
64
64
  declare class SlotCodecError extends SlotCodecError_base {}
65
- declare const VersionConflictError_base: Schema.ErrorClass<VersionConflictError, Schema.TaggedStruct<"VersionConflictError", {
65
+ declare const VersionConflictError_base: Schema.Class<VersionConflictError, Schema.TaggedStruct<"VersionConflictError", {
66
66
  readonly expected: Schema.Number;
67
67
  readonly actual: Schema.Number;
68
68
  }>, _$effect_Cause0.YieldableError>;
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ import { HasSlotKeys, MachineContext, ProvideSlots, Slot, SlotCall, SlotCalls, S
5
5
  import { ActorExit, CellPhase, DefectPhase, Supervision } from "./supervision.js";
6
6
  import { ProcessEventResult } from "./internal/transition.js";
7
7
  import { BackgroundEffect, Durability, DurabilityCommit, HandlerContext, Lifecycle, Machine, MachineRef, MakeConfig, Recovery, RecoveryContext, SpawnEffect, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, machine_d_exports } from "./machine.js";
8
- import { ActorRef, ActorRefSync, ActorSystem, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
8
+ import { ActorRef, ActorRefSync, ActorScope, ActorSystem, ActorSystemService, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
9
9
  import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
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, type DeferReplyResult, DuplicateActorError, type Durability, type DurabilityCommit, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type HandlerContext, type HasSlotKeys, type InspectionEvent, type Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, type Lifecycle, 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 Recovery, type RecoveryContext, 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 };
10
+ import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, InspectorService, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
11
+ export { ActorExit, type ActorRef, type ActorRefSync, ActorScope, ActorStoppedError, type ActorSystemService as ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type CellPhase, type DefectPhase, type DeferReplyResult, DuplicateActorError, type Durability, type DurabilityCommit, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type HandlerContext, type HasSlotKeys, type InspectionEvent, type InspectorService as Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, type Lifecycle, 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 Recovery, type RecoveryContext, 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/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { Inspector, collectingInspector, combineInspectors, consoleInspector, ma
3
3
  import { Slot } from "./slot.js";
4
4
  import { machine_exports } from "./machine.js";
5
5
  import { ActorExit, Supervision } from "./supervision.js";
6
- import { ActorSystem, Default } from "./actor.js";
6
+ import { ActorScope, 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, SlotCodecError, SlotProvisionError, State, Supervision, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
9
+ export { ActorExit, ActorScope, 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 };
@@ -1,4 +1,4 @@
1
- import { Effect, Schema, ServiceMap } from "effect";
1
+ import { Context, Effect, Schema } from "effect";
2
2
 
3
3
  //#region src/inspection.d.ts
4
4
  /**
@@ -93,15 +93,16 @@ type AnyInspectionEvent = InspectionEvent<{
93
93
  /**
94
94
  * Inspector interface for observing machine behavior
95
95
  */
96
- type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void, never, never>;
97
- interface Inspector<S, E> {
96
+ type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void>;
97
+ interface InspectorService<S, E> {
98
98
  readonly onInspect: InspectorHandler<S, E>;
99
99
  }
100
+ declare const Inspector_base: Context.ServiceClass<Inspector, "effect-machine/inspection/Inspector", InspectorService<any, any>>;
100
101
  /**
101
102
  * Inspector service tag - optional service for machine introspection
102
103
  * Uses `any` types to allow variance flexibility when providing the service
103
104
  */
104
- declare const Inspector: ServiceMap.Service<Inspector<any, any>, Inspector<any, any>>;
105
+ declare class Inspector extends Inspector_base {}
105
106
  /**
106
107
  * Create an inspector from a callback function.
107
108
  *
@@ -114,13 +115,13 @@ declare const makeInspector: <S = {
114
115
  readonly _tag: string;
115
116
  }, E = {
116
117
  readonly _tag: string;
117
- }>(onInspect: InspectorHandler<ResolveType<S>, ResolveType<E>>) => Inspector<ResolveType<S>, ResolveType<E>>;
118
+ }>(onInspect: InspectorHandler<ResolveType<S>, ResolveType<E>>) => InspectorService<ResolveType<S>, ResolveType<E>>;
118
119
  declare const makeInspectorEffect: <S = {
119
120
  readonly _tag: string;
120
121
  }, E = {
121
122
  readonly _tag: string;
122
- }>(onInspect: (event: InspectionEvent<ResolveType<S>, ResolveType<E>>) => Effect.Effect<void, never, never>) => Inspector<ResolveType<S>, ResolveType<E>>;
123
- declare const combineInspectors: <S, E>(...inspectors: ReadonlyArray<Inspector<S, E>>) => Inspector<S, E>;
123
+ }>(onInspect: (event: InspectionEvent<ResolveType<S>, ResolveType<E>>) => Effect.Effect<void>) => InspectorService<ResolveType<S>, ResolveType<E>>;
124
+ declare const combineInspectors: <S, E>(...inspectors: ReadonlyArray<InspectorService<S, E>>) => InspectorService<S, E>;
124
125
  interface TracingInspectorOptions<S, E> {
125
126
  readonly spanName?: string | ((event: InspectionEvent<S, E>) => string);
126
127
  readonly attributes?: (event: InspectionEvent<S, E>) => Readonly<Record<string, string | number | boolean>>;
@@ -130,11 +131,11 @@ declare const tracingInspector: <S extends {
130
131
  readonly _tag: string;
131
132
  }, E extends {
132
133
  readonly _tag: string;
133
- }>(options?: TracingInspectorOptions<S, E>) => Inspector<S, E>;
134
+ }>(options?: TracingInspectorOptions<S, E>) => InspectorService<S, E>;
134
135
  /**
135
136
  * Console inspector that logs events in a readable format
136
137
  */
137
- declare const consoleInspector: () => Inspector<{
138
+ declare const consoleInspector: () => InspectorService<{
138
139
  readonly _tag: string;
139
140
  }, {
140
141
  readonly _tag: string;
@@ -146,6 +147,6 @@ declare const collectingInspector: <S extends {
146
147
  readonly _tag: string;
147
148
  }, E extends {
148
149
  readonly _tag: string;
149
- }>(events: InspectionEvent<S, E>[]) => Inspector<S, E>;
150
+ }>(events: InspectionEvent<S, E>[]) => InspectorService<S, E>;
150
151
  //#endregion
151
- export { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
152
+ export { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, InspectorService, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
@@ -1,10 +1,10 @@
1
- import { Effect, Option, ServiceMap } from "effect";
1
+ import { Context, Effect, Option } from "effect";
2
2
  //#region src/inspection.ts
3
3
  /**
4
4
  * Inspector service tag - optional service for machine introspection
5
5
  * Uses `any` types to allow variance flexibility when providing the service
6
6
  */
7
- const Inspector = ServiceMap.Service("@effect/machine/Inspector");
7
+ var Inspector = class extends Context.Service()("effect-machine/inspection/Inspector") {};
8
8
  /**
9
9
  * Create an inspector from a callback function.
10
10
  *
@@ -106,30 +106,16 @@ const tracingInspector = (options) => ({ onInspect: (event) => {
106
106
  /**
107
107
  * Console inspector that logs events in a readable format
108
108
  */
109
- const consoleInspector = () => makeInspector((event) => {
109
+ const consoleInspector = () => makeInspectorEffect((event) => {
110
110
  const prefix = `[${event.actorId}]`;
111
111
  switch (event.type) {
112
- case "@machine.spawn":
113
- console.log(prefix, "spawned →", event.initialState._tag);
114
- break;
115
- case "@machine.event":
116
- console.log(prefix, "received", event.event._tag, "in", event.state._tag);
117
- break;
118
- case "@machine.transition":
119
- console.log(prefix, event.fromState._tag, "→", event.toState._tag);
120
- break;
121
- case "@machine.effect":
122
- console.log(prefix, event.effectType, "effect in", event.state._tag);
123
- break;
124
- case "@machine.task":
125
- console.log(prefix, "task", event.phase, event.taskName ?? "<unnamed>", "in", event.state._tag);
126
- break;
127
- case "@machine.error":
128
- console.log(prefix, "error in", event.phase, event.state._tag, "-", event.error);
129
- break;
130
- case "@machine.stop":
131
- console.log(prefix, "stopped in", event.finalState._tag);
132
- break;
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}`);
133
119
  }
134
120
  });
135
121
  /**
@@ -1,4 +1,4 @@
1
- import { InspectionEvent, Inspector } from "../inspection.js";
1
+ import { InspectionEvent, InspectorService } from "../inspection.js";
2
2
  import { Effect } from "effect";
3
3
 
4
4
  //#region src/internal/inspection.d.ts
@@ -6,6 +6,6 @@ import { Effect } from "effect";
6
6
  * Emit an inspection event with timestamp from Clock.
7
7
  * @internal
8
8
  */
9
- declare const emitWithTimestamp: <S, E>(inspector: Inspector<S, E> | undefined, makeEvent: (timestamp: number) => InspectionEvent<S, E>) => Effect.Effect<void, never, never>;
9
+ declare const emitWithTimestamp: <S, E>(inspector: InspectorService<S, E> | undefined, makeEvent: (timestamp: number) => InspectionEvent<S, E>) => Effect.Effect<void, never, never>;
10
10
  //#endregion
11
11
  export { emitWithTimestamp };
@@ -1,9 +1,9 @@
1
1
  import { NoReplyError } from "../errors.js";
2
- import { MachineContext, SlotsDef } from "../slot.js";
2
+ import { MachineContextTag, SlotsDef } from "../slot.js";
3
3
  import { ActorExit } from "../supervision.js";
4
4
  import { ProcessEventHooks, ProcessEventResult } from "./transition.js";
5
- import { Machine, MachineRef } from "../machine.js";
6
- import { ActorSystem } from "../actor.js";
5
+ import { Machine } from "../machine.js";
6
+ import { ActorSystemService } from "../actor.js";
7
7
  import { Deferred, Effect, Queue, Ref, Scope, SubscriptionRef } from "effect";
8
8
 
9
9
  //#region src/internal/runtime.d.ts
@@ -27,7 +27,7 @@ type RuntimeQueuedEvent<E> = {
27
27
  readonly reply: Deferred.Deferred<unknown, NoReplyError>;
28
28
  } | {
29
29
  readonly _tag: "drain";
30
- readonly done: Deferred.Deferred<void, never>;
30
+ readonly done: Deferred.Deferred<void>;
31
31
  };
32
32
  /**
33
33
  * Resources owned by the actor cell (stable across generations).
@@ -69,7 +69,7 @@ interface RuntimeHandle<S, E> {
69
69
  * Exit deferred — set exactly once with the exit reason when the runtime stops.
70
70
  * Final state → ActorExit.Final, explicit stop → ActorExit.Stopped, defect → ActorExit.Defect.
71
71
  */
72
- readonly exitDeferred: Deferred.Deferred<ActorExit<S>, never>;
72
+ readonly exitDeferred: Deferred.Deferred<ActorExit<S>>;
73
73
  /**
74
74
  * Actor scope — owns background fibers for this generation.
75
75
  * Closing this scope interrupts all background fibers.
@@ -143,9 +143,9 @@ declare const createRuntime: <S extends {
143
143
  readonly _tag: string;
144
144
  }, E extends {
145
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<{
146
+ }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, system: ActorSystemService, config: RuntimeConfig<S, E>) => Effect.Effect<{
147
147
  stop: Effect.Effect<void, never, never>;
148
- start: Effect.Effect<void, unknown, Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
148
+ start: Effect.Effect<void, unknown, Exclude<R, MachineContextTag> | Exclude<Exclude<R, MachineContextTag>, Scope.Scope>>;
149
149
  send: (event: E) => Effect.Effect<void>;
150
150
  sendWait: (event: E) => Effect.Effect<void, unknown>;
151
151
  ask: (event: E) => Effect.Effect<unknown, NoReplyError>;
@@ -40,7 +40,7 @@ import { Cause, Deferred, Effect, Exit, Fiber, Queue, Ref, Schema, Scope, Subscr
40
40
  */
41
41
  const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (machine, system, config) {
42
42
  const { actorId, hooks, lifecycle } = config;
43
- const services = yield* Effect.services();
43
+ const services = yield* Effect.context();
44
44
  const fork = Effect.runForkWith(services);
45
45
  const stateRef = config.cellResources?.stateRef ?? (yield* SubscriptionRef.make(machine.initial));
46
46
  const stoppedRef = config.cellResources?.stoppedRef ?? (yield* Ref.make(false));
@@ -105,15 +105,13 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
105
105
  }
106
106
  if (lifecycle?.onInitialSpawnEffects !== void 0) yield* lifecycle.onInitialSpawnEffects(machine.initial);
107
107
  const initialSpawnDefectSignal = (cause) => Deferred.succeed(exitDeferred, ActorExit.Defect(cause, "initial-spawn")).pipe(Effect.andThen(Ref.set(stoppedRef, true)), Effect.andThen(Effect.suspend(() => loopFiberRef.current !== void 0 ? Fiber.interrupt(loopFiberRef.current) : Effect.void)), Effect.asVoid);
108
- yield* runSpawnEffects(machine, machine.initial, initEvent, self, stateScopeRef.current, system, actorId, hooks?.onError, initialSpawnDefectSignal).pipe(Effect.catchCause((cause) => {
109
- return Effect.gen(function* () {
110
- yield* Ref.set(stoppedRef, true);
111
- yield* Scope.close(stateScopeRef.current, Exit.void);
112
- yield* Scope.close(actorScope, Exit.void);
113
- yield* Deferred.succeed(exitDeferred, ActorExit.Defect(cause, "initial-spawn"));
114
- return yield* Effect.failCause(cause);
115
- });
116
- }));
108
+ yield* runSpawnEffects(machine, machine.initial, initEvent, self, stateScopeRef.current, system, actorId, hooks?.onError, initialSpawnDefectSignal).pipe(Effect.catchCause((cause) => Effect.gen(function* () {
109
+ yield* Ref.set(stoppedRef, true);
110
+ yield* Scope.close(stateScopeRef.current, Exit.void);
111
+ yield* Scope.close(actorScope, Exit.void);
112
+ yield* Deferred.succeed(exitDeferred, ActorExit.Defect(cause, "initial-spawn"));
113
+ return yield* Effect.failCause(cause);
114
+ })));
117
115
  if (machine.finalStates.has(machine.initial._tag)) {
118
116
  if (lifecycle?.onFinal !== void 0) yield* lifecycle.onFinal(machine.initial);
119
117
  yield* Ref.set(stoppedRef, true);
@@ -262,13 +260,10 @@ const runtimeEventLoop = Effect.fn("effect-machine.runtime.eventLoop")(function*
262
260
  if (result.hasReply) {
263
261
  const replySchema = machine._replySchemas?.get(event._tag);
264
262
  if (replySchema !== void 0) {
265
- let decoded;
266
- try {
267
- decoded = Schema.decodeUnknownSync(replySchema)(result.reply);
268
- } catch (decodeError) {
263
+ const decoded = yield* Schema.decodeUnknownEffect(replySchema)(result.reply).pipe(Effect.catch((decodeError) => Effect.gen(function* () {
269
264
  yield* Deferred.die(queued.reply, decodeError);
270
265
  return yield* Effect.die(decodeError);
271
- }
266
+ })));
272
267
  yield* Deferred.succeed(queued.reply, decoded);
273
268
  } else yield* Deferred.succeed(queued.reply, result.reply);
274
269
  } else if (result.deferReply && deferredReplyRef !== void 0) deferredReplyRef.current = queued.reply;