@systemfsoftware/xstate-effect 0.0.0-stage → 0.1.0-beta.8

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/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @systemfsoftware/xstate-effect
2
+
3
+ # @systemfsoftware/xstate-effect@0.1.0-beta.8
4
+
5
+ `join` now fails with the new `ActorFailedError<E>` whenever the joined actor errors, for every kind of actor. Its `cause` is the exact value the actor failed with, typed as the actor's `ErrorFrom`: a `fromEffect` actor's own error, `unknown` for a machine or a `snapshot.children` entry. Breaking: `join` on a `fromEffect` actor no longer fails with the Effect's error directly; read it from `error.cause`, or match the `ActorFailedError` tag first. `ActorStoppedError` is unchanged.
6
+
7
+ Add `@systemfsoftware/xstate-effect`, the Effect 4 runtime for XState actors, forked from statelyai/xstate's `next` branch at 2146ae26 (MIT). It behaves like upstream's 0.1.0-alpha.7. Under `exactOptionalPropertyTypes`, optional members that can hold `undefined` declare it explicitly. The `effect` peer range is `^4.0.1` (the monorepo catalog had `^4`), so a consumer resolves at least Effect 4.0.1.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 David Khourshid
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md CHANGED
@@ -1,3 +1,263 @@
1
- # Temporary Holding Version
1
+ # @xstate/effect
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > `@systemfsoftware/xstate-effect` is forked from [statelyai/xstate](https://github.com/statelyai/xstate) (`packages/xstate-effect`, branch `next` at `2146ae26ebfc7e6a624b3a1f237f9e6ddc30b9f5`), MIT. The text below is upstream's.
4
+
5
+ Combine XState's event-driven workflows with Effect services, scopes, clocks and tracing.
6
+
7
+ - Model approval, cancellation, deadlines and retry as explicit states and events.
8
+ - Invoke Effect tasks when their result determines the next state.
9
+ - Provide services once for the actor and its child logic.
10
+ - Keep actor lifetime inside your Effect application.
11
+
12
+ This package is experimental. It targets XState v6 alpha and Effect 4.
13
+
14
+ ## Installation
15
+
16
+ <!-- package name and peer dependencies from package.json -->
17
+
18
+ ```bash
19
+ nix build github:systemfsoftware/xstate#xstate-effect
20
+ ```
21
+
22
+ See the root README's [Install](../../README.md#install) section for wiring a catalog entry. Its peer `@systemfsoftware/xstate` comes from the same flake (`#xstate`), and `effect@^4` from your own package manager.
23
+
24
+ ## XState Effect: Quick start
25
+
26
+ <!-- public API from src/index.ts; actor lifetime from src/createEffectActor.ts -->
27
+
28
+ A release waits for approval, expires after 30 seconds, and allows cancellation during deployment. A failed deployment waits for an explicit retry:
29
+
30
+ <!-- example from examples/effect-workflows/src/approval.ts -->
31
+
32
+ ```ts
33
+ import { createEffectActor, fromEffect, send, setupEffect, waitFor } from '@xstate/effect'
34
+ import { Context, Effect, Schema } from 'effect'
35
+
36
+ export class Deployments extends Context.Service<
37
+ Deployments,
38
+ { readonly deploy: (release: string) => Effect.Effect<string, Error> }
39
+ >()('@app/Deployments') {}
40
+
41
+ const deploy = fromEffect({
42
+ schemas: { input: Schema.Struct({ release: Schema.String }) },
43
+ effect: ({ input }) => Deployments.use((api) => api.deploy(input.release)),
44
+ })
45
+
46
+ export const approvalMachine = setupEffect({
47
+ schemas: { input: Schema.Struct({ release: Schema.String }) },
48
+ actors: { deploy },
49
+ }).createMachine({
50
+ context: ({ input }) => ({ release: input.release, url: '' }),
51
+ initial: 'awaitingApproval',
52
+ states: {
53
+ awaitingApproval: {
54
+ after: { 30000: { target: 'expired' } },
55
+ on: {
56
+ APPROVE: { target: 'deploying' },
57
+ CANCEL: { target: 'cancelled' },
58
+ },
59
+ },
60
+ deploying: {
61
+ invoke: {
62
+ src: 'deploy',
63
+ input: ({ context }) => ({ release: context.release }),
64
+ onDone: ({ context, event }) => ({
65
+ target: 'deployed',
66
+ context: { ...context, url: event.output },
67
+ }),
68
+ onError: { target: 'failed' },
69
+ },
70
+ on: { CANCEL: { target: 'cancelled' } },
71
+ },
72
+ failed: {
73
+ on: {
74
+ RETRY: { target: 'deploying' },
75
+ CANCEL: { target: 'cancelled' },
76
+ },
77
+ },
78
+ deployed: { type: 'final' },
79
+ expired: { type: 'final' },
80
+ cancelled: { type: 'final' },
81
+ },
82
+ })
83
+
84
+ export const program = Effect.gen(function*() {
85
+ const actor = yield* createEffectActor(approvalMachine, {
86
+ input: { release: 'v1.2.0' },
87
+ })
88
+ // A UI, webhook or CLI can send this event after a person approves.
89
+ yield* send(actor, { type: 'APPROVE' })
90
+ const snapshot = yield* waitFor(actor, (s) => s.matches('deployed'), {
91
+ timeout: '5 seconds',
92
+ })
93
+ return snapshot.context.url
94
+ })
95
+
96
+ export const result = await Effect.runPromise(
97
+ program.pipe(
98
+ Effect.scoped,
99
+ Effect.provideService(Deployments, {
100
+ // Replace this demo service with your deployment API.
101
+ deploy: (release) => Effect.succeed(`https://example.com/${release}`),
102
+ }),
103
+ ),
104
+ )
105
+ console.log(result) // 'https://example.com/v1.2.0'
106
+ ```
107
+
108
+ The demo service runs locally. Replace it with your deployment API. The machine defines which events are valid in each state; Effect provides the deployment service and owns the actor's lifetime.
109
+
110
+ Start Effect-backed logic with `createEffectActor` inside an Effect scope.
111
+
112
+ <details>
113
+ <summary>Runtime and cancellation details</summary>
114
+
115
+ - `createEffectActor` runs pure XState transitions from an Effect fiber. Its mailbox processes events in order; timers use Effect's `Clock`.
116
+ - Events are processed asynchronously. Read their outcomes with `waitFor`, `join` or `snapshots`.
117
+ - Starting Effect-backed logic with XState's `createActor` produces an error because the Effect host is missing.
118
+ - Leaving an invoking state interrupts its local Effect. It does not undo work already accepted by an external API; model cancellation or rollback explicitly when needed.
119
+
120
+ </details>
121
+
122
+ ## Guides
123
+
124
+ | Guide | Examples |
125
+ | -------------------------------------------------- | -------------------------------------------------------- |
126
+ | [Quick start](docs/quick-start.md) | Release approval, expiry, cancellation and retry. |
127
+ | [Actors](docs/actors.md) | Share an actor through a Layer and ManagedRuntime. |
128
+ | [Observing actors](docs/observing-actors.md) | Snapshot history, output and streamed reminders. |
129
+ | [Matching states](docs/matching-states.md) | Exhaustive matching and per-state context. |
130
+ | [Effect actor logic](docs/effect-logic.md) | Report tasks, upload progress and rollout health events. |
131
+ | [Schemas and actions](docs/schemas-and-actions.md) | Runtime event validation and background audit entries. |
132
+ | [Atoms and React](docs/atoms-and-react.md) | Registry ownership, approval controls and useSelector. |
133
+ | [Testing and errors](docs/testing-and-errors.md) | TestClock, task retries, supervision and typed failures. |
134
+
135
+ Runnable copies live in [examples/effect-workflows](../../examples/effect-workflows). Their tests verify the docs use the same code.
136
+
137
+ ## Actors
138
+
139
+ The actor stops and interrupts its hosted Effects when its enclosing scope closes. Use `Effect.scoped` for a bounded program, or `Layer.effect` to share an actor for an application's lifetime.
140
+
141
+ - Invoked Effect tasks and streams own their resources and release them on completion, failure or cancellation.
142
+ - Background actions use the owning actor's scope.
143
+ - Use `withActorScope` around resource acquisition to keep a resource until the owning actor stops.
144
+
145
+ Provide Layers outside the actor's scope, so services remain available during cleanup. Dispose a `ManagedRuntime` when its owner shuts down. See [actors](docs/actors.md).
146
+
147
+ ### Requirements
148
+
149
+ `RequirementsFrom<TLogic>` collects services from declared Effect actions, declared actors and inline invocations, including child machines up to 10 levels deep. `createEffectActor` returns `Effect<EffectActor<TLogic>, never, R | Scope>`. Provided action and actor overrides update that service union. Actor and invocation scopes are supplied automatically.
150
+
151
+ <details>
152
+ <summary>Requirement limits</summary>
153
+
154
+ Deeper requirements are not inferred. Provide them explicitly or flatten the machine tree. Inline spawned Effect logic is rejected; register it in `actors` before spawning it.
155
+
156
+ The actor's later errors are observed through `join` or snapshots. Invalid input rejected during creation is a defect.
157
+
158
+ </details>
159
+
160
+ ### Observing actors
161
+
162
+ <!-- actor surface from src/actor.ts -->
163
+
164
+ | Function | Use |
165
+ | ------------- | ------------------------------------------------------ |
166
+ | `send` | Enqueue an event. |
167
+ | `snapshots` | Stream the current snapshot and changes. |
168
+ | `waitFor` | Await a snapshot predicate, optionally with a timeout. |
169
+ | `join` | Await final output or failure. |
170
+ | `emitted` | Stream notifications emitted by the actor. |
171
+ | `inspect` | Stream system inspection events. |
172
+ | `deadLetters` | Observe delivery failures. |
173
+
174
+ `send` and `waitFor` support direct and pipeable usage. See [complete observation examples](docs/observing-actors.md).
175
+
176
+ ### Matching states
177
+
178
+ <!-- tagged state view from src/state.ts -->
179
+
180
+ `taggedState(snapshot)` exposes `_tag`, `value`, `context` and `snapshot`. Use `TaggedState<typeof machine>` with Effect's `Match.tag` and `Match.exhaustive`. Per-state context narrows with the tag. See [matching states](docs/matching-states.md).
181
+
182
+ ## Effect actor logic
183
+
184
+ <!-- fromEffect, fromEffectStream, fromEffectEventStream from src/fromEffect.ts -->
185
+
186
+ | Function | Behavior |
187
+ | ----------------------- | ---------------------------------------------------- |
188
+ | `fromEffect` | Run a task; its success value is the actor's output. |
189
+ | `fromEffectStream` | Expose the latest stream item as snapshot context. |
190
+ | `fromEffectEventStream` | Relay stream items to the parent as events. |
191
+
192
+ For example, a progress stream can feed an upload UI:
193
+
194
+ <!-- example from examples/effect-workflows/src/latest-stream.ts -->
195
+
196
+ ```ts
197
+ import { createEffectActor, fromEffectStream, snapshots } from '@xstate/effect'
198
+ import { Effect, Option, Stream } from 'effect'
199
+
200
+ // Demo upload progress. Replace with your upload SDK's progress stream.
201
+ const uploadProgress = fromEffectStream(Stream.make(0, 25, 60, 100))
202
+
203
+ const program = Effect.gen(function*() {
204
+ const actor = yield* createEffectActor(uploadProgress)
205
+ return yield* snapshots(actor).pipe(
206
+ Stream.filter((s) => s.context !== undefined),
207
+ Stream.map((s) => s.context),
208
+ Stream.runLast,
209
+ Effect.map(Option.getOrThrow),
210
+ )
211
+ })
212
+
213
+ export const result = await Effect.runPromise(Effect.scoped(program))
214
+ console.log(result) // 100
215
+ ```
216
+
217
+ See [Effect actor logic](docs/effect-logic.md) for tasks and a stream that drives rollout transitions.
218
+
219
+ ## Schemas and actions
220
+
221
+ <!-- schema conversion from src/schema.ts -->
222
+
223
+ `setupEffect` accepts Effect schemas for input, context, events, output and per-state context. Types are inferred without manual conversion. Add `standardSchemaValidator()` from `xstate/validation` for runtime checks.
224
+
225
+ ### Declared only
226
+
227
+ <!-- effect action contract from src/setupEffect.ts; spawn guard from src/internal.ts -->
228
+
229
+ - Register background Effect actions in `setupEffect({ actions })`; enqueue them with explicit arguments.
230
+ - Invoke `fromEffect` logic when the machine needs to wait for a result.
231
+ - Register spawned Effect logic in `actors`, then use `enq.spawn(args.actors.worker)`.
232
+
233
+ See [schemas and actions](docs/schemas-and-actions.md) for a complete audit example, runtime schema constraints and inline-source pitfalls.
234
+
235
+ ## Atoms and React
236
+
237
+ <!-- atom surface from src/atom.ts -->
238
+
239
+ `createActorAtoms` from `@xstate/effect/atom` exposes `actor`, `snapshot`, `result`, `send`, `select` and `state`. Its `Atom.runtime` must provide the logic's services. Pass `{ input }` when the logic requires input; missing or mismatched input is a type error.
240
+
241
+ - Read atoms with `@effect/atom-react` in React, or an `AtomRegistry` elsewhere.
242
+ - The registry owns their lifetime; dispose it when its owner shuts down.
243
+ - `useSelector` from `@xstate/react` can also read an existing `EffectActor` directly.
244
+
245
+ See [atoms and React](docs/atoms-and-react.md) for complete examples with imports, runtime setup and cleanup.
246
+
247
+ ## Testing and errors
248
+
249
+ <!-- error types from src/errors.ts; timeout failure from src/actor.ts -->
250
+
251
+ - Use `TestClock` to drive deadlines without waiting for real time.
252
+ - `ActorStoppedError` reports a stop before an awaited result.
253
+ - `EffectInterruptedError` reports self-interruption inside Effect logic.
254
+ - Timed waits fail with Effect's `Cause.TimeoutError`.
255
+ - `join` preserves a task's typed failure. Unexpected machine errors have type `unknown`.
256
+
257
+ See [testing and errors](docs/testing-and-errors.md) for executable deadline, retry and failure examples. Persisted snapshots record actor state; pass one to `createEffectActor(logic, { snapshot })` to resume the actor. See [persisting and restoring](docs/actors.md#persisting-and-restoring).
258
+
259
+ ## Tracing
260
+
261
+ <!-- span names and attributes from src/internal.ts and src/fromEffect.ts -->
262
+
263
+ Hosted work uses spans named `fromEffect`, `fromEffectStream`, `fromEffectEventStream` and `action.<name>`. Each carries `xstate.actor.id` and `xstate.actor.address`. Provide a `Tracer` to record and export them.
package/dist/atom.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ import { I as EffectActor, c as NotReadyError, p as RequirementsFrom, r as TaggedStateFrom, u as EffectActorOptionsArgs } from "./state-Ch1-WxXd.js";
2
+ import { AnyActorLogic, ErrorFrom, EventFromLogic, SnapshotFrom } from "@systemfsoftware/xstate";
3
+ import { AsyncResult, Atom } from "effect/reactivity";
4
+ /**
5
+ * Atoms that expose one actor to a reactive UI through
6
+ * `effect/reactivity`. Read them with the atom bindings for your
7
+ * framework, such as `@effect/atom-react`.
8
+ */
9
+ export interface ActorAtoms<TLogic extends AnyActorLogic, ER = never> {
10
+ /**
11
+ * The running actor. It starts when the atom is first read and stops when
12
+ * the atom is released, that is, when nothing reads or mounts it anymore.
13
+ */
14
+ readonly actor: Atom.Atom<AsyncResult.AsyncResult<EffectActor<TLogic>, ER>>;
15
+ /** The actor's current snapshot, updated on every transition. */
16
+ readonly snapshot: Atom.Atom<AsyncResult.AsyncResult<SnapshotFrom<TLogic>, ER>>;
17
+ /**
18
+ * The snapshot as a result: a `Failure` carrying the actor's error once
19
+ * the actor's status is `error`, so an error boundary can handle it.
20
+ */
21
+ readonly result: Atom.Atom<AsyncResult.AsyncResult<SnapshotFrom<TLogic>, ER | ErrorFrom<TLogic>>>;
22
+ /**
23
+ * Sends an event to the actor synchronously. Set it with the event, for
24
+ * example through `useAtomSet` in React. Its value reports the last send:
25
+ * a `NotReadyError` failure when the runtime is still building, otherwise
26
+ * success.
27
+ */
28
+ readonly send: Atom.Writable<AsyncResult.AsyncResult<void, ER | NotReadyError>, EventFromLogic<TLogic>>;
29
+ /** Derives an atom of a value selected from the snapshot. */
30
+ readonly select: <T>(selector: (snapshot: SnapshotFrom<TLogic>) => T) => Atom.Atom<AsyncResult.AsyncResult<T, ER>>;
31
+ /**
32
+ * The snapshot as a tagged union over the machine's states, for
33
+ * `Match.tag` or a `switch` on `_tag`. See `taggedState`.
34
+ */
35
+ readonly state: Atom.Atom<AsyncResult.AsyncResult<TaggedStateFrom<SnapshotFrom<TLogic>>, ER>>;
36
+ }
37
+ interface MissingRequirements<T> {
38
+ readonly 'The runtime does not provide services the logic requires': T;
39
+ }
40
+ /**
41
+ * Creates atoms for an actor that runs in an `Atom.runtime`. The runtime's
42
+ * Layer must provide every service the logic requires; a missing service is
43
+ * a type error on the `runtime` argument. Logic with required input also
44
+ * requires an options object containing that input.
45
+ *
46
+ * The actor is created with `createEffectActor` inside the `actor` atom's
47
+ * scope, so its lifetime follows the atom: it starts on first read and stops
48
+ * when the atom is released. Wrap the atoms with `Atom.keepAlive` to pin the
49
+ * actor for the registry's lifetime, or with `Atom.family` to create one
50
+ * actor per input.
51
+ */
52
+ export declare function createActorAtoms<TLogic extends AnyActorLogic, R, ER = never>(runtime: Atom.AtomRuntime<R, ER> & ([RequirementsFrom<TLogic>] extends [R] ? unknown : MissingRequirements<Exclude<RequirementsFrom<TLogic>, R>>), logic: TLogic, ...[options]: EffectActorOptionsArgs<TLogic>): ActorAtoms<TLogic, ER>;
53
+ export { NotReadyError };
package/dist/atom.mjs ADDED
@@ -0,0 +1,64 @@
1
+ import { f as NotReadyError, n as createEffectActor, t as taggedState } from "./state-CNrCEIpU.mjs";
2
+ import { Cause } from "effect";
3
+ import { AsyncResult, Atom } from "effect/reactivity";
4
+ // src/atom.ts
5
+ /**
6
+ * Creates atoms for an actor that runs in an `Atom.runtime`. The runtime's
7
+ * Layer must provide every service the logic requires; a missing service is
8
+ * a type error on the `runtime` argument. Logic with required input also
9
+ * requires an options object containing that input.
10
+ *
11
+ * The actor is created with `createEffectActor` inside the `actor` atom's
12
+ * scope, so its lifetime follows the atom: it starts on first read and stops
13
+ * when the atom is released. Wrap the atoms with `Atom.keepAlive` to pin the
14
+ * actor for the registry's lifetime, or with `Atom.family` to create one
15
+ * actor per input.
16
+ */
17
+ function createActorAtoms(runtime, logic, ...[options]) {
18
+ const actor = runtime.atom(createEffectActor(logic, options));
19
+ const snapshot = Atom.make((get) => {
20
+ const result = get(actor);
21
+ if (!AsyncResult.isSuccess(result)) return AsyncResult.map(result, (running) => running.getSnapshot());
22
+ const running = result.value;
23
+ const publish = () => {
24
+ get.setSelf(AsyncResult.success(running.getSnapshot()));
25
+ };
26
+ const subscription = running.subscribe({
27
+ next: publish,
28
+ error: publish,
29
+ complete: publish
30
+ });
31
+ get.addFinalizer(() => {
32
+ subscription.unsubscribe();
33
+ });
34
+ return AsyncResult.success(running.getSnapshot());
35
+ });
36
+ const result = Atom.make((get) => {
37
+ const current = get(snapshot);
38
+ if (!AsyncResult.isSuccess(current)) return current;
39
+ const value = current.value;
40
+ if (value.status === "error") return AsyncResult.failureWithPrevious(Cause.fail(value.error), { previous: get.self() });
41
+ return current;
42
+ });
43
+ const sendAtom = Atom.writable((get) => AsyncResult.map(get(actor), () => void 0), (ctx, event) => {
44
+ const current = ctx.get(actor);
45
+ if (AsyncResult.isInitial(current)) ctx.setSelf(AsyncResult.failure(Cause.fail(new NotReadyError())));
46
+ else if (AsyncResult.isFailure(current)) ctx.setSelf(AsyncResult.map(current, () => void 0));
47
+ else {
48
+ current.value.send(event);
49
+ ctx.setSelf(AsyncResult.success(void 0));
50
+ }
51
+ });
52
+ function select(selector) {
53
+ return Atom.map(snapshot, (result) => AsyncResult.map(result, selector));
54
+ }
55
+ return {
56
+ actor,
57
+ snapshot,
58
+ result,
59
+ send: sendAtom,
60
+ select,
61
+ state: select((current) => taggedState(current))
62
+ };
63
+ }
64
+ export { NotReadyError, createActorAtoms };
@@ -0,0 +1,160 @@
1
+ import { A as ToStandardSetupStates, C as fromEffectEventStream, D as EffectSetupSchemas, E as EffectSchemaLike, F as withActorScope, I as EffectActor, M as ValidateEffectSetupStates, N as effectActionBrand, O as EffectSetupStateSchema, P as ActorScope, S as fromEffect, T as EffectSchema, _ as EffectSource, a as ActorFailedError, b as EffectStreamSnapshot, d as createEffectActor, f as EffectRequirements, g as EffectSnapshot, h as EffectLogicBrand, i as taggedState, j as ValidateEffectSetupSchemas, k as ToStandardSetupSchemas, l as EffectActorOptions, m as EffectActorLogic, n as TaggedState, o as ActorStoppedError, p as RequirementsFrom, r as TaggedStateFrom, s as EffectInterruptedError, t as StateTag, v as EffectSourceArgs, w as fromEffectStream, x as EffectStreamSource, y as EffectStreamActorLogic } from "./state-Ch1-WxXd.js";
2
+ import { Cause, Duration, Effect, Stream } from "effect";
3
+ import { Actor, ActorLogicValidator, ActorRef, AnyActorRef, AnyEventObject, EmittedFrom, ErrorFrom, ErrorFrom as ErrorFrom$1, EventObject, EventRejection, InspectionEvent, MachineContext, OutputFrom, SetupConfig, SetupReturn, SetupSchemas, SetupStateSchema, SnapshotFrom, Sources, SystemRegistry, SystemRuntime } from "@systemfsoftware/xstate";
4
+ /** The event type accepted by an actor's `send` method. */
5
+ type SendableEventFrom<TActor extends AnyActorRef> = Parameters<TActor['send']>[0];
6
+ /** The event type an actor emits through `actor.on(...)`. */
7
+ type EmittedEventFrom<TActor> = TActor extends EffectActor<infer TLogic> ? EmittedFrom<TLogic> : TActor extends Actor<infer TLogic> ? EmittedFrom<TLogic> : TActor extends ActorRef<any, any, infer TEmitted, any> ? TEmitted : AnyEventObject;
8
+ /** Options for {@link waitFor}. */
9
+ interface WaitForOptions {
10
+ /**
11
+ * Fails with `Cause.TimeoutError` when no snapshot satisfies the predicate
12
+ * within this duration.
13
+ */
14
+ readonly timeout: Duration.Input;
15
+ }
16
+ /**
17
+ * A narrowing snapshot predicate. Named so both of `waitFor`'s call styles
18
+ * describe the same predicate shape.
19
+ */
20
+ type SnapshotPredicate<TActor extends AnyActorRef, TNarrowed extends SnapshotFrom<TActor>> = (snapshot: SnapshotFrom<TActor>) => snapshot is TNarrowed;
21
+ /**
22
+ * Sends an event to an actor. The returned Effect always succeeds: the event
23
+ * is enqueued, like `actor.send(event)`, and processed on the actor's own
24
+ * fiber. An event that cannot be delivered (for example to a stopped actor)
25
+ * is reported as a dead letter, observable with {@link deadLetters}.
26
+ */
27
+ export declare const send: {
28
+ <TActor extends AnyActorRef>(event: SendableEventFrom<TActor>): (actor: TActor) => Effect.Effect<void>;
29
+ <TActor extends AnyActorRef>(actor: TActor, event: SendableEventFrom<TActor>): Effect.Effect<void>;
30
+ };
31
+ /**
32
+ * Streams an actor's snapshots, starting with the current one. The stream ends
33
+ * when the actor completes or stops, and emits the error snapshot before
34
+ * ending when the actor errors. Interrupting the stream unsubscribes from the
35
+ * actor.
36
+ */
37
+ export declare function snapshots<TActor extends AnyActorRef>(actor: TActor): Stream.Stream<SnapshotFrom<TActor>>;
38
+ /**
39
+ * Streams every event an actor emits, as delivered to `actor.on('*', …)`. The
40
+ * stream ends when the actor completes, errors or stops. Interrupting the
41
+ * stream removes the listener.
42
+ */
43
+ export declare function emitted<TActor extends AnyActorRef>(actor: TActor): Stream.Stream<EmittedEventFrom<TActor>>;
44
+ /**
45
+ * Waits for the first actor snapshot that satisfies `predicate`, succeeding
46
+ * immediately when the current snapshot already does. Fails with
47
+ * `ActorStoppedError` if the actor stops or errors first, and with
48
+ * `Cause.TimeoutError` when `options.timeout` elapses. Interrupting the Effect
49
+ * unsubscribes from the actor.
50
+ */
51
+ export declare const waitFor: {
52
+ <TActor extends AnyActorRef, TNarrowed extends SnapshotFrom<TActor>>(predicate: SnapshotPredicate<TActor, TNarrowed>): (actor: TActor) => Effect.Effect<TNarrowed, ActorStoppedError>;
53
+ <TActor extends AnyActorRef>(predicate: (snapshot: SnapshotFrom<TActor>) => boolean): (actor: TActor) => Effect.Effect<SnapshotFrom<TActor>, ActorStoppedError>;
54
+ <TActor extends AnyActorRef, TNarrowed extends SnapshotFrom<TActor>>(predicate: SnapshotPredicate<TActor, TNarrowed>, options: WaitForOptions): (actor: TActor) => Effect.Effect<TNarrowed, ActorStoppedError | Cause.TimeoutError>;
55
+ <TActor extends AnyActorRef>(predicate: (snapshot: SnapshotFrom<TActor>) => boolean, options: WaitForOptions): (actor: TActor) => Effect.Effect<SnapshotFrom<TActor>, ActorStoppedError | Cause.TimeoutError>;
56
+ <TActor extends AnyActorRef, TNarrowed extends SnapshotFrom<TActor>>(actor: TActor, predicate: SnapshotPredicate<TActor, TNarrowed>): Effect.Effect<TNarrowed, ActorStoppedError>;
57
+ <TActor extends AnyActorRef>(actor: TActor, predicate: (snapshot: SnapshotFrom<TActor>) => boolean): Effect.Effect<SnapshotFrom<TActor>, ActorStoppedError>;
58
+ <TActor extends AnyActorRef, TNarrowed extends SnapshotFrom<TActor>>(actor: TActor, predicate: SnapshotPredicate<TActor, TNarrowed>, options: WaitForOptions): Effect.Effect<TNarrowed, ActorStoppedError | Cause.TimeoutError>;
59
+ <TActor extends AnyActorRef>(actor: TActor, predicate: (snapshot: SnapshotFrom<TActor>) => boolean, options: WaitForOptions): Effect.Effect<SnapshotFrom<TActor>, ActorStoppedError | Cause.TimeoutError>;
60
+ };
61
+ /**
62
+ * Joins an actor's final result, like `Fiber.join`: succeeds with its `output`
63
+ * when it is done, fails with `ActorFailedError` carrying `snapshot.error` when
64
+ * it errors, and fails with `ActorStoppedError` when it stops without output.
65
+ * Waits for a still-active actor to settle.
66
+ */
67
+ export declare function join<TActor extends AnyActorRef>(actor: TActor): Effect.Effect<OutputFrom<TActor>, ActorFailedError<ErrorFrom$1<TActor>> | ActorStoppedError>;
68
+ /**
69
+ * Streams the inspection events of the actor's system, as delivered to
70
+ * `system.inspect(…)`. The stream runs until it is interrupted or its scope
71
+ * closes.
72
+ */
73
+ export declare function inspect(actor: AnyActorRef): Stream.Stream<InspectionEvent>;
74
+ /**
75
+ * Streams the events the actor's system could not deliver, as reported by
76
+ * `system.onRejectedEvent`: sends to a stopped actor, invalid external
77
+ * events and internal events sent from outside their owner. A dead letter is
78
+ * not an actor error. The stream runs until it is interrupted or its scope
79
+ * closes.
80
+ */
81
+ export declare function deadLetters(actor: AnyActorRef): Stream.Stream<EventRejection>;
82
+ /**
83
+ * Argument an Effect action receives. It mirrors the v6 action argument
84
+ * object: the machine's `context` and the `event` that caused the transition,
85
+ * the actor itself and its family (`self`, `parent`, `children`), the
86
+ * registered `actions`, `actors`, `guards` and `delays`, the actor `system`,
87
+ * and the `params` and `output` the transition passed along.
88
+ */
89
+ type EffectActionArgs<TContext extends MachineContext = MachineContext, TEvent extends EventObject = EventObject> = {
90
+ readonly context: TContext;
91
+ readonly event: TEvent;
92
+ readonly self: AnyActorRef;
93
+ readonly parent: AnyActorRef | undefined;
94
+ readonly children: Record<string, AnyActorRef | undefined>;
95
+ readonly actions: Record<string, unknown>;
96
+ readonly actors: Record<string, unknown>;
97
+ readonly guards: Record<string, unknown>;
98
+ readonly delays: Record<string, unknown>;
99
+ readonly system: SystemRuntime<SystemRegistry>;
100
+ readonly params?: unknown;
101
+ readonly output?: unknown;
102
+ };
103
+ /**
104
+ * An action registered with `setupEffect({ actions })`. It is called
105
+ * synchronously during the transition with the arguments the transition
106
+ * enqueued, and returns an Effect that runs afterwards in the actor's Effect
107
+ * context. The Effect is interrupted when the actor stops; its failures and
108
+ * defects route to the state's `onError`.
109
+ */
110
+ type EffectAction<TContext extends MachineContext = MachineContext, TEvent extends EventObject = EventObject, TError = unknown, TRequirements = never> = (args: EffectActionArgs<TContext, TEvent>) => Effect.Effect<void, TError, TRequirements>;
111
+ type AnyEffectAction = EffectAction<any, any, any, any>;
112
+ type EffectActionRequirements<TAction> = TAction extends ((...args: any[]) => infer TResult) ? EffectRequirements<TResult> : never;
113
+ type CoreEffectAction<TAction> = TAction extends ((...args: infer TArgs) => any) ? ((...args: TArgs) => void) & {
114
+ readonly [effectActionBrand]?: EffectActionRequirements<TAction>;
115
+ } : never;
116
+ type CoreEffectActionMap<TActionMap> = { [K in keyof TActionMap]: CoreEffectAction<TActionMap[K]>; };
117
+ type EffectSetupConfig<TSchemas extends EffectSetupSchemas, TStates extends Record<string, EffectSetupStateSchema>, TActionMap extends Record<string, AnyEffectAction>, TActorMap extends Sources['actors'], TGuardMap extends Sources['guards'], TDelayMap extends Sources['delays'], TValidator extends ActorLogicValidator | undefined, TSourceSchemas extends SetupSchemas = ToStandardSetupSchemas<TSchemas>> = {
118
+ validator?: TValidator;
119
+ actions?: TActionMap & Record<string, AnyEffectAction>;
120
+ actors?: TActorMap;
121
+ guards?: NonNullable<SetupConfig<TSourceSchemas, ToStandardSetupStates<TStates>, CoreEffectActionMap<TActionMap>, TActorMap, TGuardMap, TDelayMap, TValidator>['guards']>;
122
+ delays?: NonNullable<SetupConfig<TSourceSchemas, ToStandardSetupStates<TStates>, CoreEffectActionMap<TActionMap>, TActorMap, TGuardMap, TDelayMap, TValidator>['delays']>;
123
+ schemas?: TSchemas & ([TValidator] extends [ActorLogicValidator] ? ValidateEffectSetupSchemas<TSchemas> : unknown);
124
+ states?: TStates & ([TValidator] extends [ActorLogicValidator] ? ValidateEffectSetupStates<TStates> : unknown);
125
+ };
126
+ type MergeRecord<TBase, TExtension> = Omit<TBase, keyof TExtension> & TExtension;
127
+ type MergeSetupSchemas<TBaseSchemas extends SetupSchemas, TExtensionSchemas extends SetupSchemas> = { [K in keyof TBaseSchemas | keyof TExtensionSchemas]: K extends 'events' | 'internalEvents' | 'emitted' | 'children' | 'actions' | 'guards' ? MergeRecord<K extends keyof TBaseSchemas ? NonNullable<TBaseSchemas[K]> : {}, K extends keyof TExtensionSchemas ? NonNullable<TExtensionSchemas[K]> : {}> : K extends keyof TExtensionSchemas ? TExtensionSchemas[K] : K extends keyof TBaseSchemas ? TBaseSchemas[K] : never; } extends (infer TMergedSchemas extends SetupSchemas) ? TMergedSchemas : never;
128
+ interface RuntimeValidationDoesNotSupportTransformingSchemas {
129
+ readonly __xstate_effect_error: 'Runtime validation does not support schemas with different encoded and decoded types';
130
+ }
131
+ type RuntimeValidationCompatibility<TSchemas, TStates, TValidator> = [TValidator] extends [ActorLogicValidator] ? [TSchemas] extends [ValidateEffectSetupSchemas<TSchemas>] ? [TStates] extends [ValidateEffectSetupStates<TStates>] ? unknown : RuntimeValidationDoesNotSupportTransformingSchemas : RuntimeValidationDoesNotSupportTransformingSchemas : unknown;
132
+ declare const inheritedEffectValidator: unique symbol;
133
+ type InheritedEffectValidator = typeof inheritedEffectValidator;
134
+ type ResolveExtendedValidator<TBase, TExtension> = [TExtension] extends [InheritedEffectValidator] ? TBase : Exclude<TExtension, InheritedEffectValidator>;
135
+ type ExtendValidatorConfig<TExtension> = [TExtension] extends [InheritedEffectValidator] ? {
136
+ validator?: never;
137
+ } : {
138
+ validator: TExtension;
139
+ };
140
+ type EffectSetupExtensionConfig<TBaseSchemas extends SetupSchemas, TBaseStates extends Record<string, SetupStateSchema>, TBaseValidator extends ActorLogicValidator | undefined, TExtensionSchemas extends EffectSetupSchemas, TExtensionStates extends Record<string, EffectSetupStateSchema>, TExtensionActionMap extends Record<string, AnyEffectAction>, TExtensionActorMap extends Sources['actors'], TExtensionGuardMap extends Sources['guards'], TExtensionDelayMap extends Sources['delays'], TExtensionValidator extends ActorLogicValidator | undefined | InheritedEffectValidator> = EffectSetupConfig<TExtensionSchemas, TExtensionStates, TExtensionActionMap, TExtensionActorMap, TExtensionGuardMap, TExtensionDelayMap, ResolveExtendedValidator<TBaseValidator, TExtensionValidator>, MergeSetupSchemas<TBaseSchemas, ToStandardSetupSchemas<TExtensionSchemas>>> & ExtendValidatorConfig<TExtensionValidator> & RuntimeValidationCompatibility<NoInfer<TBaseSchemas>, NoInfer<TBaseStates>, ResolveExtendedValidator<TBaseValidator, TExtensionValidator>>;
141
+ /**
142
+ * What `setupEffect` returns: the XState `SetupReturn` with an `extend` method
143
+ * that also accepts Effect schemas and Effect-returning actions. Call
144
+ * `createMachine` on it to build a machine whose registered actions and actors
145
+ * contribute to `RequirementsFrom`.
146
+ */
147
+ type EffectSetupReturn<TStates extends Record<string, SetupStateSchema> = Record<string, SetupStateSchema>, TSchemas extends SetupSchemas = {}, TSetupActionMap extends Sources['actions'] = {}, TSetupActorMap extends Sources['actors'] = {}, TSetupGuardMap extends Sources['guards'] = {}, TSetupDelayMap extends Sources['delays'] = {}, TSetupDelays extends string = Extract<keyof TSetupDelayMap, string>, TValidator extends ActorLogicValidator | undefined = undefined> = Omit<SetupReturn<TStates, TSchemas, TSetupActionMap, TSetupActorMap, TSetupGuardMap, TSetupDelayMap, TSetupDelays, SystemRegistry, TValidator>, 'extend'> & {
148
+ extend<const TExtensionSchemas extends EffectSetupSchemas = {}, const TExtensionStates extends Record<string, EffectSetupStateSchema> = {}, TExtensionActionMap extends Record<string, AnyEffectAction> = {}, TExtensionActorMap extends Sources['actors'] = {}, TExtensionGuardMap extends Sources['guards'] = {}, TExtensionDelayMap extends Sources['delays'] = {}, const TExtensionValidator extends ActorLogicValidator | undefined | InheritedEffectValidator = InheritedEffectValidator>(config: EffectSetupExtensionConfig<TSchemas, TStates, TValidator, TExtensionSchemas, TExtensionStates, TExtensionActionMap, TExtensionActorMap, TExtensionGuardMap, TExtensionDelayMap, TExtensionValidator>): EffectSetupReturn<MergeRecord<TStates, ToStandardSetupStates<TExtensionStates>>, MergeSetupSchemas<TSchemas, ToStandardSetupSchemas<TExtensionSchemas>>, MergeRecord<TSetupActionMap, CoreEffectActionMap<TExtensionActionMap>>, MergeRecord<TSetupActorMap, TExtensionActorMap>, MergeRecord<TSetupGuardMap, TExtensionGuardMap>, MergeRecord<TSetupDelayMap, TExtensionDelayMap>, TSetupDelays | Extract<keyof TExtensionDelayMap, string>, ResolveExtendedValidator<TValidator, TExtensionValidator>>;
149
+ };
150
+ /**
151
+ * The Effect-aware form of XState's `setup`. It accepts Effect `Schema` values
152
+ * wherever `setup` accepts Standard Schemas, and actions that return an
153
+ * Effect, which it wraps so the transition stays synchronous while the Effect
154
+ * runs in the actor's Effect context. Everything else, including `actors`,
155
+ * `guards`, `delays` and `extend`, behaves as in `setup`. Machines built from
156
+ * it must be started with `createEffectActor`.
157
+ */
158
+ export declare function setupEffect(): EffectSetupReturn;
159
+ export declare function setupEffect<const TSchemas extends EffectSetupSchemas = {}, const TStates extends Record<string, EffectSetupStateSchema> = Record<string, EffectSetupStateSchema>, TActionMap extends Record<string, AnyEffectAction> = {}, TActorMap extends Sources['actors'] = {}, TGuardMap extends Sources['guards'] = {}, TDelayMap extends Sources['delays'] = {}, const TValidator extends ActorLogicValidator | undefined = undefined>(config: EffectSetupConfig<TSchemas, TStates, TActionMap, TActorMap, TGuardMap, TDelayMap, TValidator>): EffectSetupReturn<ToStandardSetupStates<TStates>, ToStandardSetupSchemas<TSchemas>, CoreEffectActionMap<TActionMap>, TActorMap, TGuardMap, TDelayMap, Extract<keyof TDelayMap, string>, TValidator>;
160
+ export { ActorFailedError, ActorScope, ActorStoppedError, type EffectAction, type EffectActionArgs, EffectActor, type EffectActorLogic, type EffectActorOptions, EffectInterruptedError, type EffectLogicBrand, type EffectSchema, type EffectSchemaLike, type EffectSetupReturn, type EffectSetupSchemas, type EffectSetupStateSchema, type EffectSnapshot, type EffectSource, type EffectSourceArgs, type EffectStreamActorLogic, type EffectStreamSnapshot, type EffectStreamSource, type EmittedEventFrom, type ErrorFrom, type RequirementsFrom, type SendableEventFrom, type StateTag, type TaggedState, type TaggedStateFrom, type WaitForOptions, createEffectActor, fromEffect, fromEffectEventStream, fromEffectStream, taggedState, withActorScope };