effect-machine 0.17.1 → 0.18.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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -54
  3. package/dist/actor.d.ts +8 -45
  4. package/dist/actor.js +157 -231
  5. package/dist/cluster/adapters/in-memory.d.ts +0 -1
  6. package/dist/cluster/adapters/in-memory.js +10 -5
  7. package/dist/cluster/entity-actor-ref.d.ts +2 -3
  8. package/dist/cluster/entity-actor-ref.js +14 -17
  9. package/dist/cluster/entity-machine.d.ts +2 -8
  10. package/dist/cluster/entity-machine.js +57 -34
  11. package/dist/cluster/index.js +1 -1
  12. package/dist/cluster/persistence.d.ts +0 -1
  13. package/dist/cluster/to-entity.d.ts +19 -21
  14. package/dist/cluster/to-entity.js +18 -19
  15. package/dist/errors.d.ts +11 -37
  16. package/dist/errors.js +12 -30
  17. package/dist/index.d.ts +4 -5
  18. package/dist/index.js +4 -5
  19. package/dist/inspection.d.ts +0 -1
  20. package/dist/inspection.js +24 -13
  21. package/dist/internal/brands.d.ts +0 -1
  22. package/dist/internal/event-advancement.d.ts +50 -0
  23. package/dist/internal/event-advancement.js +79 -0
  24. package/dist/internal/inspection.d.ts +5 -9
  25. package/dist/internal/inspection.js +31 -10
  26. package/dist/internal/machine-definition.d.ts +16 -0
  27. package/dist/internal/runtime.d.ts +1 -161
  28. package/dist/internal/runtime.js +191 -150
  29. package/dist/internal/transition.d.ts +4 -135
  30. package/dist/internal/transition.js +82 -157
  31. package/dist/internal/utils.d.ts +3 -40
  32. package/dist/internal/utils.js +2 -2
  33. package/dist/machine.d.ts +47 -137
  34. package/dist/machine.js +147 -215
  35. package/dist/schema.d.ts +42 -21
  36. package/dist/schema.js +28 -18
  37. package/dist/supervision.d.ts +1 -24
  38. package/dist/supervision.js +2 -3
  39. package/dist/testing.d.ts +15 -29
  40. package/dist/testing.js +76 -95
  41. package/package.json +19 -38
  42. package/dist/slot.d.ts +0 -159
  43. package/dist/slot.js +0 -165
  44. package/v3/dist/_virtual/_rolldown/runtime.js +0 -13
  45. package/v3/dist/actor.d.ts +0 -250
  46. package/v3/dist/actor.js +0 -577
  47. package/v3/dist/cluster/adapters/in-memory.d.ts +0 -15
  48. package/v3/dist/cluster/adapters/in-memory.js +0 -62
  49. package/v3/dist/cluster/entity-actor-ref.d.ts +0 -49
  50. package/v3/dist/cluster/entity-actor-ref.js +0 -19
  51. package/v3/dist/cluster/entity-machine.d.ts +0 -74
  52. package/v3/dist/cluster/entity-machine.js +0 -166
  53. package/v3/dist/cluster/index.d.ts +0 -6
  54. package/v3/dist/cluster/index.js +0 -6
  55. package/v3/dist/cluster/persistence.d.ts +0 -48
  56. package/v3/dist/cluster/persistence.js +0 -14
  57. package/v3/dist/cluster/to-entity.d.ts +0 -69
  58. package/v3/dist/cluster/to-entity.js +0 -59
  59. package/v3/dist/errors.d.ts +0 -95
  60. package/v3/dist/errors.js +0 -54
  61. package/v3/dist/index.d.ts +0 -11
  62. package/v3/dist/index.js +0 -9
  63. package/v3/dist/inspection.d.ts +0 -151
  64. package/v3/dist/inspection.js +0 -128
  65. package/v3/dist/internal/brands.d.ts +0 -50
  66. package/v3/dist/internal/inspection.d.ts +0 -11
  67. package/v3/dist/internal/inspection.js +0 -20
  68. package/v3/dist/internal/runtime.d.ts +0 -161
  69. package/v3/dist/internal/runtime.js +0 -360
  70. package/v3/dist/internal/transition.d.ts +0 -190
  71. package/v3/dist/internal/transition.js +0 -278
  72. package/v3/dist/internal/utils.d.ts +0 -101
  73. package/v3/dist/internal/utils.js +0 -75
  74. package/v3/dist/machine.d.ts +0 -398
  75. package/v3/dist/machine.js +0 -487
  76. package/v3/dist/schema.d.ts +0 -174
  77. package/v3/dist/schema.js +0 -206
  78. package/v3/dist/slot.d.ts +0 -158
  79. package/v3/dist/slot.js +0 -165
  80. package/v3/dist/supervision.d.ts +0 -97
  81. package/v3/dist/supervision.js +0 -42
  82. package/v3/dist/testing.d.ts +0 -151
  83. package/v3/dist/testing.js +0 -189
  84. /package/{v3/dist/internal/brands.js → dist/internal/machine-definition.js} +0 -0
@@ -12,22 +12,19 @@ import { Effect, Option, Stream } from "effect";
12
12
  * yield* ref.send(OrderEvent.Process)
