effect-machine 0.4.0 → 0.7.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 (70) hide show
  1. package/README.md +36 -0
  2. package/dist/actor.d.ts +40 -4
  3. package/dist/actor.js +89 -34
  4. package/dist/cluster/entity-machine.d.ts +2 -2
  5. package/dist/cluster/entity-machine.js +1 -1
  6. package/dist/cluster/to-entity.d.ts +5 -5
  7. package/dist/cluster/to-entity.js +2 -2
  8. package/dist/errors.d.ts +25 -40
  9. package/dist/errors.js +10 -10
  10. package/dist/index.d.ts +2 -2
  11. package/dist/inspection.d.ts +3 -3
  12. package/dist/inspection.js +2 -2
  13. package/dist/internal/brands.d.ts +3 -6
  14. package/dist/internal/inspection.js +5 -1
  15. package/dist/internal/transition.d.ts +2 -2
  16. package/dist/internal/transition.js +6 -6
  17. package/dist/internal/utils.js +11 -2
  18. package/dist/machine.d.ts +5 -5
  19. package/dist/machine.js +9 -5
  20. package/dist/persistence/adapter.d.ts +18 -21
  21. package/dist/persistence/adapter.js +4 -4
  22. package/dist/persistence/adapters/in-memory.js +4 -4
  23. package/dist/persistence/persistent-actor.js +23 -14
  24. package/dist/persistence/persistent-machine.d.ts +3 -3
  25. package/dist/schema.d.ts +4 -4
  26. package/dist/schema.js +2 -2
  27. package/dist/slot.d.ts +3 -3
  28. package/dist/slot.js +2 -2
  29. package/dist-v3/_virtual/_rolldown/runtime.js +18 -0
  30. package/dist-v3/actor.d.ts +291 -0
  31. package/dist-v3/actor.js +459 -0
  32. package/dist-v3/cluster/entity-machine.d.ts +90 -0
  33. package/dist-v3/cluster/entity-machine.js +80 -0
  34. package/dist-v3/cluster/index.d.ts +3 -0
  35. package/dist-v3/cluster/index.js +4 -0
  36. package/dist-v3/cluster/to-entity.d.ts +61 -0
  37. package/dist-v3/cluster/to-entity.js +53 -0
  38. package/dist-v3/errors.d.ts +27 -0
  39. package/dist-v3/errors.js +38 -0
  40. package/dist-v3/index.d.ts +13 -0
  41. package/dist-v3/index.js +14 -0
  42. package/dist-v3/inspection.d.ts +125 -0
  43. package/dist-v3/inspection.js +50 -0
  44. package/dist-v3/internal/brands.d.ts +40 -0
  45. package/dist-v3/internal/brands.js +0 -0
  46. package/dist-v3/internal/inspection.d.ts +11 -0
  47. package/dist-v3/internal/inspection.js +15 -0
  48. package/dist-v3/internal/transition.d.ts +160 -0
  49. package/dist-v3/internal/transition.js +238 -0
  50. package/dist-v3/internal/utils.d.ts +60 -0
  51. package/dist-v3/internal/utils.js +51 -0
  52. package/dist-v3/machine.d.ts +278 -0
  53. package/dist-v3/machine.js +317 -0
  54. package/dist-v3/persistence/adapter.d.ts +125 -0
  55. package/dist-v3/persistence/adapter.js +27 -0
  56. package/dist-v3/persistence/adapters/in-memory.d.ts +32 -0
  57. package/dist-v3/persistence/adapters/in-memory.js +176 -0
  58. package/dist-v3/persistence/index.d.ts +5 -0
  59. package/dist-v3/persistence/index.js +6 -0
  60. package/dist-v3/persistence/persistent-actor.d.ts +49 -0
  61. package/dist-v3/persistence/persistent-actor.js +367 -0
  62. package/dist-v3/persistence/persistent-machine.d.ts +105 -0
  63. package/dist-v3/persistence/persistent-machine.js +24 -0
  64. package/dist-v3/schema.d.ts +141 -0
  65. package/dist-v3/schema.js +165 -0
  66. package/dist-v3/slot.d.ts +130 -0
  67. package/dist-v3/slot.js +99 -0
  68. package/dist-v3/testing.d.ts +136 -0
  69. package/dist-v3/testing.js +138 -0
  70. package/package.json +29 -21
@@ -1,10 +1,8 @@
1
1
  import { Brand } from "effect";
2
2
 
3
3
  //#region src/internal/brands.d.ts
4
- declare const StateTypeId: unique symbol;
5
- declare const EventTypeId: unique symbol;
6
- type StateTypeId = typeof StateTypeId;
7
- type EventTypeId = typeof EventTypeId;
4
+ type StateTypeId = "effect-machine/StateTypeId";
5
+ type EventTypeId = "effect-machine/EventTypeId";
8
6
  interface StateBrand extends Brand.Brand<StateTypeId> {}
9
7
  interface EventBrand extends Brand.Brand<EventTypeId> {}
