@ersbeth/picoflow 1.0.1 → 1.1.1

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 (183) hide show
  1. package/.cursor/plans/unifier-flowresource-avec-flowderivation-c9506e24.plan.md +372 -0
  2. package/README.md +17 -1
  3. package/biome.json +4 -1
  4. package/dist/picoflow.js +1155 -582
  5. package/dist/types/flow/base/flowDisposable.d.ts +67 -0
  6. package/dist/types/flow/base/flowDisposable.d.ts.map +1 -0
  7. package/dist/types/flow/base/flowEffect.d.ts +127 -0
  8. package/dist/types/flow/base/flowEffect.d.ts.map +1 -0
  9. package/dist/types/flow/base/flowGraph.d.ts +97 -0
  10. package/dist/types/flow/base/flowGraph.d.ts.map +1 -0
  11. package/dist/types/flow/base/flowSignal.d.ts +134 -0
  12. package/dist/types/flow/base/flowSignal.d.ts.map +1 -0
  13. package/dist/types/flow/base/flowTracker.d.ts +15 -0
  14. package/dist/types/flow/base/flowTracker.d.ts.map +1 -0
  15. package/dist/types/flow/base/index.d.ts +7 -0
  16. package/dist/types/flow/base/index.d.ts.map +1 -0
  17. package/dist/types/flow/base/utils.d.ts +20 -0
  18. package/dist/types/flow/base/utils.d.ts.map +1 -0
  19. package/dist/types/{advanced/array.d.ts → flow/collections/flowArray.d.ts} +50 -12
  20. package/dist/types/flow/collections/flowArray.d.ts.map +1 -0
  21. package/dist/types/flow/collections/flowMap.d.ts +224 -0
  22. package/dist/types/flow/collections/flowMap.d.ts.map +1 -0
  23. package/dist/types/flow/collections/index.d.ts +3 -0
  24. package/dist/types/flow/collections/index.d.ts.map +1 -0
  25. package/dist/types/flow/index.d.ts +4 -0
  26. package/dist/types/flow/index.d.ts.map +1 -0
  27. package/dist/types/flow/nodes/async/flowConstantAsync.d.ts +137 -0
  28. package/dist/types/flow/nodes/async/flowConstantAsync.d.ts.map +1 -0
  29. package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts +137 -0
  30. package/dist/types/flow/nodes/async/flowDerivationAsync.d.ts.map +1 -0
  31. package/dist/types/flow/nodes/async/flowNodeAsync.d.ts +343 -0
  32. package/dist/types/flow/nodes/async/flowNodeAsync.d.ts.map +1 -0
  33. package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts +81 -0
  34. package/dist/types/flow/nodes/async/flowReadonlyAsync.d.ts.map +1 -0
  35. package/dist/types/flow/nodes/async/flowStateAsync.d.ts +111 -0
  36. package/dist/types/flow/nodes/async/flowStateAsync.d.ts.map +1 -0
  37. package/dist/types/flow/nodes/async/index.d.ts +6 -0
  38. package/dist/types/flow/nodes/async/index.d.ts.map +1 -0
  39. package/dist/types/flow/nodes/index.d.ts +3 -0
  40. package/dist/types/flow/nodes/index.d.ts.map +1 -0
  41. package/dist/types/flow/nodes/sync/flowConstant.d.ts +108 -0
  42. package/dist/types/flow/nodes/sync/flowConstant.d.ts.map +1 -0
  43. package/dist/types/flow/nodes/sync/flowDerivation.d.ts +100 -0
  44. package/dist/types/flow/nodes/sync/flowDerivation.d.ts.map +1 -0
  45. package/dist/types/flow/nodes/sync/flowNode.d.ts +314 -0
  46. package/dist/types/flow/nodes/sync/flowNode.d.ts.map +1 -0
  47. package/dist/types/flow/nodes/sync/flowReadonly.d.ts +57 -0
  48. package/dist/types/flow/nodes/sync/flowReadonly.d.ts.map +1 -0
  49. package/dist/types/flow/nodes/sync/flowState.d.ts +96 -0
  50. package/dist/types/flow/nodes/sync/flowState.d.ts.map +1 -0
  51. package/dist/types/flow/nodes/sync/index.d.ts +6 -0
  52. package/dist/types/flow/nodes/sync/index.d.ts.map +1 -0
  53. package/dist/types/index.d.ts +2 -4
  54. package/dist/types/index.d.ts.map +1 -1
  55. package/dist/types/solid/converters.d.ts +34 -45
  56. package/dist/types/solid/converters.d.ts.map +1 -1
  57. package/dist/types/solid/index.d.ts +2 -2
  58. package/dist/types/solid/index.d.ts.map +1 -1
  59. package/dist/types/solid/primitives.d.ts +1 -0
  60. package/dist/types/solid/primitives.d.ts.map +1 -1
  61. package/docs/.vitepress/config.mts +1 -1
  62. package/docs/api/typedoc-sidebar.json +81 -1
  63. package/package.json +60 -58
  64. package/src/flow/base/flowDisposable.ts +71 -0
  65. package/src/flow/base/flowEffect.ts +171 -0
  66. package/src/flow/base/flowGraph.ts +288 -0
  67. package/src/flow/base/flowSignal.ts +207 -0
  68. package/src/flow/base/flowTracker.ts +17 -0
  69. package/src/flow/base/index.ts +6 -0
  70. package/src/flow/base/utils.ts +19 -0
  71. package/src/flow/collections/flowArray.ts +409 -0
  72. package/src/flow/collections/flowMap.ts +398 -0
  73. package/src/flow/collections/index.ts +2 -0
  74. package/src/flow/index.ts +3 -0
  75. package/src/flow/nodes/async/flowConstantAsync.ts +142 -0
  76. package/src/flow/nodes/async/flowDerivationAsync.ts +143 -0
  77. package/src/flow/nodes/async/flowNodeAsync.ts +474 -0
  78. package/src/flow/nodes/async/flowReadonlyAsync.ts +81 -0
  79. package/src/flow/nodes/async/flowStateAsync.ts +116 -0
  80. package/src/flow/nodes/async/index.ts +5 -0
  81. package/src/flow/nodes/await/advanced/index.ts +5 -0
  82. package/src/{advanced → flow/nodes/await/advanced}/resource.ts +37 -3
  83. package/src/{advanced → flow/nodes/await/advanced}/resourceAsync.ts +35 -3
  84. package/src/{advanced → flow/nodes/await/advanced}/stream.ts +40 -2
  85. package/src/{advanced → flow/nodes/await/advanced}/streamAsync.ts +38 -3
  86. package/src/flow/nodes/await/flowConstantAwait.ts +154 -0
  87. package/src/flow/nodes/await/flowDerivationAwait.ts +154 -0
  88. package/src/flow/nodes/await/flowNodeAwait.ts +508 -0
  89. package/src/flow/nodes/await/flowReadonlyAwait.ts +89 -0
  90. package/src/flow/nodes/await/flowStateAwait.ts +130 -0
  91. package/src/flow/nodes/await/index.ts +5 -0
  92. package/src/flow/nodes/index.ts +3 -0
  93. package/src/flow/nodes/sync/flowConstant.ts +111 -0
  94. package/src/flow/nodes/sync/flowDerivation.ts +105 -0
  95. package/src/flow/nodes/sync/flowNode.ts +439 -0
  96. package/src/flow/nodes/sync/flowReadonly.ts +57 -0
  97. package/src/flow/nodes/sync/flowState.ts +101 -0
  98. package/src/flow/nodes/sync/index.ts +5 -0
  99. package/src/index.ts +2 -47
  100. package/src/solid/converters.ts +60 -199
  101. package/src/solid/index.ts +2 -8
  102. package/src/solid/primitives.ts +4 -0
  103. package/test/base/flowEffect.test.ts +108 -0
  104. package/test/base/flowGraph.test.ts +485 -0
  105. package/test/base/flowSignal.test.ts +372 -0
  106. package/test/collections/flowArray.asyncStates.test.ts +1553 -0
  107. package/test/collections/flowArray.scalars.test.ts +1129 -0
  108. package/test/collections/flowArray.states.test.ts +1365 -0
  109. package/test/collections/flowMap.asyncStates.test.ts +1105 -0
  110. package/test/collections/flowMap.scalars.test.ts +877 -0
  111. package/test/collections/flowMap.states.test.ts +1097 -0
  112. package/test/nodes/async/flowConstantAsync.test.ts +860 -0
  113. package/test/nodes/async/flowDerivationAsync.test.ts +1517 -0
  114. package/test/nodes/async/flowStateAsync.test.ts +1387 -0
  115. package/test/{resource.test.ts → nodes/await/advanced/resource.test.ts} +21 -19
  116. package/test/{resourceAsync.test.ts → nodes/await/advanced/resourceAsync.test.ts} +3 -1
  117. package/test/{stream.test.ts → nodes/await/advanced/stream.test.ts} +30 -28
  118. package/test/{streamAsync.test.ts → nodes/await/advanced/streamAsync.test.ts} +16 -14
  119. package/test/nodes/await/flowConstantAwait.test.ts +643 -0
  120. package/test/nodes/await/flowDerivationAwait.test.ts +1583 -0
  121. package/test/nodes/await/flowStateAwait.test.ts +999 -0
  122. package/test/nodes/mixed/derivation.test.ts +1527 -0
  123. package/test/nodes/sync/flowConstant.test.ts +620 -0
  124. package/test/nodes/sync/flowDerivation.test.ts +1373 -0
  125. package/test/nodes/sync/flowState.test.ts +945 -0
  126. package/test/solid/converters.test.ts +721 -0
  127. package/test/solid/primitives.test.ts +1031 -0
  128. package/tsconfig.json +2 -1
  129. package/vitest.config.ts +7 -1
  130. package/IMPLEMENTATION_GUIDE.md +0 -1578
  131. package/dist/types/advanced/array.d.ts.map +0 -1
  132. package/dist/types/advanced/index.d.ts +0 -9
  133. package/dist/types/advanced/index.d.ts.map +0 -1
  134. package/dist/types/advanced/map.d.ts +0 -166
  135. package/dist/types/advanced/map.d.ts.map +0 -1
  136. package/dist/types/advanced/resource.d.ts +0 -78
  137. package/dist/types/advanced/resource.d.ts.map +0 -1
  138. package/dist/types/advanced/resourceAsync.d.ts +0 -56
  139. package/dist/types/advanced/resourceAsync.d.ts.map +0 -1
  140. package/dist/types/advanced/stream.d.ts +0 -117
  141. package/dist/types/advanced/stream.d.ts.map +0 -1
  142. package/dist/types/advanced/streamAsync.d.ts +0 -97
  143. package/dist/types/advanced/streamAsync.d.ts.map +0 -1
  144. package/dist/types/basic/constant.d.ts +0 -60
  145. package/dist/types/basic/constant.d.ts.map +0 -1
  146. package/dist/types/basic/derivation.d.ts +0 -89
  147. package/dist/types/basic/derivation.d.ts.map +0 -1
  148. package/dist/types/basic/disposable.d.ts +0 -82
  149. package/dist/types/basic/disposable.d.ts.map +0 -1
  150. package/dist/types/basic/effect.d.ts +0 -67
  151. package/dist/types/basic/effect.d.ts.map +0 -1
  152. package/dist/types/basic/index.d.ts +0 -10
  153. package/dist/types/basic/index.d.ts.map +0 -1
  154. package/dist/types/basic/observable.d.ts +0 -83
  155. package/dist/types/basic/observable.d.ts.map +0 -1
  156. package/dist/types/basic/signal.d.ts +0 -69
  157. package/dist/types/basic/signal.d.ts.map +0 -1
  158. package/dist/types/basic/state.d.ts +0 -47
  159. package/dist/types/basic/state.d.ts.map +0 -1
  160. package/dist/types/basic/trackingContext.d.ts +0 -33
  161. package/dist/types/basic/trackingContext.d.ts.map +0 -1
  162. package/dist/types/creators.d.ts +0 -340
  163. package/dist/types/creators.d.ts.map +0 -1
  164. package/src/advanced/array.ts +0 -222
  165. package/src/advanced/index.ts +0 -12
  166. package/src/advanced/map.ts +0 -193
  167. package/src/basic/constant.ts +0 -97
  168. package/src/basic/derivation.ts +0 -147
  169. package/src/basic/disposable.ts +0 -86
  170. package/src/basic/effect.ts +0 -104
  171. package/src/basic/index.ts +0 -9
  172. package/src/basic/observable.ts +0 -109
  173. package/src/basic/signal.ts +0 -145
  174. package/src/basic/state.ts +0 -60
  175. package/src/basic/trackingContext.ts +0 -45
  176. package/src/creators.ts +0 -395
  177. package/test/array.test.ts +0 -600
  178. package/test/constant.test.ts +0 -44
  179. package/test/derivation.test.ts +0 -539
  180. package/test/effect.test.ts +0 -29
  181. package/test/map.test.ts +0 -240
  182. package/test/signal.test.ts +0 -72
  183. package/test/state.test.ts +0 -212
