effect-machine 0.16.0 → 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 (40) hide show
  1. package/README.md +4 -0
  2. package/dist/actor.d.ts +9 -7
  3. package/dist/actor.js +2 -2
  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 +4 -3
  9. package/dist/cluster/persistence.js +1 -1
  10. package/dist/cluster/to-entity.d.ts +2 -2
  11. package/dist/index.d.ts +3 -3
  12. package/dist/inspection.d.ts +11 -10
  13. package/dist/inspection.js +9 -23
  14. package/dist/internal/inspection.d.ts +2 -2
  15. package/dist/internal/runtime.d.ts +7 -7
  16. package/dist/internal/runtime.js +9 -14
  17. package/dist/internal/transition.d.ts +9 -9
  18. package/dist/internal/utils.d.ts +3 -3
  19. package/dist/internal/utils.js +1 -1
  20. package/dist/machine.d.ts +4 -4
  21. package/dist/machine.js +20 -2
  22. package/dist/schema.d.ts +24 -13
  23. package/dist/schema.js +8 -8
  24. package/dist/slot.d.ts +7 -5
  25. package/dist/slot.js +38 -3
  26. package/dist/testing.d.ts +7 -7
  27. package/package.json +14 -18
  28. package/v3/dist/actor.d.ts +1 -1
  29. package/v3/dist/cluster/entity-machine.d.ts +1 -1
  30. package/v3/dist/cluster/entity-machine.js +4 -3
  31. package/v3/dist/cluster/to-entity.d.ts +8 -3
  32. package/v3/dist/inspection.d.ts +2 -2
  33. package/v3/dist/inspection.js +8 -22
  34. package/v3/dist/internal/runtime.d.ts +5 -5
  35. package/v3/dist/internal/runtime.js +9 -14
  36. package/v3/dist/machine.js +2 -1
  37. package/v3/dist/schema.d.ts +25 -12
  38. package/v3/dist/schema.js +8 -7
  39. package/v3/dist/slot.d.ts +3 -2
  40. 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
@@ -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,12 @@ 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: Context.Service<ActorSystem, ActorSystem>;
203
+ declare class ActorSystem extends ActorSystem_base {}
204
+ declare const ActorScope_base: Context.ServiceClass<ActorScope, "effect-machine/actor/ActorScope", Scope.Scope>;
203
205
  /**
204
206
  * Explicit scope for actor lifecycle management.
205
207
  *
@@ -209,7 +211,7 @@ declare const ActorSystem: Context.Service<ActorSystem, ActorSystem>;
209
211
  *
210
212
  * Provide via `Machine.scoped` or `Effect.provideService(ActorScope, scope)`.
211
213
  */
212
- declare const ActorScope: Context.Service<Scope.Scope, Scope.Scope>;
214
+ declare class ActorScope extends ActorScope_base {}
213
215
  /** Listener set for sync subscriptions */
214
216
  type Listeners<S> = Set<(state: S) => void>;
215
217
  /**
@@ -223,7 +225,7 @@ declare const buildActorRefCore: <S extends {
223
225
  readonly _tag: string;
224
226
  }, E extends {
225
227
  readonly _tag: string;
226
- }, 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>;
227
229
  /**
228
230
  * Create and start an actor for a machine.
229
231
  * Delegates to the shared runtime kernel with actor-specific lifecycle hooks.
@@ -244,10 +246,10 @@ declare const settlePendingReplies: (pendingReplies: Set<Deferred.Deferred<unkno
244
246
  * Create an ActorSystem instance. Must be run in a Scope.
245
247
  * @internal — use Default layer for normal usage
246
248
  */
247
- declare const makeSystem: () => Effect.Effect<ActorSystem, never, Scope.Scope>;
249
+ declare const makeSystem: () => Effect.Effect<ActorSystemService, never, Scope.Scope>;
248
250
  /**
249
251
  * Default ActorSystem layer
250
252
  */
251
253
  declare const Default: Layer.Layer<ActorSystem, never, never>;
252
254
  //#endregion