10
8
  type BrandedState = {
@@ -13,8 +11,7 @@ type BrandedState = {
13
11
  type BrandedEvent = {
14
12
  readonly _tag: string;
15
13
  } & EventBrand;
16
- declare const SchemaIdTypeId: unique symbol;
17
- type SchemaIdTypeId = typeof SchemaIdTypeId;
14
+ type SchemaIdTypeId = "effect-machine/SchemaIdTypeId";
18
15
  /**
19
16
  * Brand that captures the schema definition type D.
20
17
  * Two schemas with identical definition shapes will have compatible brands.
@@ -8,7 +8,11 @@ import { Clock, Effect } from "effect";
8
8
  const emitWithTimestamp = Effect.fn("effect-machine.emitWithTimestamp")(function* (inspector, makeEvent) {
9
9
  if (inspector === void 0) return;
10
10
  const timestamp = yield* Clock.currentTimeMillis;
11
- yield* Effect.try(() => inspector.onInspect(makeEvent(timestamp))).pipe(Effect.ignore);
11
+ yield* Effect.sync(() => {
12
+ try {
13
+ inspector.onInspect(makeEvent(timestamp));
14
+ } catch {}
15
+ });
12
16
  });
13
17
 
14
18
  //#endregion
@@ -102,7 +102,7 @@ declare const processEventCore: <S extends {
102
102
  }, E extends {
103
103
  readonly _tag: string;
104
104
  }, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, currentState: S, event: E, self: MachineRef<E>, stateScopeRef: {
105
- current: Scope.CloseableScope;
105
+ current: Scope.Closeable;
106
106
  }, system: ActorSystem, hooks?: ProcessEventHooks<S, E> | undefined) => Effect.Effect<{
107
107
  newState: S;
108
108
  previousState: S;
@@ -119,7 +119,7 @@ declare const runSpawnEffects: <S extends {
119
119
  readonly _tag: string;
120
120
  }, E extends {
121
121
  readonly _tag: string;
122
- }, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, state: S, event: E, self: MachineRef<E>, stateScope: Scope.CloseableScope, system: ActorSystem, onError?: ((info: ProcessEventError<S, E>) => Effect.Effect<void>) | undefined) => Effect.Effect<void, never, Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
122
+ }, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, state: S, event: E, self: MachineRef<E>, stateScope: Scope.Closeable, system: ActorSystem, onError?: ((info: ProcessEventError<S, E>) => Effect.Effect<void>) | undefined) => Effect.Effect<void, never, Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
123
123
  /**
124
124
  * Resolve which transition should fire for a given state and event.
125
125
  * Uses indexed O(1) lookup. First matching transition wins.
@@ -77,8 +77,8 @@ const executeTransition = Effect.fn("effect-machine.executeTransition")(function
77
77
  * @internal
78
78
  */
79
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.catchAllCause((cause) => {
81
- if (Cause.isInterruptedOnly(cause)) return Effect.interrupt;
80
+ const result = yield* executeTransition(machine, currentState, event, self, system).pipe(Effect.catchCause((cause) => {
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);
84
84
  return onError({
@@ -86,7 +86,7 @@ const processEventCore = Effect.fn("effect-machine.processEventCore")(function*
86
86
  state: currentState,
87
87
  event,
88
88
  cause
89
- }).pipe(Effect.zipRight(Effect.failCause(cause).pipe(Effect.orDie)));
89
+ }).pipe(Effect.andThen(Effect.failCause(cause).pipe(Effect.orDie)));
90
90
  }));
91
91
  if (!result.transitioned) return {
92
92
  newState: currentState,
@@ -134,15 +134,15 @@ const runSpawnEffects = Effect.fn("effect-machine.runSpawnEffects")(function* (m
134
134
  self,
135
135
  effects: effectSlots,
136
136
  system
137
- }).pipe(Effect.provideService(machine.Context, ctx), Effect.catchAllCause((cause) => {
138
- if (Cause.isInterruptedOnly(cause)) return Effect.interrupt;
137
+ }).pipe(Effect.provideService(machine.Context, ctx), Effect.catchCause((cause) => {
138
+ if (Cause.hasInterruptsOnly(cause)) return Effect.interrupt;
139
139
  if (reportError === void 0) return Effect.failCause(cause).pipe(Effect.orDie);
140
140
  return reportError({
141
141
  phase: "spawn",
142
142
  state,
143
143
  event,
144
144
  cause
145
- }).pipe(Effect.zipRight(Effect.failCause(cause).pipe(Effect.orDie)));
145
+ }).pipe(Effect.andThen(Effect.failCause(cause).pipe(Effect.orDie)));
146
146
  }));
147
147
  yield* Effect.forkScoped(effect).pipe(Effect.provideService(Scope.Scope, stateScope));
148
148
  }
@@ -1,7 +1,11 @@
1
- import { Effect } from "effect";
1
+ import { Effect, Stream } from "effect";
2
2
 
3
3
  //#region src/internal/utils.ts
4
4
  /**
5
+ * Internal utilities for effect-machine.
6
+ * @internal
7
+ */
8
+ /**
5
9
  * Internal event tags used for lifecycle effect contexts.
6
10
  * Prefixed with $ to distinguish from user events.
7
11
  * @internal
@@ -25,7 +29,7 @@ const getTag = (constructorOrValue) => {
25
29
  }
26
30
  };
27
31
  /** Check if a value is an Effect */
28
- const isEffect = (value) => typeof value === "object" && value !== null && Effect.EffectTypeId in value;
32
+ const isEffect = Effect.isEffect;
29
33
  /**
30
34
  * Stub ActorSystem that dies on any method call.
31
35
  * Used in contexts where spawning/system access isn't supported
@@ -37,6 +41,11 @@ const stubSystem = {
37
41
  restore: () => Effect.die("restore not supported in stub system"),
38
42
  get: () => Effect.die("get not supported in stub system"),
39
43
  stop: () => Effect.die("stop not supported in stub system"),
44
+ events: Stream.empty,
45
+ get actors() {
46
+ return /* @__PURE__ */ new Map();
47
+ },
48
+ subscribe: () => () => {},
40
49
  listPersisted: () => Effect.die("listPersisted not supported in stub system"),
