effect-machine 0.7.2 → 0.9.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 (51) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +6 -11
  2. package/dist/actor.d.ts +23 -3
  3. package/dist/actor.js +46 -15
  4. package/dist/cluster/entity-machine.d.ts +0 -1
  5. package/dist/cluster/entity-machine.js +3 -5
  6. package/dist/cluster/index.js +1 -2
  7. package/dist/cluster/to-entity.js +1 -3
  8. package/dist/errors.js +1 -3
  9. package/dist/index.d.ts +4 -4
  10. package/dist/index.js +2 -3
  11. package/dist/inspection.d.ts +31 -5
  12. package/dist/inspection.js +97 -5
  13. package/dist/internal/inspection.js +8 -7
  14. package/dist/internal/transition.d.ts +4 -4
  15. package/dist/internal/transition.js +11 -10
  16. package/dist/internal/utils.js +1 -3
  17. package/dist/machine.d.ts +20 -7
  18. package/dist/machine.js +64 -32
  19. package/dist/persistence/adapter.js +1 -3
  20. package/dist/persistence/adapters/in-memory.js +1 -3
  21. package/dist/persistence/index.js +1 -2
  22. package/dist/persistence/persistent-actor.js +11 -10
  23. package/dist/persistence/persistent-machine.js +1 -3
  24. package/dist/schema.js +6 -4
  25. package/dist/slot.d.ts +1 -0
  26. package/dist/slot.js +1 -3
  27. package/dist/testing.js +3 -5
  28. package/dist-v3/_virtual/_rolldown/runtime.js +6 -11
  29. package/dist-v3/actor.js +1 -3
  30. package/dist-v3/cluster/entity-machine.d.ts +0 -1
  31. package/dist-v3/cluster/entity-machine.js +1 -3
  32. package/dist-v3/cluster/index.js +1 -2
  33. package/dist-v3/cluster/to-entity.js +1 -3
  34. package/dist-v3/errors.js +1 -3
  35. package/dist-v3/index.d.ts +0 -1
  36. package/dist-v3/index.js +1 -2
  37. package/dist-v3/inspection.js +1 -3
  38. package/dist-v3/internal/inspection.js +1 -3
  39. package/dist-v3/internal/transition.js +1 -3
  40. package/dist-v3/internal/utils.js +1 -3
  41. package/dist-v3/machine.d.ts +0 -1
  42. package/dist-v3/machine.js +2 -31
  43. package/dist-v3/persistence/adapter.js +1 -3
  44. package/dist-v3/persistence/adapters/in-memory.js +1 -3
  45. package/dist-v3/persistence/index.js +1 -2
  46. package/dist-v3/persistence/persistent-actor.js +1 -3
  47. package/dist-v3/persistence/persistent-machine.js +1 -3
  48. package/dist-v3/schema.js +1 -3
  49. package/dist-v3/slot.js +1 -3
  50. package/dist-v3/testing.js +1 -3
  51. package/package.json +13 -13
@@ -1,7 +1,6 @@
1
1
  import { INTERNAL_ENTER_EVENT, isEffect } from "./utils.js";
2
2
  import { BuiltMachine } from "../machine.js";
3
3
  import { Cause, Effect, Exit, Scope } from "effect";
4
-
5
4
  //#region src/internal/transition.ts
6
5
  /**
7
6
  * Transition execution and indexing.
@@ -23,8 +22,9 @@ import { Cause, Effect, Exit, Scope } from "effect";
23
22
  *
24
23
  * @internal
25
24
  */