253
- export { ActorRef, ActorRefSync, ActorScope, ActorSystem, Default, Listeners, type ProcessEventError, type ProcessEventHooks, type ProcessEventResult, QueuedEvent, SystemEvent, SystemEventListener, TransitionInfo, buildActorRefCore, createActor, makeSystem, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
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
@@ -17,7 +17,7 @@ import { Cause, Context, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, O
17
17
  /**
18
18
  * ActorSystem service tag
19
19
  */
20
- const ActorSystem = Context.Service("@effect/machine/ActorSystem");
20
+ var ActorSystem = class extends Context.Service()("effect-machine/actor/ActorSystem") {};
21
21
  /**
22
22
  * Explicit scope for actor lifecycle management.
23
23
  *
@@ -27,7 +27,7 @@ const ActorSystem = Context.Service("@effect/machine/ActorSystem");
27
27
  *
28
28
  * Provide via `Machine.scoped` or `Effect.provideService(ActorScope, scope)`.
29
29
  */
30
- const ActorScope = Context.Service("@effect/machine/ActorScope");
30
+ var ActorScope = class extends Context.Service()("effect-machine/actor/ActorScope") {};
31
31
  /**
32
32
  * Notify all listeners of state change.
33
33
  */
@@ -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 };
@@ -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: Context.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 };
@@ -13,6 +13,6 @@ import { Context } from "effect";
13
13
  * @module
14
14
  */
15
15
  /** Service tag for PersistenceAdapter — resolve from context for shared infra. */
16
- const PersistenceAdapter = Context.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/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, ActorScope, 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, ActorScope, 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 };
@@ -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: Context.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 };
@@ -4,7 +4,7 @@ import { Context, Effect, Option } from "effect";
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 = Context.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>;
@@ -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;
@@ -1,6 +1,6 @@
1
- import { MachineContext, SlotsDef } from "../slot.js";
1
+ import { MachineContextTag, SlotsDef } from "../slot.js";
2
2
  import { Machine, MachineRef, SpawnEffect, Transition } from "../machine.js";
3
- import { ActorSystem } from "../actor.js";
3
+ import { ActorSystemService } from "../actor.js";
4
4
  import { Cause, Effect, Scope } from "effect";
5
5
 
6
6
  //#region src/internal/transition.d.ts
@@ -29,12 +29,12 @@ declare const runTransitionHandler: <S extends {
29
29
  readonly _tag: string;
30
30
  }, E extends {
31
31
  readonly _tag: string;
32
- }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, transition: Transition<S, E, SD, R>, state: S, event: E, self: MachineRef<E>, system: ActorSystem, actorId: string) => Effect.Effect<{
32
+ }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, transition: Transition<S, E, SD, R>, state: S, event: E, self: MachineRef<E>, system: ActorSystemService, actorId: string) => Effect.Effect<{
33
33
  newState: S;
34
34
  hasReply: boolean;
35
35
  deferReply: boolean;
36
36
  reply: unknown;
37
- }, never, Exclude<R, MachineContext<S, E, MachineRef<E>>>>;
37
+ }, never, Exclude<R, MachineContextTag>>;
38
38
  /**
39
39
  * Execute a transition for a given state and event.
40
40
  * Handles transition resolution, handler invocation, and guard/effect slot creation.
@@ -50,14 +50,14 @@ declare const executeTransition: <S extends {
50
50
  readonly _tag: string;
51
51
  }, E extends {
52
52
  readonly _tag: string;
53
- }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, currentState: S, event: E, self: MachineRef<E>, system: ActorSystem, actorId: string) => Effect.Effect<{
53
+ }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, currentState: S, event: E, self: MachineRef<E>, system: ActorSystemService, actorId: string) => Effect.Effect<{
54
54
  newState: S;
55
55
  transitioned: boolean;
56
56
  reenter: boolean;
57
57
  hasReply: boolean;
58
58
  deferReply: boolean;
59
59
  reply: unknown;
60
- }, never, Exclude<R, MachineContext<S, E, MachineRef<E>>>>;
60
+ }, never, Exclude<R, MachineContextTag>>;
61
61
  /**
62
62
  * Optional hooks for event processing inspection/tracing.
63
63
  */
