effect-machine 0.9.0 → 0.10.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/README.md +76 -16
- package/dist/actor.d.ts +55 -89
- package/dist/actor.js +135 -30
- package/dist/cluster/entity-machine.js +5 -3
- package/dist/errors.d.ts +12 -1
- package/dist/errors.js +8 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/internal/transition.d.ts +26 -2
- package/dist/internal/transition.js +37 -8
- package/dist/internal/utils.d.ts +7 -2
- package/dist/machine.d.ts +66 -3
- package/dist/machine.js +65 -0
- package/dist/persistence/persistent-actor.js +52 -16
- package/dist/testing.js +57 -3
- package/package.json +9 -8
- package/{dist-v3 → v3/dist}/actor.d.ts +65 -78
- package/{dist-v3 → v3/dist}/actor.js +173 -35
- package/{dist-v3 → v3/dist}/cluster/entity-machine.d.ts +1 -1
- package/{dist-v3 → v3/dist}/cluster/entity-machine.js +8 -6
- package/{dist-v3 → v3/dist}/cluster/to-entity.d.ts +1 -1
- package/{dist-v3 → v3/dist}/cluster/to-entity.js +1 -1
- package/v3/dist/errors.d.ts +76 -0
- package/{dist-v3 → v3/dist}/errors.js +9 -2
- package/v3/dist/index.d.ts +13 -0
- package/v3/dist/index.js +13 -0
- package/{dist-v3 → v3/dist}/inspection.d.ts +53 -8
- package/v3/dist/inspection.js +156 -0
- package/{dist-v3 → v3/dist}/internal/brands.d.ts +1 -1
- package/{dist-v3 → v3/dist}/internal/inspection.d.ts +1 -1
- package/v3/dist/internal/inspection.js +20 -0
- package/{dist-v3 → v3/dist}/internal/transition.d.ts +35 -11
- package/{dist-v3 → v3/dist}/internal/transition.js +47 -15
- package/{dist-v3 → v3/dist}/internal/utils.d.ts +9 -4
- package/{dist-v3 → v3/dist}/internal/utils.js +1 -1
- package/{dist-v3 → v3/dist}/machine.d.ts +86 -9
- package/{dist-v3 → v3/dist}/machine.js +128 -2
- package/{dist-v3 → v3/dist}/persistence/adapter.d.ts +18 -5
- package/{dist-v3 → v3/dist}/persistence/adapter.js +1 -1
- package/{dist-v3 → v3/dist}/persistence/adapters/in-memory.d.ts +1 -1
- package/{dist-v3 → v3/dist}/persistence/adapters/in-memory.js +1 -1
- package/{dist-v3 → v3/dist}/persistence/persistent-actor.d.ts +7 -6
- package/{dist-v3 → v3/dist}/persistence/persistent-actor.js +58 -19
- package/{dist-v3 → v3/dist}/persistence/persistent-machine.d.ts +1 -1
- package/{dist-v3 → v3/dist}/persistence/persistent-machine.js +1 -1
- package/{dist-v3 → v3/dist}/schema.d.ts +1 -1
- package/{dist-v3 → v3/dist}/schema.js +5 -2
- package/{dist-v3 → v3/dist}/slot.d.ts +4 -3
- package/{dist-v3 → v3/dist}/slot.js +1 -1
- package/{dist-v3 → v3/dist}/testing.d.ts +14 -8
- package/{dist-v3 → v3/dist}/testing.js +60 -6
- package/dist-v3/errors.d.ts +0 -27
- package/dist-v3/index.d.ts +0 -12
- package/dist-v3/index.js +0 -13
- package/dist-v3/inspection.js +0 -48
- package/dist-v3/internal/inspection.js +0 -13
- /package/{dist-v3 → v3/dist}/_virtual/_rolldown/runtime.js +0 -0
- /package/{dist-v3 → v3/dist}/cluster/index.d.ts +0 -0
- /package/{dist-v3 → v3/dist}/cluster/index.js +0 -0
- /package/{dist-v3 → v3/dist}/internal/brands.js +0 -0
- /package/{dist-v3 → v3/dist}/persistence/index.d.ts +0 -0
- /package/{dist-v3 → v3/dist}/persistence/index.js +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { stubSystem } from "./internal/utils.js";
|
|
2
2
|
import { AssertionError } from "./errors.js";
|
|
3
3
|
import { BuiltMachine } from "./machine.js";
|
|
4
|
-
import { executeTransition } from "./internal/transition.js";
|
|
4
|
+
import { executeTransition, shouldPostpone } from "./internal/transition.js";
|
|
5
5
|
import { Effect, SubscriptionRef } from "effect";
|
|
6
|
-
//#region src
|
|
6
|
+
//#region src/testing.ts
|
|
7
7
|
/**
|
|
8
8
|
* Simulate a sequence of events through a machine without running an actor.
|
|
9
9
|
* Useful for testing state transitions in isolation.
|
|
@@ -26,18 +26,44 @@ import { Effect, SubscriptionRef } from "effect";
|
|
|
26
26
|
*/
|
|
27
27
|
const simulate = Effect.fn("effect-machine.simulate")(function* (input, events) {
|
|
28
28
|
const machine = input instanceof BuiltMachine ? input._inner : input;
|
|
29
|
+
const dummySend = Effect.fn("effect-machine.testing.simulate.send")((_event) => Effect.void);
|
|
29
30
|
const dummySelf = {
|
|
30
|
-
send:
|
|
31
|
+
send: dummySend,
|
|
32
|
+
cast: dummySend,
|
|
31
33
|
spawn: () => Effect.die("spawn not supported in simulation")
|
|
32
34
|
};
|
|
33
35
|
let currentState = machine.initial;
|
|
34
36
|
const states = [currentState];
|
|
37
|
+
const hasPostponeRules = machine.postponeRules.length > 0;
|
|
38
|
+
const postponed = [];
|
|
35
39
|
for (const event of events) {
|
|
36
|
-
|
|
40
|
+
if (hasPostponeRules && shouldPostpone(machine, currentState._tag, event._tag)) {
|
|
41
|
+
postponed.push(event);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const result = yield* executeTransition(machine, currentState, event, dummySelf, stubSystem, "simulation");
|
|
37
45
|
if (!result.transitioned) continue;
|
|
46
|
+
const prevTag = currentState._tag;
|
|
38
47
|
currentState = result.newState;
|
|
39
48
|
states.push(currentState);
|
|
40
49
|
if (machine.finalStates.has(currentState._tag)) break;
|
|
50
|
+
let drainTag = prevTag;
|
|
51
|
+
while (currentState._tag !== drainTag && postponed.length > 0) {
|
|
52
|
+
drainTag = currentState._tag;
|
|
53
|
+
const drained = postponed.splice(0);
|
|
54
|
+
for (const postponedEvent of drained) {
|
|
55
|
+
if (shouldPostpone(machine, currentState._tag, postponedEvent._tag)) {
|
|
56
|
+
postponed.push(postponedEvent);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const drainResult = yield* executeTransition(machine, currentState, postponedEvent, dummySelf, stubSystem, "simulation");
|
|
60
|
+
if (drainResult.transitioned) {
|
|
61
|
+
currentState = drainResult.newState;
|
|
62
|
+
states.push(currentState);
|
|
63
|
+
if (machine.finalStates.has(currentState._tag)) break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
41
67
|
}
|
|
42
68
|
return {
|
|
43
69
|
states,
|
|
@@ -113,20 +139,48 @@ const assertNeverReaches = Effect.fn("effect-machine.assertNeverReaches")(functi
|
|
|
113
139
|
*/
|
|
114
140
|
const createTestHarness = Effect.fn("effect-machine.createTestHarness")(function* (input, options) {
|
|
115
141
|
const machine = input instanceof BuiltMachine ? input._inner : input;
|
|
142
|
+
const dummySend = Effect.fn("effect-machine.testing.harness.send")((_event) => Effect.void);
|
|
116
143
|
const dummySelf = {
|
|
117
|
-
send:
|
|
144
|
+
send: dummySend,
|
|
145
|
+
cast: dummySend,
|
|
118
146
|
spawn: () => Effect.die("spawn not supported in test harness")
|
|
119
147
|
};
|
|
120
148
|
const stateRef = yield* SubscriptionRef.make(machine.initial);
|
|
149
|
+
const hasPostponeRules = machine.postponeRules.length > 0;
|
|
150
|
+
const postponed = [];
|
|
121
151
|
return {
|
|
122
152
|
state: stateRef,
|
|
123
153
|
send: Effect.fn("effect-machine.testHarness.send")(function* (event) {
|
|
124
154
|
const currentState = yield* SubscriptionRef.get(stateRef);
|
|
125
|
-
|
|
155
|
+
if (hasPostponeRules && shouldPostpone(machine, currentState._tag, event._tag)) {
|
|
156
|
+
postponed.push(event);
|
|
157
|
+
return currentState;
|
|
158
|
+
}
|
|
159
|
+
const result = yield* executeTransition(machine, currentState, event, dummySelf, stubSystem, "test-harness");
|
|
126
160
|
if (!result.transitioned) return currentState;
|
|
161
|
+
const prevTag = currentState._tag;
|
|
127
162
|
const newState = result.newState;
|
|
128
163
|
yield* SubscriptionRef.set(stateRef, newState);
|
|
129
164
|
if (options?.onTransition !== void 0) options.onTransition(currentState, event, newState);
|
|
165
|
+
let drainTag = prevTag;
|
|
166
|
+
let currentTag = newState._tag;
|
|
167
|
+
while (currentTag !== drainTag && postponed.length > 0) {
|
|
168
|
+
drainTag = currentTag;
|
|
169
|
+
const drained = postponed.splice(0);
|
|
170
|
+
for (const postponedEvent of drained) {
|
|
171
|
+
const state = yield* SubscriptionRef.get(stateRef);
|
|
172
|
+
if (shouldPostpone(machine, state._tag, postponedEvent._tag)) {
|
|
173
|
+
postponed.push(postponedEvent);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const drainResult = yield* executeTransition(machine, state, postponedEvent, dummySelf, stubSystem, "test-harness");
|
|
177
|
+
if (drainResult.transitioned) {
|
|
178
|
+
yield* SubscriptionRef.set(stateRef, drainResult.newState);
|
|
179
|
+
currentTag = drainResult.newState._tag;
|
|
180
|
+
if (options?.onTransition !== void 0) options.onTransition(state, postponedEvent, drainResult.newState);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
130
184
|
return newState;
|
|
131
185
|
}),
|
|
132
186
|
getState: SubscriptionRef.get(stateRef)
|
package/dist-v3/errors.d.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
//#region src-v3/errors.d.ts
|
|
2
|
-
declare const DuplicateActorError_base: any;
|
|
3
|
-
/** Attempted to spawn/restore actor with ID already in use */
|
|
4
|
-
declare class DuplicateActorError extends DuplicateActorError_base {}
|
|
5
|
-
declare const UnprovidedSlotsError_base: any;
|
|
6
|
-
/** Machine has unprovided effect slots */
|
|
7
|
-
declare class UnprovidedSlotsError extends UnprovidedSlotsError_base {}
|
|
8
|
-
declare const MissingSchemaError_base: any;
|
|
9
|
-
/** Operation requires schemas attached to machine */
|
|
10
|
-
declare class MissingSchemaError extends MissingSchemaError_base {}
|
|
11
|
-
declare const InvalidSchemaError_base: any;
|
|
12
|
-
/** State/Event schema has no variants */
|
|
13
|
-
declare class InvalidSchemaError extends InvalidSchemaError_base {}
|
|
14
|
-
declare const MissingMatchHandlerError_base: any;
|
|
15
|
-
/** $match called with missing handler for tag */
|
|
16
|
-
declare class MissingMatchHandlerError extends MissingMatchHandlerError_base {}
|
|
17
|
-
declare const SlotProvisionError_base: any;
|
|
18
|
-
/** Slot handler not found at runtime (internal error) */
|
|
19
|
-
declare class SlotProvisionError extends SlotProvisionError_base {}
|
|
20
|
-
declare const ProvisionValidationError_base: any;
|
|
21
|
-
/** Machine.build() validation failed - missing or extra handlers */
|
|
22
|
-
declare class ProvisionValidationError extends ProvisionValidationError_base {}
|
|
23
|
-
declare const AssertionError_base: any;
|
|
24
|
-
/** Assertion failed in testing utilities */
|
|
25
|
-
declare class AssertionError extends AssertionError_base {}
|
|
26
|
-
//#endregion
|
|
27
|
-
export { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError };
|
package/dist-v3/index.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Event, MachineEventSchema, MachineStateSchema, State } from "./schema.js";
|
|
2
|
-
import { PersistenceConfig, PersistentMachine, isPersistentMachine } from "./persistence/persistent-machine.js";
|
|
3
|
-
import { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
4
|
-
import { EffectHandlers, EffectSlot, EffectSlots, EffectsDef, EffectsSchema, GuardHandlers, GuardSlot, GuardSlots, GuardsDef, GuardsSchema, MachineContext, Slot } from "./slot.js";
|
|
5
|
-
import { PersistentActorRef, createPersistentActor, restorePersistentActor } from "./persistence/persistent-actor.js";
|
|
6
|
-
import { ActorMetadata, PersistedEvent, PersistenceAdapter, PersistenceAdapterTag, PersistenceError, RestoreFailure, RestoreResult, Snapshot, VersionConflictError } from "./persistence/adapter.js";
|
|
7
|
-
import { InMemoryPersistenceAdapter, makeInMemoryPersistenceAdapter } from "./persistence/adapters/in-memory.js";
|
|
8
|
-
import { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, ProvideHandlers, SpawnEffect, StateHandlerContext, Transition, machine_d_exports } from "./machine.js";
|
|
9
|
-
import { ActorRef, ActorSystem, Default, SystemEvent, SystemEventListener } from "./actor.js";
|
|
10
|
-
import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
11
|
-
import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, SpawnEvent, StopEvent, TransitionEvent, collectingInspector, consoleInspector, makeInspector } from "./inspection.js";
|
|
12
|
-
export { type ActorMetadata, type ActorRef, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type BuiltMachine, DuplicateActorError, type EffectEvent, type EffectSlots, type EffectsDef, type EffectsSchema, type ErrorEvent, Event, type EventReceivedEvent, type GuardHandlers, type GuardSlot, type GuardSlots, type GuardsDef, type GuardsSchema, type HandlerContext, InMemoryPersistenceAdapter, type InspectionEvent, type Inspector, Inspector as InspectorService, InvalidSchemaError, machine_d_exports as Machine, type MachineContext, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, MissingSchemaError, type PersistOptions, type PersistedEvent, type PersistenceAdapter, PersistenceAdapterTag, type PersistenceConfig, PersistenceError, type PersistentActorRef, type PersistentMachine, type ProvideHandlers, ProvisionValidationError, type RestoreFailure, type RestoreResult, type SimulationResult, Slot, type EffectHandlers as SlotEffectHandlers, type EffectSlot as SlotEffectSlot, SlotProvisionError, type Snapshot, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, type SystemEvent, type SystemEventListener, type TestHarness, type TestHarnessOptions, type Transition, type TransitionEvent, UnprovidedSlotsError, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, consoleInspector, createPersistentActor, createTestHarness, isPersistentMachine, makeInMemoryPersistenceAdapter, makeInspector, restorePersistentActor, simulate };
|
package/dist-v3/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Inspector, collectingInspector, consoleInspector, makeInspector } from "./inspection.js";
|
|
2
|
-
import { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
3
|
-
import { isPersistentMachine } from "./persistence/persistent-machine.js";
|
|
4
|
-
import { Slot } from "./slot.js";
|
|
5
|
-
import { machine_exports } from "./machine.js";
|
|
6
|
-
import { PersistenceAdapterTag, PersistenceError, VersionConflictError } from "./persistence/adapter.js";
|
|
7
|
-
import { createPersistentActor, restorePersistentActor } from "./persistence/persistent-actor.js";
|
|
8
|
-
import { ActorSystem, Default } from "./actor.js";
|
|
9
|
-
import { Event, State } from "./schema.js";
|
|
10
|
-
import { assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
11
|
-
import { InMemoryPersistenceAdapter, makeInMemoryPersistenceAdapter } from "./persistence/adapters/in-memory.js";
|
|
12
|
-
import "./persistence/index.js";
|
|
13
|
-
export { Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, InMemoryPersistenceAdapter, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, PersistenceAdapterTag, PersistenceError, ProvisionValidationError, Slot, SlotProvisionError, State, UnprovidedSlotsError, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, consoleInspector, createPersistentActor, createTestHarness, isPersistentMachine, makeInMemoryPersistenceAdapter, makeInspector, restorePersistentActor, simulate };
|
package/dist-v3/inspection.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { Context } from "effect";
|
|
2
|
-
//#region src-v3/inspection.ts
|
|
3
|
-
/**
|
|
4
|
-
* Inspector service tag - optional service for machine introspection
|
|
5
|
-
* Uses `any` types to allow variance flexibility when providing the service
|
|
6
|
-
*/
|
|
7
|
-
const Inspector = Context.GenericTag("@effect/machine/Inspector");
|
|
8
|
-
/**
|
|
9
|
-
* Create an inspector from a callback function.
|
|
10
|
-
*
|
|
11
|
-
* Type params accept either raw tagged types or Schema constructors:
|
|
12
|
-
* - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
|
|
13
|
-
* - `makeInspector<MyState, MyEvent>(cb)` — explicit tagged types
|
|
14
|
-
* - `makeInspector<typeof MyState, typeof MyEvent>(cb)` — schema constructors (auto-extracts `.Type`)
|
|
15
|
-
*/
|
|
16
|
-
const makeInspector = (onInspect) => ({ onInspect });
|
|
17
|
-
/**
|
|
18
|
-
* Console inspector that logs events in a readable format
|
|
19
|
-
*/
|
|
20
|
-
const consoleInspector = () => makeInspector((event) => {
|
|
21
|
-
const prefix = `[${event.actorId}]`;
|
|
22
|
-
switch (event.type) {
|
|
23
|
-
case "@machine.spawn":
|
|
24
|
-
console.log(prefix, "spawned →", event.initialState._tag);
|
|
25
|
-
break;
|
|
26
|
-
case "@machine.event":
|
|
27
|
-
console.log(prefix, "received", event.event._tag, "in", event.state._tag);
|
|
28
|
-
break;
|
|
29
|
-
case "@machine.transition":
|
|
30
|
-
console.log(prefix, event.fromState._tag, "→", event.toState._tag);
|
|
31
|
-
break;
|
|
32
|
-
case "@machine.effect":
|
|
33
|
-
console.log(prefix, event.effectType, "effect in", event.state._tag);
|
|
34
|
-
break;
|
|
35
|
-
case "@machine.error":
|
|
36
|
-
console.log(prefix, "error in", event.phase, event.state._tag, "-", event.error);
|
|
37
|
-
break;
|
|
38
|
-
case "@machine.stop":
|
|
39
|
-
console.log(prefix, "stopped in", event.finalState._tag);
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
/**
|
|
44
|
-
* Collecting inspector that stores events in an array for testing
|
|
45
|
-
*/
|
|
46
|
-
const collectingInspector = (events) => ({ onInspect: (event) => events.push(event) });
|
|
47
|
-
//#endregion
|
|
48
|
-
export { Inspector, collectingInspector, consoleInspector, makeInspector };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Clock, Effect } from "effect";
|
|
2
|
-
//#region src-v3/internal/inspection.ts
|
|
3
|
-
/**
|
|
4
|
-
* Emit an inspection event with timestamp from Clock.
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
const emitWithTimestamp = Effect.fn("effect-machine.emitWithTimestamp")(function* (inspector, makeEvent) {
|
|
8
|
-
if (inspector === void 0) return;
|
|
9
|
-
const timestamp = yield* Clock.currentTimeMillis;
|
|
10
|
-
yield* Effect.try(() => inspector.onInspect(makeEvent(timestamp))).pipe(Effect.ignore);
|
|
11
|
-
});
|
|
12
|
-
//#endregion
|
|
13
|
-
export { emitWithTimestamp };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|