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.
- package/LICENSE +21 -0
- package/README.md +50 -54
- package/dist/actor.d.ts +8 -45
- package/dist/actor.js +157 -231
- package/dist/cluster/adapters/in-memory.d.ts +0 -1
- package/dist/cluster/adapters/in-memory.js +10 -5
- package/dist/cluster/entity-actor-ref.d.ts +2 -3
- package/dist/cluster/entity-actor-ref.js +14 -17
- package/dist/cluster/entity-machine.d.ts +2 -8
- package/dist/cluster/entity-machine.js +57 -34
- package/dist/cluster/index.js +1 -1
- package/dist/cluster/persistence.d.ts +0 -1
- package/dist/cluster/to-entity.d.ts +19 -21
- package/dist/cluster/to-entity.js +18 -19
- package/dist/errors.d.ts +11 -37
- package/dist/errors.js +12 -30
- package/dist/index.d.ts +4 -5
- package/dist/index.js +4 -5
- package/dist/inspection.d.ts +0 -1
- package/dist/inspection.js +24 -13
- package/dist/internal/brands.d.ts +0 -1
- package/dist/internal/event-advancement.d.ts +50 -0
- package/dist/internal/event-advancement.js +79 -0
- package/dist/internal/inspection.d.ts +5 -9
- package/dist/internal/inspection.js +31 -10
- package/dist/internal/machine-definition.d.ts +16 -0
- package/dist/internal/runtime.d.ts +1 -161
- package/dist/internal/runtime.js +191 -150
- package/dist/internal/transition.d.ts +4 -135
- package/dist/internal/transition.js +82 -157
- package/dist/internal/utils.d.ts +3 -40
- package/dist/internal/utils.js +2 -2
- package/dist/machine.d.ts +47 -137
- package/dist/machine.js +147 -215
- package/dist/schema.d.ts +42 -21
- package/dist/schema.js +28 -18
- package/dist/supervision.d.ts +1 -24
- package/dist/supervision.js +2 -3
- package/dist/testing.d.ts +15 -29
- package/dist/testing.js +76 -95
- package/package.json +19 -38
- package/dist/slot.d.ts +0 -159
- package/dist/slot.js +0 -165
- package/v3/dist/_virtual/_rolldown/runtime.js +0 -13
- package/v3/dist/actor.d.ts +0 -250
- package/v3/dist/actor.js +0 -577
- package/v3/dist/cluster/adapters/in-memory.d.ts +0 -15
- package/v3/dist/cluster/adapters/in-memory.js +0 -62
- package/v3/dist/cluster/entity-actor-ref.d.ts +0 -49
- package/v3/dist/cluster/entity-actor-ref.js +0 -19
- package/v3/dist/cluster/entity-machine.d.ts +0 -74
- package/v3/dist/cluster/entity-machine.js +0 -166
- package/v3/dist/cluster/index.d.ts +0 -6
- package/v3/dist/cluster/index.js +0 -6
- package/v3/dist/cluster/persistence.d.ts +0 -48
- package/v3/dist/cluster/persistence.js +0 -14
- package/v3/dist/cluster/to-entity.d.ts +0 -69
- package/v3/dist/cluster/to-entity.js +0 -59
- package/v3/dist/errors.d.ts +0 -95
- package/v3/dist/errors.js +0 -54
- package/v3/dist/index.d.ts +0 -11
- package/v3/dist/index.js +0 -9
- package/v3/dist/inspection.d.ts +0 -151
- package/v3/dist/inspection.js +0 -128
- package/v3/dist/internal/brands.d.ts +0 -50
- package/v3/dist/internal/inspection.d.ts +0 -11
- package/v3/dist/internal/inspection.js +0 -20
- package/v3/dist/internal/runtime.d.ts +0 -161
- package/v3/dist/internal/runtime.js +0 -360
- package/v3/dist/internal/transition.d.ts +0 -190
- package/v3/dist/internal/transition.js +0 -278
- package/v3/dist/internal/utils.d.ts +0 -101
- package/v3/dist/internal/utils.js +0 -75
- package/v3/dist/machine.d.ts +0 -398
- package/v3/dist/machine.js +0 -487
- package/v3/dist/schema.d.ts +0 -174
- package/v3/dist/schema.js +0 -206
- package/v3/dist/slot.d.ts +0 -158
- package/v3/dist/slot.js +0 -165
- package/v3/dist/supervision.d.ts +0 -97
- package/v3/dist/supervision.js +0 -42
- package/v3/dist/testing.d.ts +0 -151
- package/v3/dist/testing.js +0 -189
- /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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
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
|
|
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 {
|
|
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) =>
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
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")
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
yield*
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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.
|
|
99
|
+
}).pipe(Effect.ignore));
|
|
87
100
|
}
|
|
88
101
|
return (mailbox, replier) => Effect.gen(function* () {
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
|
|
151
|
-
|
|
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
|
|
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
|
|
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:
|
|
189
|
+
hydratedState: snapshotState,
|
|
167
190
|
initialVersion: snapshotVersion
|
|
168
191
|
};
|
|
169
192
|
}
|
package/dist/cluster/index.js
CHANGED
|
@@ -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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
* }).
|
|
54
|
-
*
|
|
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
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
}
|
|
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
|
-
* }).
|
|
36
|
-
*
|
|
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
|
-
|
|
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
|
-
}>,
|
|
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
|
-
}>,
|
|
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
|
-
}>,
|
|
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
|
-
}>,
|
|
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
|
-
}>,
|
|
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
|
-
}>,
|
|
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
|
-
}>,
|
|
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.
|
|
67
|
-
readonly actual: Schema.
|
|
68
|
-
}>,
|
|
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,
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
50
|
-
expected: Schema.
|
|
51
|
-
actual: Schema.
|
|
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,
|
|
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,
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
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
|
|
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,
|
|
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
|
-
|
|
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 };
|