26
- const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(function* (machine, transition, state, event, self, system) {
25
+ const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(function* (machine, transition, state, event, self, system, actorId) {
27
26
  const ctx = {
27
+ actorId,
28
28
  state,
29
29
  event,
30
30
  self,
@@ -51,7 +51,7 @@ const runTransitionHandler = Effect.fn("effect-machine.runTransitionHandler")(fu
51
51
  *
52
52
  * @internal
53
53
  */
54
- const executeTransition = Effect.fn("effect-machine.executeTransition")(function* (machine, currentState, event, self, system) {
54
+ const executeTransition = Effect.fn("effect-machine.executeTransition")(function* (machine, currentState, event, self, system, actorId) {
55
55
  const transition = resolveTransition(machine, currentState, event);
56
56
  if (transition === void 0) return {
57
57
  newState: currentState,
@@ -59,7 +59,7 @@ const executeTransition = Effect.fn("effect-machine.executeTransition")(function
59
59
  reenter: false
60
60
  };
61
61
  return {
62
- newState: yield* runTransitionHandler(machine, transition, currentState, event, self, system),
62
+ newState: yield* runTransitionHandler(machine, transition, currentState, event, self, system, actorId),
63
63
  transitioned: true,
64
64
  reenter: transition.reenter === true
65
65
  };
@@ -76,8 +76,8 @@ const executeTransition = Effect.fn("effect-machine.executeTransition")(function
76
76
  *
77
77
  * @internal
78
78
  */
79
- const processEventCore = Effect.fn("effect-machine.processEventCore")(function* (machine, currentState, event, self, stateScopeRef, system, hooks) {
80
- const result = yield* executeTransition(machine, currentState, event, self, system).pipe(Effect.catchCause((cause) => {
79
+ const processEventCore = Effect.fn("effect-machine.processEventCore")(function* (machine, currentState, event, self, stateScopeRef, system, actorId, hooks) {
80
+ const result = yield* executeTransition(machine, currentState, event, self, system, actorId).pipe(Effect.catchCause((cause) => {
81
81
  if (Cause.hasInterruptsOnly(cause)) return Effect.interrupt;
82
82
  const onError = hooks?.onError;
83
83
  if (onError === void 0) return Effect.failCause(cause).pipe(Effect.orDie);
@@ -102,7 +102,7 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
102
102
  stateScopeRef.current = yield* Scope.make();
103
103
  if (hooks?.onTransition !== void 0) yield* hooks.onTransition(currentState, newState, event);
104
104
  if (hooks?.onSpawnEffect !== void 0) yield* hooks.onSpawnEffect(newState);
105
- yield* runSpawnEffects(machine, newState, { _tag: INTERNAL_ENTER_EVENT }, self, stateScopeRef.current, system, hooks?.onError);
105
+ yield* runSpawnEffects(machine, newState, { _tag: INTERNAL_ENTER_EVENT }, self, stateScopeRef.current, system, actorId, hooks?.onError);
106
106
  }
107
107
  return {
108
108
  newState,
@@ -117,9 +117,10 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
117
117
  *
118
118
  * @internal
119
119
  */
120
- const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (machine, state, event, self, stateScope, system, onError) {
120
+ const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (machine, state, event, self, stateScope, system, actorId, onError) {
121
121
  const spawnEffects = findSpawnEffects(machine, state._tag);
122
122
  const ctx = {
123
+ actorId,
123
124
  state,
124
125
  event,
125
126
  self,
@@ -129,6 +130,7 @@ const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (m
129
130
  const reportError = onError;
130
131
  for (const spawnEffect of spawnEffects) {
131
132
  const effect = spawnEffect.handler({
133
+ actorId,
132
134
  state,
133
135
  event,
134
136
  self,
@@ -233,6 +235,5 @@ const findTransitions = (input, stateTag, eventTag) => {
233
235
  const findSpawnEffects = (machine, stateTag) => {
234
236
  return getIndex(machine).spawn.get(stateTag) ?? [];
235
237
  };
236
-
237
238
  //#endregion
238
- export { executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler };
239
+ export { executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler };
@@ -1,5 +1,4 @@
1
1
  import { Effect, Stream } from "effect";
2
-
3
2
  //#region src/internal/utils.ts
4
3
  /**
5
4
  * Internal utilities for effect-machine.
@@ -50,6 +49,5 @@ const stubSystem = {
50
49
  restoreMany: () => Effect.die("restoreMany not supported in stub system"),
51
50
  restoreAll: () => Effect.die("restoreAll not supported in stub system")
52
51
  };
53
-
54
52
  //#endregion
55
- export { INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, getTag, isEffect, stubSystem };
53
+ export { INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, getTag, isEffect, stubSystem };
package/dist/machine.d.ts CHANGED
@@ -5,13 +5,12 @@ import { MachineEventSchema, MachineStateSchema, VariantsUnion } from "./schema.
5
5
  import { PersistenceConfig, PersistentMachine } from "./persistence/persistent-machine.js";
6
6
  import { DuplicateActorError } from "./errors.js";
7
7
  import { findTransitions } from "./internal/transition.js";
8
- import "./persistence/index.js";
9
8
  import { ActorRef, ActorSystem } from "./actor.js";
10
9
  import { Cause, Effect, Schedule, Schema, Scope, ServiceMap } from "effect";
11
10
 
12
11
  //#region src/machine.d.ts
13
12
  declare namespace machine_d_exports {
14
- export { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, PersistenceConfig, PersistentMachine, ProvideHandlers, SlotContext, SpawnEffect, StateEffectHandler, StateHandlerContext, Transition, TransitionHandler, findTransitions, make, spawn };
13
+ export { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, PersistenceConfig, PersistentMachine, ProvideHandlers, SlotContext, SpawnEffect, StateEffectHandler, StateHandlerContext, TaskOptions, Transition, TransitionHandler, findTransitions, make, spawn };
15
14
  }
16
15
  /**
17
16
  * Self reference for sending events back to the machine
@@ -37,6 +36,7 @@ interface HandlerContext<State, Event, GD extends GuardsDef, ED extends EffectsD
37
36
  * Handler context passed to state effect handlers (onEnter, spawn, background)
38
37
  */
39
38
  interface StateHandlerContext<State, Event, ED extends EffectsDef> {
39
+ readonly actorId: string;
40
40
  readonly state: State;
41
41
  readonly event: Event;
42
42
  readonly self: MachineRef<Event>;
@@ -81,6 +81,11 @@ interface PersistOptions {
81
81
  readonly journalEvents: boolean;
82
82
  readonly machineType?: string;
83
83
  }
84
+ interface TaskOptions<State, Event, ED extends EffectsDef, A, E1, ES, EF> {
85
+ readonly onSuccess: (value: A, ctx: StateHandlerContext<State, Event, ED>) => ES;
86
+ readonly onFailure?: (cause: Cause.Cause<E1>, ctx: StateHandlerContext<State, Event, ED>) => EF;
87
+ readonly name?: string;
88
+ }
84
89
  type IsAny<T> = 0 extends 1 & T ? true : false;
85
90
  type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false;
86
91
  type NormalizeR<T> = IsAny<T> extends true ? T : IsUnknown<T> extends true ? never : T;
@@ -174,6 +179,10 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
174
179
  get effectsSchema(): EffectsSchema<EFD> | undefined;
175
180
  /** @internal */
176
181
  constructor(initial: State, stateSchema?: Schema.Schema<State>, eventSchema?: Schema.Schema<Event>, guardsSchema?: GuardsSchema<GD>, effectsSchema?: EffectsSchema<EFD>);
182
+ from<NS extends VariantsUnion<_SD> & BrandedState, R1>(state: TaggedOrConstructor<NS>, build: (scope: TransitionScope<State, Event, R, _SD, _ED, GD, EFD, NS>) => R1): Machine<State, Event, R, _SD, _ED, GD, EFD>;
183
+ from<NS extends ReadonlyArray<TaggedOrConstructor<VariantsUnion<_SD> & BrandedState>>, R1>(states: NS, build: (scope: TransitionScope<State, Event, R, _SD, _ED, GD, EFD, NS[number] extends TaggedOrConstructor<infer S extends VariantsUnion<_SD> & BrandedState> ? S : never>) => R1): Machine<State, Event, R, _SD, _ED, GD, EFD>;
184
+ /** @internal */
185
+ scopeTransition<NS extends VariantsUnion<_SD> & BrandedState, NE extends VariantsUnion<_ED> & BrandedEvent, RS extends VariantsUnion<_SD> & BrandedState>(states: ReadonlyArray<TaggedOrConstructor<NS>>, event: TaggedOrConstructor<NE>, handler: TransitionHandler<NS, NE, RS, GD, EFD, never>, reenter: boolean): Machine<State, Event, R, _SD, _ED, GD, EFD>;
177
186
  /** Register transition for a single state */
178
187
  on<NS extends VariantsUnion<_SD> & BrandedState, NE extends VariantsUnion<_ED> & BrandedEvent, RS extends VariantsUnion<_SD> & BrandedState>(state: TaggedOrConstructor<NS>, event: TaggedOrConstructor<NE>, handler: TransitionHandler<NS, NE, RS, GD, EFD, never>): Machine<State, Event, R, _SD, _ED, GD, EFD>;
179
188
  /** Register transition for multiple states (handler receives union of state types) */
@@ -220,10 +229,7 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
220
229
  * State-scoped task that runs on entry and sends success/failure events.
221
230
  * Interrupts do not emit failure events.
222
231
  */
223
- task<NS extends VariantsUnion<_SD> & BrandedState, A, E1, ES extends VariantsUnion<_ED> & BrandedEvent, EF extends VariantsUnion<_ED> & BrandedEvent>(state: TaggedOrConstructor<NS>, run: (ctx: StateHandlerContext<NS, VariantsUnion<_ED> & BrandedEvent, EFD>) => Effect.Effect<A, E1, Scope.Scope>, options: {
224
- readonly onSuccess: (value: A, ctx: StateHandlerContext<NS, VariantsUnion<_ED> & BrandedEvent, EFD>) => ES;
225
- readonly onFailure?: (cause: Cause.Cause<E1>, ctx: StateHandlerContext<NS, VariantsUnion<_ED> & BrandedEvent, EFD>) => EF;
226
- }): Machine<State, Event, R, _SD, _ED, GD, EFD>;
232
+ task<NS extends VariantsUnion<_SD> & BrandedState, A, E1, ES extends VariantsUnion<_ED> & BrandedEvent, EF extends VariantsUnion<_ED> & BrandedEvent>(state: TaggedOrConstructor<NS>, run: (ctx: StateHandlerContext<NS, VariantsUnion<_ED> & BrandedEvent, EFD>) => Effect.Effect<A, E1, Scope.Scope>, options: TaskOptions<NS, VariantsUnion<_ED> & BrandedEvent, EFD, A, E1, ES, EF>): Machine<State, Event, R, _SD, _ED, GD, EFD>;
227
233
  /**
228
234
  * Machine-lifetime effect that is forked on actor spawn and runs until the actor stops.
229
235
  * Use effect slots defined via `Slot.Effects` for the actual work.
@@ -261,6 +267,13 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
261
267
  }, R>;
262
268
  static make<SD extends Record<string, Schema.Struct.Fields>, ED extends Record<string, Schema.Struct.Fields>, S extends BrandedState, E extends BrandedEvent, GD extends GuardsDef = Record<string, never>, EFD extends EffectsDef = Record<string, never>>(config: MakeConfig<SD, ED, S, E, GD, EFD>): Machine<S, E, never, SD, ED, GD, EFD>;
263
269
  }
270
+ declare class TransitionScope<State, Event, R, _SD extends Record<string, Schema.Struct.Fields>, _ED extends Record<string, Schema.Struct.Fields>, GD extends GuardsDef, EFD extends EffectsDef, SelectedState extends VariantsUnion<_SD> & BrandedState> {
271
+ private readonly machine;
272
+ private readonly states;
273
+ constructor(machine: Machine<State, Event, R, _SD, _ED, GD, EFD>, states: ReadonlyArray<TaggedOrConstructor<SelectedState>>);
274
+ on<NE extends VariantsUnion<_ED> & BrandedEvent, RS extends VariantsUnion<_SD> & BrandedState>(event: TaggedOrConstructor<NE>, handler: TransitionHandler<SelectedState, NE, RS, GD, EFD, never>): TransitionScope<State, Event, R, _SD, _ED, GD, EFD, SelectedState>;
275
+ reenter<NE extends VariantsUnion<_ED> & BrandedEvent, RS extends VariantsUnion<_SD> & BrandedState>(event: TaggedOrConstructor<NE>, handler: TransitionHandler<SelectedState, NE, RS, GD, EFD, never>): TransitionScope<State, Event, R, _SD, _ED, GD, EFD, SelectedState>;
276
+ }
264
277
  declare const make: typeof Machine.make;
265
278
  declare const spawn: {
266
279
  <S extends {
@@ -275,4 +288,4 @@ declare const spawn: {
275
288
  }, R>(machine: BuiltMachine<S, E, R>, id: string): Effect.Effect<ActorRef<S, E>, never, R>;
276
289
  };
277
290
  //#endregion
278
- export { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, type PersistenceConfig, type PersistentMachine, ProvideHandlers, SlotContext, SpawnEffect, StateEffectHandler, StateHandlerContext, Transition, TransitionHandler, findTransitions, machine_d_exports, make, spawn };
291
+ export { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, type PersistenceConfig, type PersistentMachine, ProvideHandlers, SlotContext, SpawnEffect, StateEffectHandler, StateHandlerContext, TaskOptions, Transition, TransitionHandler, findTransitions, machine_d_exports, make, spawn };
package/dist/machine.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ import { Inspector } from "./inspection.js";
2
3
  import { getTag } from "./internal/utils.js";
3
4
  import { ProvisionValidationError, SlotProvisionError } from "./errors.js";
4
5
  import { persist } from "./persistence/persistent-machine.js";
6
+ import { emitWithTimestamp } from "./internal/inspection.js";
5
7
  import { MachineContextTag } from "./slot.js";
6
8
  import { findTransitions, invalidateIndex } from "./internal/transition.js";
7
9
  import { createActor } from "./actor.js";
8
10
  import { Cause, Effect, Exit, Option, Scope } from "effect";
9
-
10
11
  //#region src/machine.ts
11
12
  var machine_exports = /* @__PURE__ */ __exportAll({
12
13
  BuiltMachine: () => BuiltMachine,
@@ -15,6 +16,15 @@ var machine_exports = /* @__PURE__ */ __exportAll({
15
16
  make: () => make,
16
17
  spawn: () => spawn
17
18
  });
19
+ const emitTaskInspection = (input) => Effect.flatMap(Effect.serviceOption(Inspector), (inspector) => Option.isNone(inspector) ? Effect.void : emitWithTimestamp(inspector.value, (timestamp) => ({
20
+ type: "@machine.task",
21
+ actorId: input.actorId,
22
+ state: input.state,
23
+ taskName: input.taskName,
24
+ phase: input.phase,
25
+ error: input.error,
26
+ timestamp
27
+ })));
18
28
  /**
19
29
  * A finalized machine ready for spawning.
20
30
  *
@@ -121,6 +131,15 @@ var Machine = class Machine {
121
131
  })) : {}
122
132
  };
123
133
  }
134
+ from(stateOrStates, build) {
135
+ build(new TransitionScope(this, Array.isArray(stateOrStates) ? stateOrStates : [stateOrStates]));
136
+ return this;
137
+ }
138
+ /** @internal */
139
+ scopeTransition(states, event, handler, reenter) {
140
+ for (const state of states) this.addTransition(state, event, handler, reenter);
141
+ return this;
142
+ }
124
143
  on(stateOrStates, event, handler) {
125
144
  const states = Array.isArray(stateOrStates) ? stateOrStates : [stateOrStates];
126
145
  for (const s of states) this.addTransition(s, event, handler, false);
@@ -195,14 +214,41 @@ var Machine = class Machine {
195
214
  */
196
215
  task(state, run, options) {
197
216
  const handler = Effect.fn("effect-machine.task")(function* (ctx) {
217
+ yield* emitTaskInspection({
218
+ actorId: ctx.actorId,
219
+ state: ctx.state,
220
+ taskName: options.name,
221
+ phase: "start"
222
+ });
198
223
  const exit = yield* Effect.exit(run(ctx));
199
224
  if (Exit.isSuccess(exit)) {
225
+ yield* emitTaskInspection({
226
+ actorId: ctx.actorId,
227
+ state: ctx.state,
228
+ taskName: options.name,
229
+ phase: "success"
230
+ });
200
231
  yield* ctx.self.send(options.onSuccess(exit.value, ctx));
201
232
  yield* Effect.yieldNow;
202
233
  return;
203
234
  }
204
235
  const cause = exit.cause;
205
- if (Cause.hasInterruptsOnly(cause)) return;
236
+ if (Cause.hasInterruptsOnly(cause)) {
237
+ yield* emitTaskInspection({
238
+ actorId: ctx.actorId,
239
+ state: ctx.state,
240
+ taskName: options.name,
241
+ phase: "interrupt"
242
+ });
243
+ return;
244
+ }
245
+ yield* emitTaskInspection({
246
+ actorId: ctx.actorId,
247
+ state: ctx.state,
248
+ taskName: options.name,
249
+ phase: "failure",
250
+ error: Cause.pretty(cause)
251
+ });
206
252
  if (options.onFailure !== void 0) {
207
253
  yield* ctx.self.send(options.onFailure(cause, ctx));
208
254
  yield* Effect.yieldNow;
@@ -282,40 +328,26 @@ var Machine = class Machine {
282
328
  return new Machine(config.initial, config.state, config.event, config.guards, config.effects);
283
329
  }
284
330
  };
331
+ var TransitionScope = class {
332
+ constructor(machine, states) {
333
+ this.machine = machine;
334
+ this.states = states;
335
+ }
336
+ on(event, handler) {
337
+ this.machine.scopeTransition(this.states, event, handler, false);
338
+ return this;
339
+ }
340
+ reenter(event, handler) {
341
+ this.machine.scopeTransition(this.states, event, handler, true);
342
+ return this;
343
+ }
344
+ };
285
345
  const make = Machine.make;
286
- /**
287
- * Spawn an actor directly without ActorSystem ceremony.
288
- * Accepts only `BuiltMachine` (call `.build()` first).
289
- *
290
- * **Single actor, no registry.** Caller manages lifetime via `actor.stop`.
291
- * If a `Scope` exists in context, cleanup attaches automatically on scope close.
292
- *
293
- * For registry, lookup by ID, persistence, or multi-actor coordination,
294
- * use `ActorSystemService` / `system.spawn` instead.
295
- *
296
- * @example
297
- * ```ts
298
- * // Fire-and-forget — caller manages lifetime
299
- * const actor = yield* Machine.spawn(machine.build());
300
- * yield* actor.send(Event.Start);
301
- * yield* actor.awaitFinal;
302
- * yield* actor.stop;
303
- *
304
- * // Scope-aware — auto-cleans up on scope close
305
- * yield* Effect.scoped(Effect.gen(function* () {
306
- * const actor = yield* Machine.spawn(machine.build());
307
- * yield* actor.send(Event.Start);
308
- * // actor.stop called automatically when scope closes
309
- * }));
310
- * ```
311
- */
312
- const spawnImpl = Effect.fn("effect-machine.spawn")(function* (built, id) {
346
+ const spawn = Effect.fn("effect-machine.spawn")(function* (built, id) {
313
347
  const actor = yield* createActor(id ?? `actor-${Math.random().toString(36).slice(2)}`, built._inner);
314
348
  const maybeScope = yield* Effect.serviceOption(Scope.Scope);
315
349
  if (Option.isSome(maybeScope)) yield* Scope.addFinalizer(maybeScope.value, actor.stop);
316
350
  return actor;
317
351
  });
318
- const spawn = spawnImpl;
319
-
320
352
  //#endregion
321
- export { BuiltMachine, Machine, findTransitions, machine_exports, make, spawn };
353
+ export { BuiltMachine, Machine, findTransitions, machine_exports, make, spawn };
@@ -1,5 +1,4 @@
1
1
  import { Schema, ServiceMap } from "effect";
2
-
3
2
  //#region src/persistence/adapter.ts
4
3
  /**
5
4
  * Error type for persistence operations
@@ -22,6 +21,5 @@ var VersionConflictError = class extends Schema.TaggedErrorClass()("VersionConfl
22
21
  * PersistenceAdapter service tag
23
22
  */
24
23
  var PersistenceAdapterTag = class extends ServiceMap.Service()("effect-machine/src/persistence/adapter/PersistenceAdapterTag") {};
25
-
26
24
  //#endregion
27
- export { PersistenceAdapterTag, PersistenceError, VersionConflictError };
25
+ export { PersistenceAdapterTag, PersistenceError, VersionConflictError };
@@ -1,6 +1,5 @@
1
1
  import { PersistenceAdapterTag, PersistenceError, VersionConflictError } from "../adapter.js";
2
2
  import { Effect, Layer, Option, Ref, Schema } from "effect";
3
-
4
3
  //#region src/persistence/adapters/in-memory.ts
5
4
  /**
6
5
  * Create an in-memory persistence adapter.
@@ -171,6 +170,5 @@ const makeInMemoryPersistenceAdapter = make;
171
170
  * ```
172
171
  */
173
172
  const InMemoryPersistenceAdapter = Layer.effect(PersistenceAdapterTag, make);
174
-
175
173
  //#endregion
176
- export { InMemoryPersistenceAdapter, makeInMemoryPersistenceAdapter };
174
+ export { InMemoryPersistenceAdapter, makeInMemoryPersistenceAdapter };
@@ -2,5 +2,4 @@ import { isPersistentMachine, persist } from "./persistent-machine.js";
2
2
  import { PersistenceAdapterTag, PersistenceError, VersionConflictError } from "./adapter.js";
3
3
  import { createPersistentActor, restorePersistentActor } from "./persistent-actor.js";
4
4
  import { InMemoryPersistenceAdapter, makeInMemoryPersistenceAdapter } from "./adapters/in-memory.js";
5
-
6
- export { InMemoryPersistenceAdapter, PersistenceAdapterTag, PersistenceError, VersionConflictError, createPersistentActor, isPersistentMachine, makeInMemoryPersistenceAdapter, persist, restorePersistentActor };
5
+ export { InMemoryPersistenceAdapter, PersistenceAdapterTag, PersistenceError, VersionConflictError, createPersistentActor, isPersistentMachine, makeInMemoryPersistenceAdapter, persist, restorePersistentActor };
@@ -1,11 +1,10 @@
1
1
  import { Inspector } from "../inspection.js";
2
2
  import { INTERNAL_INIT_EVENT, stubSystem } from "../internal/utils.js";
3
- import { processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler } from "../internal/transition.js";
4
3
  import { emitWithTimestamp } from "../internal/inspection.js";
4
+ import { processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler } from "../internal/transition.js";
5
5
  import { PersistenceAdapterTag } from "./adapter.js";
6
6
  import { ActorSystem, buildActorRefCore, notifyListeners } from "../actor.js";
7
- import { Cause, Clock, Effect, Exit, Fiber, Option, Queue, Ref, Schedule, Scope, SubscriptionRef } from "effect";
8
-
7
+ import { Cause, Clock, Deferred, Effect, Exit, Fiber, Option, Queue, Ref, Schedule, Scope, SubscriptionRef } from "effect";
9
8
  //#region src/persistence/persistent-actor.ts
10
9
  /** Get current time in milliseconds using Effect Clock */
11
10
  const now = Clock.currentTimeMillis;
@@ -20,7 +19,7 @@ const replayEvents = Effect.fn("effect-machine.persistentActor.replayEvents")(fu
20
19
  for (const persistedEvent of events) {
21
20
  if (stopVersion !== void 0 && persistedEvent.version > stopVersion) break;
22
21
  const transition = resolveTransition(machine, state, persistedEvent.event);
23
- if (transition !== void 0) state = yield* runTransitionHandler(machine, transition, state, persistedEvent.event, self, stubSystem);
22
+ if (transition !== void 0) state = yield* runTransitionHandler(machine, transition, state, persistedEvent.event, self, stubSystem, "restore");
24
23
  version = persistedEvent.version;
25
24
  }
26
25
  return {
@@ -96,7 +95,7 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
96
95
  const self = {
97
96
  send: Effect.fn("effect-machine.persistentActor.self.send")(function* (event) {
98
97
  if (yield* Ref.get(stoppedRef)) return;
99
- yield* Queue.offer(eventQueue, event);
98
+ yield* Queue.offer(eventQueue, { event });
100
99
  }),
101
100
  spawn: (childId, childMachine) => Effect.gen(function* () {
102
101
  const child = yield* system.spawn(childId, childMachine).pipe(Effect.provideService(ActorSystem, system));
@@ -146,6 +145,7 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
146
145
  const backgroundFibers = [];
147
146
  const initEvent = { _tag: INTERNAL_INIT_EVENT };
148
147
  const initCtx = {
148
+ actorId: id,
149
149
  state: resolvedInitial,
150
150
  event: initEvent,
151
151
  self,
@@ -154,6 +154,7 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
154
154
  const { effects: effectSlots } = typedMachine._slots;
155
155
  for (const bg of typedMachine.backgroundEffects) {
156
156
  const fiber = yield* Effect.forkDetach(bg.handler({
157
+ actorId: id,
157
158
  state: resolvedInitial,
158
159
  event: initEvent,
159
160
  self,
@@ -228,7 +229,7 @@ const persistentEventLoop = Effect.fn("effect-machine.persistentActor.eventLoop"
228
229
  }))
229
230
  };
230
231
  while (true) {
231
- const event = yield* Queue.take(eventQueue);
232
+ const { event, reply } = yield* Queue.take(eventQueue);
232
233
  const currentState = yield* SubscriptionRef.get(stateRef);
233
234
  const currentVersion = yield* Ref.get(versionRef);
234
235
  yield* emitWithTimestamp(inspector, (timestamp) => ({
@@ -238,7 +239,8 @@ const persistentEventLoop = Effect.fn("effect-machine.persistentActor.eventLoop"
238
239
  event,
239
240
  timestamp
240
241
  }));
241
- const result = yield* processEventCore(typedMachine, currentState, event, self, stateScopeRef, system, hooks);
242
+ const result = yield* processEventCore(typedMachine, currentState, event, self, stateScopeRef, system, id, hooks);
243
+ if (reply !== void 0) yield* Deferred.succeed(reply, result);
242
244
  if (!result.transitioned) continue;
243
245
  const newVersion = currentVersion + 1;
244
246
  yield* Ref.set(versionRef, newVersion);
@@ -286,7 +288,7 @@ const runSpawnEffectsWithInspection = Effect.fn("effect-machine.persistentActor.
286
288
  state,
287
289
  timestamp
288
290
  }));
289
- yield* runSpawnEffects(machine, state, event, self, stateScope, system, inspector === void 0 ? void 0 : (info) => emitWithTimestamp(inspector, (timestamp) => ({
291
+ yield* runSpawnEffects(machine, state, event, self, stateScope, system, actorId, inspector === void 0 ? void 0 : (info) => emitWithTimestamp(inspector, (timestamp) => ({
290
292
  type: "@machine.error",
291
293
  actorId,
292
294
  phase: info.phase,
@@ -362,6 +364,5 @@ const restorePersistentActor = Effect.fn("effect-machine.persistentActor.restore
362
364
  const actor = yield* createPersistentActor(id, persistentMachine, maybeSnapshot, events);
363
365
  return Option.some(actor);
364
366
  });
365
-
366
367
  //#endregion
367
- export { createPersistentActor, restorePersistentActor };
368
+ export { createPersistentActor, restorePersistentActor };
@@ -1,5 +1,4 @@
1
1
  import { MissingSchemaError } from "../errors.js";
2
-
3
2
  //#region src/persistence/persistent-machine.ts
4
3
  /**
5
4
  * Type guard to check if a value is a PersistentMachine
@@ -19,6 +18,5 @@ const persist = (config) => (machine) => {
19
18
  }
20
19
  };
21
20
  };
22
-
23
21
  //#endregion
24
- export { isPersistentMachine, persist };
22
+ export { isPersistentMachine, persist };
package/dist/schema.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { InvalidSchemaError, MissingMatchHandlerError } from "./errors.js";
2
2
  import { Schema } from "effect";
3
-
4
3
  //#region src/schema.ts
5
4
  /**
6
5
  * Schema-first State/Event definitions for effect-machine.
@@ -42,6 +41,7 @@ import { Schema } from "effect";
42
41
  /**
43
42
  * Build a schema-first definition from a record of tag -> fields
44
43
  */
44
+ const RESERVED_DERIVE_KEYS = new Set(["_tag"]);
45
45
  const buildMachineSchema = (definition) => {
46
46
  const variants = {};
47
47
  const constructors = {};
@@ -59,7 +59,10 @@ const buildMachineSchema = (definition) => {
59
59
  constructor.derive = (source, partial) => {
60
60
  const result = { _tag: tag };
61
61
  for (const key of fieldNames) if (key in source) result[key] = source[key];
62
- if (partial !== void 0) for (const [key, value] of Object.entries(partial)) result[key] = value;
62
+ if (partial !== void 0) for (const [key, value] of Object.entries(partial)) {
63
+ if (RESERVED_DERIVE_KEYS.has(key)) continue;
64
+ result[key] = value;
65
+ }
63
66
  return result;
64
67
  };
65
68
  constructors[tag] = constructor;
@@ -160,6 +163,5 @@ const State = (definition) => createMachineSchema(definition);
160
163
  * ```
161
164
  */
162
165
  const Event = (definition) => createMachineSchema(definition);
163
-
164
166
  //#endregion
165
- export { Event, State };
167
+ export { Event, State };
package/dist/slot.d.ts CHANGED
@@ -43,6 +43,7 @@ type EffectSlots<D extends EffectsDef> = { readonly [K in keyof D & string]: Eff
43
43
  * Shared across all machines via MachineContextTag.
44
44
  */
45
45
  interface MachineContext<State, Event, Self> {
46
+ readonly actorId: string;
46
47
  readonly state: State;
47
48
  readonly event: Event;
48
49
  readonly self: Self;
package/dist/slot.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { ServiceMap } from "effect";
2
-
3
2
  //#region src/slot.ts
4
3
  /**
5
4
  * Slot module - schema-based, parameterized guards and effects.
@@ -94,6 +93,5 @@ const Slot = {
94
93
  Guards,
95
94
  Effects
96
95
  };
97
-
98
96
  //#endregion
99
- export { Effects, Guards, MachineContextTag, Slot };
97
+ export { Effects, Guards, MachineContextTag, Slot };
package/dist/testing.js CHANGED
@@ -3,7 +3,6 @@ import { AssertionError } from "./errors.js";
3
3
  import { BuiltMachine } from "./machine.js";
4
4
  import { executeTransition } from "./internal/transition.js";
5
5
  import { Effect, SubscriptionRef } from "effect";
6
-
7
6
  //#region src/testing.ts
8
7
  /**
9
8
  * Simulate a sequence of events through a machine without running an actor.
@@ -34,7 +33,7 @@ const simulate = Effect.fn("effect-machine.simulate")(function* (input, events)
34
33
  let currentState = machine.initial;
35
34
  const states = [currentState];
36
35
  for (const event of events) {
37
- const result = yield* executeTransition(machine, currentState, event, dummySelf, stubSystem);
36
+ const result = yield* executeTransition(machine, currentState, event, dummySelf, stubSystem, "simulation");
38
37
  if (!result.transitioned) continue;
39
38
  currentState = result.newState;
40
39
  states.push(currentState);
@@ -123,7 +122,7 @@ const createTestHarness = Effect.fn("effect-machine.createTestHarness")(function
123
122
  state: stateRef,
124
123
  send: Effect.fn("effect-machine.testHarness.send")(function* (event) {
125
124
  const currentState = yield* SubscriptionRef.get(stateRef);
126
- const result = yield* executeTransition(machine, currentState, event, dummySelf, stubSystem);
125
+ const result = yield* executeTransition(machine, currentState, event, dummySelf, stubSystem, "test-harness");
127
126
  if (!result.transitioned) return currentState;
128
127
  const newState = result.newState;
129
128
  yield* SubscriptionRef.set(stateRef, newState);
@@ -133,6 +132,5 @@ const createTestHarness = Effect.fn("effect-machine.createTestHarness")(function
133
132
  getState: SubscriptionRef.get(stateRef)
134
133
  };
135
134
  });
136
-
137
135
  //#endregion
138
- export { AssertionError, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate };
136
+ export { AssertionError, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate };
@@ -2,17 +2,12 @@
2
2
  var __defProp = Object.defineProperty;
3
3
  var __exportAll = (all, no_symbols) => {
4
4
  let target = {};
5
- for (var name in all) {
6
- __defProp(target, name, {
7
- get: all[name],
8
- enumerable: true
9
- });
10
- }
11
- if (!no_symbols) {
12
- __defProp(target, Symbol.toStringTag, { value: "Module" });
13
- }
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
14
10
  return target;
15
11
  };
16
-
17
12
  //#endregion
18
- export { __exportAll };
13
+ export { __exportAll };
package/dist-v3/actor.js CHANGED
@@ -7,7 +7,6 @@ import { emitWithTimestamp } from "./internal/inspection.js";
7
7
  import { PersistenceAdapterTag, PersistenceError } from "./persistence/adapter.js";
8
8
  import { createPersistentActor, restorePersistentActor } from "./persistence/persistent-actor.js";
9
9
  import { Cause, Context, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, Option, PubSub, Queue, Ref, Runtime, Scope, Stream, SubscriptionRef } from "effect";
10
-
11
10
  //#region src-v3/actor.ts
12
11
  /**
13
12
  * Actor system: spawning, lifecycle, and event processing.
@@ -454,6 +453,5 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
454
453
  * Default ActorSystem layer
455
454
  */
456
455
  const Default = Layer.scoped(ActorSystem, make());
457
-
458
456
  //#endregion
459
- export { ActorSystem, Default, buildActorRefCore, createActor, notifyListeners, processEventCore, resolveTransition, runSpawnEffects };
457
+ export { ActorSystem, Default, buildActorRefCore, createActor, notifyListeners, processEventCore, resolveTransition, runSpawnEffects };
@@ -1,7 +1,6 @@
1
1
  import { EffectsDef, GuardsDef } from "../slot.js";
2
2
  import { ProcessEventHooks } from "../internal/transition.js";
3
3
  import { Machine } from "../machine.js";
4
- import "../actor.js";
5
4
  import { Layer } from "effect";
6
5
  import { Entity } from "@effect/cluster";
7
6
  import { Rpc } from "@effect/rpc";
@@ -2,7 +2,6 @@ import { processEventCore, runSpawnEffects } from "../internal/transition.js";
2
2
  import { ActorSystem } from "../actor.js";
3
3
  import { Effect, Option, Queue, Ref, Scope } from "effect";
4
4
  import { Entity } from "@effect/cluster";
5
-
6
5
  //#region src-v3/cluster/entity-machine.ts
7
6
  /**
8
7
  * EntityMachine adapter - wires a machine to a cluster Entity layer.
@@ -75,6 +74,5 @@ const EntityMachine = { layer: (entity, machine, options) => {
75
74
  });
76
75
  return entity.toLayer(layer());
77
76
  } };
78
-
79
77
  //#endregion
80
- export { EntityMachine };
78
+ export { EntityMachine };
@@ -1,4 +1,3 @@
1
1
  import { EntityMachine } from "./entity-machine.js";
2
2
  import { toEntity } from "./to-entity.js";
3
-
4
- export { EntityMachine, toEntity };
3
+ export { EntityMachine, toEntity };
@@ -1,7 +1,6 @@
1
1
  import { MissingSchemaError } from "../errors.js";
2
2
  import { Entity } from "@effect/cluster";
3
3
  import { Rpc } from "@effect/rpc";
4
-
5
4
  //#region src-v3/cluster/to-entity.ts
6
5
  /**
7
6
  * Generate Entity definition from a machine.
@@ -48,6 +47,5 @@ const toEntity = (machine, options) => {
48
47
  success: stateSchema
49
48
  }), Rpc.make("GetState", { success: stateSchema })]);
50
49
  };
51
-
52
50
  //#endregion
53
- export { toEntity };
51
+ export { toEntity };
package/dist-v3/errors.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Schema } from "effect";
2
-
3
2
  //#region src-v3/errors.ts
4
3
  /**
5
4
  * Typed error classes for effect-machine.
@@ -33,6 +32,5 @@ var ProvisionValidationError = class extends Schema.TaggedError()("ProvisionVali
33
32
  }) {};
34
33
  /** Assertion failed in testing utilities */
35
34
  var AssertionError = class extends Schema.TaggedError()("AssertionError", { message: Schema.String }) {};
36
-
37
35
  //#endregion
38
- export { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError };
36
+ export { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError };