@systemfsoftware/xstate 0.0.0-bootstrap.0 → 6.0.0-beta.65

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.
@@ -0,0 +1,211 @@
1
+ import { t as EffectDescriptor } from "./effectDescriptor-EvNuy6U3.js";
2
+ import { Ar as ActorSystemRuntime, Br as InspectionEvent, C as AnyActor, D as AnyEventObject, Jt as OutputFrom, Ot as InputFrom, X as CustomExecutableActionObject, _n as SnapshotFrom, gt as EventFromLogic, hn as Snapshot, w as AnyActorLogic, yt as ExecutableActionObjectFromLogic } from "./types-B2EAwOk-.js";
3
+ /** @experimental */
4
+ export interface DurableEffectMetadata {
5
+ /** Stable within one durable execution. */
6
+ id: string;
7
+ transitionIndex: number;
8
+ effectIndex: number;
9
+ }
10
+ /** @experimental */
11
+ export interface DurableWaitMetadata {
12
+ /** Stable within one durable execution. */
13
+ id: string;
14
+ transitionIndex: number;
15
+ }
16
+ /**
17
+ * An event addressed to a durable execution's root actor, captured while
18
+ * effects settled. `source` is the live reference of the sending actor when
19
+ * one initiated the send.
20
+ *
21
+ * @experimental
22
+ */
23
+ export interface DurableRootEvent<TEvent> {
24
+ event: TEvent;
25
+ source: AnyActor | undefined;
26
+ }
27
+ /** @experimental */
28
+ export interface DurableEffect<TEffect> extends DurableEffectMetadata {
29
+ effect: TEffect;
30
+ /**
31
+ * Serializable view of the effect: actor references replaced by logical
32
+ * addresses and actor sources by source keys, for journaling and
33
+ * deduplication. Payload fields are only as serializable as their values.
34
+ */
35
+ descriptor: EffectDescriptor;
36
+ }
37
+ /**
38
+ * A durable host adapter: the runtime operations that execute this
39
+ * execution's effects, plus the durable loop hooks.
40
+ *
41
+ * The runtime operations (`sendEvent`, `scheduleTimer`, …) are installed on
42
+ * the actor system of every snapshot the execution produces, including
43
+ * children created during transitions and actors rehydrated from restored
44
+ * snapshots. Operations initiated by live child actors (parent sends,
45
+ * timers, terminations) route to them without any per-actor wiring; omitted
46
+ * operations keep their default local behavior.
47
+ *
48
+ * Events addressed to this execution's root actor do not reach `sendEvent`
49
+ * during `executeEffects`: the execution captures and retains them, and the
50
+ * execution's `waitForEvent()` hands them out before deferring to this
51
+ * adapter. While the loop is parked, a root-addressed event reaches
52
+ * `enqueueRootEvent`, or the broader `sendEvent` override when implemented,
53
+ * so the host can place it in its own mailbox.
54
+ *
55
+ * @experimental
56
+ */
57
+ export interface DurableExecutionAdapter<TLogic extends AnyActorLogic> extends Partial<ActorSystemRuntime> {
58
+ /**
59
+ * Absolute clock in milliseconds, defaulting to Date.now. Checkpoints and
60
+ * resumed executions must use the same time origin. Replay hosts should
61
+ * return the recorded scheduling time rather than the replay's wall clock.
62
+ */
63
+ now?(): number;
64
+ /**
65
+ * Accepts a timer synchronously, or fulfills its promise when registration
66
+ * accepts the timer and its delay begins. For a new timer, that acceptance
67
+ * time is read through now() and persisted. Retried/restored timers retain
68
+ * their original deadline; hosts must honor it during registration.
69
+ */
70
+ scheduleTimer?: ActorSystemRuntime['scheduleTimer'];
71
+ /**
72
+ * Enqueues an event addressed to this execution's root while the durable
73
+ * loop is parked in `waitForEvent()`. Use this when the host only owns the
74
+ * root mailbox; implementing `sendEvent` instead takes ownership of delivery
75
+ * for every target and must use `deliverEvent` for co-located actors.
76
+ */
77
+ enqueueRootEvent?(source: AnyActor | undefined, event: AnyEventObject): void | PromiseLike<void>;
78
+ /**
79
+ * Executes a custom action as a durable host step or activity. The host
80
+ * should identify the action by `type` and memoize or deduplicate it using
81
+ * `metadata.id`.
82
+ */
83
+ executeAction(action: CustomExecutableActionObject, metadata: DurableEffectMetadata, runtime: Partial<ActorSystemRuntime>): void | PromiseLike<void>;
84
+ /**
85
+ * Creates the runtime used by one effect, for hosts that key operations by
86
+ * effect ID. Overrides the adapter's runtime operations
87
+ * operation-by-operation; operations it omits keep their behavior. The
88
+ * complete effect is provided for hosts that need serializable actor
89
+ * source, input, event or target data beyond the runtime method arguments.
90
+ */
91
+ runtime?(metadata: DurableEffectMetadata, effect: ExecutableActionObjectFromLogic<TLogic>): Partial<ActorSystemRuntime>;
92
+ /**
93
+ * Waits durably for the next event addressed to this execution. Typed to
94
+ * also accept plain event objects: an adapter written against
95
+ * `AnyActorLogic` (a generic host library) cannot produce
96
+ * `EventFromLogic<TLogic>`, and the events a host relays are runtime data
97
+ * anyway — the execution narrows at its own boundary.
98
+ */
99
+ waitForEvent(metadata: DurableWaitMetadata): EventFromLogic<TLogic> | AnyEventObject | PromiseLike<EventFromLogic<TLogic> | AnyEventObject>;
100
+ /** Index assigned to the first transition. Defaults to `0`. */
101
+ transitionIndex?: number;
102
+ /**
103
+ * Pins this execution's actor identity. Session ids become
104
+ * `<executionId>:<n>`, a deterministic function of actor-creation order, so
105
+ * a replay re-creates the same session ids and journaled completion events
106
+ * (which carry the producing incarnation's `sessionId`) still match the
107
+ * children the replay re-creates. Without it, session ids embed a random
108
+ * per-process system id and journaled internal events go stale across
109
+ * replays. Uniqueness across executions is the host's responsibility.
110
+ */
111
+ executionId?: string;
112
+ }
113
+ /** @experimental */
114
+ export declare class DurableExecutionCancelledError extends Error {
115
+ constructor();
116
+ }
117
+ /** @experimental */
118
+ export declare class DurableExecutionResumeError extends Error {
119
+ constructor();
120
+ }
121
+ /**
122
+ * The snapshot type a durable execution hands back: the logic's own snapshot,
123
+ * intersected with the base `Snapshot` union so the `status`/`output`/`error`
124
+ * discriminant stays visible even when `TLogic` is an unresolved type
125
+ * parameter (a generic host library), where `SnapshotFrom` alone is opaque.
126
+ *
127
+ * @experimental
128
+ */
129
+ export type DurableSnapshot<TLogic extends AnyActorLogic> = SnapshotFrom<TLogic> & Snapshot<OutputFrom<TLogic>>;
130
+ /** @experimental */
131
+ export interface DurableExecution<TLogic extends AnyActorLogic> {
132
+ /**
133
+ * The logical address of this execution's root actor: the logic's own name,
134
+ * or `x:0` for anonymous logic. Known before any transition runs, so hosts
135
+ * can label mailboxes and wire messages without a snapshot.
136
+ */
137
+ readonly rootAddress: string;
138
+ /** The machine's id, for pinning a journal to the logic that produced it. */
139
+ readonly machineId: string;
140
+ /**
141
+ * The machine's declared `version`. Persist it with the execution and
142
+ * reject a worker whose machine version differs: a changed machine
143
+ * reorders effect ids, and memoized results silently misalign.
144
+ */
145
+ readonly machineVersion: string | undefined;
146
+ /** Index assigned to the next transition. Persist this with checkpoints. */
147
+ readonly nextTransitionIndex: number;
148
+ /**
149
+ * Restores a checkpoint on a fresh execution. Returns effects that start
150
+ * active embedded children and re-arm pending root timers; execute them
151
+ * with `executeEffects` before waiting or processing the next event.
152
+ * Does not send a machine event, replay entry actions, or advance the
153
+ * transition index. Restoration effect IDs use `restore:<index>:<effect>`.
154
+ */
155
+ restore(persistedSnapshot: Snapshot<unknown>): [snapshot: DurableSnapshot<TLogic>, effects: DurableEffect<ExecutableActionObjectFromLogic<TLogic>>[]];
156
+ initialTransition(...[input]: undefined extends InputFrom<TLogic> ? [input?: InputFrom<TLogic>] : [input: InputFrom<TLogic>]): [snapshot: DurableSnapshot<TLogic>, effects: DurableEffect<ExecutableActionObjectFromLogic<TLogic>>[]];
157
+ transition(snapshot: SnapshotFrom<TLogic>, event: EventFromLogic<TLogic>): [snapshot: DurableSnapshot<TLogic>, effects: DurableEffect<ExecutableActionObjectFromLogic<TLogic>>[]];
158
+ /**
159
+ * Returns the actor reference behind a snapshot produced by this execution,
160
+ * for addressing and inspection. `undefined` for snapshots this execution
161
+ * has not seen (for example a freshly deserialized checkpoint that has not
162
+ * been passed through `restore()` or `transition()` yet).
163
+ *
164
+ * With an `address`, returns the live actor at that logical address in the
165
+ * snapshot's actor tree instead — the root itself, one of its transitive
166
+ * children, or `undefined` when no live actor has that address (for
167
+ * example a timer firing for an actor that already completed).
168
+ */
169
+ getActorRef(snapshot: SnapshotFrom<TLogic>, address?: string): AnyActor | undefined;
170
+ /**
171
+ * Executes effects and resolves only when every runtime operation they
172
+ * transitively initiated — including operations from live child actors
173
+ * reacting to delivered events — has been accepted by the runtime; a
174
+ * failed operation rejects it. Operations are handed to the runtime one at
175
+ * a time, in initiation order.
176
+ *
177
+ * Events addressed to this execution's root actor that were produced along
178
+ * the way are retained, in order, and handed out by `waitForEvent()`
179
+ * before it defers to the adapter — so the drive loop is just
180
+ * `transition(snapshot, await waitForEvent())` + `executeEffects`.
181
+ */
182
+ executeEffects(effects: readonly DurableEffect<ExecutableActionObjectFromLogic<TLogic>>[]): Promise<void>;
183
+ /**
184
+ * Resolves with the next event addressed to this execution's root actor:
185
+ * an event a prior `executeEffects` batch captured (an invoked actor
186
+ * completing, a child reporting up), or — once none are queued — whatever
187
+ * the adapter's durable wait produces.
188
+ */
189
+ waitForEvent(): Promise<EventFromLogic<TLogic>>;
190
+ run(...[input]: undefined extends InputFrom<TLogic> ? [input?: InputFrom<TLogic>] : [input: InputFrom<TLogic>]): Promise<OutputFrom<TLogic>>;
191
+ }
192
+ /**
193
+ * Creates a host-neutral durable execution around pure actor transitions.
194
+ *
195
+ * The returned transition methods only calculate snapshots and tag their
196
+ * effects. Persistence, retries, messaging, timers and child execution remain
197
+ * responsibilities of the adapter.
198
+ *
199
+ * @experimental
200
+ */
201
+ export interface DurableExecutionOptions {
202
+ /**
203
+ * Observes the execution's inspection events — actor lifecycle, event
204
+ * routing, transitions — across the whole live actor tree. The host-side
205
+ * home for operation logs and instrumentation, so adapters stay pure
206
+ * physics.
207
+ */
208
+ inspect?: (inspectionEvent: InspectionEvent) => void;
209
+ }
210
+ /** @experimental */
211
+ export declare function createDurable<TLogic extends AnyActorLogic>(logic: TLogic, adapter: DurableExecutionAdapter<TLogic>, options?: DurableExecutionOptions): DurableExecution<TLogic>;
@@ -0,0 +1,283 @@
1
+ import { i as initialTransition, o as transition, s as getEffectDescriptor } from "./transition-ZMXyPI-x.mjs";
2
+ import { K as setInertActorScopeSnapshot, O as createStartEffect, Q as recordTimerStart, U as attachSnapshotActorRef, W as createInertActorScope, Z as getTimerStart, bt as withSystemInspector, ct as encodeAddressSegment, ft as withExecutionIdentity, ht as deliverEvent, k as createTimerEffect, pt as getSnapshotActorRef, rt as isRemoteActorRef, st as RUNTIME_OPERATIONS, ut as getRootActorId } from "./createActor-BGHd7i8Q.mjs";
3
+ // src/durable/index.ts
4
+ /** @experimental */
5
+ var DurableExecutionCancelledError = class extends Error {
6
+ constructor() {
7
+ super("Durable execution was stopped");
8
+ this.name = "DurableExecutionCancelledError";
9
+ }
10
+ };
11
+ /** @experimental */
12
+ var DurableExecutionResumeError = class extends Error {
13
+ constructor() {
14
+ super("run() can only start a fresh durable execution; resume checkpoints with restore() and the explicit transition loop");
15
+ this.name = "DurableExecutionResumeError";
16
+ }
17
+ };
18
+ /** @experimental */
19
+ function createDurable(logic, adapter, options) {
20
+ let nextTransitionIndex = adapter.transitionIndex ?? 0;
21
+ const startingTransitionIndex = nextTransitionIndex;
22
+ let restored = false;
23
+ const now = () => adapter.now?.() ?? Date.now();
24
+ const observedRoots = /* @__PURE__ */ new WeakSet();
25
+ let lastTransitionIndex = nextTransitionIndex === 0 ? void 0 : nextTransitionIndex - 1;
26
+ const restoredTimerDeadlines = /* @__PURE__ */ new WeakMap();
27
+ if (!Number.isSafeInteger(nextTransitionIndex) || nextTransitionIndex < 0) throw new RangeError("transitionIndex must be a non-negative safe integer");
28
+ const tagEffects = (effects, restoring = false) => {
29
+ const transitionIndex = restoring ? nextTransitionIndex : nextTransitionIndex++;
30
+ lastTransitionIndex = restoring ? lastTransitionIndex ?? transitionIndex : transitionIndex;
31
+ return effects.map((effect, effectIndex) => {
32
+ const tagged = {
33
+ id: `${restoring ? "restore:" : ""}${transitionIndex}:${effectIndex}`,
34
+ transitionIndex,
35
+ effectIndex,
36
+ effect
37
+ };
38
+ let descriptor;
39
+ Object.defineProperty(tagged, "descriptor", {
40
+ enumerable: true,
41
+ get: () => descriptor ??= getEffectDescriptor(effect)
42
+ });
43
+ return tagged;
44
+ });
45
+ };
46
+ const rootAddress = encodeAddressSegment(getRootActorId(logic));
47
+ const machineId = logic.id ?? rootAddress;
48
+ const machineVersion = logic.version;
49
+ const executionIdentity = adapter.executionId ? {
50
+ systemId: adapter.executionId,
51
+ nextSessionId: 0
52
+ } : void 0;
53
+ const systemRuntime = {};
54
+ for (const operation of [
55
+ ...RUNTIME_OPERATIONS,
56
+ "sendEvent",
57
+ "runStep",
58
+ "runLogic"
59
+ ]) {
60
+ const impl = adapter[operation];
61
+ if (impl) systemRuntime[operation] = impl.bind(adapter);
62
+ }
63
+ const hasSystemRuntime = Object.keys(systemRuntime).length > 0 || !!adapter.enqueueRootEvent;
64
+ let currentBatch;
65
+ const pendingRootEvents = [];
66
+ let operationTail = Promise.resolve();
67
+ const track = (batch, operation) => {
68
+ batch.pending.add(operation);
69
+ operation.catch((error) => {
70
+ batch.failures.push(error);
71
+ }).then(() => batch.pending.delete(operation));
72
+ return operation;
73
+ };
74
+ const handOff = (batch, run) => {
75
+ const operation = operationTail.then(run).then(() => void 0);
76
+ operationTail = operation.catch(() => {});
77
+ return track(batch, operation);
78
+ };
79
+ const dispatch = (run) => currentBatch ? handOff(currentBatch, run) : run();
80
+ const drain = async (batch) => {
81
+ while (batch.pending.size) await Promise.allSettled([...batch.pending]);
82
+ };
83
+ const settle = async (batch) => {
84
+ await drain(batch);
85
+ if (batch.failures.length) throw batch.failures[0];
86
+ };
87
+ function wrapRuntime(runtime, localDeliveryFallback, fallbackToActorSystem = false, timerDeadline) {
88
+ const wrapped = {};
89
+ for (const operation of RUNTIME_OPERATIONS) {
90
+ const impl = runtime[operation] ?? (fallbackToActorSystem ? (...args) => {
91
+ return (operation === "spawnActor" ? args[1] : args[0]).system[operation](...args);
92
+ } : void 0);
93
+ if (impl) wrapped[operation] = (...args) => dispatch(() => {
94
+ if (operation === "scheduleTimer" && timerDeadline) args[2] = Math.min(timerDeadline.delay, Math.max(0, timerDeadline.deadline - now()));
95
+ if (operation === "scheduleTimer") {
96
+ const timer = args[0].getSnapshot()?.timers?.[args[1]];
97
+ if (timer) {
98
+ const previousStart = getTimerStart(timer);
99
+ if (previousStart !== void 0 && !timerDeadline) args[2] = Math.min(timer.delay, Math.max(0, previousStart + timer.delay - now()));
100
+ const result = impl(...args);
101
+ if (result) return Promise.resolve(result).then(() => {
102
+ recordTimerStart(timer, previousStart ?? now());
103
+ });
104
+ recordTimerStart(timer, previousStart ?? now());
105
+ return;
106
+ }
107
+ }
108
+ return impl(...args);
109
+ });
110
+ }
111
+ if (runtime.runStep) wrapped.runStep = runtime.runStep;
112
+ if (runtime.runLogic) wrapped.runLogic = runtime.runLogic;
113
+ wrapped.sendEvent = (source, target, event) => {
114
+ if (!currentBatch && target.address === rootAddress && !runtime.sendEvent && adapter.enqueueRootEvent) return dispatch(() => adapter.enqueueRootEvent(source, event));
115
+ if (!currentBatch && target.address === rootAddress && !runtime.sendEvent) throw new Error(`A root-addressed event ("${event.type}") was produced while the durable loop was parked, but the adapter has no enqueueRootEvent or sendEvent to receive it. Implement enqueueRootEvent to place root-addressed events in the host's mailbox.`);
116
+ if (currentBatch && target.address === rootAddress) {
117
+ currentBatch.rootEvents.push({
118
+ event,
119
+ source
120
+ });
121
+ return;
122
+ }
123
+ const impl = runtime.sendEvent;
124
+ if (impl) return dispatch(() => impl(source, target, event));
125
+ if (localDeliveryFallback) return dispatch(() => deliverEvent(source, target, event));
126
+ throw new TypeError(`The durable runtime does not support the sendEvent operation (target '${target.address}')`);
127
+ };
128
+ return wrapped;
129
+ }
130
+ const wrappedSystemRuntime = hasSystemRuntime ? wrapRuntime(systemRuntime, true) : void 0;
131
+ function findByAddress(actor, address) {
132
+ if (actor.address === address) return actor;
133
+ if (!address.startsWith(`${actor.address}/`)) return;
134
+ const children = actor.getSnapshot().children;
135
+ for (const child of Object.values(children ?? {})) {
136
+ const found = child && findByAddress(child, address);
137
+ if (found) return found;
138
+ }
139
+ }
140
+ const inspect = options?.inspect;
141
+ function wireInspection(system) {
142
+ if (inspect && !system._hasInspectionObservers?.()) system.inspect(inspect);
143
+ }
144
+ function installSystemRuntime(snapshot, recursive = false) {
145
+ if (snapshot.status === "error") {
146
+ const root = getSnapshotActorRef(snapshot)?.actor;
147
+ if (root && !observedRoots.has(root)) {
148
+ root.subscribe({ error() {} });
149
+ observedRoots.add(root);
150
+ }
151
+ }
152
+ if (wrappedSystemRuntime || inspect) {
153
+ const ref = getSnapshotActorRef(snapshot)?.actor;
154
+ const systems = /* @__PURE__ */ new Set();
155
+ const visit = (actor) => {
156
+ if (!systems.has(actor.system)) {
157
+ systems.add(actor.system);
158
+ if (wrappedSystemRuntime) actor.system.runtime = wrappedSystemRuntime;
159
+ wireInspection(actor.system);
160
+ }
161
+ if (recursive) {
162
+ const children = actor.getSnapshot().children;
163
+ for (const child of Object.values(children ?? {})) if (child) visit(child);
164
+ }
165
+ };
166
+ if (ref) visit(ref);
167
+ if (!recursive || !ref) {
168
+ const children = snapshot.children;
169
+ for (const child of Object.values(children ?? {})) if (child) visit(child);
170
+ }
171
+ }
172
+ return snapshot;
173
+ }
174
+ const execution = {
175
+ rootAddress,
176
+ machineId,
177
+ machineVersion,
178
+ get nextTransitionIndex() {
179
+ return nextTransitionIndex;
180
+ },
181
+ restore(persistedSnapshot) {
182
+ if (restored || nextTransitionIndex !== startingTransitionIndex || currentBatch) throw new Error("restore() requires a fresh durable execution");
183
+ const { snapshot, scope } = withSystemInspector(inspect, () => withExecutionIdentity(executionIdentity, () => {
184
+ const scope = createInertActorScope(logic);
185
+ const snapshot = logic.restoreSnapshot ? logic.restoreSnapshot(persistedSnapshot, scope) : persistedSnapshot;
186
+ setInertActorScopeSnapshot(scope, snapshot, false);
187
+ return {
188
+ snapshot: installSystemRuntime(attachSnapshotActorRef(scope, snapshot), true),
189
+ scope
190
+ };
191
+ }));
192
+ const effects = [];
193
+ if (snapshot.status === "active") {
194
+ const { children, timers } = snapshot;
195
+ for (const child of Object.values(children ?? {})) if (child && !isRemoteActorRef(child) && child.getSnapshot().status === "active") effects.push(createStartEffect(child));
196
+ for (const timer of Object.values(timers ?? {})) {
197
+ const effect = createTimerEffect(scope, timer, timer.delay);
198
+ if (timer.startedAt !== void 0) restoredTimerDeadlines.set(effect, {
199
+ deadline: timer.startedAt + timer.delay,
200
+ delay: timer.delay
201
+ });
202
+ effects.push(effect);
203
+ }
204
+ }
205
+ restored = true;
206
+ return [snapshot, tagEffects(effects, true)];
207
+ },
208
+ initialTransition(...args) {
209
+ if (restored) throw new Error("initialTransition() cannot initialize a restored execution");
210
+ const [snapshot, effects] = withSystemInspector(inspect, () => withExecutionIdentity(executionIdentity, () => initialTransition(logic, ...args)));
211
+ return [installSystemRuntime(snapshot), tagEffects(effects)];
212
+ },
213
+ transition(snapshot, event) {
214
+ const [nextSnapshot, effects] = withSystemInspector(inspect, () => withExecutionIdentity(executionIdentity, () => transition(logic, snapshot, event)));
215
+ return [installSystemRuntime(nextSnapshot), tagEffects(effects)];
216
+ },
217
+ getActorRef(snapshot, address) {
218
+ const root = getSnapshotActorRef(snapshot)?.actor;
219
+ if (!root || address === void 0) return root;
220
+ return findByAddress(root, address);
221
+ },
222
+ async executeEffects(effects) {
223
+ if (currentBatch) throw new Error("executeEffects calls must not overlap: await the previous call before starting the next batch.");
224
+ const batch = {
225
+ rootEvents: [],
226
+ failures: [],
227
+ pending: /* @__PURE__ */ new Set()
228
+ };
229
+ currentBatch = batch;
230
+ const fallbackRuntime = hasSystemRuntime ? void 0 : {};
231
+ try {
232
+ for (const tagged of effects) {
233
+ const { effect } = tagged;
234
+ const metadata = {
235
+ id: tagged.id,
236
+ transitionIndex: tagged.transitionIndex,
237
+ effectIndex: tagged.effectIndex
238
+ };
239
+ const perEffectRuntime = adapter.runtime?.(metadata, effect);
240
+ const timerDeadline = restoredTimerDeadlines.get(effect);
241
+ const runtime = perEffectRuntime || timerDeadline ? wrapRuntime({
242
+ ...systemRuntime,
243
+ ...perEffectRuntime
244
+ }, hasSystemRuntime, !!perEffectRuntime || hasSystemRuntime, timerDeadline) : fallbackRuntime;
245
+ if (effect.kind === "action") await adapter.executeAction(effect, metadata, runtime ?? wrappedSystemRuntime ?? {});
246
+ else await effect.exec(runtime);
247
+ }
248
+ await settle(batch);
249
+ pendingRootEvents.push(...batch.rootEvents);
250
+ } catch (error) {
251
+ await drain(batch);
252
+ throw error;
253
+ } finally {
254
+ currentBatch = void 0;
255
+ }
256
+ },
257
+ async waitForEvent() {
258
+ if (lastTransitionIndex === void 0) throw new Error("Cannot wait for an event before the first transition or restore");
259
+ const queued = pendingRootEvents.shift();
260
+ if (queued) return queued.event;
261
+ return adapter.waitForEvent({
262
+ id: restored && nextTransitionIndex === 0 ? "event:restore:0" : `event:${lastTransitionIndex}`,
263
+ transitionIndex: lastTransitionIndex
264
+ });
265
+ },
266
+ async run(...args) {
267
+ if (restored || startingTransitionIndex !== 0 || nextTransitionIndex !== startingTransitionIndex) throw new DurableExecutionResumeError();
268
+ let [snapshot, effects] = execution.initialTransition(...args);
269
+ await execution.executeEffects(effects);
270
+ while (snapshot.status === "active") {
271
+ const event = await execution.waitForEvent();
272
+ [snapshot, effects] = execution.transition(snapshot, event);
273
+ await execution.executeEffects(effects);
274
+ }
275
+ const terminalSnapshot = snapshot;
276
+ if (terminalSnapshot.status === "done") return terminalSnapshot.output;
277
+ if (terminalSnapshot.status === "error") throw terminalSnapshot.error;
278
+ throw new DurableExecutionCancelledError();
279
+ }
280
+ };
281
+ return execution;
282
+ }
283
+ export { DurableExecutionCancelledError, DurableExecutionResumeError, createDurable };
@@ -0,0 +1,91 @@
1
+ import { vt as ExecutableActionObject } from "./types-B2EAwOk-.js";
2
+ /**
3
+ * A serializable view of an executable effect. Actor references are replaced
4
+ * by their logical addresses and actor sources by their registered source
5
+ * keys, so a durable host can journal, deduplicate, and route effects without
6
+ * holding live actor references. Payload fields (`event`, `input`, `params`,
7
+ * `output`, `error`) pass through by reference and are only as serializable
8
+ * as their values.
9
+ *
10
+ * @experimental
11
+ */
12
+ type EffectDescriptor = {
13
+ kind: 'builtin';
14
+ type: '@xstate.spawn';
15
+ source: string | undefined;
16
+ actor: string;
17
+ id: string;
18
+ src: string;
19
+ input: unknown;
20
+ } | {
21
+ kind: 'builtin';
22
+ type: '@xstate.start';
23
+ source: string | undefined;
24
+ actor: string;
25
+ id: string;
26
+ } | {
27
+ kind: 'builtin';
28
+ type: '@xstate.raise';
29
+ source: string;
30
+ event: unknown;
31
+ id: string | undefined;
32
+ delay: number | undefined;
33
+ } | {
34
+ kind: 'builtin';
35
+ type: '@xstate.sendTo';
36
+ source: string;
37
+ target: string;
38
+ /** The target's incarnation token, when the target is a remote handle that carries one. */
39
+ incarnation: string | undefined;
40
+ event: unknown;
41
+ id: string | undefined;
42
+ delay: number | undefined;
43
+ } | {
44
+ kind: 'builtin';
45
+ type: '@xstate.cancel';
46
+ source: string;
47
+ id: string;
48
+ } | {
49
+ kind: 'builtin';
50
+ type: '@xstate.stop';
51
+ source: string;
52
+ actor: string;
53
+ id: string;
54
+ } | {
55
+ kind: 'builtin';
56
+ type: '@xstate.terminate';
57
+ source: string;
58
+ actor: string;
59
+ id: string;
60
+ status: 'done' | 'error';
61
+ output: unknown;
62
+ error: unknown;
63
+ } | {
64
+ kind: 'builtin';
65
+ type: '@xstate.deadLetter';
66
+ source: string | undefined;
67
+ target: string | undefined;
68
+ event: unknown;
69
+ reason: string;
70
+ issues: unknown;
71
+ error: unknown;
72
+ } | {
73
+ kind: 'emit';
74
+ type: string;
75
+ source: string;
76
+ event: unknown;
77
+ } | {
78
+ kind: 'action';
79
+ type: string;
80
+ params: unknown;
81
+ };
82
+ /**
83
+ * Returns the serializable descriptor for an executable effect: the same
84
+ * discriminants (`kind`, `type`) with actor references replaced by logical
85
+ * addresses and actor sources by source keys. Payload fields pass through by
86
+ * reference.
87
+ *
88
+ * @experimental
89
+ */
90
+ declare function getEffectDescriptor(effect: ExecutableActionObject): EffectDescriptor;
91
+ export { getEffectDescriptor as n, EffectDescriptor as t };