@@ -130,7 +130,7 @@ declare const processEventCore: <S extends {
130
130
  readonly _tag: string;
131
131
  }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, currentState: S, event: E, self: MachineRef<E>, stateScopeRef: {
132
132
  current: Scope.Closeable;
133
- }, system: ActorSystem, actorId: string, hooks?: ProcessEventHooks<S, E> | undefined) => Effect.Effect<{
133
+ }, system: ActorSystemService, actorId: string, hooks?: ProcessEventHooks<S, E> | undefined) => Effect.Effect<{
134
134
  newState: S;
135
135
  previousState: S;
136
136
  transitioned: boolean;
@@ -140,7 +140,7 @@ declare const processEventCore: <S extends {
140
140
  deferReply: boolean;
141
141
  reply: unknown;
142
142
  postponed: boolean;
143
- }, never, Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
143
+ }, never, Exclude<R, MachineContextTag> | Exclude<Exclude<R, MachineContextTag>, Scope.Scope>>;
144
144
  /**
145
145
  * Run spawn effects for a state (forked into state scope, auto-cancelled on state exit).
146
146
  *
@@ -150,7 +150,7 @@ declare const runSpawnEffects: <S extends {
150
150
  readonly _tag: string;
151
151
  }, E extends {
152
152
  readonly _tag: string;
153
- }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, state: S, event: E, self: MachineRef<E>, stateScope: Scope.Closeable, system: ActorSystem, actorId: string, onError?: ((info: ProcessEventError<S, E>) => Effect.Effect<void>) | undefined, onSpawnDefect?: ((cause: Cause.Cause<unknown>) => Effect.Effect<void>) | undefined) => Effect.Effect<void, never, Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
153
+ }, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, state: S, event: E, self: MachineRef<E>, stateScope: Scope.Closeable, system: ActorSystemService, actorId: string, onError?: ((info: ProcessEventError<S, E>) => Effect.Effect<void>) | undefined, onSpawnDefect?: ((cause: Cause.Cause<unknown>) => Effect.Effect<void>) | undefined) => Effect.Effect<void, never, Exclude<Exclude<R, MachineContextTag>, Scope.Scope>>;
154
154
  /**
155
155
  * Resolve which transition should fire for a given state and event.
156
156
  * Uses indexed O(1) lookup. First matching transition wins.
@@ -1,4 +1,4 @@
1
- import { ActorSystem } from "../actor.js";
1
+ import { ActorSystemService } from "../actor.js";
2
2
  import { Effect } from "effect";
3
3
 
4
4
  //#region src/internal/utils.d.ts
@@ -91,11 +91,11 @@ declare const getTag: (constructorOrValue: {
91
91
  /** Check if a value is an Effect */
92
92
  declare const isEffect: (value: unknown) => value is Effect.Effect<unknown, unknown, unknown>;
93
93
  /**
94
- * Stub ActorSystem that dies on any method call.
94
+ * Stub ActorSystemService that dies on any method call.
95
95
  * Used in contexts where spawning/system access isn't supported
96
96
  * (testing simulation, persistent actor replay).
97
97
  * @internal
98
98
  */
99
- declare const stubSystem: ActorSystem;
99
+ declare const stubSystem: ActorSystemService;
100
100
  //#endregion
101
101
  export { ArgsOf, DeferReplyResult, DeferReplySymbol, INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, InstanceOf, ReplyResult, ReplyResultSymbol, TagOf, TaggedConstructor, TransitionResult, getTag, isDeferReplyResult, isEffect, isReplyResult, makeDeferReply, makeReply, stubSystem };
