@xstate/effect 1.0.0-alpha.8 → 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.
@@ -1,13 +1,95 @@
1
- import { Queue, Effect, Fiber, Scope, Exit, Cause, Context, Clock, Duration, Data } from 'effect';
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
- /** A mailbox item that reports a failed fire-and-forget action. */
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
- const actionFailure = Symbol.for('@xstate/effect/actionFailure');
8
- function isActionFailure(value) {
9
- return typeof value === 'object' && value !== null && actionFailure in value;
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
- Queue.offerUnsafe(this._mailbox, event);
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
- const fiber = Fiber.runIn(Effect.runForkWith(host.context)(traced), host.scope);
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) || Cause.hasInterruptsOnly(exit.cause)) {
512
+ if (Exit.isSuccess(exit)) {
363
513
  resolve();
364
514
  } else {
365
- // Effect failures are arbitrary values, not necessarily Errors.
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
- /** The owning Effect actor's scope, supplied by `createEffectActor`. */
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
- /** Options for {@link createEffectActor}. */
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
- [actionFailure]: true,
634
+ kind: 'actionFailure',
473
635
  error
474
636
  });
475
637
  });
476
638
  }
477
639
  } catch (error) {
478
640
  offer({
479
- [actionFailure]: true,
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(event);
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(timerEvent);
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
- [actionFailure]: true,
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
- const item = yield* Effect.promise(() => durable.waitForEvent().then(event => event, () => undefined));
635
- if (item === undefined || stopped) {
636
- break;
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 (isActionFailure(item)) {
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,66 +872,40 @@ 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
- /** The tag of the machine itself, used when the root state is parallel. */
719
- const MACHINE_TAG = '(machine)';
720
-
721
875
  /**
722
876
  * The dotted path of a state value: `'idle'`, `'form.editing'`. A parallel
723
- * state has no single path, so its tag stops at the parallel state, or is
724
- * `'(machine)'` when the machine itself is parallel.
877
+ * state has no single path, so its tag stops at the parallel state. When the
878
+ * machine itself is parallel, the tag is `TRootTag`: the machine id, or `''`
879
+ * for a machine without one.
880
+ *
881
+ * @experimental
725
882
  */
726
883
 
727
884
  /**
728
885
  * A machine snapshot as a tagged union over its states. `_tag` is the state's
729
886
  * dotted path and `context` is the context of that state, including any
730
887
  * per-state context schema, so `Match.tag` narrows both.
888
+ *
889
+ * @experimental
731
890
  */
732
891
 
733
- /** The tagged state union of a machine. */
892
+ /**
893
+ * The tagged state union of a machine.
894
+ *
895
+ * @experimental
896
+ */
734
897
 
735
898
  /** Computes the dotted path tag of a state value. */
736
- function stateTag(value, prefix = '') {
899
+ function stateTag(value, rootTag, prefix = '') {
737
900
  if (typeof value === 'string') {
738
901
  return prefix ? `${prefix}.${value}` : value;
739
902
  }
740
903
  const keys = Object.keys(value);
741
904
  if (keys.length !== 1) {
742
- return prefix || MACHINE_TAG;
905
+ return prefix || rootTag;
743
906
  }
744
907
  const key = keys[0];
745
- return stateTag(value[key], prefix ? `${prefix}.${key}` : key);
908
+ return stateTag(value[key], rootTag, prefix ? `${prefix}.${key}` : key);
746
909
  }
747
910
 
748
911
  /**
@@ -759,14 +922,16 @@ function stateTag(value, prefix = '') {
759
922
  * );
760
923
  * view(taggedState(snapshot));
761
924
  * ```
925
+ *
926
+ * @experimental
762
927
  */
763
928
  function taggedState(snapshot) {
764
929
  return {
765
- _tag: stateTag(snapshot.value),
930
+ _tag: stateTag(snapshot.value, snapshot.machine.id),
766
931
  value: snapshot.value,
767
932
  context: snapshot.context,
768
933
  snapshot
769
934
  };
770
935
  }
771
936
 
772
- export { ActorStoppedError as A, EffectInterruptedError as E, NotReadyError as N, runHostedEffect as a, EffectActor as b, createEffectActor as c, ActorScope as d, relayToParent as r, startHostedEffect as s, taggedState as t, withActorScope as w };
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 { c as createEffectActor, N as NotReadyError, t as taggedState } from './state-ea62b88e.js';
4
- export { N as NotReadyError } from './state-ea62b88e.js';
5
- import 'xstate';
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(Cause.fail(value.error), {
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 state = select(current => taggedState(current));
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