13
13
  * ```
14
14
  */
15
- const makeEntityActorRef = (client, entityId) => {
16
- const c = client;
17
- return {
18
- entityId,
19
- send: (event) => c.Send({ event }),
20
- ask: ((event) => c.Ask({ event })),
21
- snapshot: c.GetState(),
22
- watch: c.WatchState(),
23
- waitFor: (predicate) => Effect.gen(function* () {
24
- const current = yield* c.GetState();
25
- if (predicate(current)) return current;
26
- const result = yield* c.WatchState().pipe(Stream.filter(predicate), Stream.take(1), Stream.runHead);
27
- if (Option.isSome(result)) return result.value;
28
- return yield* new ActorStoppedError({ actorId: entityId });
29
- })
30
- };
31
- };
15
+ const makeEntityActorRef = (client, entityId) => ({
16
+ entityId,
17
+ send: (event) => client.Send({ event }),
18
+ ask: ((event) => client.Ask({ event })),
19
+ snapshot: client.GetState(),
20
+ watch: client.WatchState(),
21
+ waitFor: (predicate) => Effect.gen(function* () {
22
+ const current = yield* client.GetState();
23
+ if (predicate(current)) return current;
24
+ const result = yield* client.WatchState().pipe(Stream.filter(predicate), Stream.take(1), Stream.runHead);
25
+ if (Option.isSome(result)) return result.value;
26
+ return yield* ActorStoppedError.make({ actorId: entityId });
27
+ })
28
+ });
32
29
  //#endregion
33
30
  export { makeEntityActorRef };
@@ -1,24 +1,18 @@
1
- import { ProcessEventHooks } from "../internal/transition.js";
2
1
  import { Machine } from "../machine.js";
3
2
  import { EntityPersistenceConfig } from "./persistence.js";
4
3
  import { Duration, Layer, Schedule } from "effect";
5
4
  import { Entity } from "effect/unstable/cluster";
6
5
  import { Rpc } from "effect/unstable/rpc";
7
-
8
6
  //#region src/cluster/entity-machine.d.ts
9
7
  /**
10
8
  * Options for EntityMachine.layer
11
9
  */
12
- interface EntityMachineOptions<S, E> {
10
+ interface EntityMachineOptions<S> {
13
11
  /**
14
12
  * Initialize state from entity ID.
15
13
  * Called once when entity is first activated.
16
14
  */
17
15
  readonly initializeState?: (entityId: string) => S;
18
- /**
19
- * Optional hooks for inspection/tracing.
20
- */
21
- readonly hooks?: ProcessEventHooks<S, E>;
22
16
  /**
23
17
  * Maximum idle time before entity deactivation.
24
18
  * Forwarded to Entity.toLayerQueue.
@@ -65,7 +59,7 @@ declare const EntityMachine: {
65
59
  readonly _tag: string;
66
60
  }, E extends {
67
61
  readonly _tag: string;
68
- }, R, EntityType extends string, Rpcs extends Rpc.Any>(entity: Entity.Entity<EntityType, Rpcs>, machine: Machine<S, E, R, any, any, any>, options?: EntityMachineOptions<S, E>) => Layer.Layer<never, never, R>;
62
+ }, R, EntityType extends string, Rpcs extends Rpc.Any>(entity: Entity.Entity<EntityType, Rpcs>, machine: Machine<S, E, R, any, any>, options?: EntityMachineOptions<S>) => Layer.Layer<never, never, R>;
69
63
  };
70
64
  //#endregion
71
65
  export { EntityMachine, EntityMachineOptions };
@@ -1,6 +1,8 @@
1
- import { replay } from "../machine.js";
1
+ import { makeInspectionHooks } from "../internal/inspection.js";
2
+ import { Inspector } from "../inspection.js";
2
3
  import { createRuntime } from "../internal/runtime.js";
3
4
  import { ActorSystem, makeSystem } from "../actor.js";
5
+ import { replay } from "../machine.js";
4
6
  import { PersistenceAdapter } from "./persistence.js";
5
7
  import { Clock, Effect, Option, Queue, Ref, Stream, SubscriptionRef } from "effect";
6
8
  import { Entity } from "effect/unstable/cluster";
@@ -36,23 +38,30 @@ import { Entity } from "effect/unstable/cluster";
36
38
  const EntityMachine = { layer: (entity, machine, options) => {
37
39
  const persistence = options?.persistence;
38
40
  const build = Effect.gen(function* () {
39
- const entityId = yield* Effect.serviceOption(Entity.CurrentAddress).pipe(Effect.map((opt) => opt._tag === "Some" ? opt.value.entityId : ""));
41
+ const entityId = yield* Effect.serviceOption(Entity.CurrentAddress).pipe(Effect.map((opt) => {
42
+ if (opt._tag === "Some") return opt.value.entityId;
43
+ return "";
44
+ }));
45
+ const inspector = Option.getOrUndefined(yield* Effect.serviceOption(Inspector));
40
46
  const existingSystem = yield* Effect.serviceOption(ActorSystem);
41
- const system = Option.isSome(existingSystem) ? existingSystem.value : yield* makeSystem();
47
+ let system;
48
+ if (Option.isSome(existingSystem)) system = existingSystem.value;
49
+ else system = yield* makeSystem();
42
50
  const persistCtx = yield* hydratePersistence(persistence, entity, entityId, machine, options?.initializeState);
43
- const initialState = persistCtx.hydratedState ?? (options?.initializeState !== void 0 ? options.initializeState(entityId) : void 0);
44
- const machineWithState = initialState !== void 0 ? Object.create(machine, { initial: {
45
- value: initialState,
46
- enumerable: true
47
- } }) : machine;
51
+ let initialState = persistCtx.hydratedState;
52
+ if (initialState === void 0 && options?.initializeState !== void 0) initialState = options.initializeState(entityId);
53
+ let machineWithState = machine;
54
+ if (initialState !== void 0) machineWithState = machine._withInitial(initialState);
48
55
  const versionRef = yield* Ref.make(persistCtx.initialVersion);
49
56
  const computedInitial = initialState ?? machine.initial;
50
57
  const stateRef = yield* SubscriptionRef.make(computedInitial);
51
58
  const stoppedRef = yield* Ref.make(false);
52
59
  const eventQueue = yield* Queue.unbounded();
60
+ let hooks = void 0;
61
+ if (inspector !== void 0) hooks = makeInspectionHooks(entityId, inspector);
53
62
  const runtime = yield* createRuntime(machineWithState, system, {
54
63
  actorId: entityId,
55
- hooks: options?.hooks,
64
+ hooks,
56
65
  childIdPrefix: `${entityId}/`,
57
66
  cellResources: {
58
67
  stateRef,
@@ -65,15 +74,19 @@ const EntityMachine = { layer: (entity, machine, options) => {
65
74
  const { adapter: pAdapter, key } = persistCtx;
66
75
  const strategy = persistence?.strategy ?? "snapshot";
67
76
  const schedule = persistence?.snapshotSchedule;
68
- if (strategy === "snapshot") yield* SubscriptionRef.changes(runtime.stateRef).pipe(schedule !== void 0 ? Stream.schedule(schedule) : (s) => s, Stream.runForEach((state) => Effect.gen(function* () {
69
- const version = yield* Ref.get(versionRef);
70
- const now = yield* Clock.currentTimeMillis;
71
- yield* pAdapter.saveSnapshot(key, {
72
- state,
73
- version,
74
- timestamp: now
75
- });
76
- }).pipe(Effect.catch(() => Effect.void))), Effect.forkScoped);
77
+ if (strategy === "snapshot") {
78
+ let applySchedule = (s) => s;
79
+ if (schedule !== void 0) applySchedule = Stream.schedule(schedule);
80
+ yield* SubscriptionRef.changes(runtime.stateRef).pipe(applySchedule, Stream.runForEach((state) => Effect.gen(function* () {
81
+ const version = yield* Ref.get(versionRef);
82
+ const now = yield* Clock.currentTimeMillis;
83
+ yield* pAdapter.saveSnapshot(key, {
84
+ state,
85
+ version,
86
+ timestamp: now
87
+ });
88
+ }).pipe(Effect.ignore)), Effect.forkScoped);
89
+ }
77
90
  yield* Effect.addFinalizer(() => Effect.gen(function* () {
78
91
  const state = yield* SubscriptionRef.get(runtime.stateRef);
79
92
  const version = yield* Ref.get(versionRef);
@@ -83,14 +96,16 @@ const EntityMachine = { layer: (entity, machine, options) => {
83
96
  version,
84
97
  timestamp: now
85
98
  });
86
- }).pipe(Effect.catch(() => Effect.void)));
99
+ }).pipe(Effect.ignore));
87
100
  }
88
101
  return (mailbox, replier) => Effect.gen(function* () {
89
- const hasPersistence = persistCtx.adapter !== void 0;
90
- const journalCtx = hasPersistence && (persistence?.strategy ?? "snapshot") === "journal" ? {
91
- adapter: persistCtx.adapter,
102
+ const adapter = persistCtx.adapter;
103
+ const hasPersistence = adapter !== void 0;
104
+ let journalCtx = void 0;
105
+ if (adapter !== void 0 && (persistence?.strategy ?? "snapshot") === "journal") journalCtx = {
106
+ adapter,
92
107
  key: persistCtx.key
93
- } : void 0;
108
+ };
94
109
  while (true) {
95
110
  const request = yield* Queue.take(mailbox);
96
111
  switch (request.tag) {
@@ -105,7 +120,7 @@ const EntityMachine = { layer: (entity, machine, options) => {
105
120
  }
106
121
  case "Ask": {
107
122
  const event = request.payload.event;
108
- const reply = yield* runtime.ask(event);
123
+ const reply = yield* runtime.ask(event).pipe(Effect.orDie);
109
124
  if (journalCtx !== void 0) yield* persistEvent(journalCtx.adapter, journalCtx.key, versionRef, event);
110
125
  else if (hasPersistence) yield* Ref.update(versionRef, (v) => v + 1);
111
126
  yield* replier.succeed(request, reply);
@@ -116,10 +131,7 @@ const EntityMachine = { layer: (entity, machine, options) => {
116
131
  yield* replier.succeed(request, state);
117
132
  break;
118
133
  }
119
- case "WatchState":
120
- yield* replier.succeed(request, SubscriptionRef.changes(runtime.stateRef));
121
- break;
122
- default: break;
134
+ case "WatchState": yield* replier.succeed(request, SubscriptionRef.changes(runtime.stateRef));
123
135
  }
124
136
  }
125
137
  });
@@ -129,7 +141,9 @@ const EntityMachine = { layer: (entity, machine, options) => {
129
141
  if (options?.mailboxCapacity !== void 0) clusterOptions.mailboxCapacity = options.mailboxCapacity;
130
142
  if (options?.disableFatalDefects !== void 0) clusterOptions.disableFatalDefects = options.disableFatalDefects;
131
143
  if (options?.defectRetryPolicy !== void 0) clusterOptions.defectRetryPolicy = options.defectRetryPolicy;
132
- return entity.toLayerQueue(build.pipe(Effect.orDie), Object.keys(clusterOptions).length > 0 ? clusterOptions : void 0);
144
+ let resolvedClusterOptions = void 0;
145
+ if (Object.keys(clusterOptions).length > 0) resolvedClusterOptions = clusterOptions;
146
+ return entity.toLayerQueue(build.pipe(Effect.orDie), resolvedClusterOptions);
133
147
  } };
134
148
  const noPersistence = {
135
149
  adapter: void 0,
@@ -147,23 +161,32 @@ const hydratePersistence = (persistence, entityDef, entityId, machine, initializ
147
161
  };
148
162
  const maybeSnapshot = yield* adapter.loadSnapshot(key);
149
163
  if ((persistence.strategy ?? "snapshot") === "journal") {
150
- const baseState = Option.isSome(maybeSnapshot) ? maybeSnapshot.value.state : initializeState !== void 0 ? initializeState(entityId) : machine.initial;
151
- const snapshotVersion = Option.isSome(maybeSnapshot) ? maybeSnapshot.value.version : 0;
164
+ let baseState;
165
+ if (Option.isSome(maybeSnapshot)) baseState = maybeSnapshot.value.state;
166
+ else if (initializeState !== void 0) baseState = initializeState(entityId);
167
+ else baseState = machine.initial;
168
+ let snapshotVersion = 0;
169
+ if (Option.isSome(maybeSnapshot)) snapshotVersion = maybeSnapshot.value.version;
152
170
  const events = yield* adapter.loadEvents(key, snapshotVersion);
153
171
  if (events.length > 0) {
154
- const hydratedState = yield* replay(machine, events.map((e) => e.event), { from: baseState });
172
+ const eventValues = events.map((e) => e.event);
173
+ const hydratedState = yield* replay(machine, eventValues, { from: baseState });
155
174
  const lastEvent = events[events.length - 1];
175
+ let initialVersion = snapshotVersion;
176
+ if (lastEvent !== void 0) initialVersion = lastEvent.version;
156
177
  return {
157
178
  adapter,
158
179
  key,
159
180
  hydratedState,
160
- initialVersion: lastEvent !== void 0 ? lastEvent.version : snapshotVersion
181
+ initialVersion
161
182
  };
162
183
  }
184
+ let snapshotState = void 0;
185
+ if (Option.isSome(maybeSnapshot)) snapshotState = maybeSnapshot.value.state;
163
186
  return {
164
187
  adapter,
165
188
  key,
166
- hydratedState: Option.isSome(maybeSnapshot) ? maybeSnapshot.value.state : void 0,
189
+ hydratedState: snapshotState,
167
190
  initialVersion: snapshotVersion
168
191
  };
169
192
  }
@@ -1,5 +1,5 @@
1
- import { PersistenceAdapter } from "./persistence.js";
2
1
  import { toEntity } from "./to-entity.js";
2
+ import { PersistenceAdapter } from "./persistence.js";
3
3
  import { EntityMachine } from "./entity-machine.js";
4
4
  import { makeEntityActorRef } from "./entity-actor-ref.js";
5
5
  import { makeInMemoryPersistenceAdapter } from "./adapters/in-memory.js";
@@ -1,6 +1,5 @@
1
1
  import { PersistenceError, VersionConflictError } from "../errors.js";
2
2
  import { Context, Effect, Option, Schedule } from "effect";
3
-
4
3
  //#region src/cluster/persistence.d.ts
5
4
  /** Namespaced key preventing cross-type collisions (e.g. Order/123 vs User/123). */
6
5
  interface PersistenceKey {
@@ -1,9 +1,8 @@
1
+ import { MachineEventSchema, MachineStateSchema } from "../schema.js";
1
2
  import { Machine } from "../machine.js";
2
3
  import { Schema } from "effect";
3
4
  import { Entity } from "effect/unstable/cluster";
4
5
  import { Rpc } from "effect/unstable/rpc";
5
- import * as _$effect_unstable_rpc_RpcSchema0 from "effect/unstable/rpc/RpcSchema";
6
-
7
6
  //#region src/cluster/to-entity.d.ts
8
7
  /**
9
8
  * Options for toEntity.
@@ -14,18 +13,17 @@ interface ToEntityOptions {
14
13
  */
15
14
  readonly type: string;
16
15
  }
17
- /**
18
- * Default RPC protocol for entity machines.
19
- *
20
- * - `Send` - Send event to machine (fire-and-forget), returns new state
21
- * - `Ask` - Send event and get domain reply (typed via Event.reply() schemas)
22
- * - `GetState` - Get current state
23
- */
24
- type EntityRpcs<StateSchema extends Schema.Top, EventSchema extends Schema.Top> = readonly [Rpc.Rpc<"Send", Schema.Struct<{
25
- readonly event: EventSchema;
26
- }>, StateSchema>, Rpc.Rpc<"Ask", Schema.Struct<{
27
- readonly event: EventSchema;
28
- }>, typeof Schema.Unknown>, Rpc.Rpc<"GetState", typeof Schema.Void, StateSchema>];
16
+ declare const makeEntityProtocol: <StateSchema extends Schema.Top, EventSchema extends Schema.Top>(stateSchema: StateSchema, eventSchema: EventSchema) => (Rpc.Rpc<"Ask", {
17
+ event: EventSchema;
18
+ } extends (infer T) ? T extends {
19
+ event: EventSchema;
20
+ } ? T extends Schema.Struct.Fields ? Schema.Struct<T> : T : never : never, Schema.Unknown, Schema.Never, never, never> | Rpc.Rpc<"GetState", Schema.Void, StateSchema, Schema.Never, never, never> | Rpc.Rpc<"Send", {
21
+ event: EventSchema;
22
+ } extends (infer T_1) ? T_1 extends {
23
+ event: EventSchema;
24
+ } ? T_1 extends Schema.Struct.Fields ? Schema.Struct<T_1> : T_1 : never : never, StateSchema, Schema.Never, never, never> | Rpc.Rpc<"WatchState", Schema.Void, import("effect/unstable/rpc/RpcSchema").Stream<StateSchema, Schema.Never>, Schema.Never, never, never>)[];
25
+ /** RPC protocol owned by `toEntity`. */
26
+ type EntityRpcs<StateSchema extends Schema.Top, EventSchema extends Schema.Top> = ReturnType<typeof makeEntityProtocol<StateSchema, EventSchema>>[number];
29
27
  /**
30
28
  * Generate an Entity definition from a machine.
31
29
  *
@@ -50,8 +48,8 @@ type EntityRpcs<StateSchema extends Schema.Top, EventSchema extends Schema.Top>
50
48
  * state: OrderState,
51
49
  * event: OrderEvent,
52
50
  * initial: OrderState.Pending({ orderId: "" }),
53
- * }).pipe(
54
- * Machine.on(OrderState.Pending, OrderEvent.Ship, ...),
51
+ * }).on(OrderState.Pending, OrderEvent.Ship, ({ event }) =>
52
+ * OrderState.Shipped({ trackingId: event.trackingId }),
55
53
  * )
56
54
  *
57
55
  * const OrderEntity = toEntity(orderMachine, { type: "Order" })
@@ -61,10 +59,10 @@ declare const toEntity: <S extends {
61
59
  readonly _tag: string;
62
60
  }, E extends {
63
61
  readonly _tag: string;
64
- }, R>(machine: Machine<S, E, R, any, any, any>, options: ToEntityOptions) => Entity.Entity<string, Rpc.Rpc<"Send", Schema.Struct<{
65
- event: Schema.Schema<E>;
66
- }>, Schema.Schema<S>, Schema.Never, never, never> | Rpc.Rpc<"Ask", Schema.Struct<{
67
- event: Schema.Schema<E>;
68
- }>, Schema.Unknown, Schema.Never, never, never> | Rpc.Rpc<"GetState", Schema.Void, Schema.Schema<S>, Schema.Never, never, never> | Rpc.Rpc<"WatchState", Schema.Void, _$effect_unstable_rpc_RpcSchema0.Stream<Schema.Schema<S>, Schema.Never>, Schema.Never, never, never>>;
62
+ }, R, SD extends Record<string, Schema.Struct.Fields>, ED extends Record<string, Schema.Struct.Fields>>(machine: Machine<S, E, R, SD, ED>, options: ToEntityOptions) => Entity.Entity<string, EntityRpcs<MachineStateSchema<SD> & {
63
+ readonly Type: S;
64
+ }, MachineEventSchema<ED> & {
65
+ readonly Type: E;
66
+ }>>;
69
67
  //#endregion
70
68
  export { EntityRpcs, ToEntityOptions, toEntity };
@@ -1,4 +1,3 @@
1
- import { MissingSchemaError } from "../errors.js";
2
1
  import { Schema } from "effect";
3
2
  import { Entity } from "effect/unstable/cluster";
4
3
  import { Rpc } from "effect/unstable/rpc";
@@ -8,6 +7,21 @@ import { Rpc } from "effect/unstable/rpc";
8
7
  *
9
8
  * @module
10
9
  */
10
+ const makeEntityProtocol = (stateSchema, eventSchema) => [
11
+ Rpc.make("Send", {
12
+ payload: { event: eventSchema },
13
+ success: stateSchema
14
+ }),
15
+ Rpc.make("Ask", {
16
+ payload: { event: eventSchema },
17
+ success: Schema.Unknown
18
+ }),
19
+ Rpc.make("GetState", { success: stateSchema }),
20
+ Rpc.make("WatchState", {
21
+ success: stateSchema,
22
+ stream: true
23
+ })
24
+ ];
11
25
  /**
12
26
  * Generate an Entity definition from a machine.
13
27
  *
@@ -32,8 +46,8 @@ import { Rpc } from "effect/unstable/rpc";
32
46
  * state: OrderState,
33
47
  * event: OrderEvent,
34
48
  * initial: OrderState.Pending({ orderId: "" }),
35
- * }).pipe(
36
- * Machine.on(OrderState.Pending, OrderEvent.Ship, ...),
49
+ * }).on(OrderState.Pending, OrderEvent.Ship, ({ event }) =>
50
+ * OrderState.Shipped({ trackingId: event.trackingId }),
37
51
  * )
38
52
  *
39
53
  * const OrderEntity = toEntity(orderMachine, { type: "Order" })
@@ -42,22 +56,7 @@ import { Rpc } from "effect/unstable/rpc";
42
56
  const toEntity = (machine, options) => {
43
57
  const stateSchema = machine.stateSchema;
44
58
  const eventSchema = machine.eventSchema;
45
- if (stateSchema === void 0 || eventSchema === void 0) throw new MissingSchemaError({ operation: "toEntity" });
46
- return Entity.make(options.type, [
47
- Rpc.make("Send", {
48
- payload: { event: eventSchema },
49
- success: stateSchema
50
- }),
51
- Rpc.make("Ask", {
52
- payload: { event: eventSchema },
53
- success: Schema.Unknown
54
- }),
55
- Rpc.make("GetState", { success: stateSchema }),
56
- Rpc.make("WatchState", {
57
- success: stateSchema,
58
- stream: true
59
- })
60
- ]);
59
+ return Entity.make(options.type, makeEntityProtocol(stateSchema, eventSchema));
61
60
  };
62
61
  //#endregion
63
62
  export { toEntity };
package/dist/errors.d.ts CHANGED
@@ -1,72 +1,46 @@
1
1
  import { Schema } from "effect";
2
- import * as _$effect_Cause0 from "effect/Cause";
3
-
4
2
  //#region src/errors.d.ts
5
3
  declare const DuplicateActorError_base: Schema.Class<DuplicateActorError, Schema.TaggedStruct<"DuplicateActorError", {
6
4
  readonly actorId: Schema.String;
7
- }>, _$effect_Cause0.YieldableError>;
5
+ }>, import("effect/Cause").YieldableError>;
8
6
  /** Attempted to spawn/restore actor with ID already in use */
9
7
  declare class DuplicateActorError extends DuplicateActorError_base {}
10
- declare const MissingSchemaError_base: Schema.Class<MissingSchemaError, Schema.TaggedStruct<"MissingSchemaError", {
11
- readonly operation: Schema.String;
12
- }>, _$effect_Cause0.YieldableError>;
13
- /** Operation requires schemas attached to machine */
14
- declare class MissingSchemaError extends MissingSchemaError_base {}
15
8
  declare const InvalidSchemaError_base: Schema.Class<InvalidSchemaError, Schema.TaggedStruct<"InvalidSchemaError", {
16
9
  readonly message: Schema.String;
17
- }>, _$effect_Cause0.YieldableError>;
10
+ }>, import("effect/Cause").YieldableError>;
18
11
  /** State/Event schema has no variants */
19
12
  declare class InvalidSchemaError extends InvalidSchemaError_base {}
20
13
  declare const MissingMatchHandlerError_base: Schema.Class<MissingMatchHandlerError, Schema.TaggedStruct<"MissingMatchHandlerError", {
21
14
  readonly tag: Schema.String;
22
- }>, _$effect_Cause0.YieldableError>;
15
+ }>, import("effect/Cause").YieldableError>;
23
16
  /** $match called with missing handler for tag */
24
17
  declare class MissingMatchHandlerError extends MissingMatchHandlerError_base {}
25
- declare const SlotProvisionError_base: Schema.Class<SlotProvisionError, Schema.TaggedStruct<"SlotProvisionError", {
26
- readonly slotName: Schema.String;
27
- readonly slotType: Schema.Literal<"slot">;
28
- }>, _$effect_Cause0.YieldableError>;
29
- /** Slot handler not found at runtime (internal error) */
30
- declare class SlotProvisionError extends SlotProvisionError_base {}
31
- declare const ProvisionValidationError_base: Schema.Class<ProvisionValidationError, Schema.TaggedStruct<"ProvisionValidationError", {
32
- readonly missing: Schema.$Array<Schema.String>;
33
- readonly extra: Schema.$Array<Schema.String>;
34
- }>, _$effect_Cause0.YieldableError>;
35
- /** Slot provision validation failed — missing or extra handlers */
36
- declare class ProvisionValidationError extends ProvisionValidationError_base {}
37
18
  declare const AssertionError_base: Schema.Class<AssertionError, Schema.TaggedStruct<"AssertionError", {
38
19
  readonly message: Schema.String;
39
- }>, _$effect_Cause0.YieldableError>;
20
+ }>, import("effect/Cause").YieldableError>;
40
21
  /** Assertion failed in testing utilities */
41
22
  declare class AssertionError extends AssertionError_base {}
42
23
  declare const ActorStoppedError_base: Schema.Class<ActorStoppedError, Schema.TaggedStruct<"ActorStoppedError", {
43
24
  readonly actorId: Schema.String;
44
- }>, _$effect_Cause0.YieldableError>;
25
+ }>, import("effect/Cause").YieldableError>;
45
26
  /** Actor was stopped while a call/ask was pending */
46
27
  declare class ActorStoppedError extends ActorStoppedError_base {}
47
28
  declare const NoReplyError_base: Schema.Class<NoReplyError, Schema.TaggedStruct<"NoReplyError", {
48
29
  readonly actorId: Schema.String;
49
30
  readonly eventTag: Schema.String;
50
- }>, _$effect_Cause0.YieldableError>;
31
+ }>, import("effect/Cause").YieldableError>;
51
32
  /** ask() was used but the transition handler did not call reply */
52
33
  declare class NoReplyError extends NoReplyError_base {}
53
34
  declare const PersistenceError_base: Schema.Class<PersistenceError, Schema.TaggedStruct<"PersistenceError", {
54
35
  readonly message: Schema.String;
55
- }>, _$effect_Cause0.YieldableError>;
36
+ }>, import("effect/Cause").YieldableError>;
56
37
  /** Persistence adapter operation failed */
57
38
  declare class PersistenceError extends PersistenceError_base {}
58
- declare const SlotCodecError_base: Schema.Class<SlotCodecError, Schema.TaggedStruct<"SlotCodecError", {
59
- readonly slotName: Schema.String;
60
- readonly phase: Schema.Literals<readonly ["input", "output"]>;
61
- readonly message: Schema.String;
62
- }>, _$effect_Cause0.YieldableError>;
63
- /** Slot input/output schema validation failed */
64
- declare class SlotCodecError extends SlotCodecError_base {}
65
39
  declare const VersionConflictError_base: Schema.Class<VersionConflictError, Schema.TaggedStruct<"VersionConflictError", {
66
- readonly expected: Schema.Number;
67
- readonly actual: Schema.Number;
68
- }>, _$effect_Cause0.YieldableError>;
40
+ readonly expected: Schema.Finite;
41
+ readonly actual: Schema.Finite;
42
+ }>, import("effect/Cause").YieldableError>;
69
43
  /** Optimistic locking failure — stored version doesn't match expected */
70
44
  declare class VersionConflictError extends VersionConflictError_base {}
71
45
  //#endregion
72
- export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError };
46
+ export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, NoReplyError, PersistenceError, VersionConflictError };
package/dist/errors.js CHANGED
@@ -3,7 +3,7 @@ import { Schema } from "effect";
3
3
  /**
4
4
  * Typed error classes for effect-machine.
5
5
  *
6
- * All errors extend Schema.TaggedErrorClassClass for:
6
+ * All errors extend Schema.TaggedError for:
7
7
  * - Type-safe catching via Effect.catchTag
8
8
  * - Serialization support
9
9
  * - Composable error handling
@@ -11,44 +11,26 @@ import { Schema } from "effect";
11
11
  * @module
12
12
  */
13
13
  /** Attempted to spawn/restore actor with ID already in use */
14
- var DuplicateActorError = class extends Schema.TaggedErrorClass()("DuplicateActorError", { actorId: Schema.String }) {};
15
- /** Operation requires schemas attached to machine */
16
- var MissingSchemaError = class extends Schema.TaggedErrorClass()("MissingSchemaError", { operation: Schema.String }) {};
14
+ var DuplicateActorError = class extends Schema.TaggedError()("DuplicateActorError", { actorId: Schema.String }) {};
17
15
  /** State/Event schema has no variants */
18
- var InvalidSchemaError = class extends Schema.TaggedErrorClass()("InvalidSchemaError", { message: Schema.String }) {};
16
+ var InvalidSchemaError = class extends Schema.TaggedError()("InvalidSchemaError", { message: Schema.String }) {};
19
17
  /** $match called with missing handler for tag */
20
- var MissingMatchHandlerError = class extends Schema.TaggedErrorClass()("MissingMatchHandlerError", { tag: Schema.String }) {};
21
- /** Slot handler not found at runtime (internal error) */
22
- var SlotProvisionError = class extends Schema.TaggedErrorClass()("SlotProvisionError", {
23
- slotName: Schema.String,
24
- slotType: Schema.Literal("slot")
25
- }) {};
26
- /** Slot provision validation failed — missing or extra handlers */
27
- var ProvisionValidationError = class extends Schema.TaggedErrorClass()("ProvisionValidationError", {
28
- missing: Schema.Array(Schema.String),
29
- extra: Schema.Array(Schema.String)
30
- }) {};
18
+ var MissingMatchHandlerError = class extends Schema.TaggedError()("MissingMatchHandlerError", { tag: Schema.String }) {};
31
19
  /** Assertion failed in testing utilities */
32
- var AssertionError = class extends Schema.TaggedErrorClass()("AssertionError", { message: Schema.String }) {};
20
+ var AssertionError = class extends Schema.TaggedError()("AssertionError", { message: Schema.String }) {};
33
21
  /** Actor was stopped while a call/ask was pending */
34
- var ActorStoppedError = class extends Schema.TaggedErrorClass()("ActorStoppedError", { actorId: Schema.String }) {};
22
+ var ActorStoppedError = class extends Schema.TaggedError()("ActorStoppedError", { actorId: Schema.String }) {};
35
23
  /** ask() was used but the transition handler did not call reply */
36
- var NoReplyError = class extends Schema.TaggedErrorClass()("NoReplyError", {
24
+ var NoReplyError = class extends Schema.TaggedError()("NoReplyError", {
37
25
  actorId: Schema.String,
38
26
  eventTag: Schema.String
39
27
  }) {};
40
28
  /** Persistence adapter operation failed */
41
- var PersistenceError = class extends Schema.TaggedErrorClass()("PersistenceError", { message: Schema.String }) {};
42
- /** Slot input/output schema validation failed */
43
- var SlotCodecError = class extends Schema.TaggedErrorClass()("SlotCodecError", {
44
- slotName: Schema.String,
45
- phase: Schema.Literals(["input", "output"]),
46
- message: Schema.String
47
- }) {};
29
+ var PersistenceError = class extends Schema.TaggedError()("PersistenceError", { message: Schema.String }) {};
48
30
  /** Optimistic locking failure — stored version doesn't match expected */
49
- var VersionConflictError = class extends Schema.TaggedErrorClass()("VersionConflictError", {
50
- expected: Schema.Number,
51
- actual: Schema.Number
31
+ var VersionConflictError = class extends Schema.TaggedError()("VersionConflictError", {
32
+ expected: Schema.Finite,
33
+ actual: Schema.Finite
52
34
  }) {};
53
35
  //#endregion
54
- export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError };
36
+ export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, NoReplyError, PersistenceError, VersionConflictError };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,10 @@
1
1
  import { DeferReplyResult, ReplyResult } from "./internal/utils.js";
2
2
  import { Event, MachineEventSchema, MachineStateSchema, ReplyFields, State } from "./schema.js";
3
- import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError } from "./errors.js";
4
- import { HasSlotKeys, MachineContext, ProvideSlots, Slot, SlotCall, SlotCalls, SlotFnDef, SlotHandler, SlotInvocation, SlotRequest, SlotResult, SlotsDef, SlotsSchema } from "./slot.js";
5
- import { ActorExit, CellPhase, DefectPhase, Supervision } from "./supervision.js";
3
+ import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, NoReplyError, PersistenceError, VersionConflictError } from "./errors.js";
4
+ import { ActorExit, DefectPhase, Supervision } from "./supervision.js";
5
+ import { Durability, DurabilityCommit, HandlerContext, Lifecycle, Machine, MachineRef, MakeConfig, Recovery, RecoveryContext, StateHandlerContext, TaskOptions, TimeoutConfig, machine_d_exports } from "./machine.js";
6
6
  import { ProcessEventResult } from "./internal/transition.js";
7
- import { BackgroundEffect, Durability, DurabilityCommit, HandlerContext, Lifecycle, Machine, MachineRef, MakeConfig, Recovery, RecoveryContext, SpawnEffect, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, machine_d_exports } from "./machine.js";
8
7
  import { ActorRef, ActorRefSync, ActorScope, ActorSystem, ActorSystemService, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
9
8
  import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
10
9
  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 };
10
+ export { ActorExit, type ActorRef, type ActorRefSync, ActorScope, ActorStoppedError, type ActorSystemService as ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type DefectPhase, type DeferReplyResult, DuplicateActorError, type Durability, type DurabilityCommit, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type HandlerContext, type InspectionEvent, type InspectorService as Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, type Lifecycle, machine_d_exports as Machine, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, NoReplyError, PersistenceError, type ProcessEventResult, type Recovery, type RecoveryContext, type ReplyFields, type ReplyResult, type SimulationResult, 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 TransitionEvent, type TransitionInfo, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
package/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
- import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError } from "./errors.js";
1
+ import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, NoReplyError, PersistenceError, VersionConflictError } from "./errors.js";
2
+ import { Event, State } from "./schema.js";
2
3
  import { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
3
- import { Slot } from "./slot.js";
4
- import { machine_exports } from "./machine.js";
5
4
  import { ActorExit, Supervision } from "./supervision.js";
6
5
  import { ActorScope, ActorSystem, Default } from "./actor.js";
6
+ import { machine_exports } from "./machine.js";
7
7
  import { assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
8
- import { Event, State } from "./schema.js";
9
- export { ActorExit, ActorScope, ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, Slot, SlotCodecError, SlotProvisionError, State, Supervision, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
8
+ export { ActorExit, ActorScope, ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, NoReplyError, PersistenceError, State, Supervision, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
@@ -1,5 +1,4 @@
1
1
  import { Context, Effect, Schema } from "effect";
2
-
3
2
  //#region src/inspection.d.ts
4
3
  /**
5
4
  * Resolve a type param: if it's a Schema, extract `.Type`; otherwise use as-is.