@xstate/effect 1.0.0-alpha.9 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -9
- package/dist/declarations/src/actor.d.ts +33 -7
- package/dist/declarations/src/actorScope.d.ts +7 -1
- package/dist/declarations/src/atom.d.ts +11 -9
- package/dist/declarations/src/createEffectActor.d.ts +16 -5
- package/dist/declarations/src/effectActor.d.ts +20 -11
- package/dist/declarations/src/effectLogic.d.ts +30 -10
- package/dist/declarations/src/errors.d.ts +37 -4
- package/dist/declarations/src/index.d.ts +3 -2
- package/dist/declarations/src/oxlint.d.ts +3 -0
- package/dist/declarations/src/persistence.d.ts +45 -0
- package/dist/declarations/src/schema.d.ts +10 -0
- package/dist/declarations/src/setupEffect.d.ts +56 -13
- package/dist/declarations/src/state.d.ts +11 -1
- package/dist/declarations/src/test.d.ts +13 -0
- package/dist/declarations/src/types.d.ts +3 -2
- package/dist/{state-a2e5cb31.js → state-a2154dce.js} +240 -73
- package/dist/xstate-effect-atom.js +14 -8
- package/dist/xstate-effect-oxlint.d.ts +3 -0
- package/dist/xstate-effect-oxlint.js +126 -0
- package/dist/xstate-effect-test.d.ts +2 -0
- package/dist/xstate-effect-test.js +13 -0
- package/dist/xstate-effect.js +286 -35
- package/package.json +17 -5
- package/dist/declarations/src/brands.d.ts +0 -1
|
@@ -1,13 +1,95 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { stopActor, terminateActor, deliverEvent, isMachineSnapshot } from 'xstate';
|
|
1
|
+
import { Cause, Data, Queue, Effect, Exit, Fiber, Scope, Context, Clock, Duration } from 'effect';
|
|
2
|
+
import { StateMachine, stopActor, terminateActor, deliverEvent, isMachineSnapshot } from 'xstate';
|
|
3
3
|
import { createDurable } from 'xstate/durable';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
function _checkPrivateRedeclaration(e, t) {
|
|
6
|
+
if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function _classPrivateFieldInitSpec(e, t, a) {
|
|
10
|
+
_checkPrivateRedeclaration(e, t), t.set(e, a);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function _checkInRHS(e) {
|
|
14
|
+
if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null"));
|
|
15
|
+
return e;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function _assertClassBrand(e, t, n) {
|
|
19
|
+
if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
|
|
20
|
+
throw new TypeError("Private element is not present on this object");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function _classPrivateFieldGet2(s, a) {
|
|
24
|
+
return s.get(_assertClassBrand(s, a));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var _effectFailure = /*#__PURE__*/new WeakMap();
|
|
28
|
+
/**
|
|
29
|
+
* Preserves an Effect failure, defect or interruption through XState error routing.
|
|
30
|
+
*
|
|
31
|
+
* @experimental
|
|
32
|
+
*/
|
|
33
|
+
class EffectFailure extends Error {
|
|
34
|
+
static is(value) {
|
|
35
|
+
return typeof value === 'object' && value !== null && _effectFailure.has(_checkInRHS(value)) && _classPrivateFieldGet2(_effectFailure, value);
|
|
36
|
+
}
|
|
37
|
+
constructor(cause) {
|
|
38
|
+
super(Cause.pretty(cause));
|
|
39
|
+
this.cause = cause;
|
|
40
|
+
this._tag = 'EffectFailure';
|
|
41
|
+
_classPrivateFieldInitSpec(this, _effectFailure, true);
|
|
42
|
+
this.name = 'EffectFailure';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @deprecated Inspect `EffectFailure.cause` for interruption instead.
|
|
48
|
+
*
|
|
49
|
+
* @experimental
|
|
50
|
+
*/
|
|
51
|
+
class EffectInterruptedError extends Data.TaggedError('EffectInterruptedError') {
|
|
52
|
+
get message() {
|
|
53
|
+
return 'Effect was interrupted before the actor completed';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Reported by `waitFor` when the actor stops or errors before a snapshot
|
|
59
|
+
* matches, and by `join` when the actor stops without output. `join` reports
|
|
60
|
+
* an errored actor's outcome instead, preserving an Effect failure's Cause.
|
|
61
|
+
*
|
|
62
|
+
* @experimental
|
|
63
|
+
*/
|
|
64
|
+
class ActorStoppedError extends Data.TaggedError('ActorStoppedError') {
|
|
65
|
+
get message() {
|
|
66
|
+
return `Actor "${this.actorId}" ${this.snapshot.status === 'error' ? 'errored' : 'stopped'} before completing`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Reported by the `send` atom of `createActorAtoms` when an event is sent
|
|
72
|
+
* before the actor's runtime has finished building.
|
|
73
|
+
*
|
|
74
|
+
* @experimental
|
|
75
|
+
*/
|
|
76
|
+
class NotReadyError extends Data.TaggedError('NotReadyError') {
|
|
77
|
+
get message() {
|
|
78
|
+
return 'The actor is not ready yet';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
6
81
|
|
|
7
|
-
|
|
8
|
-
function
|
|
9
|
-
return
|
|
82
|
+
/** @internal */
|
|
83
|
+
function causeFromError(error) {
|
|
84
|
+
return error instanceof EffectFailure ? error.cause : Cause.fail(error);
|
|
10
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* An event rejected at the actor's delivery boundary.
|
|
88
|
+
*
|
|
89
|
+
* @experimental
|
|
90
|
+
*/
|
|
91
|
+
class EventRejectedError extends Data.TaggedError('EventRejectedError') {}
|
|
92
|
+
|
|
11
93
|
const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
|
|
12
94
|
|
|
13
95
|
/**
|
|
@@ -39,6 +121,8 @@ function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
|
39
121
|
* contract (`send`, `getSnapshot`, `subscribe`, `on`), so it works with
|
|
40
122
|
* `useSelector`, this package's actor functions and the inspection APIs, while
|
|
41
123
|
* the actor itself is driven by an Effect fiber over pure transitions.
|
|
124
|
+
*
|
|
125
|
+
* @experimental
|
|
42
126
|
*/
|
|
43
127
|
class EffectActor {
|
|
44
128
|
constructor(logic, root, snapshot, _mailbox, _stopExecution, _inspectors) {
|
|
@@ -57,6 +141,7 @@ class EffectActor {
|
|
|
57
141
|
this._observers = new Set();
|
|
58
142
|
this._listeners = new Map();
|
|
59
143
|
this._settled = false;
|
|
144
|
+
this._pending = new Set();
|
|
60
145
|
this._root = root;
|
|
61
146
|
this.id = root.id;
|
|
62
147
|
this.address = root.address;
|
|
@@ -73,11 +158,69 @@ class EffectActor {
|
|
|
73
158
|
|
|
74
159
|
/** Sends an event; the actor processes it on its own fiber. */
|
|
75
160
|
send(event) {
|
|
161
|
+
if (this._deliveryError(event)) return;
|
|
162
|
+
Queue.offerUnsafe(this._mailbox, {
|
|
163
|
+
kind: 'event',
|
|
164
|
+
event
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** @internal */
|
|
169
|
+
_sendAndAwait(event) {
|
|
170
|
+
return Effect.callback(resume => {
|
|
171
|
+
const error = this._deliveryError(event);
|
|
172
|
+
if (error) {
|
|
173
|
+
resume(Effect.fail(error));
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const receipt = {
|
|
177
|
+
resume: exit => resume(exit)
|
|
178
|
+
};
|
|
179
|
+
this._pending.add(receipt);
|
|
180
|
+
Queue.offerUnsafe(this._mailbox, {
|
|
181
|
+
kind: 'event',
|
|
182
|
+
event,
|
|
183
|
+
receipt
|
|
184
|
+
});
|
|
185
|
+
return Effect.sync(() => {
|
|
186
|
+
this._pending.delete(receipt);
|
|
187
|
+
receipt.resume = undefined;
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
_deliveryError(event) {
|
|
76
192
|
if (this._settled) {
|
|
77
193
|
this.system.deadLetter(undefined, this._root, event, 'stopped');
|
|
78
|
-
return;
|
|
194
|
+
return this._stoppedError();
|
|
79
195
|
}
|
|
80
|
-
|
|
196
|
+
if (this.logic instanceof StateMachine && this.logic.isInternalEventType(event.type)) {
|
|
197
|
+
this.system.deadLetter(undefined, this._root, event, 'internalEvent');
|
|
198
|
+
return new EventRejectedError({
|
|
199
|
+
actorId: this.id,
|
|
200
|
+
event,
|
|
201
|
+
reason: 'internalEvent'
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** @internal */
|
|
208
|
+
_rejectReceipts() {
|
|
209
|
+
for (const receipt of this._pending) this._completeReceipt(receipt, Exit.fail(this._stoppedError()));
|
|
210
|
+
}
|
|
211
|
+
_stoppedError() {
|
|
212
|
+
return new ActorStoppedError({
|
|
213
|
+
actorId: this.id,
|
|
214
|
+
snapshot: this._snapshot
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** @internal */
|
|
219
|
+
_completeReceipt(receipt, exit) {
|
|
220
|
+
if (!receipt || !this._pending.delete(receipt)) return;
|
|
221
|
+
const resume = receipt.resume;
|
|
222
|
+
receipt.resume = undefined;
|
|
223
|
+
resume?.(exit);
|
|
81
224
|
}
|
|
82
225
|
|
|
83
226
|
/** Stops the actor, its children and every Effect it hosts. */
|
|
@@ -151,7 +294,8 @@ class EffectActor {
|
|
|
151
294
|
}
|
|
152
295
|
|
|
153
296
|
/** @internal Publishes a snapshot produced by the execution loop. */
|
|
154
|
-
_publish(snapshot) {
|
|
297
|
+
_publish(snapshot, receipt) {
|
|
298
|
+
if (this._settled) return;
|
|
155
299
|
this._snapshot = snapshot;
|
|
156
300
|
const status = snapshot.status;
|
|
157
301
|
if (status === 'active') {
|
|
@@ -160,16 +304,19 @@ class EffectActor {
|
|
|
160
304
|
}
|
|
161
305
|
return;
|
|
162
306
|
}
|
|
163
|
-
this._settle(snapshot);
|
|
307
|
+
this._settle(snapshot, receipt);
|
|
164
308
|
}
|
|
165
309
|
|
|
166
310
|
/** @internal Marks the actor stopped and notifies observers. */
|
|
167
|
-
_settle(snapshot) {
|
|
311
|
+
_settle(snapshot, processing) {
|
|
168
312
|
if (this._settled) {
|
|
169
313
|
return;
|
|
170
314
|
}
|
|
171
315
|
this._snapshot = snapshot;
|
|
172
316
|
this._settled = true;
|
|
317
|
+
for (const receipt of this._pending) {
|
|
318
|
+
if (receipt !== processing) this._completeReceipt(receipt, Exit.fail(this._stoppedError()));
|
|
319
|
+
}
|
|
173
320
|
const observers = [...this._observers];
|
|
174
321
|
this._observers.clear();
|
|
175
322
|
const status = snapshot.status;
|
|
@@ -314,7 +461,7 @@ function trackEffect(actor, host, interrupt) {
|
|
|
314
461
|
* The fiber belongs to the host scope, so closing the owning actor also
|
|
315
462
|
* waits for asynchronous invocation finalizers.
|
|
316
463
|
*/
|
|
317
|
-
function startHostedEffect(actor, effect, spanName, onExit) {
|
|
464
|
+
function startHostedEffect(actor, effect, spanName, onExit, onCancel) {
|
|
318
465
|
const host = requireEffectHost(actor);
|
|
319
466
|
let active = true;
|
|
320
467
|
const traced = Effect.withSpan(spanName, {
|
|
@@ -331,11 +478,18 @@ function startHostedEffect(actor, effect, spanName, onExit) {
|
|
|
331
478
|
}
|
|
332
479
|
active = false;
|
|
333
480
|
untrackEffect(actor, host, cancel);
|
|
481
|
+
onCancel?.();
|
|
334
482
|
interrupt();
|
|
335
483
|
};
|
|
336
|
-
|
|
484
|
+
// Register the fiber before its body runs: the body can synchronously
|
|
485
|
+
// trigger the host's close, which only awaits registered fibers.
|
|
486
|
+
const registered = Effect.withFiber(fiber => {
|
|
487
|
+
Fiber.runIn(fiber, host.scope);
|
|
488
|
+
host.fibers.add(fiber);
|
|
489
|
+
return traced;
|
|
490
|
+
});
|
|
491
|
+
const fiber = Effect.runForkWith(host.context)(registered);
|
|
337
492
|
const interrupt = () => fiber.interruptUnsafe();
|
|
338
|
-
host.fibers.add(fiber);
|
|
339
493
|
fiber.addObserver(exit => {
|
|
340
494
|
host.fibers.delete(fiber);
|
|
341
495
|
if (!active) {
|
|
@@ -351,22 +505,16 @@ function startHostedEffect(actor, effect, spanName, onExit) {
|
|
|
351
505
|
return cancel;
|
|
352
506
|
}
|
|
353
507
|
|
|
354
|
-
/**
|
|
355
|
-
* Runs an Effect in the actor's host context and settles when it exits.
|
|
356
|
-
* Interruption settles without error; failures and defects reject with the
|
|
357
|
-
* squashed cause so the actor's error handling can observe them.
|
|
358
|
-
*/
|
|
508
|
+
/** @internal */
|
|
359
509
|
function runHostedEffect(actor, effect, spanName) {
|
|
360
510
|
return new Promise((resolve, reject) => {
|
|
361
511
|
startHostedEffect(actor, effect, spanName, exit => {
|
|
362
|
-
if (Exit.isSuccess(exit)
|
|
512
|
+
if (Exit.isSuccess(exit)) {
|
|
363
513
|
resolve();
|
|
364
514
|
} else {
|
|
365
|
-
|
|
366
|
-
// oxlint-disable-next-line typescript/prefer-promise-reject-errors
|
|
367
|
-
reject(Cause.squash(exit.cause));
|
|
515
|
+
reject(new EffectFailure(exit.cause));
|
|
368
516
|
}
|
|
369
|
-
});
|
|
517
|
+
}, resolve);
|
|
370
518
|
});
|
|
371
519
|
}
|
|
372
520
|
|
|
@@ -403,12 +551,18 @@ function relayToParent(actor, event) {
|
|
|
403
551
|
}
|
|
404
552
|
}
|
|
405
553
|
|
|
406
|
-
/**
|
|
554
|
+
/**
|
|
555
|
+
* The owning Effect actor's scope, supplied by `createEffectActor`.
|
|
556
|
+
*
|
|
557
|
+
* @experimental
|
|
558
|
+
*/
|
|
407
559
|
class ActorScope extends Context.Service()('@xstate/effect/ActorScope') {}
|
|
408
560
|
|
|
409
561
|
/**
|
|
410
562
|
* Acquires resources in the owning actor's scope. Their finalizers run when
|
|
411
563
|
* that actor stops, even if the invoking task finishes or is cancelled first.
|
|
564
|
+
*
|
|
565
|
+
* @experimental
|
|
412
566
|
*/
|
|
413
567
|
function withActorScope(effect) {
|
|
414
568
|
return ActorScope.use(scope => Scope.provide(effect, scope));
|
|
@@ -417,7 +571,11 @@ function withActorScope(effect) {
|
|
|
417
571
|
const XSTATE_TIMER = 'xstate.timer';
|
|
418
572
|
const XSTATE_INIT = 'xstate.init';
|
|
419
573
|
|
|
420
|
-
/**
|
|
574
|
+
/**
|
|
575
|
+
* Options for {@link createEffectActor}.
|
|
576
|
+
*
|
|
577
|
+
* @experimental
|
|
578
|
+
*/
|
|
421
579
|
|
|
422
580
|
/**
|
|
423
581
|
* Creates and starts an actor as an Effect interpreter over pure transitions.
|
|
@@ -432,6 +590,8 @@ const XSTATE_INIT = 'xstate.init';
|
|
|
432
590
|
* The actor is a scoped resource: it stops, and every Effect it hosts is
|
|
433
591
|
* interrupted, when the enclosing `Scope` closes. The returned Effect never
|
|
434
592
|
* fails; the actor's own outcome is its snapshot status, read with `join`.
|
|
593
|
+
*
|
|
594
|
+
* @experimental
|
|
435
595
|
*/
|
|
436
596
|
function createEffectActor(logic, ...[options]) {
|
|
437
597
|
return Effect.acquireRelease(Effect.gen(function* () {
|
|
@@ -443,6 +603,8 @@ function createEffectActor(logic, ...[options]) {
|
|
|
443
603
|
const runFork = Effect.runForkWith(context);
|
|
444
604
|
const runPromise = Effect.runPromiseWith(context);
|
|
445
605
|
const mailbox = yield* Queue.unbounded();
|
|
606
|
+
let delivered;
|
|
607
|
+
const getDelivered = () => delivered;
|
|
446
608
|
const timers = new Map();
|
|
447
609
|
// `root` and `actor` are declared after the adapter below; its
|
|
448
610
|
// callbacks only run once they are initialized.
|
|
@@ -469,14 +631,14 @@ function createEffectActor(logic, ...[options]) {
|
|
|
469
631
|
if (result && typeof result.then === 'function') {
|
|
470
632
|
void Promise.resolve(result).catch(error => {
|
|
471
633
|
offer({
|
|
472
|
-
|
|
634
|
+
kind: 'actionFailure',
|
|
473
635
|
error
|
|
474
636
|
});
|
|
475
637
|
});
|
|
476
638
|
}
|
|
477
639
|
} catch (error) {
|
|
478
640
|
offer({
|
|
479
|
-
|
|
641
|
+
kind: 'actionFailure',
|
|
480
642
|
error
|
|
481
643
|
});
|
|
482
644
|
}
|
|
@@ -500,7 +662,10 @@ function createEffectActor(logic, ...[options]) {
|
|
|
500
662
|
},
|
|
501
663
|
sendEvent: (source, target, event) => {
|
|
502
664
|
if (isRoot(target)) {
|
|
503
|
-
offer(
|
|
665
|
+
offer({
|
|
666
|
+
kind: 'event',
|
|
667
|
+
event: event
|
|
668
|
+
});
|
|
504
669
|
return;
|
|
505
670
|
}
|
|
506
671
|
deliverEvent(source, target, event);
|
|
@@ -522,7 +687,10 @@ function createEffectActor(logic, ...[options]) {
|
|
|
522
687
|
...timer
|
|
523
688
|
};
|
|
524
689
|
if (isRoot(source)) {
|
|
525
|
-
offer(
|
|
690
|
+
offer({
|
|
691
|
+
kind: 'event',
|
|
692
|
+
event: timerEvent
|
|
693
|
+
});
|
|
526
694
|
} else {
|
|
527
695
|
deliverEvent(source, source, timerEvent);
|
|
528
696
|
}
|
|
@@ -542,8 +710,15 @@ function createEffectActor(logic, ...[options]) {
|
|
|
542
710
|
}
|
|
543
711
|
}
|
|
544
712
|
},
|
|
545
|
-
waitForEvent: () => runPromise(Queue.take(mailbox))
|
|
713
|
+
waitForEvent: () => runPromise(Queue.take(mailbox)).then(item => {
|
|
714
|
+
delivered = item;
|
|
715
|
+
return item.kind === 'event' ? item.event : {
|
|
716
|
+
type: 'xstate.effect.actionFailure'
|
|
717
|
+
};
|
|
718
|
+
})
|
|
546
719
|
}, {
|
|
720
|
+
// A live actor needs one FIFO for child events, sends and timers.
|
|
721
|
+
captureRootEvents: false,
|
|
547
722
|
inspect: event => {
|
|
548
723
|
// The pure step scope re-materializes the root ref per step and
|
|
549
724
|
// announces it again; observers should see the root once.
|
|
@@ -591,6 +766,7 @@ function createEffectActor(logic, ...[options]) {
|
|
|
591
766
|
status: 'stopped'
|
|
592
767
|
});
|
|
593
768
|
}
|
|
769
|
+
actor._rejectReceipts();
|
|
594
770
|
closeEffectHost(host);
|
|
595
771
|
};
|
|
596
772
|
|
|
@@ -624,19 +800,23 @@ function createEffectActor(logic, ...[options]) {
|
|
|
624
800
|
bindEffectHost(actor, host);
|
|
625
801
|
const executeEffects = batch => Effect.promise(() => durable.executeEffects(batch).then(() => undefined, error => {
|
|
626
802
|
offer({
|
|
627
|
-
|
|
803
|
+
kind: 'actionFailure',
|
|
628
804
|
error
|
|
629
805
|
});
|
|
630
806
|
}));
|
|
631
807
|
const loop = Effect.gen(function* () {
|
|
632
808
|
yield* executeEffects(effects);
|
|
633
809
|
while (snapshot.status === 'active' && !stopped) {
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
810
|
+
delivered = undefined;
|
|
811
|
+
const received = yield* Effect.promise(() => durable.waitForEvent().catch(() => undefined));
|
|
812
|
+
if (received === undefined || stopped) break;
|
|
813
|
+
const item = getDelivered() ?? {
|
|
814
|
+
kind: 'event',
|
|
815
|
+
event: received
|
|
816
|
+
};
|
|
817
|
+
const receipt = item.kind === 'event' ? item.receipt : undefined;
|
|
638
818
|
let event;
|
|
639
|
-
if (
|
|
819
|
+
if (item.kind === 'actionFailure') {
|
|
640
820
|
const errorEvent = logic.getExecutionErrorEvent?.(snapshot, item.error);
|
|
641
821
|
if (!errorEvent) {
|
|
642
822
|
snapshot = errorSnapshot(snapshot, item.error);
|
|
@@ -644,16 +824,25 @@ function createEffectActor(logic, ...[options]) {
|
|
|
644
824
|
}
|
|
645
825
|
event = errorEvent;
|
|
646
826
|
} else {
|
|
647
|
-
event = item;
|
|
827
|
+
event = item.event;
|
|
648
828
|
}
|
|
649
829
|
try {
|
|
650
830
|
[snapshot, effects] = durable.transition(snapshot, event);
|
|
651
831
|
} catch (error) {
|
|
652
832
|
snapshot = errorSnapshot(snapshot, error);
|
|
833
|
+
actor._publish(snapshot, receipt);
|
|
834
|
+
actor._completeReceipt(receipt, Exit.succeed(snapshot));
|
|
653
835
|
break;
|
|
654
836
|
}
|
|
655
|
-
actor._publish(snapshot);
|
|
837
|
+
actor._publish(snapshot, receipt);
|
|
838
|
+
if (stopped) break;
|
|
839
|
+
const rejectedReason = effects.length === 1 && effects[0].effect.type === '@xstate.deadLetter' && 'reason' in effects[0].effect && effects[0].effect.reason === 'invalidEvent' ? effects[0].effect.reason : undefined;
|
|
656
840
|
yield* executeEffects(effects);
|
|
841
|
+
actor._completeReceipt(receipt, rejectedReason !== undefined ? Exit.fail(new EventRejectedError({
|
|
842
|
+
actorId: actor.id,
|
|
843
|
+
event,
|
|
844
|
+
reason: rejectedReason
|
|
845
|
+
})) : Exit.succeed(snapshot));
|
|
657
846
|
}
|
|
658
847
|
if (!stopped) {
|
|
659
848
|
actor._publish(snapshot);
|
|
@@ -683,52 +872,28 @@ function createEffectActor(logic, ...[options]) {
|
|
|
683
872
|
}) => actor));
|
|
684
873
|
}
|
|
685
874
|
|
|
686
|
-
/**
|
|
687
|
-
* The failure an Effect-backed actor reports when its Effect was interrupted
|
|
688
|
-
* by something other than the actor being stopped, such as `Effect.interrupt`,
|
|
689
|
-
* losing an `Effect.race`, or an `Effect.timeout` that interrupts.
|
|
690
|
-
*/
|
|
691
|
-
class EffectInterruptedError extends Data.TaggedError('EffectInterruptedError') {
|
|
692
|
-
get message() {
|
|
693
|
-
return 'Effect was interrupted before the actor completed';
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
/**
|
|
698
|
-
* Reported by `waitFor` when the actor stops or errors before a snapshot
|
|
699
|
-
* matches, and by `join` when the actor stops without output. `join` reports
|
|
700
|
-
* an errored actor's own `snapshot.error` instead.
|
|
701
|
-
*/
|
|
702
|
-
class ActorStoppedError extends Data.TaggedError('ActorStoppedError') {
|
|
703
|
-
get message() {
|
|
704
|
-
return `Actor "${this.actorId}" ${this.snapshot.status === 'error' ? 'errored' : 'stopped'} before completing`;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
/**
|
|
709
|
-
* Reported by the `send` atom of `createActorAtoms` when an event is sent
|
|
710
|
-
* before the actor's runtime has finished building.
|
|
711
|
-
*/
|
|
712
|
-
class NotReadyError extends Data.TaggedError('NotReadyError') {
|
|
713
|
-
get message() {
|
|
714
|
-
return 'The actor is not ready yet';
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
|
|
718
875
|
/**
|
|
719
876
|
* The dotted path of a state value: `'idle'`, `'form.editing'`. A parallel
|
|
720
877
|
* state has no single path, so its tag stops at the parallel state. When the
|
|
721
878
|
* machine itself is parallel, the tag is `TRootTag`: the machine id, or `''`
|
|
722
879
|
* for a machine without one.
|
|
880
|
+
*
|
|
881
|
+
* @experimental
|
|
723
882
|
*/
|
|
724
883
|
|
|
725
884
|
/**
|
|
726
885
|
* A machine snapshot as a tagged union over its states. `_tag` is the state's
|
|
727
886
|
* dotted path and `context` is the context of that state, including any
|
|
728
887
|
* per-state context schema, so `Match.tag` narrows both.
|
|
888
|
+
*
|
|
889
|
+
* @experimental
|
|
729
890
|
*/
|
|
730
891
|
|
|
731
|
-
/**
|
|
892
|
+
/**
|
|
893
|
+
* The tagged state union of a machine.
|
|
894
|
+
*
|
|
895
|
+
* @experimental
|
|
896
|
+
*/
|
|
732
897
|
|
|
733
898
|
/** Computes the dotted path tag of a state value. */
|
|
734
899
|
function stateTag(value, rootTag, prefix = '') {
|
|
@@ -757,6 +922,8 @@ function stateTag(value, rootTag, prefix = '') {
|
|
|
757
922
|
* );
|
|
758
923
|
* view(taggedState(snapshot));
|
|
759
924
|
* ```
|
|
925
|
+
*
|
|
926
|
+
* @experimental
|
|
760
927
|
*/
|
|
761
928
|
function taggedState(snapshot) {
|
|
762
929
|
return {
|
|
@@ -767,4 +934,4 @@ function taggedState(snapshot) {
|
|
|
767
934
|
};
|
|
768
935
|
}
|
|
769
936
|
|
|
770
|
-
export { ActorStoppedError as A,
|
|
937
|
+
export { ActorStoppedError as A, EffectFailure as E, NotReadyError as N, causeFromError as a, runHostedEffect as b, createEffectActor as c, EffectActor as d, ActorScope as e, EventRejectedError as f, EffectInterruptedError as g, relayToParent as r, startHostedEffect as s, taggedState as t, withActorScope as w };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Cause } from 'effect';
|
|
2
2
|
import { Atom, AsyncResult } from 'effect/reactivity';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { StateMachine } from 'xstate';
|
|
4
|
+
import { c as createEffectActor, a as causeFromError, N as NotReadyError, t as taggedState } from './state-a2154dce.js';
|
|
5
|
+
export { N as NotReadyError } from './state-a2154dce.js';
|
|
6
6
|
import 'xstate/durable';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -11,6 +11,8 @@ import 'xstate/durable';
|
|
|
11
11
|
* framework, such as `@effect/atom-react`.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
/** @experimental */
|
|
15
|
+
|
|
14
16
|
/**
|
|
15
17
|
* Creates atoms for an actor that runs in an `Atom.runtime`. The runtime's
|
|
16
18
|
* Layer must provide every service the logic requires; a missing service is
|
|
@@ -22,6 +24,8 @@ import 'xstate/durable';
|
|
|
22
24
|
* when the atom is released. Wrap the atoms with `Atom.keepAlive` to pin the
|
|
23
25
|
* actor for the registry's lifetime, or with `Atom.family` to create one
|
|
24
26
|
* actor per input.
|
|
27
|
+
*
|
|
28
|
+
* @experimental
|
|
25
29
|
*/
|
|
26
30
|
function createActorAtoms(runtime, logic, ...[options]) {
|
|
27
31
|
const host = runtime;
|
|
@@ -55,7 +59,7 @@ function createActorAtoms(runtime, logic, ...[options]) {
|
|
|
55
59
|
}
|
|
56
60
|
const value = current.value;
|
|
57
61
|
if (value.status === 'error') {
|
|
58
|
-
return AsyncResult.failureWithPrevious(
|
|
62
|
+
return AsyncResult.failureWithPrevious(causeFromError(value.error), {
|
|
59
63
|
previous: get.self()
|
|
60
64
|
});
|
|
61
65
|
}
|
|
@@ -75,15 +79,17 @@ function createActorAtoms(runtime, logic, ...[options]) {
|
|
|
75
79
|
function select(selector) {
|
|
76
80
|
return Atom.map(snapshot, result => AsyncResult.map(result, selector));
|
|
77
81
|
}
|
|
78
|
-
const
|
|
79
|
-
return {
|
|
82
|
+
const base = {
|
|
80
83
|
actor,
|
|
81
84
|
snapshot,
|
|
82
85
|
result,
|
|
83
86
|
send: sendAtom,
|
|
84
|
-
select
|
|
85
|
-
state
|
|
87
|
+
select
|
|
86
88
|
};
|
|
89
|
+
return logic instanceof StateMachine ? {
|
|
90
|
+
...base,
|
|
91
|
+
state: select(current => taggedState(current))
|
|
92
|
+
} : base;
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
export { createActorAtoms };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export * from "./declarations/src/oxlint.js";
|
|
2
|
+
export { default } from "./declarations/src/oxlint.js";
|
|
3
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieHN0YXRlLWVmZmVjdC1veGxpbnQuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4vZGVjbGFyYXRpb25zL3NyYy9veGxpbnQuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSJ9
|