@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
@@ -1,539 +0,0 @@
1
- import { describe, expect, test, vi } from "vitest";
2
- import { derivation, effect, resource, signal, state } from "#package";
3
-
4
- describe("derivation", () => {
5
- describe("from state", () => {
6
- test("is updated", () => {
7
- const $state = state(1);
8
- const $derivation = derivation((t) => $state.get(t) * 2);
9
- expect($derivation.pick()).toBe(2);
10
-
11
- $state.set(2);
12
- expect($derivation.pick()).toBe(4);
13
- });
14
-
15
- test("get throws when disposed", () => {
16
- const $state = state(1);
17
- const $derivation = derivation((t) => $state.get(t) * 2);
18
- expect($derivation.pick()).toBe(2);
19
-
20
- $state.set(2);
21
- expect($derivation.pick()).toBe(4);
22
-
23
- $derivation.dispose();
24
- expect(() => $derivation.pick()).toThrow(
25
- "[PicoFlow] Primitive is disposed",
26
- );
27
- });
28
-
29
- test("get throws when state is disposed", () => {
30
- const $state = state(1);
31
- const $derivation = derivation((t) => $state.get(t) * 2);
32
- expect($derivation.pick()).toBe(2);
33
-
34
- $state.set(2);
35
- expect($derivation.pick()).toBe(4);
36
-
37
- $state.dispose();
38
- expect(() => $derivation.pick()).toThrow(
39
- "[PicoFlow] Primitive is disposed",
40
- );
41
- });
42
-
43
- test("is updated (chained dependencies)", () => {
44
- const $state = state(1);
45
- const $derivation1 = derivation((t) => $state.get(t) * 2);
46
- const $derivation2 = derivation((t) => $derivation1.get(t) * 2);
47
-
48
- expect($derivation2.pick()).toBe(4);
49
-
50
- $state.set(2);
51
- expect($derivation2.pick()).toBe(8);
52
- });
53
-
54
- test("is updated (multiple dependencies)", () => {
55
- const $state1 = state(1);
56
- const $state2 = state(2);
57
- const $derivation = derivation((t) => $state1.get(t) + $state2.get(t));
58
-
59
- expect($derivation.pick()).toBe(3);
60
-
61
- $state1.set(2);
62
- expect($derivation.pick()).toBe(4);
63
-
64
- $state2.set(3);
65
- expect($derivation.pick()).toBe(5);
66
- });
67
-
68
- test("is updated (multiple dependants)", () => {
69
- const $state = state(1);
70
- const $derivation1 = derivation((t) => $state.get(t) * 2);
71
- const $derivation2 = derivation((t) => $state.get(t) * 3);
72
-
73
- expect($derivation1.pick()).toBe(2);
74
- expect($derivation2.pick()).toBe(3);
75
-
76
- $state.set(2);
77
- expect($derivation1.pick()).toBe(4);
78
- expect($derivation2.pick()).toBe(6);
79
-
80
- $state.set(3);
81
- expect($derivation1.pick()).toBe(6);
82
- expect($derivation2.pick()).toBe(9);
83
- });
84
-
85
- test("is updated (async)", async () => {
86
- const $state = state(1);
87
- const $derivation = derivation(async (t) => $state.get(t) * 2);
88
-
89
- expect(await $derivation.pick()).toBe(2);
90
-
91
- $state.set(2);
92
- expect(await $derivation.pick()).toBe(4);
93
- });
94
-
95
- test("is updated (async chain)", async () => {
96
- const $state = state(1);
97
- const $derivation1 = derivation(async (t) => $state.get(t) * 2);
98
- const $derivation2 = derivation(
99
- async (t) => (await $derivation1.get(t)) * 2,
100
- );
101
-
102
- expect(await $derivation2.pick()).toBe(4);
103
-
104
- $state.set(2);
105
- expect(await $derivation2.pick()).toBe(8);
106
- });
107
- });
108
-
109
- describe("from resource", () => {
110
- test("from resource is updated", async () => {
111
- let resourceCounter = 0;
112
- const fetchResource = async () => {
113
- resourceCounter++;
114
- return resourceCounter;
115
- };
116
- const $resource = resource(fetchResource);
117
- const $derivation = derivation((t) => ($resource.get(t) ?? 0) * 2);
118
-
119
- expect($derivation.pick()).toBe(0);
120
-
121
- await $resource.fetch();
122
- expect($derivation.pick()).toBe(2);
123
-
124
- await $resource.fetch();
125
- expect($derivation.pick()).toBe(4);
126
-
127
- await $resource.fetch();
128
- expect($derivation.pick()).toBe(6);
129
- });
130
- });
131
- });
132
-
133
- describe("effect", () => {
134
- describe("from signal", () => {
135
- test("called when triggered", () => {
136
- const $signal = signal();
137
- const $derivation = derivation((t) => {
138
- $signal.watch(t);
139
- });
140
- const effectFn = vi.fn();
141
- effect((t) => {
142
- $derivation.watch(t);
143
- effectFn();
144
- });
145
-
146
- expect(effectFn).toHaveBeenCalledTimes(1);
147
-
148
- $signal.trigger();
149
- expect(effectFn).toHaveBeenCalledTimes(2);
150
-
151
- $signal.trigger();
152
- expect(effectFn).toHaveBeenCalledTimes(3);
153
-
154
- $signal.trigger();
155
- expect(effectFn).toHaveBeenCalledTimes(4);
156
- });
157
-
158
- test("called when triggered (chained dependencies)", () => {
159
- const $signal = signal();
160
- const $derivation1 = derivation((t) => $signal.watch(t));
161
- const $derivation2 = derivation((t) => $derivation1.watch(t));
162
- const effectFn = vi.fn();
163
- effect((t) => {
164
- $derivation2.watch(t);
165
- effectFn();
166
- });
167
-
168
- expect(effectFn).toHaveBeenCalledTimes(1);
169
-
170
- $signal.trigger();
171
- expect(effectFn).toHaveBeenCalledTimes(2);
172
- });
173
-
174
- test("called when triggered (multiple dependencies)", () => {
175
- const $signal1 = signal();
176
- const $signal2 = signal();
177
- const $derivation = derivation((t) => {
178
- $signal1.watch(t);
179
- $signal2.watch(t);
180
- });
181
- const effectFn = vi.fn();
182
- effect((t) => {
183
- $derivation.watch(t);
184
- effectFn();
185
- });
186
-
187
- expect(effectFn).toHaveBeenCalledTimes(1);
188
-
189
- $signal1.trigger();
190
- expect(effectFn).toHaveBeenCalledTimes(2);
191
-
192
- $signal2.trigger();
193
- expect(effectFn).toHaveBeenCalledTimes(3);
194
- });
195
-
196
- test("called when is updated (multiple dependants)", () => {
197
- const $signal = signal();
198
- const $derivation1 = derivation((t) => $signal.watch(t));
199
- const $derivation2 = derivation((t) => $signal.watch(t));
200
- const effect1Fn = vi.fn();
201
- const effect2Fn = vi.fn();
202
-
203
- effect((t) => effect1Fn($derivation1.get(t)));
204
- effect((t) => effect2Fn($derivation2.get(t)));
205
-
206
- expect(effect1Fn).toHaveBeenCalledTimes(1);
207
- expect(effect2Fn).toHaveBeenCalledTimes(1);
208
-
209
- $signal.trigger();
210
- expect(effect1Fn).toHaveBeenCalledTimes(2);
211
- expect(effect2Fn).toHaveBeenCalledTimes(2);
212
-
213
- $signal.trigger();
214
- expect(effect1Fn).toHaveBeenCalledTimes(3);
215
- expect(effect2Fn).toHaveBeenCalledTimes(3);
216
- });
217
-
218
- test("called when triggered (with state)", () => {
219
- const $signal = signal();
220
- const $state = state(1);
221
- const $derivation = derivation((t) => {
222
- $signal.watch(t);
223
- return $state.get(t) * 2;
224
- });
225
- const effectFn = vi.fn();
226
- effect((t) => effectFn($derivation.get(t)));
227
-
228
- expect(effectFn).toHaveBeenCalledTimes(1);
229
- expect(effectFn).toHaveBeenLastCalledWith(2);
230
-
231
- $signal.trigger();
232
- expect(effectFn).toHaveBeenCalledTimes(2);
233
- expect(effectFn).toHaveBeenLastCalledWith(2);
234
-
235
- $signal.trigger();
236
- expect(effectFn).toHaveBeenCalledTimes(3);
237
- expect(effectFn).toHaveBeenLastCalledWith(2);
238
-
239
- $state.set(2);
240
- expect(effectFn).toHaveBeenCalledTimes(4);
241
- expect(effectFn).toHaveBeenLastCalledWith(4);
242
-
243
- $signal.trigger();
244
- expect(effectFn).toHaveBeenCalledTimes(5);
245
- expect(effectFn).toHaveBeenLastCalledWith(4);
246
- });
247
- });
248
-
249
- describe("from state", () => {
250
- test("called when is updated", () => {
251
- const $state = state(1);
252
- const $derivation = derivation((t) => $state.get(t) * 2);
253
- const effectFn = vi.fn();
254
- effect((t) => effectFn($derivation.get(t)));
255
-
256
- expect(effectFn).toHaveBeenCalledTimes(1);
257
- expect(effectFn).toHaveBeenLastCalledWith(2);
258
-
259
- $state.set(2);
260
- expect(effectFn).toHaveBeenCalledTimes(2);
261
- expect(effectFn).toHaveBeenLastCalledWith(4);
262
- });
263
-
264
- test("called when is updated (chained dependencies)", () => {
265
- const $state = state(1);
266
- const $derivation1 = derivation((t) => $state.get(t) * 2);
267
- const $derivation2 = derivation((t) => $derivation1.get(t) * 2);
268
- const effectFn = vi.fn();
269
- effect((t) => effectFn($derivation2.get(t)));
270
-
271
- expect(effectFn).toHaveBeenCalledTimes(1);
272
- expect(effectFn).toHaveBeenLastCalledWith(4);
273
-
274
- $state.set(2);
275
- expect(effectFn).toHaveBeenCalledTimes(2);
276
- expect(effectFn).toHaveBeenLastCalledWith(8);
277
- });
278
-
279
- test("called when is updated (multiple dependencies)", () => {
280
- const $state1 = state(1);
281
- const $state2 = state(2);
282
- const $derivation = derivation((t) => $state1.get(t) + $state2.get(t));
283
- const effectFn = vi.fn();
284
- effect((t) => effectFn($derivation.get(t)));
285
-
286
- expect(effectFn).toHaveBeenCalledTimes(1);
287
- expect(effectFn).toHaveBeenLastCalledWith(3);
288
-
289
- $state1.set(2);
290
- expect(effectFn).toHaveBeenCalledTimes(2);
291
- expect(effectFn).toHaveBeenLastCalledWith(4);
292
-
293
- $state2.set(3);
294
- expect(effectFn).toHaveBeenCalledTimes(3);
295
- expect(effectFn).toHaveBeenLastCalledWith(5);
296
- });
297
-
298
- test("called when is updated (multiple dependants)", () => {
299
- const $state = state(1);
300
- const $derivation1 = derivation((t) => $state.get(t) * 2);
301
- const $derivation2 = derivation((t) => $state.get(t) * 3);
302
- const effect1Fn = vi.fn();
303
- const effect2Fn = vi.fn();
304
-
305
- effect((t) => effect1Fn($derivation1.get(t)));
306
- effect((t) => effect2Fn($derivation2.get(t)));
307
-
308
- expect(effect1Fn).toHaveBeenCalledTimes(1);
309
- expect(effect1Fn).toHaveBeenLastCalledWith(2);
310
- expect(effect2Fn).toHaveBeenCalledTimes(1);
311
- expect(effect2Fn).toHaveBeenLastCalledWith(3);
312
-
313
- $state.set(2);
314
- expect(effect1Fn).toHaveBeenCalledTimes(2);
315
- expect(effect1Fn).toHaveBeenLastCalledWith(4);
316
- expect(effect2Fn).toHaveBeenCalledTimes(2);
317
- expect(effect2Fn).toHaveBeenLastCalledWith(6);
318
-
319
- $state.set(3);
320
- expect(effect1Fn).toHaveBeenCalledTimes(3);
321
- expect(effect1Fn).toHaveBeenLastCalledWith(6);
322
- expect(effect2Fn).toHaveBeenCalledTimes(3);
323
- expect(effect2Fn).toHaveBeenLastCalledWith(9);
324
- });
325
-
326
- test("called when is updated (async)", async () => {
327
- const $state = state(1);
328
- const $derivation = derivation(async (t) => $state.get(t) * 2);
329
- const effectFn = vi.fn();
330
- effect((t) => effectFn($derivation.get(t)));
331
-
332
- expect(effectFn).toHaveBeenCalledTimes(1);
333
- expect(await effectFn.mock.calls[0][0]).toEqual(2);
334
-
335
- $state.set(2);
336
- expect(effectFn).toHaveBeenCalledTimes(2);
337
- expect(await effectFn.mock.calls[1][0]).toEqual(4);
338
- });
339
-
340
- test("called when is updated (async chain)", async () => {
341
- const $state = state(1);
342
- const $derivation1 = derivation(async (t) => $state.get(t) * 2);
343
- const $derivation2 = derivation(
344
- async (t) => (await $derivation1.get(t)) * 2,
345
- );
346
- const effectFn = vi.fn();
347
- effect((t) => effectFn($derivation2.get(t)));
348
-
349
- expect(effectFn).toHaveBeenCalledTimes(1);
350
- expect(await effectFn.mock.calls[0][0]).toEqual(4);
351
-
352
- $state.set(2);
353
- expect(effectFn).toHaveBeenCalledTimes(2);
354
- expect(await effectFn.mock.calls[1][0]).toEqual(8);
355
- });
356
-
357
- test("NOT called when derivation is disposed", () => {
358
- const $state = state(1);
359
- const $derivation = derivation((t) => $state.get(t) * 2);
360
- const effectFn = vi.fn();
361
- effect((t) => effectFn($derivation.get(t)));
362
-
363
- expect(effectFn).toHaveBeenCalledTimes(1);
364
- expect(effectFn).toHaveBeenLastCalledWith(2);
365
-
366
- $state.set(2);
367
- expect(effectFn).toHaveBeenCalledTimes(2);
368
- expect(effectFn).toHaveBeenLastCalledWith(4);
369
-
370
- $derivation.dispose();
371
-
372
- $state.set(3);
373
- expect(effectFn).toHaveBeenCalledTimes(2);
374
- expect(effectFn).toHaveBeenLastCalledWith(4);
375
- });
376
-
377
- test("NOT called when derivation is disposed (watch)", () => {
378
- const $state = state(1);
379
- const $derivation = derivation((t) => $state.get(t) * 2);
380
- const effectFn = vi.fn();
381
- effect((t) => {
382
- $derivation.watch(t);
383
- effectFn();
384
- });
385
-
386
- expect(effectFn).toHaveBeenCalledTimes(1);
387
-
388
- $state.set(2);
389
- expect(effectFn).toHaveBeenCalledTimes(2);
390
-
391
- $derivation.dispose();
392
-
393
- $state.set(3);
394
- expect(effectFn).toHaveBeenCalledTimes(2);
395
- });
396
-
397
- test("NOT called when disposed", () => {
398
- const $state = state(1);
399
- const $derivation = derivation((t) => $state.get(t) * 2);
400
- const effectFn = vi.fn();
401
- const $effect = effect((t) => effectFn($derivation.get(t)));
402
-
403
- expect(effectFn).toHaveBeenCalledTimes(1);
404
- expect(effectFn).toHaveBeenLastCalledWith(2);
405
-
406
- $state.set(2);
407
- expect(effectFn).toHaveBeenCalledTimes(2);
408
- expect(effectFn).toHaveBeenLastCalledWith(4);
409
-
410
- $effect.dispose();
411
-
412
- $state.set(3);
413
- expect(effectFn).toHaveBeenCalledTimes(2);
414
- expect(effectFn).toHaveBeenLastCalledWith(4);
415
- });
416
- });
417
-
418
- describe("from resource", () => {
419
- test("called when is updated", async () => {
420
- let resourceCounter = 0;
421
- const fetchResource = async () => {
422
- resourceCounter++;
423
- return resourceCounter;
424
- };
425
- const $resource = resource(fetchResource);
426
- const $derivation = derivation((t) => ($resource.get(t) ?? 0) * 2);
427
- const effectFn = vi.fn();
428
- effect((t) => effectFn($derivation.get(t)));
429
-
430
- expect(effectFn).toHaveBeenCalledTimes(1);
431
- expect(effectFn).toHaveBeenLastCalledWith(0);
432
-
433
- await $resource.fetch();
434
- expect(effectFn).toHaveBeenCalledTimes(2);
435
- expect(effectFn).toHaveBeenLastCalledWith(2);
436
-
437
- await $resource.fetch();
438
- expect(effectFn).toHaveBeenCalledTimes(3);
439
- expect(effectFn).toHaveBeenLastCalledWith(4);
440
- });
441
- });
442
-
443
- describe("complex test", () => {
444
- test("test", () => {
445
- const obj1 = {
446
- cond: state(false),
447
- num: state(2),
448
- dispose: (options: { self: boolean }) => {
449
- obj1.cond.dispose(options);
450
- obj1.num.dispose(options);
451
- },
452
- };
453
- const obj2 = {
454
- cond: state(false),
455
- num: state(4),
456
- dispose: (options: { self: boolean }) => {
457
- obj2.cond.dispose(options);
458
- obj2.num.dispose(options);
459
- },
460
- };
461
- const $state = state(obj1);
462
- const $derivationCond = derivation((t) => $state.get(t).cond.get(t));
463
- const $derivationNum = derivation((t) => $state.get(t).num.get(t) * 2);
464
- const effectCondFn = vi.fn();
465
- const effectNumFn = vi.fn();
466
- effect((t) => effectCondFn($derivationCond.get(t)));
467
- effect((t) => effectNumFn($derivationNum.get(t)));
468
-
469
- expect(effectCondFn).toHaveBeenCalledTimes(1);
470
- expect(effectCondFn).toHaveBeenLastCalledWith(false);
471
- expect(effectNumFn).toHaveBeenCalledTimes(1);
472
- expect(effectNumFn).toHaveBeenLastCalledWith(4);
473
-
474
- $state.pick().num.set(3);
475
- expect(effectCondFn).toHaveBeenCalledTimes(1);
476
- expect(effectCondFn).toHaveBeenLastCalledWith(false);
477
- expect(effectNumFn).toHaveBeenCalledTimes(2);
478
- expect(effectNumFn).toHaveBeenLastCalledWith(6);
479
-
480
- $state.pick().cond.set(true);
481
- expect(effectCondFn).toHaveBeenCalledTimes(2);
482
- expect(effectCondFn).toHaveBeenLastCalledWith(true);
483
- expect(effectNumFn).toHaveBeenCalledTimes(2);
484
- expect(effectNumFn).toHaveBeenLastCalledWith(6);
485
-
486
- $state.set(obj2);
487
- expect(effectCondFn).toHaveBeenCalledTimes(3);
488
- expect(effectCondFn).toHaveBeenLastCalledWith(false);
489
- expect(effectNumFn).toHaveBeenCalledTimes(3);
490
- expect(effectNumFn).toHaveBeenLastCalledWith(8);
491
-
492
- $state.pick().cond.set(true);
493
- expect(effectCondFn).toHaveBeenCalledTimes(4); // fails -> called 3 times
494
- expect(effectCondFn).toHaveBeenLastCalledWith(true);
495
- expect(effectNumFn).toHaveBeenCalledTimes(3);
496
- expect(effectNumFn).toHaveBeenLastCalledWith(8);
497
-
498
- $state.pick().num.set(5);
499
- expect(effectCondFn).toHaveBeenCalledTimes(4);
500
- expect(effectCondFn).toHaveBeenLastCalledWith(true);
501
- expect(effectNumFn).toHaveBeenCalledTimes(4);
502
- expect(effectNumFn).toHaveBeenLastCalledWith(10);
503
- });
504
-
505
- test("test", () => {
506
- const obj = {
507
- cond: state(false),
508
- b: state(2),
509
- };
510
-
511
- const $state = state(obj);
512
- const $derivation = derivation((t) => {
513
- const cond = $state.get(t).cond.get(t);
514
- if (cond) {
515
- return $state.get(t).b.get(t) * 2;
516
- }
517
- return 0;
518
- });
519
-
520
- const effectFn = vi.fn();
521
- effect((t) => effectFn($derivation.get(t)));
522
-
523
- expect(effectFn).toHaveBeenCalledTimes(1);
524
- expect(effectFn).toHaveBeenLastCalledWith(0);
525
-
526
- $state.pick().cond.set(true);
527
- expect(effectFn).toHaveBeenCalledTimes(2);
528
- expect(effectFn).toHaveBeenLastCalledWith(4);
529
-
530
- $state.set({ cond: state(false), b: state(3) });
531
- expect(effectFn).toHaveBeenCalledTimes(3);
532
- expect(effectFn).toHaveBeenLastCalledWith(0);
533
-
534
- $state.pick().cond.set(true);
535
- expect(effectFn).toHaveBeenCalledTimes(4);
536
- expect(effectFn).toHaveBeenLastCalledWith(6);
537
- });
538
- });
539
- });
@@ -1,29 +0,0 @@
1
- import { describe, expect, test, vi } from "vitest";
2
- import { effect, signal } from "#package";
3
-
4
- describe("effect", () => {
5
- test("disposed is correct", () => {
6
- const $signal = signal();
7
- const effectFn = vi.fn();
8
- const $effect = effect((t) => {
9
- $signal.watch(t);
10
- effectFn();
11
- });
12
-
13
- expect($effect.disposed).toBe(false);
14
- $effect.dispose();
15
- expect($effect.disposed).toBe(true);
16
- });
17
-
18
- test("throw when disposed twice", () => {
19
- const $signal = signal();
20
- const effectFn = vi.fn();
21
- const $effect = effect((t) => {
22
- $signal.watch(t);
23
- effectFn();
24
- });
25
-
26
- $effect.dispose();
27
- expect(() => $effect.dispose()).toThrow("Effect is disposed");
28
- });
29
- });