@@ -56,7 +56,7 @@ const getTag = (constructorOrValue) => {
56
56
  /** Check if a value is an Effect */
57
57
  const isEffect = Effect.isEffect;
58
58
  /**
59
- * Stub ActorSystem that dies on any method call.
59
+ * Stub ActorSystemService that dies on any method call.
60
60
  * Used in contexts where spawning/system access isn't supported
61
61
  * (testing simulation, persistent actor replay).
62
62
  * @internal
package/dist/machine.d.ts CHANGED
@@ -2,10 +2,10 @@ import { DeferReplyResult, ReplyResult, TransitionResult } from "./internal/util
2
2
  import { BrandedEvent, BrandedState, ExtractReply, TaggedOrConstructor } from "./internal/brands.js";
3
3
  import { MachineEventSchema, MachineStateSchema, VariantsUnion } from "./schema.js";
4
4
  import { DuplicateActorError } from "./errors.js";
5
- import { MachineContext, ProvideSlots, SlotCalls, SlotsDef, SlotsSchema } from "./slot.js";
5
+ import { MachineContext, MachineContextTag, ProvideSlots, SlotCalls, SlotsDef, SlotsSchema } from "./slot.js";
6
6
  import { Supervision } from "./supervision.js";
7
7
  import { findTransitions } from "./internal/transition.js";
8
- import { ActorRef, ActorSystem } from "./actor.js";
8
+ import { ActorRef, ActorSystemService } from "./actor.js";
9
9
  import { Cause, Context, Duration, Effect, Option, Schema, Scope } from "effect";
10
10
 
11
11
  //#region src/machine.d.ts
@@ -48,7 +48,7 @@ interface StateHandlerContext<State, Event, SD extends SlotsDef = Record<string,
48
48
  readonly event: Event;
49
49
  readonly self: MachineRef<Event>;
50
50
  readonly slots: SlotCalls<SD>;
51
- readonly system: ActorSystem;
51
+ readonly system: ActorSystemService;
52
52
  }
53
53
  /**
54
54
  * Transition handler function.
@@ -196,7 +196,7 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
196
196
  * Context tag for accessing machine state/event/self in slot handlers.
197
197
  * Uses shared module-level tag for all machines.
198
198
  */
199
- readonly Context: Context.Service<MachineContext<State, Event, MachineRef<Event>>, MachineContext<State, Event, MachineRef<Event>>>;
199
+ readonly Context: Context.Service<MachineContextTag, MachineContext<State, Event, MachineRef<Event>>>;
200
200
  get transitions(): ReadonlyArray<Transition<State, Event, SD, R>>;
201
201
  get spawnEffects(): ReadonlyArray<SpawnEffect<State, Event, SD, R>>;
202
202
  get backgroundEffects(): ReadonlyArray<BackgroundEffect<State, Event, SD, R>>;
package/dist/machine.js CHANGED
@@ -76,6 +76,24 @@ const materializeMachine = (machine, handlers) => {
76
76
  * - `SD`: Slot definitions
77
77
  */
78
78
  var Machine = class Machine {
79
+ initial;
80
+ /** @internal */ _transitions;
81
+ /** @internal */ _spawnEffects;
82
+ /** @internal */ _backgroundEffects;
83
+ /** @internal */ _finalStates;
84
+ /** @internal */ _postponeRules;
85
+ /** @internal */ _slotsSchema;
86
+ /** @internal */ _slotHandlers;
87
+ /** @internal */ _slots;
88
+ /** @internal */ _slotValidation;
89
+ stateSchema;
90
+ eventSchema;
91
+ /** @internal */ _replySchemas;
92
+ /**
93
+ * Context tag for accessing machine state/event/self in slot handlers.
94
+ * Uses shared module-level tag for all machines.
95
+ */
96
+ Context = MachineContextTag;
79
97
  get transitions() {
80
98
  return this._transitions;
81
99
  }
@@ -99,7 +117,6 @@ var Machine = class Machine {
99
117
  }
100
118
  /** @internal */
101
119
  constructor(initial, stateSchema, eventSchema, slotsSchema, slotValidation = true) {
102
- this.Context = MachineContextTag;
103
120
  this.initial = initial;
104
121
  this._transitions = [];
105
122
  this._spawnEffects = [];
@@ -161,7 +178,8 @@ var Machine = class Machine {
161
178
  this._slots = this._slotsSchema !== void 0 ? this._slotsSchema._createSlots(resolve) : {};
162
179
  }
163
180
  from(stateOrStates, build) {
164
- build(new TransitionScope(this, Array.isArray(stateOrStates) ? stateOrStates : [stateOrStates]));
181
+ const states = Array.isArray(stateOrStates) ? stateOrStates : [stateOrStates];
182
+ build(new TransitionScope(this, states));
165
183
  return this;
166
184
  }
167
185
  /** @internal */