@@ -0,0 +1,372 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { effect, signal } from "#package";
3
+
4
+ describe("FlowSignal", () => {
5
+ describe("unit", () => {
6
+ describe("disposal", () => {
7
+ it("should have disposed property set to false initially and true after disposal", () => {
8
+ const $signal = signal();
9
+ expect($signal.disposed).toBe(false);
10
+ $signal.dispose();
11
+ expect($signal.disposed).toBe(true);
12
+ });
13
+
14
+ it("should throw error when disposed twice", () => {
15
+ const $signal = signal();
16
+ $signal.dispose();
17
+ expect(() => $signal.dispose()).toThrow(
18
+ "[PicoFlow] Primitive is disposed",
19
+ );
20
+ });
21
+
22
+ it("should dispose signal successfully", () => {
23
+ const $signal = signal();
24
+ expect(() => $signal.dispose()).not.toThrow();
25
+ expect($signal.disposed).toBe(true);
26
+ });
27
+
28
+ it("should accept self option without throwing", () => {
29
+ const $signal = signal();
30
+ expect(() => $signal.dispose({ self: true })).not.toThrow();
31
+ expect($signal.disposed).toBe(true);
32
+ });
33
+
34
+ it("should accept default options without throwing", () => {
35
+ const $signal = signal();
36
+ expect(() => $signal.dispose()).not.toThrow();
37
+ expect($signal.disposed).toBe(true);
38
+ });
39
+ });
40
+
41
+ describe("trigger", () => {
42
+ it("should return a promise when triggered", () => {
43
+ const $signal = signal();
44
+ const result = $signal.trigger();
45
+ expect(result).toBeInstanceOf(Promise);
46
+ });
47
+
48
+ it("should throw error when trigger is called after disposal", async () => {
49
+ const $signal = signal();
50
+ $signal.dispose();
51
+ await expect($signal.trigger()).rejects.toThrow(
52
+ "[PicoFlow] Primitive is disposed",
53
+ );
54
+ });
55
+
56
+ it("should allow multiple triggers", async () => {
57
+ const $signal = signal();
58
+ const promise1 = $signal.trigger();
59
+ const promise2 = $signal.trigger();
60
+ const promise3 = $signal.trigger();
61
+
62
+ expect(promise1).toBeInstanceOf(Promise);
63
+ expect(promise2).toBeInstanceOf(Promise);
64
+ expect(promise3).toBeInstanceOf(Promise);
65
+
66
+ await Promise.all([promise1, promise2, promise3]);
67
+ });
68
+ });
69
+
70
+ describe("watch", () => {
71
+ it("should throw error when watch is called after disposal", () => {
72
+ const $signal = signal();
73
+ const $tracker = signal(); // Use another signal as FlowTracker
74
+ $signal.dispose();
75
+ expect(() => $signal.watch($tracker)).toThrow(
76
+ "[PicoFlow] Primitive is disposed",
77
+ );
78
+ });
79
+ });
80
+ });
81
+
82
+ describe("integration", () => {
83
+ describe("with effects", () => {
84
+ describe("watch", () => {
85
+ it("should register effect when watch is called", async () => {
86
+ const $signal = signal();
87
+ const effectFn = vi.fn();
88
+ effect((t) => {
89
+ $signal.watch(t);
90
+ effectFn();
91
+ });
92
+
93
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
94
+ expect(effectFn).toHaveBeenCalledTimes(1);
95
+ });
96
+
97
+ it("should throw error when watch is called after signal disposal", async () => {
98
+ const $signal = signal();
99
+ const effectFn = vi.fn();
100
+ effect((t) => {
101
+ $signal.watch(t);
102
+ effectFn();
103
+ });
104
+
105
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
106
+
107
+ $signal.dispose();
108
+
109
+ effect((t) => {
110
+ expect(() => $signal.watch(t)).toThrow(
111
+ "[PicoFlow] Primitive is disposed",
112
+ );
113
+ });
114
+
115
+ await expect($signal.trigger()).rejects.toThrow(
116
+ "[PicoFlow] Primitive is disposed",
117
+ );
118
+ });
119
+ });
120
+
121
+ describe("trigger", () => {
122
+ it("should notify effects when triggered", async () => {
123
+ const $signal = signal();
124
+ const effectFn = vi.fn();
125
+ effect((t) => {
126
+ $signal.watch(t);
127
+ effectFn();
128
+ });
129
+
130
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
131
+
132
+ $signal.trigger();
133
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(2));
134
+
135
+ $signal.trigger();
136
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(3));
137
+ });
138
+
139
+ it("should notify multiple effects when triggered", async () => {
140
+ const $signal = signal();
141
+ const effectFn1 = vi.fn();
142
+ const effectFn2 = vi.fn();
143
+ const effectFn3 = vi.fn();
144
+
145
+ effect((t) => {
146
+ $signal.watch(t);
147
+ effectFn1();
148
+ });
149
+
150
+ effect((t) => {
151
+ $signal.watch(t);
152
+ effectFn2();
153
+ });
154
+
155
+ effect((t) => {
156
+ $signal.watch(t);
157
+ effectFn3();
158
+ });
159
+
160
+ await vi.waitFor(() => {
161
+ expect(effectFn1).toHaveBeenCalledTimes(1);
162
+ expect(effectFn2).toHaveBeenCalledTimes(1);
163
+ expect(effectFn3).toHaveBeenCalledTimes(1);
164
+ });
165
+
166
+ $signal.trigger();
167
+ await vi.waitFor(() => {
168
+ expect(effectFn1).toHaveBeenCalledTimes(2);
169
+ expect(effectFn2).toHaveBeenCalledTimes(2);
170
+ expect(effectFn3).toHaveBeenCalledTimes(2);
171
+ });
172
+ });
173
+
174
+ it("should not notify effects after they are disposed", async () => {
175
+ const $signal = signal();
176
+ const effectFn = vi.fn();
177
+ const $effect = effect((t) => {
178
+ $signal.watch(t);
179
+ effectFn();
180
+ });
181
+
182
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
183
+
184
+ $signal.trigger();
185
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(2));
186
+
187
+ $effect.dispose();
188
+
189
+ $signal.trigger();
190
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(2));
191
+ });
192
+
193
+ it("should notify effects multiple times on multiple triggers", async () => {
194
+ const $signal = signal();
195
+ const effectFn = vi.fn();
196
+ effect((t) => {
197
+ $signal.watch(t);
198
+ effectFn();
199
+ });
200
+
201
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
202
+
203
+ $signal.trigger();
204
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(2));
205
+
206
+ $signal.trigger();
207
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(3));
208
+
209
+ $signal.trigger();
210
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(4));
211
+ });
212
+
213
+ it("should await trigger promise before effects complete", async () => {
214
+ const $signal = signal();
215
+ const executionOrder: string[] = [];
216
+ const effectFn = vi.fn();
217
+
218
+ effect((t) => {
219
+ $signal.watch(t);
220
+ executionOrder.push("effect-executed");
221
+ effectFn();
222
+ });
223
+
224
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
225
+ executionOrder.push("after-initial-effect");
226
+
227
+ const triggerPromise = $signal.trigger();
228
+ executionOrder.push("trigger-called");
229
+
230
+ await triggerPromise;
231
+ executionOrder.push("trigger-resolved");
232
+
233
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(2));
234
+
235
+ expect(executionOrder).toEqual([
236
+ "effect-executed",
237
+ "after-initial-effect",
238
+ "effect-executed",
239
+ "trigger-called",
240
+ "trigger-resolved",
241
+ ]);
242
+ });
243
+ });
244
+
245
+ describe("dispose", () => {
246
+ it("should dispose effects when signal is disposed", async () => {
247
+ const $signal = signal();
248
+ const effectFn = vi.fn();
249
+ const $effect = effect((t) => {
250
+ $signal.watch(t);
251
+ effectFn();
252
+ });
253
+
254
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
255
+ expect($effect.disposed).toBe(false);
256
+
257
+ $signal.dispose();
258
+
259
+ expect($effect.disposed).toBe(true);
260
+
261
+ await expect($signal.trigger()).rejects.toThrow(
262
+ "[PicoFlow] Primitive is disposed",
263
+ );
264
+ });
265
+
266
+ it("should not dispose effects when signal is disposed with self option", async () => {
267
+ const $signal = signal();
268
+ const effectFn = vi.fn();
269
+ const $effect = effect((t) => {
270
+ $signal.watch(t);
271
+ effectFn();
272
+ });
273
+
274
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
275
+ expect($effect.disposed).toBe(false);
276
+
277
+ $signal.dispose({ self: true });
278
+
279
+ expect($effect.disposed).toBe(false);
280
+ expect($signal.disposed).toBe(true);
281
+ });
282
+
283
+ it("should unregister effects when signal is disposed with self option", async () => {
284
+ const $signal = signal();
285
+ const effectFn = vi.fn();
286
+ const $effect = effect((t) => {
287
+ $signal.watch(t);
288
+ effectFn();
289
+ });
290
+
291
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
292
+
293
+ $signal.dispose({ self: true });
294
+
295
+ // Effect should still be active but not notified
296
+ expect($effect.disposed).toBe(false);
297
+
298
+ // But signal is disposed so trigger will fail
299
+ await expect($signal.trigger()).rejects.toThrow(
300
+ "[PicoFlow] Primitive is disposed",
301
+ );
302
+ });
303
+ });
304
+ });
305
+
306
+ describe("signal chaining", () => {
307
+ it("should notify listener signals when triggered", async () => {
308
+ const $signal1 = signal();
309
+ const $signal2 = signal();
310
+ const effectFn = vi.fn();
311
+
312
+ // signal2 watches signal1
313
+ effect((t) => {
314
+ $signal1.watch(t);
315
+ $signal2.trigger();
316
+ });
317
+
318
+ // effect watches signal2
319
+ effect((t) => {
320
+ $signal2.watch(t);
321
+ effectFn();
322
+ });
323
+
324
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(1));
325
+
326
+ $signal1.trigger();
327
+ await vi.waitFor(() => expect(effectFn).toHaveBeenCalledTimes(2));
328
+ });
329
+
330
+ // TODO: Fix this test
331
+ it.skip("should notify chained signals in correct order", async () => {
332
+ const $signal1 = signal();
333
+ const $signal2 = signal();
334
+ const $signal3 = signal();
335
+ const executionOrder: string[] = [];
336
+
337
+ effect((t) => {
338
+ $signal1.watch(t);
339
+ executionOrder.push("signal1-triggered");
340
+ $signal2.trigger();
341
+ });
342
+
343
+ effect((t) => {
344
+ $signal2.watch(t);
345
+ executionOrder.push("signal2-triggered");
346
+ $signal3.trigger();
347
+ });
348
+
349
+ effect((t) => {
350
+ $signal3.watch(t);
351
+ executionOrder.push("signal3-triggered");
352
+ });
353
+
354
+ await vi.waitFor(() =>
355
+ expect(executionOrder.length).toBeGreaterThan(0),
356
+ );
357
+
358
+ executionOrder.length = 0; // Clear initial execution
359
+
360
+ $signal1.trigger();
361
+ await vi.waitFor(() => expect(executionOrder.length).toBe(5));
362
+ console.log(executionOrder);
363
+
364
+ expect(executionOrder).toEqual([
365
+ "signal1-triggered",
366
+ "signal2-triggered",
367
+ "signal3-triggered",
368
+ ]);
369
+ });
370
+ });
371
+ });
372
+ });