effect-machine 0.12.0 → 0.14.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.
Files changed (53) hide show
  1. package/README.md +133 -324
  2. package/dist/actor.d.ts +46 -28
  3. package/dist/actor.js +276 -315
  4. package/dist/cluster/entity-machine.d.ts +1 -1
  5. package/dist/cluster/entity-machine.js +20 -9
  6. package/dist/cluster/to-entity.d.ts +3 -3
  7. package/dist/errors.d.ts +24 -20
  8. package/dist/errors.js +10 -6
  9. package/dist/index.d.ts +5 -4
  10. package/dist/index.js +3 -2
  11. package/dist/internal/runtime.d.ts +82 -7
  12. package/dist/internal/runtime.js +162 -58
  13. package/dist/internal/transition.d.ts +12 -11
  14. package/dist/internal/transition.js +12 -14
  15. package/dist/machine.d.ts +148 -140
  16. package/dist/machine.js +141 -155
  17. package/dist/schema.d.ts +14 -0
  18. package/dist/schema.js +10 -1
  19. package/dist/slot.d.ts +112 -86
  20. package/dist/slot.js +92 -59
  21. package/dist/supervision.d.ts +97 -0
  22. package/dist/supervision.js +42 -0
  23. package/dist/testing.d.ts +21 -12
  24. package/dist/testing.js +23 -26
  25. package/package.json +7 -7
  26. package/v3/dist/actor.d.ts +53 -30
  27. package/v3/dist/actor.js +286 -311
  28. package/v3/dist/cluster/entity-machine.d.ts +1 -1
  29. package/v3/dist/cluster/entity-machine.js +5 -5
  30. package/v3/dist/cluster/to-entity.d.ts +1 -1
  31. package/v3/dist/errors.d.ts +14 -10
  32. package/v3/dist/errors.js +11 -7
  33. package/v3/dist/index.d.ts +6 -5
  34. package/v3/dist/index.js +3 -2
  35. package/v3/dist/inspection.d.ts +3 -22
  36. package/v3/dist/inspection.js +1 -15
  37. package/v3/dist/internal/brands.d.ts +4 -8
  38. package/v3/dist/internal/inspection.js +1 -1
  39. package/v3/dist/internal/runtime.d.ts +87 -10
  40. package/v3/dist/internal/runtime.js +177 -61
  41. package/v3/dist/internal/transition.d.ts +13 -12
  42. package/v3/dist/internal/transition.js +14 -16
  43. package/v3/dist/internal/utils.js +5 -1
  44. package/v3/dist/machine.d.ts +158 -143
  45. package/v3/dist/machine.js +148 -155
  46. package/v3/dist/schema.d.ts +25 -11
  47. package/v3/dist/schema.js +18 -5
  48. package/v3/dist/slot.d.ts +112 -86
  49. package/v3/dist/slot.js +92 -59
  50. package/v3/dist/supervision.d.ts +97 -0
  51. package/v3/dist/supervision.js +42 -0
  52. package/v3/dist/testing.d.ts +21 -12
  53. package/v3/dist/testing.js +23 -24
@@ -1,13 +1,22 @@
1
1
  import { stubSystem } from "./internal/utils.js";
2
2
  import { AssertionError } from "./errors.js";
3
- import { BuiltMachine } from "./machine.js";
4
3
  import { executeTransition, shouldPostpone } from "./internal/transition.js";
4
+ import { materializeMachine } from "./machine.js";
5
5
  import { Effect, SubscriptionRef } from "effect";
6
6
  //#region src/testing.ts
7
+ const makeDummySelf = (label) => {
8
+ const dummySend = Effect.fn(label)((_event) => Effect.void);
9
+ return {
10
+ send: dummySend,
11
+ cast: dummySend,
12
+ spawn: () => Effect.die(`spawn not supported in ${label}`),
13
+ reply: () => Effect.succeed(false)
14
+ };
15
+ };
7
16
  /**
8
17
  * Simulate a sequence of events through a machine without running an actor.
9
18
  * Useful for testing state transitions in isolation.
10
- * Does not run onEnter/spawn/background effects, but does run guard/effect slots
19
+ * Does not run onEnter/spawn/background effects, but does run slots
11
20
  * within transition handlers.
12
21
  *
13
22
  * @example
@@ -24,14 +33,9 @@ import { Effect, SubscriptionRef } from "effect";
24
33
  * expect(result.states).toHaveLength(3) // Idle -> Loading -> Success
25
34
  * ```
26
35
  */
