@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.
@@ -0,0 +1,447 @@
1
+ import { Cause, Context, Effect, Queue, Schema, Scope, Stream } from "effect";
2
+ import { ActorLogic, ActorLogicValidator, ActorOptions, ActorRef, AnyActor, AnyActorLogic, AnyActorRef, AnyActorSystem, AnyEventObject, AnyMachineSnapshot, AnyStateMachine, EmittedFrom, EventFromLogic, EventObject, InputFrom, InspectionEvent, MachineContext, MachineSnapshot, Observer, RequiredActorOptionsFor, RequiredActorOptionsKeys, SetupSchemas, SetupStateSchema, SetupStateSchemas, Snapshot, SnapshotFrom, StandardSchemaV1, StateContextFromStateValue, StateSchema, StateValueFromStateSchema, Subscription } from "@systemfsoftware/xstate";
3
+ /** A mailbox item that reports a failed fire-and-forget action. */
4
+ interface ActionFailure {
5
+ readonly [actionFailure]: true;
6
+ readonly error: unknown;
7
+ }
8
+ declare const actionFailure: unique symbol;
9
+ type MailboxItem<TEvent> = TEvent | ActionFailure;
10
+ declare const symbolObservable: typeof Symbol.observable;
11
+ /**
12
+ * The handle `createEffectActor` returns. It implements XState's `ActorRef`
13
+ * contract (`send`, `getSnapshot`, `subscribe`, `on`), so it works with
14
+ * `useSelector`, this package's actor functions and the inspection APIs, while
15
+ * the actor itself is driven by an Effect fiber over pure transitions.
16
+ */
17
+ declare class EffectActor<TLogic extends AnyActorLogic> implements ActorRef<SnapshotFrom<TLogic>, EventFromLogic<TLogic>, EmittedFrom<TLogic>> {
18
+ readonly logic: TLogic;
19
+ private readonly _mailbox;
20
+ private readonly _stopExecution;
21
+ private readonly _inspectors;
22
+ readonly id: string;
23
+ readonly address: string;
24
+ readonly sessionId: string | undefined;
25
+ /** The actor system that hosts this actor and its children. */
26
+ readonly system: AnyActor['system'];
27
+ private _snapshot;
28
+ private readonly _observers;
29
+ private readonly _listeners;
30
+ private _settled;
31
+ constructor(logic: TLogic, root: AnyActor, snapshot: SnapshotFrom<TLogic>, _mailbox: Queue.Queue<MailboxItem<EventFromLogic<TLogic>>>, _stopExecution: () => void, _inspectors: Set<(event: InspectionEvent) => void>);
32
+ getSnapshot(): SnapshotFrom<TLogic>;
33
+ getPersistedSnapshot(): Snapshot<unknown>;
34
+ /** Sends an event; the actor processes it on its own fiber. */
35
+ send(event: EventFromLogic<TLogic>): void;
36
+ /** Stops the actor, its children and every Effect it hosts. */
37
+ stop(): this;
38
+ subscribe(observer: Observer<SnapshotFrom<TLogic>>): Subscription;
39
+ subscribe(nextListener?: (snapshot: SnapshotFrom<TLogic>) => void, errorListener?: (error: any) => void, completeListener?: () => void): Subscription;
40
+ on<TType extends EmittedFrom<TLogic>['type'] | '*'>(type: TType, handler: (emitted: EmittedFrom<TLogic> & (TType extends '*' ? unknown : {
41
+ type: TType;
42
+ })) => void): Subscription;
43
+ /**
44
+ * Observes the inspection events of this actor and its children: every
45
+ * actor creation and transition of the execution.
46
+ */
47
+ inspect(observer: Observer<InspectionEvent> | ((event: InspectionEvent) => void)): Subscription;
48
+ [symbolObservable](): this;
49
+ toJSON(): {
50
+ xstate$$type: number;
51
+ id: string;
52
+ };
53
+ }
54
+ declare const ActorScopeService: Context.ServiceClass<ActorScope, "@systemfsoftware/xstate-effect/actorScope", Scope.Scope>;
55
+ /** The owning Effect actor's scope, supplied by `createEffectActor`. */
56
+ declare class ActorScope extends ActorScopeService {}
57
+ /**
58
+ * Acquires resources in the owning actor's scope. Their finalizers run when
59
+ * that actor stops, even if the invoking task finishes or is cancelled first.
60
+ */
61
+ declare function withActorScope<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, Exclude<R, Scope.Scope> | ActorScope>;
62
+ declare const effectActionBrand: unique symbol;
63
+ /**
64
+ * An Effect `Schema` accepted by this package. `setupEffect`, `fromEffect`,
65
+ * `fromEffectStream` and `fromEffectEventStream` convert it to a Standard
66
+ * Schema, so XState infers the decoded `Schema.Type` without an explicit call
67
+ * to `Schema.toStandardSchemaV1`.
68
+ */
69
+ type EffectSchema = Schema.ConstraintDecoder<unknown>;
70
+ /**
71
+ * Either an Effect {@link EffectSchema} or a Standard Schema. Every schema
72
+ * position in this package accepts both, so Effect schemas and schemas from
73
+ * other libraries can be mixed in one machine.
74
+ */
75
+ type EffectSchemaLike = StandardSchemaV1 | EffectSchema;
76
+ interface RuntimeValidationDoesNotSupportTransformingSchemas {
77
+ readonly __xstate_effect_error: 'Runtime validation does not support schemas with different encoded and decoded types';
78
+ }
79
+ type IsAny<T> = 0 extends 1 & T ? true : false;
80
+ type ToStandardSchema<TSchema> = TSchema extends StandardSchemaV1 ? TSchema : TSchema extends EffectSchema ? StandardSchemaV1<TSchema['Encoded'], TSchema['Type']> & TSchema : never;
81
+ type AssertNonTransformingSchema<TSchema> = TSchema extends EffectSchemaLike ? IsAny<StandardSchemaV1.InferInput<ToStandardSchema<TSchema>>> extends true ? TSchema : IsAny<StandardSchemaV1.InferOutput<ToStandardSchema<TSchema>>> extends true ? TSchema : [StandardSchemaV1.InferInput<ToStandardSchema<TSchema>>, StandardSchemaV1.InferOutput<ToStandardSchema<TSchema>>] extends [StandardSchemaV1.InferOutput<ToStandardSchema<TSchema>>, StandardSchemaV1.InferInput<ToStandardSchema<TSchema>>] ? TSchema : RuntimeValidationDoesNotSupportTransformingSchemas : TSchema;
82
+ type EffectSchemaShape<TValue> = TValue extends StandardSchemaV1 ? EffectSchemaLike : TValue extends Record<string, unknown> ? { [K in keyof TValue]: EffectSchemaShape<TValue[K]>; } : TValue;
83
+ type ToStandardSchemaShape<TValue> = TValue extends EffectSchemaLike ? ToStandardSchema<TValue> : TValue extends Record<string, unknown> ? { [K in keyof TValue]: ToStandardSchemaShape<TValue[K]>; } : TValue;
84
+ /**
85
+ * The `schemas` option of `setupEffect`: XState's `SetupSchemas` with every
86
+ * schema position widened to {@link EffectSchemaLike}. Covers `context`,
87
+ * `input`, `output` and the per-key records for `events`, `internalEvents`,
88
+ * `emitted` and `children`.
89
+ */
90
+ type EffectSetupSchemas = { [K in keyof SetupSchemas]?: EffectSchemaShape<NonNullable<SetupSchemas[K]>>; };
91
+ type ValidateEffectActorSchemas<TSchemas> = { [K in keyof TSchemas]: AssertNonTransformingSchema<TSchemas[K]>; };
92
+ type ValidateEffectSetupSchemas<TSchemas> = { [K in keyof TSchemas]: K extends 'events' | 'internalEvents' | 'emitted' | 'children' ? { [P in keyof TSchemas[K]]: AssertNonTransformingSchema<TSchemas[K][P]>; } : K extends 'context' | 'input' | 'output' ? AssertNonTransformingSchema<TSchemas[K]> : TSchemas[K]; };
93
+ type ToStandardSetupSchemas<TSchemas> = { [K in keyof TSchemas]: ToStandardSchemaShape<TSchemas[K]>; } extends (infer TStandardSchemas extends SetupSchemas) ? TStandardSchemas : never;
94
+ /**
95
+ * One node of the `states` option of `setupEffect`: the schemas declared for
96
+ * that state, and the same shape recursively for its child states. It is
97
+ * XState's `SetupStateSchema` with Effect schemas allowed in every schema
98
+ * position.
99
+ */
100
+ interface EffectSetupStateSchema {
101
+ schemas?: EffectSchemaShape<SetupStateSchemas>;
102
+ states?: Record<string, EffectSetupStateSchema>;
103
+ }
104
+ type ValidateEffectSetupStates<TStates> = { [K in keyof TStates]: TStates[K] extends EffectSetupStateSchema ? { [P in keyof TStates[K]]: P extends 'schemas' ? TStates[K][P] extends Record<string, unknown> ? { [S in keyof TStates[K][P]]: AssertNonTransformingSchema<TStates[K][P][S]>; } : TStates[K][P] : P extends 'states' ? TStates[K][P] extends Record<string, EffectSetupStateSchema> ? ValidateEffectSetupStates<TStates[K][P]> : TStates[K][P] : TStates[K][P]; } : TStates[K]; };
105
+ type ToStandardSetupStateSchema<TStateSchema> = TStateSchema extends EffectSetupStateSchema ? { [K in keyof TStateSchema]: K extends 'schemas' ? ToStandardSchemaShape<TStateSchema[K]> : K extends 'states' ? TStateSchema[K] extends Record<string, EffectSetupStateSchema> ? ToStandardSetupStates<TStateSchema[K]> : TStateSchema[K] : TStateSchema[K]; } extends (infer TStandardStateSchema extends SetupStateSchema) ? TStandardStateSchema : never : never;
106
+ type ToStandardSetupStates<TStates> = { [K in keyof TStates]: ToStandardSetupStateSchema<TStates[K]>; };
107
+ declare const effectLogicBrand: unique symbol;
108
+ /**
109
+ * Type-level marker attached to logic created by `fromEffect`,
110
+ * `fromEffectStream` and `fromEffectEventStream`. It carries the logic's
111
+ * failure type and its Effect service requirements, which is how
112
+ * `RequirementsFrom` collects the `R` channel of `createEffectActor` without
113
+ * inspecting the logic at runtime.
114
+ */
115
+ interface EffectLogicBrand<TError, TRequirements> {
116
+ readonly [effectLogicBrand]: {
117
+ readonly error: TError;
118
+ readonly requirements: TRequirements;
119
+ };
120
+ }
121
+ /**
122
+ * Snapshot of a `fromEffect` actor. The actor holds no context of its own: it
123
+ * is `active` while the Effect runs, `done` with the Effect's success value as
124
+ * `output`, or `error` with the Effect's failure, defect or
125
+ * `EffectInterruptedError` as `error`.
126
+ */
127
+ type EffectSnapshot<TOutput, TError, TInput> = Snapshot<TOutput> & {
128
+ readonly context: undefined;
129
+ readonly input: TInput | undefined;
130
+ readonly error: TError | undefined;
131
+ };
132
+ /**
133
+ * Argument passed to the function form of an Effect source. It gives the
134
+ * source the actor's `input`, its own reference (`self`), the actor `system`,
135
+ * and `emit` for publishing events that `actor.on(...)` and `emitted(actor)`
136
+ * observe.
137
+ */
138
+ type EffectSourceArgs<TInput> = {
139
+ readonly input: TInput;
140
+ readonly self: AnyActorRef;
141
+ readonly system: AnyActorSystem;
142
+ /** Emits an event that can be observed with `actor.on(...)` or `emitted(actor)`. */
143
+ readonly emit: (event: AnyEventObject) => void;
144
+ };
145
+ /**
146
+ * What `fromEffect` accepts as its Effect: either an Effect value, or a
147
+ * function of {@link EffectSourceArgs} returning one. The function form is
148
+ * called once per actor start, so it sees that actor's input.
149
+ */
150
+ type EffectSource<TOutput, TError, TInput, TRequirements> = Effect.Effect<TOutput, TError, TRequirements> | ((args: EffectSourceArgs<TInput>) => Effect.Effect<TOutput, TError, TRequirements>);
151
+ type EffectActorSchemas = {
152
+ readonly input?: EffectSchemaLike;
153
+ readonly output?: EffectSchemaLike;
154
+ };
155
+ type EffectSourceConfig<TOutput, TError, TInput, TRequirements, TSchemas extends EffectActorSchemas = EffectActorSchemas, TValidator extends ActorLogicValidator | undefined = ActorLogicValidator | undefined> = {
156
+ readonly id?: string;
157
+ readonly validator?: TValidator;
158
+ readonly schemas?: TSchemas & ([TValidator] extends [ActorLogicValidator] ? ValidateEffectActorSchemas<TSchemas> : unknown);
159
+ readonly effect: EffectSource<TOutput, TError, TInput, TRequirements>;
160
+ };
161
+ type SchemaOutput<TSchema extends EffectSchemaLike> = StandardSchemaV1.InferOutput<ToStandardSchema<TSchema>>;
162
+ type EffectSuccess<T> = T extends Effect.Effect<infer A, any, any> ? A : never;
163
+ type EffectFailure<T> = T extends Effect.Effect<any, infer E, any> ? E : never;
164
+ type EffectSchemaValidationConfig<TSchemas extends EffectActorSchemas> = {
165
+ readonly validator: ActorLogicValidator;
166
+ readonly schemas: TSchemas & ValidateEffectActorSchemas<TSchemas>;
167
+ } | {
168
+ readonly validator?: undefined;
169
+ readonly schemas: TSchemas;
170
+ };
171
+ /**
172
+ * Actor logic produced by `fromEffect` and `fromEffectEventStream`. It is
173
+ * ordinary XState actor logic carrying {@link EffectLogicBrand}, so a machine
174
+ * can invoke or spawn it, and `createEffectActor` can collect its
175
+ * requirements.
176
+ */
177
+ type EffectActorLogic<TOutput, TError, TInput, TRequirements> = ActorLogic<EffectSnapshot<TOutput, TError, TInput>, EventObject, TInput, AnyActorSystem> & {
178
+ readonly id?: string;
179
+ } & EffectLogicBrand<TError, TRequirements>;
180
+ /**
181
+ * Snapshot of a `fromEffectStream` actor. `context` holds the most recent
182
+ * stream item, or `undefined` before the first one. The actor reaches `done`
183
+ * with no output when the stream completes, and `error` when it fails.
184
+ */
185
+ type EffectStreamSnapshot<TItem, TError, TInput> = Snapshot<undefined> & {
186
+ readonly context: TItem | undefined;
187
+ readonly input: TInput | undefined;
188
+ readonly error: TError | undefined;
189
+ };
190
+ /**
191
+ * Actor logic produced by `fromEffectStream`. Its snapshot is an
192
+ * {@link EffectStreamSnapshot}, so the parent reads the latest item from the
193
+ * child's `context` rather than from events.
194
+ */
195
+ type EffectStreamActorLogic<TItem, TError, TInput, TRequirements> = ActorLogic<EffectStreamSnapshot<TItem, TError, TInput>, EventObject, TInput, AnyActorSystem> & {
196
+ readonly id?: string;
197
+ } & EffectLogicBrand<TError, TRequirements>;
198
+ /**
199
+ * Creates actor logic that runs an Effect. The actor completes with the
200
+ * Effect's success value as its output and fails with the Effect's error, its
201
+ * squashed defect, or an `EffectInterruptedError` when the Effect interrupts
202
+ * itself. Stopping the actor interrupts the Effect without an error. Accepts
203
+ * an Effect, a function of {@link EffectSourceArgs} returning one, or a config
204
+ * object with `id`, `schemas`, `validator` and `effect`. The logic must be run
205
+ * under `createEffectActor`, which provides the Effect services it declares.
206
+ * Resources belong to this task's scope and close on completion, failure or
207
+ * interruption. Use `withActorScope` to retain a resource until the owning
208
+ * Effect actor stops.
209
+ */
210
+ declare function fromEffect<const TInputSchema extends EffectSchemaLike, const TOutputSchema extends EffectSchemaLike, TError = unknown, TRequirements = never>(config: Omit<EffectSourceConfig<SchemaOutput<TOutputSchema>, TError, SchemaOutput<TInputSchema>, TRequirements>, 'schemas' | 'validator'> & EffectSchemaValidationConfig<{
211
+ input: TInputSchema;
212
+ output: TOutputSchema;
213
+ }>): EffectActorLogic<SchemaOutput<TOutputSchema>, TError, SchemaOutput<TInputSchema>, TRequirements>;
214
+ declare function fromEffect<const TInputSchema extends EffectSchemaLike, TEffect extends Effect.Effect<any, any, any>>(config: Omit<EffectSourceConfig<EffectSuccess<TEffect>, EffectFailure<TEffect>, SchemaOutput<TInputSchema>, EffectRequirements<TEffect>, {
215
+ input: TInputSchema;
216
+ }>, 'effect' | 'schemas' | 'validator'> & EffectSchemaValidationConfig<{
217
+ input: TInputSchema;
218
+ output?: never;
219
+ }> & {
220
+ effect: TEffect | ((args: EffectSourceArgs<SchemaOutput<TInputSchema>>) => TEffect);
221
+ }): EffectActorLogic<EffectSuccess<TEffect>, EffectFailure<TEffect>, SchemaOutput<TInputSchema>, EffectRequirements<TEffect>>;
222
+ declare function fromEffect<const TOutputSchema extends EffectSchemaLike, TError = unknown, TInput = undefined, TRequirements = never>(config: Omit<EffectSourceConfig<SchemaOutput<TOutputSchema>, TError, TInput, TRequirements>, 'schemas' | 'validator'> & EffectSchemaValidationConfig<{
223
+ input?: never;
224
+ output: TOutputSchema;
225
+ }>): EffectActorLogic<SchemaOutput<TOutputSchema>, TError, TInput, TRequirements>;
226
+ declare function fromEffect<TOutput, TError = unknown, TInput = undefined, TRequirements = never>(config: EffectSourceConfig<TOutput, TError, TInput, TRequirements> & {
227
+ schemas?: undefined;
228
+ }): EffectActorLogic<TOutput, TError, TInput, TRequirements>;
229
+ declare function fromEffect<TOutput, TError = unknown, TRequirements = never>(effect: Effect.Effect<TOutput, TError, TRequirements>): EffectActorLogic<TOutput, TError, undefined, TRequirements>;
230
+ declare function fromEffect<TOutput, TError = unknown, TInput = undefined, TRequirements = never>(effect: (args: EffectSourceArgs<TInput>) => Effect.Effect<TOutput, TError, TRequirements>): EffectActorLogic<TOutput, TError, TInput, TRequirements>;
231
+ /**
232
+ * What `fromEffectStream` and `fromEffectEventStream` accept as their stream:
233
+ * either a Stream value, or a function of {@link EffectSourceArgs} returning
234
+ * one. The function form is called once per actor start.
235
+ */
236
+ type EffectStreamSource<TItem, TError, TInput, TRequirements> = Stream.Stream<TItem, TError, TRequirements> | ((args: EffectSourceArgs<TInput>) => Stream.Stream<TItem, TError, TRequirements>);
237
+ type EffectStreamConfig<TItem, TError, TInput, TRequirements, TSchemas extends {
238
+ readonly input?: EffectSchemaLike;
239
+ } = {
240
+ readonly input?: EffectSchemaLike;
241
+ }, TValidator extends ActorLogicValidator | undefined = ActorLogicValidator | undefined> = {
242
+ readonly id?: string;
243
+ readonly validator?: TValidator;
244
+ readonly schemas?: TSchemas & ([TValidator] extends [ActorLogicValidator] ? ValidateEffectActorSchemas<TSchemas> : unknown);
245
+ readonly stream: EffectStreamSource<TItem, TError, TInput, TRequirements>;
246
+ };
247
+ type StreamItem<T> = T extends Stream.Stream<infer A, any, any> ? A : never;
248
+ type StreamError<T> = T extends Stream.Stream<any, infer E, any> ? E : never;
249
+ type StreamRequirements<T> = T extends Stream.Stream<any, any, infer R> ? R : never;
250
+ /**
251
+ * Creates actor logic that runs a Stream and exposes its most recent item as
252
+ * the actor's `context`. The actor reaches `done` when the stream completes
253
+ * and `error` when it fails. Accepts a Stream, a function of
254
+ * {@link EffectSourceArgs} returning one, or a config object with `id`,
255
+ * `schemas`, `validator` and `stream`. Its resources close when the stream
256
+ * completes, fails or is interrupted.
257
+ */
258
+ declare function fromEffectStream<const TInputSchema extends EffectSchemaLike, TStream extends Stream.Stream<any, any, any>>(config: Omit<EffectStreamConfig<StreamItem<TStream>, StreamError<TStream>, SchemaOutput<TInputSchema>, StreamRequirements<TStream>>, 'stream' | 'schemas' | 'validator'> & EffectSchemaValidationConfig<{
259
+ input: TInputSchema;
260
+ }> & {
261
+ stream: TStream | ((args: EffectSourceArgs<SchemaOutput<TInputSchema>>) => TStream);
262
+ }): EffectStreamActorLogic<StreamItem<TStream>, StreamError<TStream>, SchemaOutput<TInputSchema>, StreamRequirements<TStream>>;
263
+ declare function fromEffectStream<TItem, TError = unknown, TInput = undefined, TRequirements = never>(config: EffectStreamConfig<TItem, TError, TInput, TRequirements> & {
264
+ schemas?: undefined;
265
+ }): EffectStreamActorLogic<TItem, TError, TInput, TRequirements>;
266
+ declare function fromEffectStream<TItem, TError = unknown, TInput = undefined, TRequirements = never>(stream: EffectStreamSource<TItem, TError, TInput, TRequirements>): EffectStreamActorLogic<TItem, TError, TInput, TRequirements>;
267
+ /**
268
+ * Creates actor logic that runs a Stream of events and relays each item to the
269
+ * parent machine as an event, the way `fromEventObservable` does. The actor
270
+ * has no output: it reaches `done` when the stream completes and `error` when
271
+ * it fails. Accepts the same forms as `fromEffectStream`. Its resources close
272
+ * when the stream completes, fails or is interrupted.
273
+ */
274
+ declare function fromEffectEventStream<const TInputSchema extends EffectSchemaLike, TStream extends Stream.Stream<EventObject, any, any>>(config: Omit<EffectStreamConfig<StreamItem<TStream>, StreamError<TStream>, SchemaOutput<TInputSchema>, StreamRequirements<TStream>>, 'stream' | 'schemas' | 'validator'> & EffectSchemaValidationConfig<{
275
+ input: TInputSchema;
276
+ }> & {
277
+ stream: TStream | ((args: EffectSourceArgs<SchemaOutput<TInputSchema>>) => TStream);
278
+ }): EffectActorLogic<undefined, StreamError<TStream>, SchemaOutput<TInputSchema>, StreamRequirements<TStream>>;
279
+ declare function fromEffectEventStream<TEvent extends EventObject, TError = unknown, TInput = undefined, TRequirements = never>(config: EffectStreamConfig<TEvent, TError, TInput, TRequirements> & {
280
+ schemas?: undefined;
281
+ }): EffectActorLogic<undefined, TError, TInput, TRequirements>;
282
+ declare function fromEffectEventStream<TEvent extends EventObject, TError = unknown, TInput = undefined, TRequirements = never>(stream: EffectStreamSource<TEvent, TError, TInput, TRequirements>): EffectActorLogic<undefined, TError, TInput, TRequirements>;
283
+ /** The `R` channel of an Effect type, or `never` for anything else. */
284
+ type EffectRequirements<T> = T extends Effect.Effect<any, any, infer R> ? R : never;
285
+ type RequirementsFromActions<T> = T extends Record<string, (...args: any[]) => any> ? T[keyof T] extends (infer TAction) ? TAction extends {
286
+ readonly [effectActionBrand]?: infer R;
287
+ } ? unknown extends R ? EffectRequirements<TAction extends ((...args: any[]) => infer TResult) ? TResult : never> : Exclude<R, undefined> : EffectRequirements<TAction extends ((...args: any[]) => infer TResult) ? TResult : never> : never : never;
288
+ /**
289
+ * Recursion budget for walking registered child machines. A machine cannot
290
+ * contain itself as a registered actor type, but deeply nested machine trees
291
+ * are capped at this depth to keep the conditional type finite.
292
+ */
293
+ type MaxDepth = 10;
294
+ type PrevDepth = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
295
+ type Depth = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
296
+ type RequirementsFromActors<T, TDepth extends Depth> = T extends Record<string, any> ? RequirementsFrom<T[keyof T], TDepth> : never;
297
+ /** `invoke` accepts a single config or an array of them. */
298
+ type InvokeEntry<TInvoke> = TInvoke extends readonly (infer U)[] ? U : TInvoke;
299
+ /**
300
+ * Requirements of the logic passed inline as `invoke.src`. A string `src`
301
+ * names an actor registered in `setup({ actors })`, whose requirements are
302
+ * already collected from the actor map, so it contributes nothing here.
303
+ */
304
+ type RequirementsFromInvoke<TInvoke, TDepth extends Depth> = InvokeEntry<TInvoke> extends (infer TEntry) ? TEntry extends {
305
+ src: infer TSrc;
306
+ } ? TSrc extends string ? never : RequirementsFrom<TSrc, TDepth> : never : never;
307
+ /**
308
+ * Walks the machine's literal config tree (the state schema) collecting
309
+ * requirements from inline `invoke.src` logic at the root and in every
310
+ * descendant state node.
311
+ */
312
+ type RequirementsFromStateSchema<TSchema, TDepth extends Depth> = (TSchema extends {
313
+ invoke: infer TInvoke;
314
+ } ? RequirementsFromInvoke<TInvoke, TDepth> : never) | (TSchema extends {
315
+ states: infer TStates;
316
+ } ? TStates extends Record<string, any> ? RequirementsFromStateSchema<TStates[keyof TStates], TDepth> : never : never);
317
+ /**
318
+ * Collects the Effect service requirements of an actor logic.
319
+ *
320
+ * Actor and invocation scopes are supplied by the host and excluded here.
321
+ * For Effect logic this is the remaining `R`. For a state machine it is the
322
+ * union of the requirements of its registered Effect actions, its registered
323
+ * Effect actors, the Effect logic passed inline as `invoke.src` anywhere in
324
+ * its state tree, and — recursively — the requirements of any child machine
325
+ * reached either way (capped at `MaxDepth` levels of machine nesting).
326
+ */
327
+ type RequirementsFrom<T, TDepth extends Depth = MaxDepth> = T extends EffectLogicBrand<any, infer R> ? Exclude<R, ActorScope | Scope.Scope> : T extends {
328
+ readonly _actionMap: infer TActionMap;
329
+ readonly _actorMap: infer TActorMap;
330
+ readonly _stateSchema: infer TStateSchema;
331
+ } ? Exclude<RequirementsFromActions<TActionMap>, ActorScope | Scope.Scope> | ([TDepth] extends [0] ? never : RequirementsFromActors<TActorMap, PrevDepth[TDepth]> | RequirementsFromStateSchema<TStateSchema, PrevDepth[TDepth]>) : never;
332
+ /** Options for {@link createEffectActor}. */
333
+ type EffectActorOptions<TLogic extends AnyActorLogic> = {
334
+ readonly input?: InputFrom<TLogic>;
335
+ /**
336
+ * A snapshot from `actor.getPersistedSnapshot()`. The actor resumes in that
337
+ * state without re-running entry actions, and pending timers keep their
338
+ * original deadlines, as with XState's `createActor(logic, { snapshot })`.
339
+ * State-machine children resume their persisted state and completed
340
+ * children stay done. Effect tasks and streams that were running, at the
341
+ * root or as children, start again from the beginning. A restored actor
342
+ * does not need `input`.
343
+ */
344
+ readonly snapshot?: ActorOptions<TLogic>['snapshot'];
345
+ } & RequiredActorOptionsFor<TLogic>;
346
+ type EffectActorOptionsArgs<TLogic extends AnyActorLogic> = [RequiredActorOptionsKeys<TLogic>] extends [never] ? [options?: EffectActorOptions<TLogic>] : [options: EffectActorOptions<TLogic>];
347
+ /**
348
+ * Creates and starts an actor as an Effect interpreter over pure transitions.
349
+ *
350
+ * Each step is `transition(snapshot, event)`, a pure function that returns
351
+ * the next snapshot and the actions to run. An Effect fiber owns the loop:
352
+ * the mailbox is a `Queue`, timers are `Effect.sleep` fibers on the Effect
353
+ * `Clock`, and declared Effect actions run as forked Effects in the actor's
354
+ * `Scope` with the services captured here. Child actors are started as live
355
+ * XState actors whose Effects run in the same host.
356
+ *
357
+ * The actor is a scoped resource: it stops, and every Effect it hosts is
358
+ * interrupted, when the enclosing `Scope` closes. The returned Effect never
359
+ * fails; the actor's own outcome is its snapshot status, read with `join`.
360
+ */
361
+ declare function createEffectActor<TLogic extends AnyActorLogic>(logic: TLogic, ...[options]: EffectActorOptionsArgs<TLogic>): Effect.Effect<EffectActor<TLogic>, never, RequirementsFrom<TLogic> | Scope.Scope>;
362
+ declare const EffectInterruptedError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
363
+ readonly _tag: "EffectInterruptedError";
364
+ } & Readonly<A>;
365
+ /**
366
+ * The failure an Effect-backed actor reports when its Effect was interrupted
367
+ * by something other than the actor being stopped, such as `Effect.interrupt`,
368
+ * losing an `Effect.race`, or an `Effect.timeout` that interrupts.
369
+ */
370
+ declare class EffectInterruptedError extends EffectInterruptedError_base<{
371
+ readonly cause: Cause.Cause<never>;
372
+ }> {
373
+ get message(): string;
374
+ }
375
+ declare const ActorStoppedError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
376
+ readonly _tag: "ActorStoppedError";
377
+ } & Readonly<A>;
378
+ /**
379
+ * Reported by `waitFor` when the actor stops or errors before a snapshot
380
+ * matches, and by `join` when the actor stops without output. `join` reports
381
+ * an errored actor's own `snapshot.error` instead.
382
+ */
383
+ declare class ActorStoppedError extends ActorStoppedError_base<{
384
+ readonly actorId: string;
385
+ readonly snapshot: Snapshot<unknown>;
386
+ }> {
387
+ get message(): string;
388
+ }
389
+ declare const ActorFailedError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
390
+ readonly _tag: "@systemfsoftware/xstate-effect/errors/ActorFailedError";
391
+ } & Readonly<A>;
392
+ declare class ActorFailedError<E = unknown> extends ActorFailedError_base<{
393
+ readonly cause: E;
394
+ }> {
395
+ get message(): string;
396
+ }
397
+ declare const NotReadyError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
398
+ readonly _tag: "NotReadyError";
399
+ } & Readonly<A>;
400
+ /**
401
+ * Reported by the `send` atom of `createActorAtoms` when an event is sent
402
+ * before the actor's runtime has finished building.
403
+ */
404
+ declare class NotReadyError extends NotReadyError_base {
405
+ get message(): string;
406
+ }
407
+ type IsUnion<T, U = T> = T extends unknown ? [U] extends [T] ? false : true : never;
408
+ type Join<TPrefix extends string, TKey extends string> = TPrefix extends '' ? TKey : `${TPrefix}.${TKey}`;
409
+ /** The tag of the machine itself, used when the root state is parallel. */
410
+ declare const MACHINE_TAG = "(machine)";
411
+ /**
412
+ * The dotted path of a state value: `'idle'`, `'form.editing'`. A parallel
413
+ * state has no single path, so its tag stops at the parallel state, or is
414
+ * `'(machine)'` when the machine itself is parallel.
415
+ */
416
+ type StateTag<TValue, TPrefix extends string = ''> = string extends TValue ? string : TValue extends string ? Join<TPrefix, TValue> : TValue extends object ? string extends keyof TValue ? string : IsUnion<keyof TValue & string> extends true ? TPrefix extends '' ? typeof MACHINE_TAG : TPrefix : { [K in keyof TValue & string]: StateTag<TValue[K], Join<TPrefix, K>>; }[keyof TValue & string] : never;
417
+ type TaggedStateOf<TSnapshot, TValue, TContext extends MachineContext, TSchema extends StateSchema> = TValue extends unknown ? {
418
+ readonly _tag: StateTag<TValue>;
419
+ readonly value: TValue;
420
+ readonly context: StateContextFromStateValue<TSchema, TContext, TValue>;
421
+ readonly snapshot: TSnapshot;
422
+ } : never;
423
+ /**
424
+ * A machine snapshot as a tagged union over its states. `_tag` is the state's
425
+ * dotted path and `context` is the context of that state, including any
426
+ * per-state context schema, so `Match.tag` narrows both.
427
+ */
428
+ type TaggedStateFrom<TSnapshot> = TSnapshot extends MachineSnapshot<infer TContext, infer _TEvent, infer _TChildren, infer _TStateValue, infer _TTag, infer _TOutput, infer _TMeta, infer TSchema> ? TaggedStateOf<TSnapshot, StateValueFromStateSchema<TSchema>, TContext, TSchema> : never;
429
+ /** The tagged state union of a machine. */
430
+ type TaggedState<TMachine extends AnyStateMachine> = TaggedStateFrom<SnapshotFrom<TMachine>>;
431
+ /**
432
+ * Views a machine snapshot as a tagged union member for `Match.tag`,
433
+ * `Match.tags` or a `switch` on `_tag`.
434
+ *
435
+ * @example
436
+ *
437
+ * ```ts
438
+ * const view = Match.type<TaggedStateFrom<typeof snapshot>>().pipe(
439
+ * Match.tag('loading', ({ context }) => `Loading ${context.id}`),
440
+ * Match.tag('done', () => 'Done'),
441
+ * Match.exhaustive
442
+ * );
443
+ * view(taggedState(snapshot));
444
+ * ```
445
+ */
446
+ declare function taggedState<TSnapshot extends AnyMachineSnapshot>(snapshot: TSnapshot): TaggedStateFrom<TSnapshot>;
447
+ export { ToStandardSetupStates as A, fromEffectEventStream as C, EffectSetupSchemas as D, EffectSchemaLike as E, withActorScope as F, EffectActor as I, ValidateEffectSetupStates as M, effectActionBrand as N, EffectSetupStateSchema as O, ActorScope as P, fromEffect as S, EffectSchema as T, EffectSource as _, ActorFailedError as a, EffectStreamSnapshot as b, NotReadyError as c, createEffectActor as d, EffectRequirements as f, EffectSnapshot as g, EffectLogicBrand as h, taggedState as i, ValidateEffectSetupSchemas as j, ToStandardSetupSchemas as k, EffectActorOptions as l, EffectActorLogic as m, TaggedState as n, ActorStoppedError as o, RequirementsFrom as p, TaggedStateFrom as r, EffectInterruptedError as s, StateTag as t, EffectActorOptionsArgs as u, EffectSourceArgs as v, fromEffectStream as w, EffectStreamSource as x, EffectStreamActorLogic as y };
package/package.json CHANGED
@@ -1,6 +1,63 @@
1
1
  {
2
2
  "name": "@systemfsoftware/xstate-effect",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "license": "MIT",
4
+ "version": "0.1.0-beta.8",
5
+ "author": "Ryan Lee <drdgvhbh@gmail.com>",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/systemfsoftware/xstate.git",
9
+ "directory": "packages/xstate-effect"
10
+ },
11
+ "homepage": "https://github.com/systemfsoftware/xstate/tree/main/packages/xstate-effect#readme",
12
+ "bugs": "https://github.com/systemfsoftware/xstate/issues",
13
+ "description": "Effect 4 actors for XState machines: services, scopes, clocks and tracing from Effect — forked under systemfsoftware from statelyai/xstate (@xstate/effect at 2146ae26).",
14
+ "type": "module",
15
+ "sideEffects": false,
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "peerDependencies": {
20
+ "@systemfsoftware/xstate": "^6.0.0-beta.65",
21
+ "effect": "^4.1.0"
22
+ },
23
+ "devDependencies": {
24
+ "@effect/tsgo": "0.64.1",
25
+ "@microsoft/api-extractor": "7.59.1",
26
+ "@systemfsoftware/arethetypeswrong-cli": "file:../../.deps/arethetypeswrong-cli.tgz",
27
+ "@systemfsoftware/tsconfig": "file:../../.deps/tsconfig.tgz",
28
+ "@systemfsoftware/vitest": "file:../../.deps/vitest.tgz",
29
+ "@systemfsoftware/xstate": "^6.0.0-beta.65",
30
+ "@types/node": "24.19.1",
31
+ "effect": "4.1.2",
32
+ "fast-check": "4.9.0",
33
+ "rimraf": "6.1.3",
34
+ "tsdown": "0.23.0",
35
+ "typescript": "7.0.2",
36
+ "vitest": "5.0.3"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public",
40
+ "provenance": true
41
+ },
42
+ "exports": {
43
+ ".": {
44
+ "types": "./dist/index.d.ts",
45
+ "default": "./dist/index.mjs"
46
+ },
47
+ "./atom": {
48
+ "types": "./dist/atom.d.ts",
49
+ "default": "./dist/atom.mjs"
50
+ },
51
+ "./package.json": "./package.json"
52
+ },
53
+ "scripts": {
54
+ "clean": "rimraf dist",
55
+ "build": "tsdown -l warn && pnpm api:check",
56
+ "typecheck": "tsc -b",
57
+ "test": "vitest run",
58
+ "lint:tsgo": "effect-tsgo diagnostics --project tsconfig.app.json --format ${TSGO_FORMAT:-text} && ../../scripts/tsgo-test-diagnostics.ts",
59
+ "attw": "attw --pack .",
60
+ "api:check": "api-extractor run && api-extractor run --config api-extractor.atom.json",
61
+ "api:update": "api-extractor run --local && api-extractor run --local --config api-extractor.atom.json"
62
+ }
6
63
  }