41
50
  restoreMany: () => Effect.die("restoreMany not supported in stub system"),
42
51
  restoreAll: () => Effect.die("restoreAll not supported in stub system")
package/dist/machine.d.ts CHANGED
@@ -7,7 +7,7 @@ import { DuplicateActorError } from "./errors.js";
7
7
  import { findTransitions } from "./internal/transition.js";
8
8
  import "./persistence/index.js";
9
9
  import { ActorRef, ActorSystem } from "./actor.js";
10
- import { Cause, Context, Effect, Schedule, Schema, Scope } from "effect";
10
+ import { Cause, Effect, Schedule, Schema, Scope, ServiceMap } from "effect";
11
11
 
12
12
  //#region src/machine.d.ts
13
13
  declare namespace machine_d_exports {
@@ -159,13 +159,13 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
159
159
  guards: GuardSlots<GD>;
160
160
  effects: EffectSlots<EFD>;
161
161
  };
162
- readonly stateSchema?: Schema.Schema<State, unknown, never>;
163
- readonly eventSchema?: Schema.Schema<Event, unknown, never>;
162
+ readonly stateSchema?: Schema.Schema<State>;
163
+ readonly eventSchema?: Schema.Schema<Event>;
164
164
  /**
165
165
  * Context tag for accessing machine state/event/self in slot handlers.
166
166
  * Uses shared module-level tag for all machines.
167
167
  */
168
- readonly Context: Context.Tag<MachineContext<State, Event, MachineRef<Event>>, MachineContext<State, Event, MachineRef<Event>>>;
168
+ readonly Context: ServiceMap.Service<MachineContext<State, Event, MachineRef<Event>>, MachineContext<State, Event, MachineRef<Event>>>;
169
169
  get transitions(): ReadonlyArray<Transition<State, Event, GD, EFD, R>>;
170
170
  get spawnEffects(): ReadonlyArray<SpawnEffect<State, Event, EFD, R>>;
171
171
  get backgroundEffects(): ReadonlyArray<BackgroundEffect<State, Event, EFD, R>>;
@@ -173,7 +173,7 @@ declare class Machine<State, Event, R = never, _SD extends Record<string, Schema
173
173
  get guardsSchema(): GuardsSchema<GD> | undefined;
174
174
  get effectsSchema(): EffectsSchema<EFD> | undefined;
175
175
  /** @internal */
176
- constructor(initial: State, stateSchema?: Schema.Schema<State, unknown, never>, eventSchema?: Schema.Schema<Event, unknown, never>, guardsSchema?: GuardsSchema<GD>, effectsSchema?: EffectsSchema<EFD>);
176
+ constructor(initial: State, stateSchema?: Schema.Schema<State>, eventSchema?: Schema.Schema<Event>, guardsSchema?: GuardsSchema<GD>, effectsSchema?: EffectsSchema<EFD>);
177
177
  /** Register transition for a single state */
178
178
  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
179
  /** Register transition for multiple states (handler receives union of state types) */