27
- const simulate = Effect.fn("effect-machine.simulate")(function* (input, events) {
28
- const machine = input instanceof BuiltMachine ? input._inner : input;
29
- const dummySend = Effect.fn("effect-machine.testing.simulate.send")((_event) => Effect.void);
30
- const dummySelf = {
31
- send: dummySend,
32
- cast: dummySend,
33
- spawn: () => Effect.die("spawn not supported in simulation")
34
- };
36
+ const simulate = Effect.fn("effect-machine.simulate")(function* (input, events, options) {
37
+ const machine = materializeMachine(input, options?.slots);
38
+ const dummySelf = makeDummySelf("effect-machine.testing.simulate");
35
39
  let currentState = machine.initial;
36
40
  const states = [currentState];
37
41
  const hasPostponeRules = machine.postponeRules.length > 0;
@@ -73,8 +77,8 @@ const simulate = Effect.fn("effect-machine.simulate")(function* (input, events)
73
77
  /**
74
78
  * Assert that a machine can reach a specific state given a sequence of events
75
79
  */
76
- const assertReaches = Effect.fn("effect-machine.assertReaches")(function* (input, events, expectedTag) {
77
- const result = yield* simulate(input, events);
80
+ const assertReaches = Effect.fn("effect-machine.assertReaches")(function* (input, events, expectedTag, options) {
81
+ const result = yield* simulate(input, events, options);
78
82
  if (result.finalState._tag !== expectedTag) return yield* new AssertionError({ message: `Expected final state "${expectedTag}" but got "${result.finalState._tag}". States visited: ${result.states.map((s) => s._tag).join(" -> ")}` });
79
83
  return result.finalState;
80
84
  });
@@ -90,8 +94,8 @@ const assertReaches = Effect.fn("effect-machine.assertReaches")(function* (input
90
94
  * )
91
95
  * ```
92
96
  */
93
- const assertPath = Effect.fn("effect-machine.assertPath")(function* (input, events, expectedPath) {
94
- const result = yield* simulate(input, events);
97
+ const assertPath = Effect.fn("effect-machine.assertPath")(function* (input, events, expectedPath, options) {
98
+ const result = yield* simulate(input, events, options);
95
99
  const actualPath = result.states.map((s) => s._tag);
96
100
  if (actualPath.length !== expectedPath.length) return yield* new AssertionError({ message: `Path length mismatch. Expected ${expectedPath.length} states but got ${actualPath.length}.\nExpected: ${expectedPath.join(" -> ")}\nActual: ${actualPath.join(" -> ")}` });
97
101
  for (let i = 0; i < expectedPath.length; i++) if (actualPath[i] !== expectedPath[i]) return yield* new AssertionError({ message: `Path mismatch at position ${i}. Expected "${expectedPath[i]}" but got "${actualPath[i]}".\nExpected: ${expectedPath.join(" -> ")}\nActual: ${actualPath.join(" -> ")}` });
@@ -110,15 +114,15 @@ const assertPath = Effect.fn("effect-machine.assertPath")(function* (input, even
110
114
  * )
111
115
  * ```
112
116
  */
113
- const assertNeverReaches = Effect.fn("effect-machine.assertNeverReaches")(function* (input, events, forbiddenTag) {
114
- const result = yield* simulate(input, events);
117
+ const assertNeverReaches = Effect.fn("effect-machine.assertNeverReaches")(function* (input, events, forbiddenTag, options) {
118
+ const result = yield* simulate(input, events, options);
115
119
  const visitedIndex = result.states.findIndex((s) => s._tag === forbiddenTag);
116
120
  if (visitedIndex !== -1) return yield* new AssertionError({ message: `Machine reached forbidden state "${forbiddenTag}" at position ${visitedIndex}.\nStates visited: ${result.states.map((s) => s._tag).join(" -> ")}` });
117
121
  return result;
118
122
  });
119
123
  /**
120
124
  * Create a test harness for step-by-step testing.
121
- * Does not run onEnter/spawn/background effects, but does run guard/effect slots
125
+ * Does not run onEnter/spawn/background effects, but does run slots
122
126
  * within transition handlers.
123
127
  *
124
128
  * @example Basic usage
@@ -138,13 +142,8 @@ const assertNeverReaches = Effect.fn("effect-machine.assertNeverReaches")(functi
138
142
  * ```
139
143
  */
140
144
  const createTestHarness = Effect.fn("effect-machine.createTestHarness")(function* (input, options) {
141
- const machine = input instanceof BuiltMachine ? input._inner : input;
142
- const dummySend = Effect.fn("effect-machine.testing.harness.send")((_event) => Effect.void);
143
- const dummySelf = {
144
- send: dummySend,
145
- cast: dummySend,
146
- spawn: () => Effect.die("spawn not supported in test harness")
147
- };
145
+ const machine = materializeMachine(input, options?.slots);
146
+ const dummySelf = makeDummySelf("effect-machine.testing.harness");
148
147
  const stateRef = yield* SubscriptionRef.make(machine.initial);
149
148
  const hasPostponeRules = machine.postponeRules.length > 0;
150
149
  const postponed = [];