effect-machine 0.10.0 → 0.11.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 +65 -62
- package/dist/actor.d.ts +26 -94
- package/dist/actor.js +38 -95
- package/dist/index.d.ts +3 -7
- package/dist/index.js +1 -6
- package/dist/internal/transition.d.ts +1 -1
- package/dist/internal/transition.js +1 -1
- package/dist/internal/utils.js +1 -5
- package/dist/machine.d.ts +31 -35
- package/dist/machine.js +63 -13
- package/package.json +2 -2
- package/v3/dist/actor.d.ts +25 -93
- package/v3/dist/actor.js +37 -94
- package/v3/dist/index.d.ts +3 -7
- package/v3/dist/index.js +1 -6
- package/v3/dist/internal/utils.js +1 -5
- package/v3/dist/machine.d.ts +31 -35
- package/v3/dist/machine.js +63 -13
- package/dist/persistence/adapter.d.ts +0 -135
- package/dist/persistence/adapter.js +0 -25
- package/dist/persistence/adapters/in-memory.d.ts +0 -32
- package/dist/persistence/adapters/in-memory.js +0 -174
- package/dist/persistence/index.d.ts +0 -5
- package/dist/persistence/index.js +0 -5
- package/dist/persistence/persistent-actor.d.ts +0 -50
- package/dist/persistence/persistent-actor.js +0 -404
- package/dist/persistence/persistent-machine.d.ts +0 -105
- package/dist/persistence/persistent-machine.js +0 -22
- package/v3/dist/persistence/adapter.d.ts +0 -138
- package/v3/dist/persistence/adapter.js +0 -25
- package/v3/dist/persistence/adapters/in-memory.d.ts +0 -32
- package/v3/dist/persistence/adapters/in-memory.js +0 -174
- package/v3/dist/persistence/index.d.ts +0 -5
- package/v3/dist/persistence/index.js +0 -5
- package/v3/dist/persistence/persistent-actor.d.ts +0 -50
- package/v3/dist/persistence/persistent-actor.js +0 -404
- package/v3/dist/persistence/persistent-machine.d.ts +0 -105
- package/v3/dist/persistence/persistent-machine.js +0 -22
package/README.md
CHANGED
|
@@ -208,7 +208,7 @@ machine
|
|
|
208
208
|
|
|
209
209
|
### Event Postpone
|
|
210
210
|
|
|
211
|
-
`.postpone()` — gen_statem-style event postpone. When a matching event arrives in the given state, it is buffered. After the next state transition (tag change), buffered events drain in FIFO order:
|
|
211
|
+
`.postpone()` — gen_statem-style event postpone. When a matching event arrives in the given state, it is buffered. After the next state transition (tag change), buffered events drain in FIFO order, looping until stable:
|
|
212
212
|
|
|
213
213
|
```ts
|
|
214
214
|
machine
|
|
@@ -257,6 +257,31 @@ const child = yield * parent.system.get("worker-1"); // Option<ActorRef>
|
|
|
257
257
|
|
|
258
258
|
Every actor always has a system — `Machine.spawn` creates an implicit one if no `ActorSystem` is in context.
|
|
259
259
|
|
|
260
|
+
### Persistence
|
|
261
|
+
|
|
262
|
+
Persistence is composed from primitives — no built-in adapter or framework:
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
// Snapshot persistence — observe state changes, save externally
|
|
266
|
+
yield * actor.changes.pipe(Stream.runForEach((state) => saveSnapshot(actor.id, state)));
|
|
267
|
+
|
|
268
|
+
// Event journal — observe transitions
|
|
269
|
+
yield * actor.transitions.pipe(Stream.runForEach(({ event }) => appendEvent(actor.id, event)));
|
|
270
|
+
|
|
271
|
+
// Restore from snapshot
|
|
272
|
+
const savedState = yield * loadSnapshot(id);
|
|
273
|
+
const actor = yield * Machine.spawn(machine, { hydrate: savedState });
|
|
274
|
+
|
|
275
|
+
// Restore from event log
|
|
276
|
+
const events = yield * loadEvents(id);
|
|
277
|
+
const state = yield * Machine.replay(machine, events);
|
|
278
|
+
const actor = yield * Machine.spawn(machine, { hydrate: state });
|
|
279
|
+
|
|
280
|
+
// Restore from snapshot + tail events
|
|
281
|
+
const state = yield * Machine.replay(machine, tailEvents, { from: snapshot });
|
|
282
|
+
const actor = yield * Machine.spawn(machine, { hydrate: state });
|
|
283
|
+
```
|
|
284
|
+
|
|
260
285
|
### System Observation
|
|
261
286
|
|
|
262
287
|
React to actors joining and leaving the system:
|
|
@@ -296,21 +321,6 @@ expect(result.states.map((s) => s._tag)).toEqual(["Idle", "Loading", "Done"]);
|
|
|
296
321
|
yield * assertPath(machine, events, ["Idle", "Loading", "Done"]);
|
|
297
322
|
```
|
|
298
323
|
|
|
299
|
-
## Documentation
|
|
300
|
-
|
|
301
|
-
See the [primer](./primer/) for comprehensive documentation:
|
|
302
|
-
|
|
303
|
-
| Topic | File | Description |
|
|
304
|
-
| ----------- | ----------------------------------------- | ------------------------------ |
|
|
305
|
-
| Overview | [index.md](./primer/index.md) | Navigation and quick reference |
|
|
306
|
-
| Basics | [basics.md](./primer/basics.md) | Core concepts |
|
|
307
|
-
| Handlers | [handlers.md](./primer/handlers.md) | Transitions, guards, reply |
|
|
308
|
-
| Effects | [effects.md](./primer/effects.md) | spawn, background, timeouts |
|
|
309
|
-
| Testing | [testing.md](./primer/testing.md) | simulate, harness, assertions |
|
|
310
|
-
| Actors | [actors.md](./primer/actors.md) | ActorSystem, ActorRef |
|
|
311
|
-
| Persistence | [persistence.md](./primer/persistence.md) | Snapshots, event sourcing |
|
|
312
|
-
| Gotchas | [gotchas.md](./primer/gotchas.md) | Common mistakes |
|
|
313
|
-
|
|
314
324
|
## API Quick Reference
|
|
315
325
|
|
|
316
326
|
### Building
|
|
@@ -330,58 +340,41 @@ See the [primer](./primer/) for comprehensive documentation:
|
|
|
330
340
|
| `.final(State.X)` | Mark final state |
|
|
331
341
|
| `.build({ slot: impl })` | Provide implementations, returns `BuiltMachine` (terminal) |
|
|
332
342
|
| `.build()` | Finalize no-slot machine, returns `BuiltMachine` (terminal) |
|
|
333
|
-
| `.persist(config)` | Enable persistence |
|
|
334
|
-
|
|
335
|
-
### State Constructors
|
|
336
|
-
|
|
337
|
-
| Method | Purpose |
|
|
338
|
-
| -------------------------------------- | ------------------------------ |
|
|
339
|
-
| `State.X.derive(source)` | Pick target fields from source |
|
|
340
|
-
| `State.X.derive(source, { field: v })` | Pick fields + apply overrides |
|
|
341
|
-
| `State.$is("X")(value)` | Type guard |
|
|
342
|
-
| `State.$match(value, { X: fn, ... })` | Pattern matching |
|
|
343
343
|
|
|
344
344
|
### Running
|
|
345
345
|
|
|
346
|
-
| Method
|
|
347
|
-
|
|
|
348
|
-
| `Machine.spawn(machine)`
|
|
349
|
-
| `Machine.spawn(machine, id)`
|
|
350
|
-
| `
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
| Function | Description |
|
|
355
|
-
| ------------------------------------------ | ---------------------------------------------------------------- |
|
|
356
|
-
| `simulate(machine, events)` | Run events, get all states (accepts `Machine` or `BuiltMachine`) |
|
|
357
|
-
| `createTestHarness(machine)` | Step-by-step testing (accepts `Machine` or `BuiltMachine`) |
|
|
358
|
-
| `assertPath(machine, events, path)` | Assert exact path |
|
|
359
|
-
| `assertReaches(machine, events, tag)` | Assert final state |
|
|
360
|
-
| `assertNeverReaches(machine, events, tag)` | Assert state never visited |
|
|
346
|
+
| Method | Purpose |
|
|
347
|
+
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
348
|
+
| `Machine.spawn(machine)` | Single actor, no registry. Caller manages lifetime via `actor.stop`. Auto-cleans up if `Scope` present. |
|
|
349
|
+
| `Machine.spawn(machine, id)` | Same as above with custom ID |
|
|
350
|
+
| `Machine.spawn(machine, { hydrate: s })` | Restore from saved state — re-runs spawn effects for that state |
|
|
351
|
+
| `Machine.replay(machine, events)` | Fold events through handlers to compute state (for event sourcing restore) |
|
|
352
|
+
| `system.spawn(id, machine)` | Registry, lookup by ID, bulk ops. Cleans up on system teardown. |
|
|
361
353
|
|
|
362
354
|
### Actor
|
|
363
355
|
|
|
364
|
-
| Method | Description
|
|
365
|
-
| -------------------------------- |
|
|
366
|
-
| `actor.send(event)` | Fire-and-forget (queue event)
|
|
367
|
-
| `actor.cast(event)` | Alias for send (OTP gen_server:cast)
|
|
368
|
-
| `actor.call(event)` | Request-reply, returns `ProcessEventResult`
|
|
369
|
-
| `actor.ask<R>(event)` | Typed domain reply from handler
|
|
370
|
-
| `actor.snapshot` | Get current state
|
|
371
|
-
| `actor.matches(tag)` | Check state tag
|
|
372
|
-
| `actor.can(event)` | Can handle event?
|
|
373
|
-
| `actor.changes` | Stream of changes
|
|
374
|
-
| `actor.
|
|
375
|
-
| `actor.
|
|
376
|
-
| `actor.
|
|
377
|
-
| `actor.
|
|
378
|
-
| `actor.
|
|
379
|
-
| `actor.sync.
|
|
380
|
-
| `actor.sync.
|
|
381
|
-
| `actor.sync.
|
|
382
|
-
| `actor.sync.
|
|
383
|
-
| `actor.
|
|
384
|
-
| `actor.
|
|
356
|
+
| Method | Description |
|
|
357
|
+
| -------------------------------- | ----------------------------------------------- |
|
|
358
|
+
| `actor.send(event)` | Fire-and-forget (queue event) |
|
|
359
|
+
| `actor.cast(event)` | Alias for send (OTP gen_server:cast) |
|
|
360
|
+
| `actor.call(event)` | Request-reply, returns `ProcessEventResult` |
|
|
361
|
+
| `actor.ask<R>(event)` | Typed domain reply from handler |
|
|
362
|
+
| `actor.snapshot` | Get current state |
|
|
363
|
+
| `actor.matches(tag)` | Check state tag |
|
|
364
|
+
| `actor.can(event)` | Can handle event? |
|
|
365
|
+
| `actor.changes` | Stream of state changes |
|
|
366
|
+
| `actor.transitions` | Stream of `{ fromState, toState, event }` edges |
|
|
367
|
+
| `actor.waitFor(State.X)` | Wait for state (constructor or fn) |
|
|
368
|
+
| `actor.awaitFinal` | Wait final state |
|
|
369
|
+
| `actor.sendAndWait(ev, State.X)` | Send + wait for state |
|
|
370
|
+
| `actor.subscribe(fn)` | Sync callback |
|
|
371
|
+
| `actor.sync.send(event)` | Sync fire-and-forget (for UI) |
|
|
372
|
+
| `actor.sync.stop()` | Sync stop |
|
|
373
|
+
| `actor.sync.snapshot()` | Sync get state |
|
|
374
|
+
| `actor.sync.matches(tag)` | Sync check state tag |
|
|
375
|
+
| `actor.sync.can(event)` | Sync can handle event? |
|
|
376
|
+
| `actor.system` | Access the actor's `ActorSystem` |
|
|
377
|
+
| `actor.children` | Child actors (`ReadonlyMap`) |
|
|
385
378
|
|
|
386
379
|
### ActorSystem
|
|
387
380
|
|
|
@@ -394,6 +387,16 @@ See the [primer](./primer/) for comprehensive documentation:
|
|
|
394
387
|
| `system.subscribe(fn)` | Sync callback for spawn/stop events |
|
|
395
388
|
| `system.events` | Async `Stream<SystemEvent>` for spawn/stop |
|
|
396
389
|
|
|
390
|
+
### Testing
|
|
391
|
+
|
|
392
|
+
| Function | Description |
|
|
393
|
+
| ------------------------------------------ | ---------------------------------------------------------------- |
|
|
394
|
+
| `simulate(machine, events)` | Run events, get all states (accepts `Machine` or `BuiltMachine`) |
|
|
395
|
+
| `createTestHarness(machine)` | Step-by-step testing (accepts `Machine` or `BuiltMachine`) |
|
|
396
|
+
| `assertPath(machine, events, path)` | Assert exact path |
|
|
397
|
+
| `assertReaches(machine, events, tag)` | Assert final state |
|
|
398
|
+
| `assertNeverReaches(machine, events, tag)` | Assert state never visited |
|
|
399
|
+
|
|
397
400
|
## License
|
|
398
401
|
|
|
399
402
|
MIT
|
package/dist/actor.d.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { EffectsDef, GuardsDef, MachineContext } from "./slot.js";
|
|
2
|
-
import { PersistentMachine } from "./persistence/persistent-machine.js";
|
|
3
2
|
import { ActorStoppedError, DuplicateActorError, NoReplyError } from "./errors.js";
|
|
4
3
|
import { ProcessEventError, ProcessEventHooks, ProcessEventResult, processEventCore, resolveTransition, runSpawnEffects } from "./internal/transition.js";
|
|
5
|
-
import { PersistentActorRef } from "./persistence/persistent-actor.js";
|
|
6
|
-
import { ActorMetadata, PersistenceAdapterTag, PersistenceError, RestoreResult, VersionConflictError } from "./persistence/adapter.js";
|
|
7
4
|
import { BuiltMachine, Machine, MachineRef } from "./machine.js";
|
|
8
|
-
import { Deferred, Effect, Layer, Option, Queue, Ref, Scope, ServiceMap, Stream, SubscriptionRef } from "effect";
|
|
5
|
+
import { Deferred, Effect, Layer, Option, PubSub, Queue, Ref, Scope, ServiceMap, Stream, SubscriptionRef } from "effect";
|
|
9
6
|
import * as effect_Tracer0 from "effect/Tracer";
|
|
10
7
|
|
|
11
8
|
//#region src/actor.d.ts
|
|
@@ -39,6 +36,15 @@ interface ActorRefSync<State extends {
|
|
|
39
36
|
readonly matches: (tag: State["_tag"]) => boolean;
|
|
40
37
|
readonly can: (event: Event) => boolean;
|
|
41
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Information about a successful transition.
|
|
41
|
+
* Emitted on the `transitions` stream after each accepted event.
|
|
42
|
+
*/
|
|
43
|
+
interface TransitionInfo<State, Event> {
|
|
44
|
+
readonly fromState: State;
|
|
45
|
+
readonly toState: State;
|
|
46
|
+
readonly event: Event;
|
|
47
|
+
}
|
|
42
48
|
interface ActorRef<State extends {
|
|
43
49
|
readonly _tag: string;
|
|
44
50
|
}, Event> {
|
|
@@ -70,6 +76,14 @@ interface ActorRef<State extends {
|
|
|
70
76
|
readonly can: (event: Event) => Effect.Effect<boolean>;
|
|
71
77
|
/** Stream of state changes. */
|
|
72
78
|
readonly changes: Stream.Stream<State>;
|
|
79
|
+
/**
|
|
80
|
+
* Stream of accepted transitions (edge stream).
|
|
81
|
+
*
|
|
82
|
+
* Emits `{ fromState, toState, event }` on every successful transition,
|
|
83
|
+
* including same-state reenters. PubSub-backed — late subscribers miss
|
|
84
|
+
* past edges. This is observational, not a durability guarantee.
|
|
85
|
+
*/
|
|
86
|
+
readonly transitions: Stream.Stream<TransitionInfo<State, Event>>;
|
|
73
87
|
/** Wait for a state matching predicate or variant (includes current snapshot). */
|
|
74
88
|
readonly waitFor: {
|
|
75
89
|
(predicate: (state: State) => boolean): Effect.Effect<State>;
|
|
@@ -123,54 +137,17 @@ interface ActorSystem {
|
|
|
123
137
|
/**
|
|
124
138
|
* Spawn a new actor with the given machine.
|
|
125
139
|
*
|
|
126
|
-
* For regular machines, returns ActorRef.
|
|
127
|
-
* For persistent machines (created with Machine.persist), returns PersistentActorRef.
|
|
128
|
-
*
|
|
129
|
-
* All effect slots must be provided via `.build()` before spawning.
|
|
130
|
-
*
|
|
131
140
|
* @example
|
|
132
141
|
* ```ts
|
|
133
|
-
* // Regular machine (built)
|
|
134
142
|
* const built = machine.build({ fetchData: ... })
|
|
135
143
|
* const actor = yield* system.spawn("my-actor", built);
|
|
136
|
-
*
|
|
137
|
-
* // Persistent machine (auto-detected)
|
|
138
|
-
* const persistentActor = yield* system.spawn("my-actor", persistentMachine);
|
|
139
|
-
* persistentActor.persist; // available
|
|
140
|
-
* persistentActor.version; // available
|
|
141
|
-
* ```
|
|
142
|
-
*/
|
|
143
|
-
readonly spawn: {
|
|
144
|
-
<S extends {
|
|
145
|
-
readonly _tag: string;
|
|
146
|
-
}, E extends {
|
|
147
|
-
readonly _tag: string;
|
|
148
|
-
}, R>(id: string, machine: BuiltMachine<S, E, R>): Effect.Effect<ActorRef<S, E>, DuplicateActorError, R>;
|
|
149
|
-
<S extends {
|
|
150
|
-
readonly _tag: string;
|
|
151
|
-
}, E extends {
|
|
152
|
-
readonly _tag: string;
|
|
153
|
-
}, R>(id: string, machine: PersistentMachine<S, E, R>): Effect.Effect<PersistentActorRef<S, E, R>, PersistenceError | VersionConflictError | DuplicateActorError, R | PersistenceAdapterTag>;
|
|
154
|
-
};
|
|
155
|
-
/**
|
|
156
|
-
* Restore an actor from persistence.
|
|
157
|
-
* Returns None if no persisted state exists for the given ID.
|
|
158
|
-
*
|
|
159
|
-
* @example
|
|
160
|
-
* ```ts
|
|
161
|
-
* const maybeActor = yield* system.restore("order-1", persistentMachine);
|
|
162
|
-
* if (Option.isSome(maybeActor)) {
|
|
163
|
-
* const actor = maybeActor.value;
|
|
164
|
-
* const state = yield* actor.snapshot;
|
|
165
|
-
* console.log(`Restored to state: ${state._tag}`);
|
|
166
|
-
* }
|
|
167
144
|
* ```
|
|
168
145
|
*/
|
|
169
|
-
readonly
|
|
146
|
+
readonly spawn: <S extends {
|
|
170
147
|
readonly _tag: string;
|
|
171
148
|
}, E extends {
|
|
172
149
|
readonly _tag: string;
|
|
173
|
-
}, R>(id: string, machine:
|
|
150
|
+
}, R>(id: string, machine: BuiltMachine<S, E, R>) => Effect.Effect<ActorRef<S, E>, DuplicateActorError, R>;
|
|
174
151
|
/**
|
|
175
152
|
* Get an existing actor by ID
|
|
176
153
|
*/
|
|
@@ -194,53 +171,6 @@ interface ActorSystem {
|
|
|
194
171
|
* Returns an unsubscribe function.
|
|
195
172
|
*/
|
|
196
173
|
readonly subscribe: (fn: SystemEventListener) => () => void;
|
|
197
|
-
/**
|
|
198
|
-
* List all persisted actor metadata.
|
|
199
|
-
* Returns empty array if adapter doesn't support registry.
|
|
200
|
-
*
|
|
201
|
-
* @example
|
|
202
|
-
* ```ts
|
|
203
|
-
* const actors = yield* system.listPersisted();
|
|
204
|
-
* for (const meta of actors) {
|
|
205
|
-
* console.log(`${meta.id}: ${meta.stateTag} (v${meta.version})`);
|
|
206
|
-
* }
|
|
207
|
-
* ```
|
|
208
|
-
*/
|
|
209
|
-
readonly listPersisted: () => Effect.Effect<ReadonlyArray<ActorMetadata>, PersistenceError, PersistenceAdapterTag>;
|
|
210
|
-
/**
|
|
211
|
-
* Restore multiple actors by ID.
|
|
212
|
-
* Returns both successfully restored actors and failures.
|
|
213
|
-
*
|
|
214
|
-
* @example
|
|
215
|
-
* ```ts
|
|
216
|
-
* const result = yield* system.restoreMany(["order-1", "order-2"], orderMachine);
|
|
217
|
-
* console.log(`Restored: ${result.restored.length}, Failed: ${result.failed.length}`);
|
|
218
|
-
* ```
|
|
219
|
-
*/
|
|
220
|
-
readonly restoreMany: <S extends {
|
|
221
|
-
readonly _tag: string;
|
|
222
|
-
}, E extends {
|
|
223
|
-
readonly _tag: string;
|
|
224
|
-
}, R>(ids: ReadonlyArray<string>, machine: PersistentMachine<S, E, R>) => Effect.Effect<RestoreResult<S, E, R>, never, R | PersistenceAdapterTag>;
|
|
225
|
-
/**
|
|
226
|
-
* Restore all persisted actors for a machine type.
|
|
227
|
-
* Uses adapter registry if available, otherwise returns empty result.
|
|
228
|
-
*
|
|
229
|
-
* @example
|
|
230
|
-
* ```ts
|
|
231
|
-
* const result = yield* system.restoreAll(orderMachine, {
|
|
232
|
-
* filter: (meta) => meta.stateTag !== "Done"
|
|
233
|
-
* });
|
|
234
|
-
* console.log(`Restored ${result.restored.length} active orders`);
|
|
235
|
-
* ```
|
|
236
|
-
*/
|
|
237
|
-
readonly restoreAll: <S extends {
|
|
238
|
-
readonly _tag: string;
|
|
239
|
-
}, E extends {
|
|
240
|
-
readonly _tag: string;
|
|
241
|
-
}, R>(machine: PersistentMachine<S, E, R>, options?: {
|
|
242
|
-
filter?: (meta: ActorMetadata) => boolean;
|
|
243
|
-
}) => Effect.Effect<RestoreResult<S, E, R>, PersistenceError, R | PersistenceAdapterTag>;
|
|
244
174
|
}
|
|
245
175
|
/**
|
|
246
176
|
* ActorSystem service tag
|
|
@@ -253,13 +183,13 @@ type Listeners<S> = Set<(state: S) => void>;
|
|
|
253
183
|
*/
|
|
254
184
|
declare const notifyListeners: <S>(listeners: Listeners<S>, state: S) => void;
|
|
255
185
|
/**
|
|
256
|
-
* Build core ActorRef methods
|
|
186
|
+
* Build core ActorRef methods.
|
|
257
187
|
*/
|
|
258
188
|
declare const buildActorRefCore: <S extends {
|
|
259
189
|
readonly _tag: string;
|
|
260
190
|
}, E extends {
|
|
261
191
|
readonly _tag: string;
|
|
262
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(id: string, machine: Machine<S, E, R, any, any, GD, EFD>, stateRef: SubscriptionRef.SubscriptionRef<S>, eventQueue: Queue.Queue<QueuedEvent<E>>, stoppedRef: Ref.Ref<boolean>, listeners: Listeners<S>, stop: Effect.Effect<void>, system: ActorSystem, childrenMap: ReadonlyMap<string, ActorRef<AnyState, unknown>>, pendingReplies: Set<Deferred.Deferred<unknown, unknown>>) => ActorRef<S, E>;
|
|
192
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(id: string, machine: Machine<S, E, R, any, any, GD, EFD>, stateRef: SubscriptionRef.SubscriptionRef<S>, eventQueue: Queue.Queue<QueuedEvent<E>>, stoppedRef: Ref.Ref<boolean>, listeners: Listeners<S>, stop: Effect.Effect<void>, system: ActorSystem, childrenMap: ReadonlyMap<string, ActorRef<AnyState, unknown>>, pendingReplies: Set<Deferred.Deferred<unknown, unknown>>, transitionsPubSub?: PubSub.PubSub<TransitionInfo<S, E>>) => ActorRef<S, E>;
|
|
263
193
|
/**
|
|
264
194
|
* Create and start an actor for a machine
|
|
265
195
|
*/
|
|
@@ -267,7 +197,9 @@ declare const createActor: <S extends {
|
|
|
267
197
|
readonly _tag: string;
|
|
268
198
|
}, E extends {
|
|
269
199
|
readonly _tag: string;
|
|
270
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(id: string, machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD
|
|
200
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(id: string, machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, options?: {
|
|
201
|
+
initialState?: S;
|
|
202
|
+
} | undefined) => Effect.Effect<ActorRef<S, E>, never, Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, effect_Tracer0.ParentSpan> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope> | Exclude<Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>, effect_Tracer0.ParentSpan>>;
|
|
271
203
|
/** Fail all pending call/ask Deferreds with ActorStoppedError. Safe to call multiple times. */
|
|
272
204
|
declare const settlePendingReplies: (pendingReplies: Set<Deferred.Deferred<unknown, unknown>>, actorId: string) => Effect.Effect<void, never, never>;
|
|
273
205
|
/**
|
|
@@ -275,4 +207,4 @@ declare const settlePendingReplies: (pendingReplies: Set<Deferred.Deferred<unkno
|
|
|
275
207
|
*/
|
|
276
208
|
declare const Default: Layer.Layer<ActorSystem, never, never>;
|
|
277
209
|
//#endregion
|
|
278
|
-
export { ActorRef, ActorRefSync, ActorSystem, Default, Listeners, type ProcessEventError, type ProcessEventHooks, type ProcessEventResult, QueuedEvent, SystemEvent, SystemEventListener, buildActorRefCore, createActor, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
|
|
210
|
+
export { ActorRef, ActorRefSync, ActorSystem, Default, Listeners, type ProcessEventError, type ProcessEventHooks, type ProcessEventResult, QueuedEvent, SystemEvent, SystemEventListener, TransitionInfo, buildActorRefCore, createActor, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
|
package/dist/actor.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { Inspector } from "./inspection.js";
|
|
2
2
|
import { INTERNAL_INIT_EVENT } from "./internal/utils.js";
|
|
3
3
|
import { ActorStoppedError, DuplicateActorError, NoReplyError } from "./errors.js";
|
|
4
|
-
import { isPersistentMachine } from "./persistence/persistent-machine.js";
|
|
5
4
|
import { emitWithTimestamp } from "./internal/inspection.js";
|
|
6
5
|
import { processEventCore, resolveTransition, runSpawnEffects, shouldPostpone } from "./internal/transition.js";
|
|
7
|
-
import { PersistenceAdapterTag, PersistenceError } from "./persistence/adapter.js";
|
|
8
|
-
import { createPersistentActor, restorePersistentActor } from "./persistence/persistent-actor.js";
|
|
9
6
|
import { Cause, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, Option, PubSub, Queue, Ref, Scope, Semaphore, ServiceMap, Stream, SubscriptionRef } from "effect";
|
|
10
7
|
//#region src/actor.ts
|
|
11
8
|
/**
|
|
@@ -29,9 +26,9 @@ const notifyListeners = (listeners, state) => {
|
|
|
29
26
|
} catch {}
|
|
30
27
|
};
|
|
31
28
|
/**
|
|
32
|
-
* Build core ActorRef methods
|
|
29
|
+
* Build core ActorRef methods.
|
|
33
30
|
*/
|
|
34
|
-
const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listeners, stop, system, childrenMap, pendingReplies) => {
|
|
31
|
+
const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listeners, stop, system, childrenMap, pendingReplies, transitionsPubSub) => {
|
|
35
32
|
const send = Effect.fn("effect-machine.actor.send")(function* (event) {
|
|
36
33
|
if (yield* Ref.get(stoppedRef)) return;
|
|
37
34
|
yield* Queue.offer(eventQueue, {
|
|
@@ -119,6 +116,7 @@ const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listen
|
|
|
119
116
|
matches,
|
|
120
117
|
can,
|
|
121
118
|
changes: SubscriptionRef.changes(stateRef),
|
|
119
|
+
transitions: transitionsPubSub !== void 0 ? Stream.fromPubSub(transitionsPubSub) : Stream.empty,
|
|
122
120
|
waitFor,
|
|
123
121
|
awaitFinal,
|
|
124
122
|
sendAndWait,
|
|
@@ -149,7 +147,8 @@ const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listen
|
|
|
149
147
|
/**
|
|
150
148
|
* Create and start an actor for a machine
|
|
151
149
|
*/
|
|
152
|
-
const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machine) {
|
|
150
|
+
const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machine, options) {
|
|
151
|
+
const initial = options?.initialState ?? machine.initial;
|
|
153
152
|
yield* Effect.annotateCurrentSpan("effect_machine.actor.id", id);
|
|
154
153
|
const existingSystem = yield* Effect.serviceOption(ActorSystem);
|
|
155
154
|
let system;
|
|
@@ -184,20 +183,20 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
184
183
|
return child;
|
|
185
184
|
})
|
|
186
185
|
};
|
|
187
|
-
yield* Effect.annotateCurrentSpan("effect_machine.actor.initial_state",
|
|
186
|
+
yield* Effect.annotateCurrentSpan("effect_machine.actor.initial_state", initial._tag);
|
|
188
187
|
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
189
188
|
type: "@machine.spawn",
|
|
190
189
|
actorId: id,
|
|
191
|
-
initialState:
|
|
190
|
+
initialState: initial,
|
|
192
191
|
timestamp
|
|
193
192
|
}));
|
|
194
|
-
const stateRef = yield* SubscriptionRef.make(
|
|
193
|
+
const stateRef = yield* SubscriptionRef.make(initial);
|
|
195
194
|
const listeners = /* @__PURE__ */ new Set();
|
|
196
195
|
const backgroundFibers = [];
|
|
197
196
|
const initEvent = { _tag: INTERNAL_INIT_EVENT };
|
|
198
197
|
const ctx = {
|
|
199
198
|
actorId: id,
|
|
200
|
-
state:
|
|
199
|
+
state: initial,
|
|
201
200
|
event: initEvent,
|
|
202
201
|
self,
|
|
203
202
|
system
|
|
@@ -206,7 +205,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
206
205
|
for (const bg of machine.backgroundEffects) {
|
|
207
206
|
const fiber = yield* Effect.forkDetach(bg.handler({
|
|
208
207
|
actorId: id,
|
|
209
|
-
state:
|
|
208
|
+
state: initial,
|
|
210
209
|
event: initEvent,
|
|
211
210
|
self,
|
|
212
211
|
effects: effectSlots,
|
|
@@ -215,14 +214,14 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
215
214
|
backgroundFibers.push(fiber);
|
|
216
215
|
}
|
|
217
216
|
const stateScopeRef = { current: yield* Scope.make() };
|
|
218
|
-
yield* runSpawnEffectsWithInspection(machine,
|
|
219
|
-
if (machine.finalStates.has(
|
|
217
|
+
yield* runSpawnEffectsWithInspection(machine, initial, initEvent, self, stateScopeRef.current, id, inspectorValue, system);
|
|
218
|
+
if (machine.finalStates.has(initial._tag)) {
|
|
220
219
|
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
221
220
|
yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
|
|
222
221
|
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
223
222
|
type: "@machine.stop",
|
|
224
223
|
actorId: id,
|
|
225
|
-
finalState:
|
|
224
|
+
finalState: initial,
|
|
226
225
|
timestamp
|
|
227
226
|
}));
|
|
228
227
|
yield* Ref.set(stoppedRef, true);
|
|
@@ -230,7 +229,8 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
230
229
|
return buildActorRefCore(id, machine, stateRef, eventQueue, stoppedRef, listeners, Ref.set(stoppedRef, true).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid), system, childrenMap, /* @__PURE__ */ new Set());
|
|
231
230
|
}
|
|
232
231
|
const pendingReplies = /* @__PURE__ */ new Set();
|
|
233
|
-
const
|
|
232
|
+
const transitionsPubSub = yield* PubSub.unbounded();
|
|
233
|
+
const loopFiber = yield* Effect.forkDetach(eventLoop(machine, stateRef, eventQueue, stoppedRef, self, listeners, backgroundFibers, stateScopeRef, id, inspectorValue, system, pendingReplies, transitionsPubSub));
|
|
234
234
|
return buildActorRefCore(id, machine, stateRef, eventQueue, stoppedRef, listeners, Effect.gen(function* () {
|
|
235
235
|
const finalState = yield* SubscriptionRef.get(stateRef);
|
|
236
236
|
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
@@ -245,7 +245,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
245
245
|
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
246
246
|
yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
|
|
247
247
|
if (implicitSystemScope !== void 0) yield* Scope.close(implicitSystemScope, Exit.void);
|
|
248
|
-
}).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid), system, childrenMap, pendingReplies);
|
|
248
|
+
}).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid), system, childrenMap, pendingReplies, transitionsPubSub);
|
|
249
249
|
});
|
|
250
250
|
/** Fail all pending call/ask Deferreds with ActorStoppedError. Safe to call multiple times. */
|
|
251
251
|
const settlePendingReplies = (pendingReplies, actorId) => Effect.sync(() => {
|
|
@@ -258,7 +258,7 @@ const settlePendingReplies = (pendingReplies, actorId) => Effect.sync(() => {
|
|
|
258
258
|
* Includes postpone buffer — events matching postpone rules are buffered
|
|
259
259
|
* and drained after state tag changes (gen_statem semantics).
|
|
260
260
|
*/
|
|
261
|
-
const eventLoop = Effect.fn("effect-machine.actor.eventLoop")(function* (machine, stateRef, eventQueue, stoppedRef, self, listeners, backgroundFibers, stateScopeRef, actorId, inspector, system, pendingReplies) {
|
|
261
|
+
const eventLoop = Effect.fn("effect-machine.actor.eventLoop")(function* (machine, stateRef, eventQueue, stoppedRef, self, listeners, backgroundFibers, stateScopeRef, actorId, inspector, system, pendingReplies, transitionsPubSub) {
|
|
262
262
|
const postponed = [];
|
|
263
263
|
const hasPostponeRules = machine.postponeRules.length > 0;
|
|
264
264
|
const processQueued = Effect.fn("effect-machine.actor.processQueued")(function* (queued) {
|
|
@@ -301,6 +301,11 @@ const eventLoop = Effect.fn("effect-machine.actor.eventLoop")(function* (machine
|
|
|
301
301
|
}));
|
|
302
302
|
break;
|
|
303
303
|
}
|
|
304
|
+
if (result.transitioned) yield* PubSub.publish(transitionsPubSub, {
|
|
305
|
+
fromState: result.previousState,
|
|
306
|
+
toState: result.newState,
|
|
307
|
+
event
|
|
308
|
+
});
|
|
304
309
|
return {
|
|
305
310
|
shouldStop,
|
|
306
311
|
stateChanged: result.lifecycleRan
|
|
@@ -316,15 +321,21 @@ const eventLoop = Effect.fn("effect-machine.actor.eventLoop")(function* (machine
|
|
|
316
321
|
yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
|
|
317
322
|
return;
|
|
318
323
|
}
|
|
319
|
-
|
|
324
|
+
let drainTriggered = stateChanged;
|
|
325
|
+
while (drainTriggered && postponed.length > 0) {
|
|
326
|
+
drainTriggered = false;
|
|
320
327
|
const drained = postponed.splice(0);
|
|
321
|
-
for (const entry of drained)
|
|
322
|
-
yield*
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
+
for (const entry of drained) {
|
|
329
|
+
const drain = yield* processQueued(entry);
|
|
330
|
+
if (drain.shouldStop) {
|
|
331
|
+
yield* Ref.set(stoppedRef, true);
|
|
332
|
+
settlePostponedBuffer(postponed, pendingReplies, actorId);
|
|
333
|
+
yield* settlePendingReplies(pendingReplies, actorId);
|
|
334
|
+
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
335
|
+
yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (drain.stateChanged) drainTriggered = true;
|
|
328
339
|
}
|
|
329
340
|
}
|
|
330
341
|
}
|
|
@@ -480,25 +491,7 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
480
491
|
if (MutableHashMap.has(actorsMap, id)) return yield* new DuplicateActorError({ actorId: id });
|
|
481
492
|
return yield* registerActor(id, yield* createActor(id, built._inner));
|
|
482
493
|
});
|
|
483
|
-
const
|
|
484
|
-
if (MutableHashMap.has(actorsMap, id)) return yield* new DuplicateActorError({ actorId: id });
|
|
485
|
-
const adapter = yield* PersistenceAdapterTag;
|
|
486
|
-
const maybeSnapshot = yield* adapter.loadSnapshot(id, persistentMachine.persistence.stateSchema);
|
|
487
|
-
return yield* registerActor(id, yield* createPersistentActor(id, persistentMachine, maybeSnapshot, yield* adapter.loadEvents(id, persistentMachine.persistence.eventSchema, Option.isSome(maybeSnapshot) ? maybeSnapshot.value.version : void 0)));
|
|
488
|
-
});
|
|
489
|
-
const spawnImpl = Effect.fn("effect-machine.actorSystem.spawn")(function* (id, machine) {
|
|
490
|
-
if (isPersistentMachine(machine)) return yield* spawnPersistent(id, machine);
|
|
491
|
-
return yield* spawnRegular(id, machine);
|
|
492
|
-
});
|
|
493
|
-
function spawn(id, machine) {
|
|
494
|
-
return withSpawnGate(spawnImpl(id, machine));
|
|
495
|
-
}
|
|
496
|
-
const restoreImpl = Effect.fn("effect-machine.actorSystem.restore")(function* (id, persistentMachine) {
|
|
497
|
-
const maybeActor = yield* restorePersistentActor(id, persistentMachine);
|
|
498
|
-
if (Option.isSome(maybeActor)) yield* registerActor(id, maybeActor.value);
|
|
499
|
-
return maybeActor;
|
|
500
|
-
});
|
|
501
|
-
const restore = (id, persistentMachine) => withSpawnGate(restoreImpl(id, persistentMachine));
|
|
494
|
+
const spawn = (id, machine) => withSpawnGate(spawnRegular(id, machine));
|
|
502
495
|
const get = Effect.fn("effect-machine.actorSystem.get")(function* (id) {
|
|
503
496
|
return yield* Effect.sync(() => MutableHashMap.get(actorsMap, id));
|
|
504
497
|
});
|
|
@@ -515,55 +508,8 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
515
508
|
yield* actor.stop;
|
|
516
509
|
return true;
|
|
517
510
|
});
|
|
518
|
-
const listPersisted = Effect.fn("effect-machine.actorSystem.listPersisted")(function* () {
|
|
519
|
-
const adapter = yield* PersistenceAdapterTag;
|
|
520
|
-
if (adapter.listActors === void 0) return [];
|
|
521
|
-
return yield* adapter.listActors();
|
|
522
|
-
});
|
|
523
|
-
const restoreMany = Effect.fn("effect-machine.actorSystem.restoreMany")(function* (ids, persistentMachine) {
|
|
524
|
-
const restored = [];
|
|
525
|
-
const failed = [];
|
|
526
|
-
for (const id of ids) {
|
|
527
|
-
if (MutableHashMap.has(actorsMap, id)) continue;
|
|
528
|
-
const result = yield* Effect.result(restore(id, persistentMachine));
|
|
529
|
-
if (result._tag === "Failure") failed.push({
|
|
530
|
-
id,
|
|
531
|
-
error: result.failure
|
|
532
|
-
});
|
|
533
|
-
else if (Option.isSome(result.success)) restored.push(result.success.value);
|
|
534
|
-
else failed.push({
|
|
535
|
-
id,
|
|
536
|
-
error: new PersistenceError({
|
|
537
|
-
operation: "restore",
|
|
538
|
-
actorId: id,
|
|
539
|
-
message: "No persisted state found"
|
|
540
|
-
})
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
return {
|
|
544
|
-
restored,
|
|
545
|
-
failed
|
|
546
|
-
};
|
|
547
|
-
});
|
|
548
|
-
const restoreAll = Effect.fn("effect-machine.actorSystem.restoreAll")(function* (persistentMachine, options) {
|
|
549
|
-
const adapter = yield* PersistenceAdapterTag;
|
|
550
|
-
if (adapter.listActors === void 0) return {
|
|
551
|
-
restored: [],
|
|
552
|
-
failed: []
|
|
553
|
-
};
|
|
554
|
-
const machineType = persistentMachine.persistence.machineType;
|
|
555
|
-
if (machineType === void 0) return yield* new PersistenceError({
|
|
556
|
-
operation: "restoreAll",
|
|
557
|
-
actorId: "*",
|
|
558
|
-
message: "restoreAll requires explicit machineType in persistence config"
|
|
559
|
-
});
|
|
560
|
-
let filtered = (yield* adapter.listActors()).filter((meta) => meta.machineType === machineType);
|
|
561
|
-
if (options?.filter !== void 0) filtered = filtered.filter(options.filter);
|
|
562
|
-
return yield* restoreMany(filtered.map((meta) => meta.id), persistentMachine);
|
|
563
|
-
});
|
|
564
511
|
return ActorSystem.of({
|
|
565
512
|
spawn,
|
|
566
|
-
restore,
|
|
567
513
|
get,
|
|
568
514
|
stop,
|
|
569
515
|
events: Stream.fromPubSub(eventPubSub),
|
|
@@ -579,10 +525,7 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
579
525
|
return () => {
|
|
580
526
|
eventListeners.delete(fn);
|
|
581
527
|
};
|
|
582
|
-
}
|
|
583
|
-
listPersisted,
|
|
584
|
-
restoreMany,
|
|
585
|
-
restoreAll
|
|
528
|
+
}
|
|
586
529
|
});
|
|
587
530
|
});
|
|
588
531
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { EffectHandlers, EffectSlot, EffectSlots, EffectsDef, EffectsSchema, GuardHandlers, GuardSlot, GuardSlots, GuardsDef, GuardsSchema, MachineContext, Slot } from "./slot.js";
|
|
2
2
|
import { Event, MachineEventSchema, MachineStateSchema, State } from "./schema.js";
|
|
3
|
-
import { PersistenceConfig, PersistentMachine, isPersistentMachine } from "./persistence/persistent-machine.js";
|
|
4
3
|
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
5
4
|
import { ProcessEventResult } from "./internal/transition.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { InMemoryPersistenceAdapter, makeInMemoryPersistenceAdapter } from "./persistence/adapters/in-memory.js";
|
|
9
|
-
import { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, ProvideHandlers, SpawnEffect, StateHandlerContext, TaskOptions, Transition, machine_d_exports } from "./machine.js";
|
|
10
|
-
import { ActorRef, ActorRefSync, ActorSystem, Default, SystemEvent, SystemEventListener } from "./actor.js";
|
|
5
|
+
import { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, ProvideHandlers, SpawnEffect, StateHandlerContext, TaskOptions, Transition, machine_d_exports } from "./machine.js";
|
|
6
|
+
import { ActorRef, ActorRefSync, ActorSystem, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
|
|
11
7
|
import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
12
8
|
import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
13
|
-
export { type
|
|
9
|
+
export { type ActorRef, type ActorRefSync, ActorStoppedError, 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, type InspectionEvent, type Inspector, type InspectorHandler, 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, NoReplyError, type ProcessEventResult, type ProvideHandlers, ProvisionValidationError, type SimulationResult, Slot, type EffectHandlers as SlotEffectHandlers, type EffectSlot as SlotEffectSlot, SlotProvisionError, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, UnprovidedSlotsError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|