package/dist/machine.js CHANGED
@@ -98,7 +98,9 @@ var Machine = class Machine {
98
98
  this.stateSchema = stateSchema;
99
99
  this.eventSchema = eventSchema;
100
100
  this._slots = {
101
- guards: this._guardsSchema !== void 0 ? this._guardsSchema._createSlots((name, params) => Effect.flatMap(Effect.serviceOptional(this.Context).pipe(Effect.orDie), (ctx) => {
101
+ guards: this._guardsSchema !== void 0 ? this._guardsSchema._createSlots((name, params) => Effect.flatMap(Effect.serviceOption(this.Context), (maybeCtx) => {
102
+ if (Option.isNone(maybeCtx)) return Effect.die("MachineContext not available");
103
+ const ctx = maybeCtx.value;
102
104
  const handler = this._guardHandlers.get(name);
103
105
  if (handler === void 0) return Effect.die(new SlotProvisionError({
104
106
  slotName: name,
@@ -107,7 +109,9 @@ var Machine = class Machine {
107
109
  const result = handler(params, ctx);
108
110
  return typeof result === "boolean" ? Effect.succeed(result) : result;
109
111
  })) : {},
110
- effects: this._effectsSchema !== void 0 ? this._effectsSchema._createSlots((name, params) => Effect.flatMap(Effect.serviceOptional(this.Context).pipe(Effect.orDie), (ctx) => {
112
+ effects: this._effectsSchema !== void 0 ? this._effectsSchema._createSlots((name, params) => Effect.flatMap(Effect.serviceOption(this.Context), (maybeCtx) => {
113
+ if (Option.isNone(maybeCtx)) return Effect.die("MachineContext not available");
114
+ const ctx = maybeCtx.value;
111
115
  const handler = this._effectHandlers.get(name);
112
116
  if (handler === void 0) return Effect.die(new SlotProvisionError({
113
117
  slotName: name,
@@ -194,14 +198,14 @@ var Machine = class Machine {
194
198
  const exit = yield* Effect.exit(run(ctx));
195
199
  if (Exit.isSuccess(exit)) {
196
200
  yield* ctx.self.send(options.onSuccess(exit.value, ctx));
197
- yield* Effect.yieldNow();
201
+ yield* Effect.yieldNow;
198
202
  return;
199
203
  }
200
204
  const cause = exit.cause;
201
- if (Cause.isInterruptedOnly(cause)) return;
205
+ if (Cause.hasInterruptsOnly(cause)) return;
202
206
  if (options.onFailure !== void 0) {
203
207
  yield* ctx.self.send(options.onFailure(cause, ctx));
204
- yield* Effect.yieldNow();
208
+ yield* Effect.yieldNow;
205
209
  return;
206
210
  }
207
211
  return yield* Effect.failCause(cause).pipe(Effect.orDie);
@@ -1,6 +1,7 @@
1
1
  import { DuplicateActorError } from "../errors.js";
2
2
  import { PersistentActorRef } from "./persistent-actor.js";
3
- import { Context, Effect, Option, Schema } from "effect";
3
+ import { Effect, Option, Schema, ServiceMap } from "effect";
4
+ import * as effect_Cause0 from "effect/Cause";
4
5
 
5
6
  //#region src/persistence/adapter.d.ts
6
7
  /**
@@ -64,20 +65,20 @@ interface PersistenceAdapter {
64
65
  * Save a snapshot of actor state.
65
66
  * Implementations should use optimistic locking — fail if version mismatch.
66
67
  */
67
- readonly saveSnapshot: <S, SI>(id: string, snapshot: Snapshot<S>, schema: Schema.Schema<S, SI, never>) => Effect.Effect<void, PersistenceError | VersionConflictError>;
68
+ readonly saveSnapshot: <S>(id: string, snapshot: Snapshot<S>, schema: Schema.Codec<S, unknown, never, never>) => Effect.Effect<void, PersistenceError | VersionConflictError>;
68
69
  /**
69
70
  * Load the latest snapshot for an actor.
70
71
  * Returns None if no snapshot exists.
71
72
  */
72
- readonly loadSnapshot: <S, SI>(id: string, schema: Schema.Schema<S, SI, never>) => Effect.Effect<Option.Option<Snapshot<S>>, PersistenceError>;
73
+ readonly loadSnapshot: <S>(id: string, schema: Schema.Codec<S, unknown, never, never>) => Effect.Effect<Option.Option<Snapshot<S>>, PersistenceError>;
73
74
  /**
74
75
  * Append an event to the actor's event journal.
75
76
  */
76
- readonly appendEvent: <E, EI>(id: string, event: PersistedEvent<E>, schema: Schema.Schema<E, EI, never>) => Effect.Effect<void, PersistenceError>;
77
+ readonly appendEvent: <E>(id: string, event: PersistedEvent<E>, schema: Schema.Codec<E, unknown, never, never>) => Effect.Effect<void, PersistenceError>;
77
78
  /**
78
79
  * Load events from the journal, optionally after a specific version.
79
80
  */
80
- readonly loadEvents: <E, EI>(id: string, schema: Schema.Schema<E, EI, never>, afterVersion?: number) => Effect.Effect<ReadonlyArray<PersistedEvent<E>>, PersistenceError>;
81
+ readonly loadEvents: <E>(id: string, schema: Schema.Codec<E, unknown, never, never>, afterVersion?: number) => Effect.Effect<ReadonlyArray<PersistedEvent<E>>, PersistenceError>;
81
82
  /**
82
83
  * Delete all persisted data for an actor (snapshot + events).
83
84
  */
@@ -106,30 +107,26 @@ interface PersistenceAdapter {
106
107
  */
107
108
  readonly loadMetadata?: (id: string) => Effect.Effect<Option.Option<ActorMetadata>, PersistenceError>;
108
109
  }
109
- declare const PersistenceError_base: Schema.TaggedErrorClass<PersistenceError, "PersistenceError", {
110
- readonly _tag: Schema.tag<"PersistenceError">;
111
- } & {
112
- operation: typeof Schema.String;
113
- actorId: typeof Schema.String;
114
- cause: Schema.optional<typeof Schema.Unknown>;
115
- message: Schema.optional<typeof Schema.String>;
116
- }>;
110
+ declare const PersistenceError_base: Schema.ErrorClass<PersistenceError, Schema.TaggedStruct<"PersistenceError", {
111
+ readonly operation: Schema.String;
112
+ readonly actorId: Schema.String;
113
+ readonly cause: Schema.optional<Schema.Unknown>;
114
+ readonly message: Schema.optional<Schema.String>;
115
+ }>, effect_Cause0.YieldableError>;
117
116
  /**
118
117
  * Error type for persistence operations
119
118
  */
120
119
  declare class PersistenceError extends PersistenceError_base {}
121
- declare const VersionConflictError_base: Schema.TaggedErrorClass<VersionConflictError, "VersionConflictError", {
122
- readonly _tag: Schema.tag<"VersionConflictError">;
123
- } & {
124
- actorId: typeof Schema.String;
125
- expectedVersion: typeof Schema.Number;
126
- actualVersion: typeof Schema.Number;
127
- }>;
120
+ declare const VersionConflictError_base: Schema.ErrorClass<VersionConflictError, Schema.TaggedStruct<"VersionConflictError", {
121
+ readonly actorId: Schema.String;
122
+ readonly expectedVersion: Schema.Number;
123
+ readonly actualVersion: Schema.Number;
124
+ }>, effect_Cause0.YieldableError>;
128
125
  /**
129
126
  * Version conflict error — snapshot version doesn't match expected
130
127
  */
131
128
  declare class VersionConflictError extends VersionConflictError_base {}
132
- declare const PersistenceAdapterTag_base: Context.TagClass<PersistenceAdapterTag, "effect-machine/src/persistence/adapter/PersistenceAdapterTag", PersistenceAdapter>;
129
+ declare const PersistenceAdapterTag_base: ServiceMap.ServiceClass<PersistenceAdapterTag, "effect-machine/src/persistence/adapter/PersistenceAdapterTag", PersistenceAdapter>;
133
130
  /**
134
131
  * PersistenceAdapter service tag
135
132
  */
@@ -1,10 +1,10 @@
1
- import { Context, Schema } from "effect";
1
+ import { Schema, ServiceMap } from "effect";
2
2
 
3
3
  //#region src/persistence/adapter.ts
4
4
  /**
5
5
  * Error type for persistence operations
6
6
  */
7
- var PersistenceError = class extends Schema.TaggedError()("PersistenceError", {
7
+ var PersistenceError = class extends Schema.TaggedErrorClass()("PersistenceError", {
8
8
  operation: Schema.String,
9
9
  actorId: Schema.String,
10
10
  cause: Schema.optional(Schema.Unknown),
@@ -13,7 +13,7 @@ var PersistenceError = class extends Schema.TaggedError()("PersistenceError", {
13
13
  /**
14
14
  * Version conflict error — snapshot version doesn't match expected
15
15
  */
16
- var VersionConflictError = class extends Schema.TaggedError()("VersionConflictError", {
16
+ var VersionConflictError = class extends Schema.TaggedErrorClass()("VersionConflictError", {
17
17
  actorId: Schema.String,
18
18
  expectedVersion: Schema.Number,
19
19
  actualVersion: Schema.Number
@@ -21,7 +21,7 @@ var VersionConflictError = class extends Schema.TaggedError()("VersionConflictEr
21
21
  /**
22
22
  * PersistenceAdapter service tag
23
23
  */
24
- var PersistenceAdapterTag = class extends Context.Tag("effect-machine/src/persistence/adapter/PersistenceAdapterTag")() {};
24
+ var PersistenceAdapterTag = class extends ServiceMap.Service()("effect-machine/src/persistence/adapter/PersistenceAdapterTag") {};
25
25
 
26
26
  //#endregion
27
27
  export { PersistenceAdapterTag, PersistenceError, VersionConflictError };
@@ -42,7 +42,7 @@ const make = Effect.gen(function* () {
42
42
  actualVersion: snapshot.version
43
43
  });
44
44
  }
45
- const encoded = yield* Schema.encode(schema)(snapshot.state).pipe(Effect.mapError((cause) => new PersistenceError({
45
+ const encoded = yield* Schema.encodeEffect(schema)(snapshot.state).pipe(Effect.mapError((cause) => new PersistenceError({
46
46
  operation: "saveSnapshot",
47
47
  actorId: id,
48
48
  cause,
@@ -61,7 +61,7 @@ const make = Effect.gen(function* () {
61
61
  const actorStorage = yield* getOrCreateStorage(id);
62
62
  if (Option.isNone(actorStorage.snapshot)) return Option.none();
63
63
  const stored = actorStorage.snapshot.value;
64
- const decoded = yield* Schema.decode(schema)(stored.data).pipe(Effect.mapError((cause) => new PersistenceError({
64
+ const decoded = yield* Schema.decodeEffect(schema)(stored.data).pipe(Effect.mapError((cause) => new PersistenceError({
65
65
  operation: "loadSnapshot",
66
66
  actorId: id,
67
67
  cause,
@@ -75,7 +75,7 @@ const make = Effect.gen(function* () {
75
75
  }),
76
76
  appendEvent: Effect.fn("effect-machine.persistence.inMemory.appendEvent")(function* (id, event, schema) {
77
77
  yield* getOrCreateStorage(id);
78
- const encoded = yield* Schema.encode(schema)(event.event).pipe(Effect.mapError((cause) => new PersistenceError({
78
+ const encoded = yield* Schema.encodeEffect(schema)(event.event).pipe(Effect.mapError((cause) => new PersistenceError({
79
79
  operation: "appendEvent",
80
80
  actorId: id,
81
81
  cause,
@@ -95,7 +95,7 @@ const make = Effect.gen(function* () {
95
95
  const decoded = [];
96
96
  for (const stored of actorStorage.events) {
97
97
  if (afterVersion !== void 0 && stored.version <= afterVersion) continue;
98
- const event = yield* Schema.decode(schema)(stored.data).pipe(Effect.mapError((cause) => new PersistenceError({
98
+ const event = yield* Schema.decodeEffect(schema)(stored.data).pipe(Effect.mapError((cause) => new PersistenceError({
99
99
  operation: "loadEvents",
100
100
  actorId: id,
101
101
  cause,
@@ -31,7 +31,7 @@ const replayEvents = Effect.fn("effect-machine.persistentActor.replayEvents")(fu
31
31
  /**
32
32
  * Build PersistentActorRef with all methods
33
33
  */
34
- const buildPersistentActorRef = (id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, listeners, stop, adapter, system) => {
34
+ const buildPersistentActorRef = (id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, listeners, stop, adapter, system, childrenMap) => {
35
35
  const { machine, persistence } = persistentMachine;
36
36
  const typedMachine = machine;
37
37
  const persist = Effect.gen(function* () {
@@ -71,7 +71,7 @@ const buildPersistentActorRef = (id, persistentMachine, stateRef, versionRef, ev
71
71
  }
72
72
  });
73
73
  return {
74
- ...buildActorRefCore(id, typedMachine, stateRef, eventQueue, stoppedRef, listeners, stop, system),
74
+ ...buildActorRefCore(id, typedMachine, stateRef, eventQueue, stoppedRef, listeners, stop, system, childrenMap),
75
75
  persist,
76
76
  version,
77
77
  replayTo
@@ -92,12 +92,21 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
92
92
  const inspector = Option.getOrUndefined(yield* Effect.serviceOption(Inspector));
93
93
  const eventQueue = yield* Queue.unbounded();
94
94
  const stoppedRef = yield* Ref.make(false);
95
+ const childrenMap = /* @__PURE__ */ new Map();
95
96
  const self = {
96
97
  send: Effect.fn("effect-machine.persistentActor.self.send")(function* (event) {
97
98
  if (yield* Ref.get(stoppedRef)) return;
98
99
  yield* Queue.offer(eventQueue, event);
99
100
  }),
100
- spawn: (childId, childMachine) => system.spawn(childId, childMachine).pipe(Effect.provideService(ActorSystem, system))
101
+ spawn: (childId, childMachine) => Effect.gen(function* () {
102
+ const child = yield* system.spawn(childId, childMachine).pipe(Effect.provideService(ActorSystem, system));
103
+ childrenMap.set(childId, child);
104
+ const maybeScope = yield* Effect.serviceOption(Scope.Scope);
105
+ if (Option.isSome(maybeScope)) yield* Scope.addFinalizer(maybeScope.value, Effect.sync(() => {
106
+ childrenMap.delete(childId);
107
+ }));
108
+ return child;
109
+ })
101
110
  };
102
111
  let resolvedInitial;
103
112
  let initialVersion;
@@ -130,10 +139,10 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
130
139
  }));
131
140
  const snapshotEnabledRef = yield* Ref.make(true);
132
141
  const persistenceQueue = yield* Queue.unbounded();
133
- const persistenceFiber = yield* Effect.forkDaemon(persistenceWorker(persistenceQueue));
142
+ const persistenceFiber = yield* Effect.forkDetach(persistenceWorker(persistenceQueue));
134
143
  yield* Queue.offer(persistenceQueue, saveMetadata(id, resolvedInitial, initialVersion, createdAt, persistence, adapter));
135
144
  const snapshotQueue = yield* Queue.unbounded();
136
- const snapshotFiber = yield* Effect.forkDaemon(snapshotWorker(id, persistence, adapter, snapshotQueue, snapshotEnabledRef));
145
+ const snapshotFiber = yield* Effect.forkDetach(snapshotWorker(id, persistence, adapter, snapshotQueue, snapshotEnabledRef));
137
146
  const backgroundFibers = [];
138
147
  const initEvent = { _tag: INTERNAL_INIT_EVENT };
139
148
  const initCtx = {
@@ -144,7 +153,7 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
144
153
  };
145
154
  const { effects: effectSlots } = typedMachine._slots;
146
155
  for (const bg of typedMachine.backgroundEffects) {
147
- const fiber = yield* Effect.forkDaemon(bg.handler({
156
+ const fiber = yield* Effect.forkDetach(bg.handler({
148
157
  state: resolvedInitial,
149
158
  event: initEvent,
150
159
  self,
@@ -167,9 +176,9 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
167
176
  finalState: resolvedInitial,
168
177
  timestamp
169
178
  }));
170
- return buildPersistentActorRef(id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, listeners, Ref.set(stoppedRef, true).pipe(Effect.withSpan("effect-machine.persistentActor.stop"), Effect.asVoid), adapter, system);
179
+ return buildPersistentActorRef(id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, listeners, Ref.set(stoppedRef, true).pipe(Effect.withSpan("effect-machine.persistentActor.stop"), Effect.asVoid), adapter, system, childrenMap);
171
180
  }
172
- const loopFiber = yield* Effect.forkDaemon(persistentEventLoop(id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, self, listeners, adapter, createdAt, stateScopeRef, backgroundFibers, snapshotQueue, snapshotEnabledRef, persistenceQueue, snapshotFiber, persistenceFiber, inspector, system));
181
+ const loopFiber = yield* Effect.forkDetach(persistentEventLoop(id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, self, listeners, adapter, createdAt, stateScopeRef, backgroundFibers, snapshotQueue, snapshotEnabledRef, persistenceQueue, snapshotFiber, persistenceFiber, inspector, system));
173
182
  return buildPersistentActorRef(id, persistentMachine, stateRef, versionRef, eventQueue, stoppedRef, listeners, Effect.gen(function* () {
174
183
  const finalState = yield* SubscriptionRef.get(stateRef);
175
184
  yield* emitWithTimestamp(inspector, (timestamp) => ({
@@ -184,7 +193,7 @@ const createPersistentActor = Effect.fn("effect-machine.persistentActor.spawn")(
184
193
  yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
185
194
  yield* Fiber.interrupt(snapshotFiber);
186
195
  yield* Fiber.interrupt(persistenceFiber);
187
- }).pipe(Effect.withSpan("effect-machine.persistentActor.stop"), Effect.asVoid), adapter, system);
196
+ }).pipe(Effect.withSpan("effect-machine.persistentActor.stop"), Effect.asVoid), adapter, system, childrenMap);
188
197
  });
189
198
  /**
190
199
  * Main event loop for persistent actor
@@ -241,7 +250,7 @@ const persistentEventLoop = Effect.fn("effect-machine.persistentActor.eventLoop"
241
250
  version: newVersion,
242
251
  timestamp: yield* now
243
252
  };
244
- const journalTask = adapter.appendEvent(id, persistedEvent, persistence.eventSchema).pipe(Effect.catchAll((e) => Effect.logWarning(`Failed to journal event for actor ${id}`, e)), Effect.asVoid);
253
+ const journalTask = adapter.appendEvent(id, persistedEvent, persistence.eventSchema).pipe(Effect.catchEager((e) => Effect.logWarning(`Failed to journal event for actor ${id}`, e)), Effect.asVoid);
245
254
  yield* Queue.offer(persistenceQueue, journalTask);
246
255
  }
247
256
  yield* Queue.offer(persistenceQueue, saveMetadata(id, result.newState, newVersion, createdAt, persistence, adapter));
@@ -297,11 +306,11 @@ const persistenceWorker = Effect.fn("effect-machine.persistentActor.persistenceW
297
306
  * Snapshot scheduler worker (runs in background).
298
307
  */
299
308
  const snapshotWorker = Effect.fn("effect-machine.persistentActor.snapshotWorker")(function* (id, persistence, adapter, queue, enabledRef) {
300
- const driver = yield* Schedule.driver(persistence.snapshotSchedule);
309
+ const step = yield* Schedule.toStep(persistence.snapshotSchedule);
301
310
  while (true) {
302
311
  const { state, version } = yield* Queue.take(queue);
303
312
  if (!(yield* Ref.get(enabledRef))) continue;
304
- if (!(yield* driver.next(state).pipe(Effect.match({
313
+ if (!(yield* step(yield* Clock.currentTimeMillis, state).pipe(Effect.match({
305
314
  onFailure: () => false,
306
315
  onSuccess: () => true
307
316
  })))) {
@@ -321,7 +330,7 @@ const saveSnapshot = Effect.fn("effect-machine.persistentActor.saveSnapshot")(fu
321
330
  version,
322
331
  timestamp: yield* now
323
332
  };
324
- yield* adapter.saveSnapshot(id, snapshot, persistence.stateSchema).pipe(Effect.catchAll((e) => Effect.logWarning(`Failed to save snapshot for actor ${id}`, e)));
333
+ yield* adapter.saveSnapshot(id, snapshot, persistence.stateSchema).pipe(Effect.catchEager((e) => Effect.logWarning(`Failed to save snapshot for actor ${id}`, e)));
325
334
  });
326
335
  /**
327
336
  * Save or update actor metadata if adapter supports registry.
@@ -338,7 +347,7 @@ const saveMetadata = Effect.fn("effect-machine.persistentActor.saveMetadata")(fu
338
347
  lastActivityAt,
339
348
  version,
340
349
  stateTag: state._tag
341
- }).pipe(Effect.catchAll((e) => Effect.logWarning(`Failed to save metadata for actor ${id}`, e)));
350
+ }).pipe(Effect.catchEager((e) => Effect.logWarning(`Failed to save metadata for actor ${id}`, e)));
342
351
  });
343
352
  /**
344
353
  * Restore an actor from persistence.
@@ -16,7 +16,7 @@ type BrandedEvent = {
16
16
  * Note: Schema types S and E should match the structural shape of the machine's
17
17
  * state and event types (without brands). The schemas don't know about brands.
18
18
  */
19
- interface PersistenceConfig<S, E, SSI = unknown, ESI = unknown> {
19
+ interface PersistenceConfig<S, E> {
20
20
  /**
21
21
  * Schedule controlling when snapshots are taken.
22
22
  * Input is the new state after each transition.
@@ -36,12 +36,12 @@ interface PersistenceConfig<S, E, SSI = unknown, ESI = unknown> {
36
36
  * Schema for serializing/deserializing state.
37
37
  * Always present at runtime (resolved from config or machine).
38
38
  */
39
- readonly stateSchema: Schema.Schema<S, SSI, never>;
39
+ readonly stateSchema: Schema.Codec<S, unknown, never, never>;
40
40
  /**
41
41
  * Schema for serializing/deserializing events.
42
42
  * Always present at runtime (resolved from config or machine).
43
43
  */
44
- readonly eventSchema: Schema.Schema<E, ESI, never>;
44
+ readonly eventSchema: Schema.Codec<E, unknown, never, never>;
45
45
  /**
46
46
  * User-provided identifier for the machine type.
47
47
  * Used for filtering actors in restoreAll.
package/dist/schema.d.ts CHANGED
@@ -36,8 +36,8 @@ type IsEmptyFields<Fields extends Schema.Struct.Fields> = keyof Fields extends n
36
36
  */
37
37
  type VariantConstructors<D extends Record<string, Schema.Struct.Fields>, Brand> = { readonly [K in keyof D & string]: IsEmptyFields<D[K]> extends true ? TaggedStructType<K, D[K]> & Brand & {
38
38
  readonly derive: (source: object) => TaggedStructType<K, D[K]> & Brand;
39
- } : ((args: Schema.Struct.Constructor<D[K]>) => TaggedStructType<K, D[K]> & Brand) & {
40
- readonly derive: (source: object, partial?: Partial<Schema.Struct.Constructor<D[K]>>) => TaggedStructType<K, D[K]> & Brand;
39
+ } : ((args: Schema.Struct.Type<D[K]>) => TaggedStructType<K, D[K]> & Brand) & {
40
+ readonly derive: (source: object, partial?: Partial<Schema.Struct.Type<D[K]>>) => TaggedStructType<K, D[K]> & Brand;
41
41
  readonly _tag: K;
42
42
  } };
43
43
  /**
@@ -78,14 +78,14 @@ interface MachineSchemaBase<D extends Record<string, Schema.Struct.Fields>, Bran
78
78
  * The D type parameter captures the definition, creating a unique brand
79
79
  * per distinct schema definition shape.
80
80
  */
81
- type MachineStateSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Schema<VariantsUnion<D> & FullStateBrand<D>, VariantsUnion<D>, never> & MachineSchemaBase<D, FullStateBrand<D>> & VariantConstructors<D, FullStateBrand<D>>;
81
+ type MachineStateSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Codec<VariantsUnion<D> & FullStateBrand<D>, unknown, never, never> & MachineSchemaBase<D, FullStateBrand<D>> & VariantConstructors<D, FullStateBrand<D>>;
82
82
  /**
83
83
  * Schema-first event definition (same structure as state, different brand)
84
84
  *
85
85
  * The D type parameter captures the definition, creating a unique brand
86
86
  * per distinct schema definition shape.
87
87
  */
88
- type MachineEventSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Schema<VariantsUnion<D> & FullEventBrand<D>, VariantsUnion<D>, never> & MachineSchemaBase<D, FullEventBrand<D>> & VariantConstructors<D, FullEventBrand<D>>;
88
+ type MachineEventSchema<D extends Record<string, Schema.Struct.Fields>> = Schema.Codec<VariantsUnion<D> & FullEventBrand<D>, unknown, never, never> & MachineSchemaBase<D, FullEventBrand<D>> & VariantConstructors<D, FullEventBrand<D>>;
89
89
  /**
90
90
  * Create a schema-first State definition.
91
91
  *
package/dist/schema.js CHANGED
@@ -69,8 +69,8 @@ const buildMachineSchema = (definition) => {
69
69
  };
70
70
  }
71
71
  const variantArray = Object.values(variants);
72
- if (variantArray.length === 0) throw new InvalidSchemaError();
73
- const unionSchema = variantArray.length === 1 ? variantArray[0] : Schema.Union(...variantArray);
72
+ if (variantArray.length === 0) throw new InvalidSchemaError({});
73
+ const unionSchema = variantArray.length === 1 ? variantArray[0] : Schema.Union(variantArray);
74
74
  const $is = (tag) => (u) => typeof u === "object" && u !== null && "_tag" in u && u._tag === tag;
75
75
  const $match = (valueOrCases, maybeCases) => {
76
76
  if (maybeCases !== void 0) {
package/dist/slot.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ActorSystem } from "./actor.js";
2
- import { Context, Effect, Schema } from "effect";
2
+ import { Effect, Schema, ServiceMap } from "effect";
3
3
 
4
4
  //#region src/slot.d.ts
5
5
  /** Schema fields definition (like Schema.Struct.Fields) */
6
- type Fields = Record<string, Schema.Schema.All>;
6
+ type Fields = Record<string, Schema.Top>;
7
7
  /** Extract the encoded type from schema fields (used for parameters) */
8
8
  type FieldsToParams<F extends Fields> = keyof F extends never ? void : Schema.Schema.Type<Schema.Struct<F>>;
9
9
  /**
@@ -53,7 +53,7 @@ interface MachineContext<State, Event, Self> {
53
53
  * Single module-level tag instead of per-machine allocation.
54
54
  * @internal
55
55
  */
56
- declare const MachineContextTag: Context.Tag<MachineContext<any, any, any>, MachineContext<any, any, any>>;
56
+ declare const MachineContextTag: ServiceMap.Service<MachineContext<any, any, any>, MachineContext<any, any, any>>;
57
57
  /**
58
58
  * Guard handler implementation.
59
59
  * Receives params and context, returns Effect<boolean>.
package/dist/slot.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Context } from "effect";
1
+ import { ServiceMap } from "effect";
2
2
 
3
3
  //#region src/slot.ts
4
4
  /**
@@ -41,7 +41,7 @@ import { Context } from "effect";
41
41
  * Single module-level tag instead of per-machine allocation.
42
42
  * @internal
43
43
  */
44
- const MachineContextTag = Context.GenericTag("@effect-machine/Context");
44
+ const MachineContextTag = ServiceMap.Service("@effect-machine/Context");
45
45
  /**
46
46
  * Generic slot schema factory. Used internally by Guards() and Effects().
47
47
  * @internal
@@ -0,0 +1,18 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
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
+ }
14
+ return target;
15
+ };
16
+
17
+ //#endregion
18
+ export { __exportAll };