@ersbeth/picoflow 0.2.4 → 1.0.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 (248) hide show
  1. package/.cursor/plans/update-js-e795d61b.plan.md +567 -0
  2. package/.gitlab-ci.yml +24 -0
  3. package/.vscode/settings.json +3 -3
  4. package/CHANGELOG.md +51 -0
  5. package/IMPLEMENTATION_GUIDE.md +1578 -0
  6. package/README.md +9 -134
  7. package/biome.json +32 -32
  8. package/dist/picoflow.js +610 -436
  9. package/dist/types/advanced/array.d.ts +0 -6
  10. package/dist/types/advanced/array.d.ts.map +1 -1
  11. package/dist/types/advanced/index.d.ts +5 -5
  12. package/dist/types/advanced/index.d.ts.map +1 -1
  13. package/dist/types/advanced/map.d.ts +114 -23
  14. package/dist/types/advanced/map.d.ts.map +1 -1
  15. package/dist/types/advanced/resource.d.ts +51 -12
  16. package/dist/types/advanced/resource.d.ts.map +1 -1
  17. package/dist/types/advanced/resourceAsync.d.ts +28 -13
  18. package/dist/types/advanced/resourceAsync.d.ts.map +1 -1
  19. package/dist/types/advanced/stream.d.ts +74 -16
  20. package/dist/types/advanced/stream.d.ts.map +1 -1
  21. package/dist/types/advanced/streamAsync.d.ts +69 -15
  22. package/dist/types/advanced/streamAsync.d.ts.map +1 -1
  23. package/dist/types/basic/constant.d.ts +44 -16
  24. package/dist/types/basic/constant.d.ts.map +1 -1
  25. package/dist/types/basic/derivation.d.ts +73 -24
  26. package/dist/types/basic/derivation.d.ts.map +1 -1
  27. package/dist/types/basic/disposable.d.ts +65 -6
  28. package/dist/types/basic/disposable.d.ts.map +1 -1
  29. package/dist/types/basic/effect.d.ts +27 -16
  30. package/dist/types/basic/effect.d.ts.map +1 -1
  31. package/dist/types/basic/index.d.ts +7 -8
  32. package/dist/types/basic/index.d.ts.map +1 -1
  33. package/dist/types/basic/observable.d.ts +62 -13
  34. package/dist/types/basic/observable.d.ts.map +1 -1
  35. package/dist/types/basic/signal.d.ts +35 -6
  36. package/dist/types/basic/signal.d.ts.map +1 -1
  37. package/dist/types/basic/state.d.ts +25 -4
  38. package/dist/types/basic/state.d.ts.map +1 -1
  39. package/dist/types/basic/trackingContext.d.ts +33 -0
  40. package/dist/types/basic/trackingContext.d.ts.map +1 -0
  41. package/dist/types/creators.d.ts +271 -26
  42. package/dist/types/creators.d.ts.map +1 -1
  43. package/dist/types/index.d.ts +60 -7
  44. package/dist/types/index.d.ts.map +1 -1
  45. package/dist/types/solid/converters.d.ts +5 -5
  46. package/dist/types/solid/converters.d.ts.map +1 -1
  47. package/dist/types/solid/index.d.ts +2 -2
  48. package/dist/types/solid/index.d.ts.map +1 -1
  49. package/dist/types/solid/primitives.d.ts +96 -4
  50. package/dist/types/solid/primitives.d.ts.map +1 -1
  51. package/docs/.vitepress/config.mts +110 -0
  52. package/docs/api/classes/FlowArray.md +489 -0
  53. package/docs/api/classes/FlowConstant.md +350 -0
  54. package/docs/api/classes/FlowDerivation.md +334 -0
  55. package/docs/api/classes/FlowEffect.md +100 -0
  56. package/docs/api/classes/FlowMap.md +512 -0
  57. package/docs/api/classes/FlowObservable.md +306 -0
  58. package/docs/api/classes/FlowResource.md +380 -0
  59. package/docs/api/classes/FlowResourceAsync.md +362 -0
  60. package/docs/api/classes/FlowSignal.md +160 -0
  61. package/docs/api/classes/FlowState.md +368 -0
  62. package/docs/api/classes/FlowStream.md +367 -0
  63. package/docs/api/classes/FlowStreamAsync.md +364 -0
  64. package/docs/api/classes/SolidDerivation.md +75 -0
  65. package/docs/api/classes/SolidResource.md +91 -0
  66. package/docs/api/classes/SolidState.md +71 -0
  67. package/docs/api/classes/TrackingContext.md +33 -0
  68. package/docs/api/functions/array.md +58 -0
  69. package/docs/api/functions/constant.md +45 -0
  70. package/docs/api/functions/derivation.md +53 -0
  71. package/docs/api/functions/effect.md +49 -0
  72. package/docs/api/functions/from.md +220 -0
  73. package/docs/api/functions/isDisposable.md +49 -0
  74. package/docs/api/functions/map.md +57 -0
  75. package/docs/api/functions/resource.md +52 -0
  76. package/docs/api/functions/resourceAsync.md +50 -0
  77. package/docs/api/functions/signal.md +36 -0
  78. package/docs/api/functions/state.md +47 -0
  79. package/docs/api/functions/stream.md +53 -0
  80. package/docs/api/functions/streamAsync.md +50 -0
  81. package/docs/api/index.md +118 -0
  82. package/docs/api/interfaces/FlowDisposable.md +65 -0
  83. package/docs/api/interfaces/SolidObservable.md +19 -0
  84. package/docs/api/type-aliases/FlowArrayAction.md +49 -0
  85. package/docs/api/type-aliases/FlowStreamDisposer.md +15 -0
  86. package/docs/api/type-aliases/FlowStreamSetter.md +27 -0
  87. package/docs/api/type-aliases/FlowStreamUpdater.md +32 -0
  88. package/docs/api/type-aliases/NotPromise.md +18 -0
  89. package/docs/api/type-aliases/SolidGetter.md +17 -0
  90. package/docs/api/typedoc-sidebar.json +1 -0
  91. package/docs/examples/examples.md +2313 -0
  92. package/docs/examples/patterns.md +649 -0
  93. package/docs/guide/advanced/disposal.md +426 -0
  94. package/docs/guide/advanced/solidjs.md +221 -0
  95. package/docs/guide/advanced/upgrading.md +464 -0
  96. package/docs/guide/introduction/concepts.md +56 -0
  97. package/docs/guide/introduction/conventions.md +61 -0
  98. package/docs/guide/introduction/getting-started.md +134 -0
  99. package/docs/guide/introduction/lifecycle.md +371 -0
  100. package/docs/guide/primitives/array.md +400 -0
  101. package/docs/guide/primitives/constant.md +380 -0
  102. package/docs/guide/primitives/derivations.md +348 -0
  103. package/docs/guide/primitives/effects.md +458 -0
  104. package/docs/guide/primitives/map.md +387 -0
  105. package/docs/guide/primitives/overview.md +175 -0
  106. package/docs/guide/primitives/resources.md +858 -0
  107. package/docs/guide/primitives/signal.md +259 -0
  108. package/docs/guide/primitives/state.md +368 -0
  109. package/docs/guide/primitives/streams.md +931 -0
  110. package/docs/index.md +47 -0
  111. package/docs/public/logo.svg +1 -0
  112. package/package.json +57 -41
  113. package/src/advanced/array.ts +208 -210
  114. package/src/advanced/index.ts +7 -7
  115. package/src/advanced/map.ts +178 -68
  116. package/src/advanced/resource.ts +87 -43
  117. package/src/advanced/resourceAsync.ts +62 -42
  118. package/src/advanced/stream.ts +113 -50
  119. package/src/advanced/streamAsync.ts +120 -61
  120. package/src/basic/constant.ts +82 -49
  121. package/src/basic/derivation.ts +128 -84
  122. package/src/basic/disposable.ts +74 -15
  123. package/src/basic/effect.ts +85 -77
  124. package/src/basic/index.ts +7 -8
  125. package/src/basic/observable.ts +94 -36
  126. package/src/basic/signal.ts +133 -105
  127. package/src/basic/state.ts +46 -25
  128. package/src/basic/trackingContext.ts +45 -0
  129. package/src/creators.ts +297 -54
  130. package/src/index.ts +96 -43
  131. package/src/solid/converters.ts +186 -67
  132. package/src/solid/index.ts +8 -2
  133. package/src/solid/primitives.ts +167 -65
  134. package/test/array.test.ts +592 -612
  135. package/test/constant.test.ts +31 -33
  136. package/test/derivation.test.ts +531 -536
  137. package/test/effect.test.ts +21 -21
  138. package/test/map.test.ts +233 -137
  139. package/test/resource.test.ts +119 -121
  140. package/test/resourceAsync.test.ts +98 -100
  141. package/test/signal.test.ts +51 -55
  142. package/test/state.test.ts +186 -168
  143. package/test/stream.test.ts +189 -189
  144. package/test/streamAsync.test.ts +186 -186
  145. package/tsconfig.json +19 -18
  146. package/typedoc.json +37 -0
  147. package/vite.config.ts +23 -23
  148. package/vitest.config.ts +7 -7
  149. package/api/doc/index.md +0 -31
  150. package/api/doc/picoflow.array.md +0 -55
  151. package/api/doc/picoflow.constant.md +0 -55
  152. package/api/doc/picoflow.derivation.md +0 -55
  153. package/api/doc/picoflow.effect.md +0 -55
  154. package/api/doc/picoflow.flowarray._constructor_.md +0 -49
  155. package/api/doc/picoflow.flowarray._lastaction.md +0 -13
  156. package/api/doc/picoflow.flowarray.clear.md +0 -17
  157. package/api/doc/picoflow.flowarray.dispose.md +0 -55
  158. package/api/doc/picoflow.flowarray.get.md +0 -19
  159. package/api/doc/picoflow.flowarray.length.md +0 -13
  160. package/api/doc/picoflow.flowarray.md +0 -273
  161. package/api/doc/picoflow.flowarray.pop.md +0 -17
  162. package/api/doc/picoflow.flowarray.push.md +0 -53
  163. package/api/doc/picoflow.flowarray.set.md +0 -53
  164. package/api/doc/picoflow.flowarray.setitem.md +0 -69
  165. package/api/doc/picoflow.flowarray.shift.md +0 -17
  166. package/api/doc/picoflow.flowarray.splice.md +0 -85
  167. package/api/doc/picoflow.flowarray.unshift.md +0 -53
  168. package/api/doc/picoflow.flowarrayaction.md +0 -37
  169. package/api/doc/picoflow.flowconstant._constructor_.md +0 -49
  170. package/api/doc/picoflow.flowconstant.get.md +0 -25
  171. package/api/doc/picoflow.flowconstant.md +0 -88
  172. package/api/doc/picoflow.flowderivation._constructor_.md +0 -49
  173. package/api/doc/picoflow.flowderivation.get.md +0 -23
  174. package/api/doc/picoflow.flowderivation.md +0 -86
  175. package/api/doc/picoflow.flowdisposable.dispose.md +0 -55
  176. package/api/doc/picoflow.flowdisposable.md +0 -43
  177. package/api/doc/picoflow.floweffect._constructor_.md +0 -54
  178. package/api/doc/picoflow.floweffect.dispose.md +0 -21
  179. package/api/doc/picoflow.floweffect.disposed.md +0 -13
  180. package/api/doc/picoflow.floweffect.md +0 -131
  181. package/api/doc/picoflow.flowgetter.md +0 -15
  182. package/api/doc/picoflow.flowmap._lastdeleted.md +0 -21
  183. package/api/doc/picoflow.flowmap._lastset.md +0 -21
  184. package/api/doc/picoflow.flowmap.delete.md +0 -61
  185. package/api/doc/picoflow.flowmap.md +0 -133
  186. package/api/doc/picoflow.flowmap.setat.md +0 -77
  187. package/api/doc/picoflow.flowobservable.get.md +0 -19
  188. package/api/doc/picoflow.flowobservable.md +0 -68
  189. package/api/doc/picoflow.flowobservable.subscribe.md +0 -55
  190. package/api/doc/picoflow.flowresource._constructor_.md +0 -49
  191. package/api/doc/picoflow.flowresource.fetch.md +0 -27
  192. package/api/doc/picoflow.flowresource.get.md +0 -23
  193. package/api/doc/picoflow.flowresource.md +0 -100
  194. package/api/doc/picoflow.flowresourceasync._constructor_.md +0 -49
  195. package/api/doc/picoflow.flowresourceasync.fetch.md +0 -27
  196. package/api/doc/picoflow.flowresourceasync.get.md +0 -23
  197. package/api/doc/picoflow.flowresourceasync.md +0 -100
  198. package/api/doc/picoflow.flowsignal.dispose.md +0 -59
  199. package/api/doc/picoflow.flowsignal.disposed.md +0 -18
  200. package/api/doc/picoflow.flowsignal.md +0 -112
  201. package/api/doc/picoflow.flowsignal.trigger.md +0 -21
  202. package/api/doc/picoflow.flowstate.md +0 -52
  203. package/api/doc/picoflow.flowstate.set.md +0 -61
  204. package/api/doc/picoflow.flowstream._constructor_.md +0 -49
  205. package/api/doc/picoflow.flowstream.dispose.md +0 -21
  206. package/api/doc/picoflow.flowstream.get.md +0 -23
  207. package/api/doc/picoflow.flowstream.md +0 -100
  208. package/api/doc/picoflow.flowstreamasync._constructor_.md +0 -54
  209. package/api/doc/picoflow.flowstreamasync.dispose.md +0 -21
  210. package/api/doc/picoflow.flowstreamasync.get.md +0 -23
  211. package/api/doc/picoflow.flowstreamasync.md +0 -100
  212. package/api/doc/picoflow.flowstreamdisposer.md +0 -13
  213. package/api/doc/picoflow.flowstreamsetter.md +0 -13
  214. package/api/doc/picoflow.flowstreamupdater.md +0 -19
  215. package/api/doc/picoflow.flowwatcher.md +0 -15
  216. package/api/doc/picoflow.from.md +0 -55
  217. package/api/doc/picoflow.from_1.md +0 -55
  218. package/api/doc/picoflow.from_2.md +0 -55
  219. package/api/doc/picoflow.from_3.md +0 -55
  220. package/api/doc/picoflow.from_4.md +0 -55
  221. package/api/doc/picoflow.from_5.md +0 -55
  222. package/api/doc/picoflow.isdisposable.md +0 -55
  223. package/api/doc/picoflow.map.md +0 -59
  224. package/api/doc/picoflow.md +0 -544
  225. package/api/doc/picoflow.resource.md +0 -55
  226. package/api/doc/picoflow.resourceasync.md +0 -55
  227. package/api/doc/picoflow.signal.md +0 -19
  228. package/api/doc/picoflow.solidderivation._constructor_.md +0 -49
  229. package/api/doc/picoflow.solidderivation.get.md +0 -13
  230. package/api/doc/picoflow.solidderivation.md +0 -94
  231. package/api/doc/picoflow.solidgetter.md +0 -13
  232. package/api/doc/picoflow.solidobservable.get.md +0 -13
  233. package/api/doc/picoflow.solidobservable.md +0 -57
  234. package/api/doc/picoflow.solidresource._constructor_.md +0 -49
  235. package/api/doc/picoflow.solidresource.get.md +0 -13
  236. package/api/doc/picoflow.solidresource.latest.md +0 -13
  237. package/api/doc/picoflow.solidresource.md +0 -157
  238. package/api/doc/picoflow.solidresource.refetch.md +0 -13
  239. package/api/doc/picoflow.solidresource.state.md +0 -13
  240. package/api/doc/picoflow.solidstate._constructor_.md +0 -49
  241. package/api/doc/picoflow.solidstate.get.md +0 -13
  242. package/api/doc/picoflow.solidstate.md +0 -115
  243. package/api/doc/picoflow.solidstate.set.md +0 -13
  244. package/api/doc/picoflow.state.md +0 -55
  245. package/api/doc/picoflow.stream.md +0 -55
  246. package/api/doc/picoflow.streamasync.md +0 -55
  247. package/api/picoflow.public.api.md +0 -244
  248. package/api-extractor.json +0 -61
@@ -1,620 +1,600 @@
1
1
  import { describe, expect, test, vi } from "vitest";
2
- import { type FlowState, array, effect, state } from "#package";
2
+ import { array, effect, type FlowState, state } from "#package";
3
3
 
4
4
  describe("array", () => {
5
- test("is initialized", () => {
6
- const $array = array([state(1), state(2), state(3)]);
5
+ test("is initialized", () => {
6
+ const $array = array([state(1), state(2), state(3)]);
7
7
 
8
- expect($array.get().map((state) => state.get())).toEqual([1, 2, 3]);
9
- });
10
-
11
- test("is updated (set)", () => {
12
- const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
13
- expect($array.get().map((state) => state.get())).toEqual([0, 1, 2]);
14
-
15
- $array.set([state(1), state(2), state(3)]);
16
- expect($array.get().map((state) => state.get())).toEqual([1, 2, 3]);
17
- });
18
-
19
- test("is updated (setItem)", () => {
20
- const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
21
- expect($array.get().map((state) => state.get())).toEqual([0, 1, 2]);
22
-
23
- $array.setItem(0, state(1));
24
- expect($array.get().map((state) => state.get())).toEqual([1, 1, 2]);
25
-
26
- $array.setItem(1, state(2));
27
- expect($array.get().map((state) => state.get())).toEqual([1, 2, 2]);
28
-
29
- $array.setItem(2, state(3));
30
- expect($array.get().map((state) => state.get())).toEqual([1, 2, 3]);
31
- });
32
-
33
- test("is updated (push/pop)", () => {
34
- const $array = array<FlowState<number>>();
35
- expect($array.get()).toEqual([]);
36
-
37
- $array.push(state(0));
38
- expect($array.get().map((state) => state.get())).toEqual([0]);
39
-
40
- $array.push(state(1));
41
- expect($array.get().map((state) => state.get())).toEqual([0, 1]);
42
-
43
- $array.push(state(2));
44
- expect($array.get().map((state) => state.get())).toEqual([0, 1, 2]);
45
-
46
- $array.pop();
47
- expect($array.get().map((state) => state.get())).toEqual([0, 1]);
48
-
49
- $array.pop();
50
- expect($array.get().map((state) => state.get())).toEqual([0]);
51
-
52
- $array.pop();
53
- expect($array.get().map((state) => state.get())).toEqual([]);
54
- });
55
-
56
- test("is updated (unshift/shift)", () => {
57
- const $array = array<FlowState<number>>();
58
- expect($array.get()).toEqual([]);
59
-
60
- $array.unshift(state(0));
61
- expect($array.get().map((state) => state.get())).toEqual([0]);
62
-
63
- $array.unshift(state(1));
64
- expect($array.get().map((state) => state.get())).toEqual([1, 0]);
65
-
66
- $array.unshift(state(2));
67
- expect($array.get().map((state) => state.get())).toEqual([2, 1, 0]);
68
-
69
- $array.shift();
70
- expect($array.get().map((state) => state.get())).toEqual([1, 0]);
71
-
72
- $array.shift();
73
- expect($array.get().map((state) => state.get())).toEqual([0]);
74
-
75
- $array.shift();
76
- expect($array.get().map((state) => state.get())).toEqual([]);
77
- });
78
-
79
- test("is updated (splice)", () => {
80
- const $array = array<FlowState<number>>([
81
- state(0),
82
- state(1),
83
- state(2),
84
- state(3),
85
- state(4),
86
- ]);
87
- expect($array.get().map((state) => state.get())).toEqual([
88
- 0, 1, 2, 3, 4,
89
- ]);
90
-
91
- $array.splice(1, 2);
92
- expect($array.get().map((state) => state.get())).toEqual([0, 3, 4]);
93
-
94
- $array.splice(1, 0, state(1), state(2));
95
- expect($array.get().map((state) => state.get())).toEqual([
96
- 0, 1, 2, 3, 4,
97
- ]);
98
- });
99
-
100
- test("is updated (clear)", () => {
101
- const $array = array<FlowState<number>>([
102
- state(0),
103
- state(1),
104
- state(2),
105
- state(3),
106
- state(4),
107
- ]);
108
- expect($array.get().map((state) => state.get())).toEqual([
109
- 0, 1, 2, 3, 4,
110
- ]);
111
-
112
- $array.clear();
113
- expect($array.get().map((state) => state.get())).toEqual([]);
114
- });
115
-
116
- test("is item updated", () => {
117
- const $array = array<FlowState<number>>([
118
- state(0),
119
- state(1),
120
- state(2),
121
- state(3),
122
- state(4),
123
- ]);
124
- expect($array.get().map((state) => state.get())).toEqual([
125
- 0, 1, 2, 3, 4,
126
- ]);
127
-
128
- $array.get()[0].set(1);
129
- expect($array.get().map((state) => state.get())).toEqual([
130
- 1, 1, 2, 3, 4,
131
- ]);
132
-
133
- $array.get()[1].set(2);
134
- expect($array.get().map((state) => state.get())).toEqual([
135
- 1, 2, 2, 3, 4,
136
- ]);
137
-
138
- $array.get()[2].set(3);
139
- expect($array.get().map((state) => state.get())).toEqual([
140
- 1, 2, 3, 3, 4,
141
- ]);
142
-
143
- $array.get()[3].set(4);
144
- expect($array.get().map((state) => state.get())).toEqual([
145
- 1, 2, 3, 4, 4,
146
- ]);
147
-
148
- $array.get()[4].set(5);
149
- expect($array.get().map((state) => state.get())).toEqual([
150
- 1, 2, 3, 4, 5,
151
- ]);
152
- });
153
-
154
- test("throws when disposed (get)", () => {
155
- const $array = array([state(1), state(2), state(3)]);
156
- $array.dispose();
157
- expect(() => $array.get()).toThrowError(
158
- "[PicoFlow] Primitive is disposed",
159
- );
160
- });
161
-
162
- test("throws when disposed (set)", () => {
163
- const $array = array([state(1), state(2), state(3)]);
164
- $array.dispose();
165
- expect(() => $array.set([state(1)])).toThrowError(
166
- "[PicoFlow] Primitive is disposed",
167
- );
168
- });
169
-
170
- test("throws when disposed (setItem)", () => {
171
- const $array = array([state(1), state(2), state(3)]);
172
- $array.dispose();
173
- expect(() => $array.setItem(0, state(3))).toThrowError(
174
- "[PicoFlow] Primitive is disposed",
175
- );
176
- });
177
-
178
- test("throws when disposed (push)", () => {
179
- const $array = array([state(1), state(2), state(3)]);
180
- $array.dispose();
181
- expect(() => $array.push(state(3))).toThrowError(
182
- "[PicoFlow] Primitive is disposed",
183
- );
184
- });
185
-
186
- test("throws when disposed (pop)", () => {
187
- const $array = array([state(1), state(2), state(3)]);
188
- $array.dispose();
189
- expect(() => $array.pop()).toThrowError(
190
- "[PicoFlow] Primitive is disposed",
191
- );
192
- });
193
-
194
- test("throws when disposed (unshift)", () => {
195
- const $array = array([state(1), state(2), state(3)]);
196
- $array.dispose();
197
- expect(() => $array.unshift(state(3))).toThrowError(
198
- "[PicoFlow] Primitive is disposed",
199
- );
200
- });
201
-
202
- test("throws when disposed (shift)", () => {
203
- const $array = array([state(1), state(2), state(3)]);
204
- $array.dispose();
205
- expect(() => $array.shift()).toThrowError(
206
- "[PicoFlow] Primitive is disposed",
207
- );
208
- });
209
-
210
- test("throws when disposed (splice)", () => {
211
- const $array = array<FlowState<number>>([
212
- state(0),
213
- state(1),
214
- state(2),
215
- state(3),
216
- state(4),
217
- ]);
218
- $array.dispose();
219
- expect(() => $array.splice(1, 2)).toThrowError(
220
- "[PicoFlow] Primitive is disposed",
221
- );
222
- });
8
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 2, 3]);
9
+ });
10
+
11
+ test("is updated (set)", () => {
12
+ const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
13
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1, 2]);
14
+
15
+ $array.set([state(1), state(2), state(3)]);
16
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 2, 3]);
17
+ });
18
+
19
+ test("is updated (setItem)", () => {
20
+ const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
21
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1, 2]);
22
+
23
+ $array.setItem(0, state(1));
24
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 1, 2]);
25
+
26
+ $array.setItem(1, state(2));
27
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 2, 2]);
28
+
29
+ $array.setItem(2, state(3));
30
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 2, 3]);
31
+ });
32
+
33
+ test("is updated (push/pop)", () => {
34
+ const $array = array<FlowState<number>>();
35
+ expect($array.pick()).toEqual([]);
36
+
37
+ $array.push(state(0));
38
+ expect($array.pick().map((state) => state.pick())).toEqual([0]);
39
+
40
+ $array.push(state(1));
41
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1]);
42
+
43
+ $array.push(state(2));
44
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1, 2]);
45
+
46
+ $array.pop();
47
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1]);
48
+
49
+ $array.pop();
50
+ expect($array.pick().map((state) => state.pick())).toEqual([0]);
51
+
52
+ $array.pop();
53
+ expect($array.pick().map((state) => state.pick())).toEqual([]);
54
+ });
55
+
56
+ test("is updated (unshift/shift)", () => {
57
+ const $array = array<FlowState<number>>();
58
+ expect($array.pick()).toEqual([]);
59
+
60
+ $array.unshift(state(0));
61
+ expect($array.pick().map((state) => state.pick())).toEqual([0]);
62
+
63
+ $array.unshift(state(1));
64
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 0]);
65
+
66
+ $array.unshift(state(2));
67
+ expect($array.pick().map((state) => state.pick())).toEqual([2, 1, 0]);
68
+
69
+ $array.shift();
70
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 0]);
71
+
72
+ $array.shift();
73
+ expect($array.pick().map((state) => state.pick())).toEqual([0]);
74
+
75
+ $array.shift();
76
+ expect($array.pick().map((state) => state.pick())).toEqual([]);
77
+ });
78
+
79
+ test("is updated (splice)", () => {
80
+ const $array = array<FlowState<number>>([
81
+ state(0),
82
+ state(1),
83
+ state(2),
84
+ state(3),
85
+ state(4),
86
+ ]);
87
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1, 2, 3, 4]);
88
+
89
+ $array.splice(1, 2);
90
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 3, 4]);
91
+
92
+ $array.splice(1, 0, state(1), state(2));
93
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1, 2, 3, 4]);
94
+ });
95
+
96
+ test("is updated (clear)", () => {
97
+ const $array = array<FlowState<number>>([
98
+ state(0),
99
+ state(1),
100
+ state(2),
101
+ state(3),
102
+ state(4),
103
+ ]);
104
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1, 2, 3, 4]);
105
+
106
+ $array.clear();
107
+ expect($array.pick().map((state) => state.pick())).toEqual([]);
108
+ });
109
+
110
+ test("is item updated", () => {
111
+ const $array = array<FlowState<number>>([
112
+ state(0),
113
+ state(1),
114
+ state(2),
115
+ state(3),
116
+ state(4),
117
+ ]);
118
+ expect($array.pick().map((state) => state.pick())).toEqual([0, 1, 2, 3, 4]);
119
+
120
+ $array.pick()[0].set(1);
121
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 1, 2, 3, 4]);
122
+
123
+ $array.pick()[1].set(2);
124
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 2, 2, 3, 4]);
125
+
126
+ $array.pick()[2].set(3);
127
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 2, 3, 3, 4]);
128
+
129
+ $array.pick()[3].set(4);
130
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 2, 3, 4, 4]);
131
+
132
+ $array.pick()[4].set(5);
133
+ expect($array.pick().map((state) => state.pick())).toEqual([1, 2, 3, 4, 5]);
134
+ });
135
+
136
+ test("throws when disposed (get)", () => {
137
+ const $array = array([state(1), state(2), state(3)]);
138
+ $array.dispose();
139
+ expect(() => $array.pick()).toThrowError(
140
+ "[PicoFlow] Primitive is disposed",
141
+ );
142
+ });
143
+
144
+ test("throws when disposed (set)", () => {
145
+ const $array = array([state(1), state(2), state(3)]);
146
+ $array.dispose();
147
+ expect(() => $array.set([state(1)])).toThrowError(
148
+ "[PicoFlow] Primitive is disposed",
149
+ );
150
+ });
151
+
152
+ test("throws when disposed (setItem)", () => {
153
+ const $array = array([state(1), state(2), state(3)]);
154
+ $array.dispose();
155
+ expect(() => $array.setItem(0, state(3))).toThrowError(
156
+ "[PicoFlow] Primitive is disposed",
157
+ );
158
+ });
159
+
160
+ test("throws when disposed (push)", () => {
161
+ const $array = array([state(1), state(2), state(3)]);
162
+ $array.dispose();
163
+ expect(() => $array.push(state(3))).toThrowError(
164
+ "[PicoFlow] Primitive is disposed",
165
+ );
166
+ });
167
+
168
+ test("throws when disposed (pop)", () => {
169
+ const $array = array([state(1), state(2), state(3)]);
170
+ $array.dispose();
171
+ expect(() => $array.pop()).toThrowError("[PicoFlow] Primitive is disposed");
172
+ });
173
+
174
+ test("throws when disposed (unshift)", () => {
175
+ const $array = array([state(1), state(2), state(3)]);
176
+ $array.dispose();
177
+ expect(() => $array.unshift(state(3))).toThrowError(
178
+ "[PicoFlow] Primitive is disposed",
179
+ );
180
+ });
181
+
182
+ test("throws when disposed (shift)", () => {
183
+ const $array = array([state(1), state(2), state(3)]);
184
+ $array.dispose();
185
+ expect(() => $array.shift()).toThrowError(
186
+ "[PicoFlow] Primitive is disposed",
187
+ );
188
+ });
189
+
190
+ test("throws when disposed (splice)", () => {
191
+ const $array = array<FlowState<number>>([
192
+ state(0),
193
+ state(1),
194
+ state(2),
195
+ state(3),
196
+ state(4),
197
+ ]);
198
+ $array.dispose();
199
+ expect(() => $array.splice(1, 2)).toThrowError(
200
+ "[PicoFlow] Primitive is disposed",
201
+ );
202
+ });
223
203
  });
224
204
 
225
205
  describe("effect", () => {
226
- test("called when initialized", () => {
227
- const $array = array([state(1), state(2), state(3)]);
228
- const effectFn = vi.fn();
229
- effect((get) => effectFn(get($array).map((state) => get(state))));
230
-
231
- expect(effectFn).toHaveBeenCalledTimes(1);
232
- expect(effectFn).toHaveBeenLastCalledWith([1, 2, 3]);
233
- });
234
-
235
- test("called when updated (set)", () => {
236
- const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
237
- const effectFn = vi.fn();
238
- effect((get) => effectFn(get($array).map((state) => get(state))));
239
-
240
- expect(effectFn).toHaveBeenCalledTimes(1);
241
- expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2]);
242
-
243
- $array.set([state(1), state(2), state(3)]);
244
- expect(effectFn).toHaveBeenLastCalledWith([1, 2, 3]);
245
- });
246
-
247
- test("called when updated (push/pop)", () => {
248
- const $array = array<FlowState<number>>();
249
- const effectFn = vi.fn();
250
- effect((get) => effectFn(get($array).map((state) => get(state))));
251
-
252
- expect(effectFn).toHaveBeenCalledTimes(1);
253
- expect(effectFn).toHaveBeenLastCalledWith([]);
254
-
255
- $array.push(state(0));
256
- expect(effectFn).toHaveBeenCalledTimes(2);
257
- expect(effectFn).toHaveBeenLastCalledWith([0]);
258
-
259
- $array.push(state(1));
260
- expect(effectFn).toHaveBeenCalledTimes(3);
261
- expect(effectFn).toHaveBeenLastCalledWith([0, 1]);
262
-
263
- $array.push(state(2));
264
- expect(effectFn).toHaveBeenCalledTimes(4);
265
- expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2]);
266
-
267
- $array.pop();
268
- expect(effectFn).toHaveBeenCalledTimes(5);
269
- expect(effectFn).toHaveBeenLastCalledWith([0, 1]);
270
-
271
- $array.pop();
272
- expect(effectFn).toHaveBeenCalledTimes(6);
273
- expect(effectFn).toHaveBeenLastCalledWith([0]);
274
-
275
- $array.pop();
276
- expect(effectFn).toHaveBeenCalledTimes(7);
277
- expect(effectFn).toHaveBeenLastCalledWith([]);
278
- });
279
-
280
- test("called when updated (unshift/shift)", () => {
281
- const $array = array<FlowState<number>>();
282
- const effectFn = vi.fn();
283
- effect((get) => effectFn(get($array).map((state) => get(state))));
284
-
285
- expect(effectFn).toHaveBeenCalledTimes(1);
286
- expect(effectFn).toHaveBeenLastCalledWith([]);
287
-
288
- $array.unshift(state(0));
289
- expect(effectFn).toHaveBeenCalledTimes(2);
290
- expect(effectFn).toHaveBeenLastCalledWith([0]);
291
-
292
- $array.unshift(state(1));
293
- expect(effectFn).toHaveBeenCalledTimes(3);
294
- expect(effectFn).toHaveBeenLastCalledWith([1, 0]);
295
-
296
- $array.unshift(state(2));
297
- expect(effectFn).toHaveBeenCalledTimes(4);
298
- expect(effectFn).toHaveBeenLastCalledWith([2, 1, 0]);
299
-
300
- $array.shift();
301
- expect(effectFn).toHaveBeenCalledTimes(5);
302
- expect(effectFn).toHaveBeenLastCalledWith([1, 0]);
303
-
304
- $array.shift();
305
- expect(effectFn).toHaveBeenCalledTimes(6);
306
- expect(effectFn).toHaveBeenLastCalledWith([0]);
307
-
308
- $array.shift();
309
- expect(effectFn).toHaveBeenCalledTimes(7);
310
- expect(effectFn).toHaveBeenLastCalledWith([]);
311
- });
312
-
313
- test("called when updated (splice)", () => {
314
- const $array = array<FlowState<number>>([
315
- state(0),
316
- state(1),
317
- state(2),
318
- state(3),
319
- state(4),
320
- ]);
321
- const effectFn = vi.fn();
322
- effect((get) => effectFn(get($array).map((state) => get(state))));
323
-
324
- expect(effectFn).toHaveBeenCalledTimes(1);
325
- expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2, 3, 4]);
326
-
327
- $array.splice(1, 2);
328
- expect(effectFn).toHaveBeenCalledTimes(2);
329
- expect(effectFn).toHaveBeenLastCalledWith([0, 3, 4]);
330
-
331
- $array.splice(1, 0, state(1), state(2));
332
- expect(effectFn).toHaveBeenCalledTimes(3);
333
- expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2, 3, 4]);
334
- });
335
-
336
- test("called when updated (clear)", () => {
337
- const $array = array<FlowState<number>>([
338
- state(0),
339
- state(1),
340
- state(2),
341
- state(3),
342
- state(4),
343
- ]);
344
- const effectFn = vi.fn();
345
- effect((get) => effectFn(get($array).map((state) => get(state))));
346
-
347
- expect(effectFn).toHaveBeenCalledTimes(1);
348
- expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2, 3, 4]);
349
-
350
- $array.clear();
351
- expect(effectFn).toHaveBeenCalledTimes(2);
352
- expect(effectFn).toHaveBeenLastCalledWith([]);
353
- });
354
-
355
- test("called when item updated", () => {
356
- const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
357
- const effectFn = vi.fn();
358
- const effect0Fn = vi.fn();
359
- const effect1Fn = vi.fn();
360
- const effect2Fn = vi.fn();
361
-
362
- effect((get) => effectFn(get($array).map((state) => get(state))));
363
- effect((get) => effect0Fn(get(get($array)[0])));
364
- effect((get) => effect1Fn(get(get($array)[1])));
365
- effect((get) => effect2Fn(get(get($array)[2])));
366
-
367
- expect(effectFn).toHaveBeenCalledTimes(1);
368
- expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2]);
369
- expect(effect0Fn).toHaveBeenCalledTimes(1);
370
- expect(effect0Fn).toHaveBeenLastCalledWith(0);
371
- expect(effect1Fn).toHaveBeenCalledTimes(1);
372
- expect(effect1Fn).toHaveBeenLastCalledWith(1);
373
- expect(effect2Fn).toHaveBeenCalledTimes(1);
374
- expect(effect2Fn).toHaveBeenLastCalledWith(2);
375
-
376
- $array.get()[0].set(1);
377
- expect(effectFn).toHaveBeenCalledTimes(2);
378
- expect(effectFn).toHaveBeenLastCalledWith([1, 1, 2]);
379
- expect(effect0Fn).toHaveBeenCalledTimes(2);
380
- expect(effect0Fn).toHaveBeenLastCalledWith(1);
381
- expect(effect1Fn).toHaveBeenCalledTimes(1);
382
- expect(effect1Fn).toHaveBeenLastCalledWith(1);
383
- expect(effect2Fn).toHaveBeenCalledTimes(1);
384
- expect(effect2Fn).toHaveBeenLastCalledWith(2);
385
-
386
- $array.get()[1].set(2);
387
- expect(effectFn).toHaveBeenCalledTimes(3);
388
- expect(effectFn).toHaveBeenLastCalledWith([1, 2, 2]);
389
- expect(effect0Fn).toHaveBeenCalledTimes(2);
390
- expect(effect0Fn).toHaveBeenLastCalledWith(1);
391
- expect(effect1Fn).toHaveBeenCalledTimes(2);
392
- expect(effect1Fn).toHaveBeenLastCalledWith(2);
393
- expect(effect2Fn).toHaveBeenCalledTimes(1);
394
- expect(effect2Fn).toHaveBeenLastCalledWith(2);
395
-
396
- $array.get()[2].set(3);
397
- expect(effectFn).toHaveBeenCalledTimes(4);
398
- expect(effectFn).toHaveBeenLastCalledWith([1, 2, 3]);
399
- expect(effect0Fn).toHaveBeenCalledTimes(2);
400
- expect(effect0Fn).toHaveBeenLastCalledWith(1);
401
- expect(effect1Fn).toHaveBeenCalledTimes(2);
402
- expect(effect1Fn).toHaveBeenLastCalledWith(2);
403
- expect(effect2Fn).toHaveBeenCalledTimes(2);
404
- expect(effect2Fn).toHaveBeenLastCalledWith(3);
405
- });
406
-
407
- test("called when item replaced", () => {
408
- const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
409
- const effectFn = vi.fn();
410
- const effect0Fn = vi.fn();
411
-
412
- effect((get) => effectFn(get($array).map((state) => get(state))));
413
- effect((get) => effect0Fn(get(get($array)[0])));
414
-
415
- expect(effectFn).toHaveBeenCalledTimes(1);
416
- expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2]);
417
- expect(effect0Fn).toHaveBeenCalledTimes(1);
418
- expect(effect0Fn).toHaveBeenLastCalledWith(0);
419
-
420
- $array.setItem(0, state(3));
421
- expect(effectFn).toHaveBeenCalledTimes(2);
422
- expect(effectFn).toHaveBeenLastCalledWith([3, 1, 2]);
423
- expect(effect0Fn).toHaveBeenCalledTimes(2);
424
- expect(effect0Fn).toHaveBeenLastCalledWith(3);
425
-
426
- $array.shift();
427
- expect(effectFn).toHaveBeenCalledTimes(3);
428
- expect(effectFn).toHaveBeenLastCalledWith([1, 2]);
429
- expect(effect0Fn).toHaveBeenCalledTimes(3);
430
- expect(effect0Fn).toHaveBeenLastCalledWith(1);
431
-
432
- $array.unshift(state(4));
433
- expect(effectFn).toHaveBeenCalledTimes(4);
434
- expect(effectFn).toHaveBeenLastCalledWith([4, 1, 2]);
435
- expect(effect0Fn).toHaveBeenCalledTimes(4);
436
- expect(effect0Fn).toHaveBeenLastCalledWith(4);
437
- });
438
-
439
- describe("lastAction", () => {
440
- test("called when initialized", () => {
441
- const $array = array([1, 2, 3]);
442
- const effectFn = vi.fn();
443
- effect((get) => effectFn(get($array.$lastAction)));
444
-
445
- expect(effectFn).toHaveBeenCalledTimes(1);
446
- expect(effectFn).toHaveBeenLastCalledWith({
447
- type: "set",
448
- items: [1, 2, 3],
449
- });
450
- });
451
-
452
- test("called when updated (set)", () => {
453
- const $array = array([0, 1, 2]);
454
- const effectFn = vi.fn();
455
- effect((get) => effectFn(get($array.$lastAction)));
456
-
457
- expect(effectFn).toHaveBeenCalledTimes(1);
458
- expect(effectFn).toHaveBeenLastCalledWith({
459
- type: "set",
460
- items: [0, 1, 2],
461
- });
462
- $array.set([1, 2, 3]);
463
- expect(effectFn).toHaveBeenCalledTimes(2);
464
- expect(effectFn).toHaveBeenLastCalledWith({
465
- type: "set",
466
- items: [1, 2, 3],
467
- });
468
- });
469
-
470
- test("called when updated (push/pop)", () => {
471
- const $array = array<number>();
472
- const effectFn = vi.fn();
473
- effect((get) => effectFn(get($array.$lastAction)));
474
-
475
- expect(effectFn).toHaveBeenCalledTimes(1);
476
- expect(effectFn).toHaveBeenLastCalledWith({
477
- type: "set",
478
- items: [],
479
- });
480
-
481
- $array.push(0);
482
- expect(effectFn).toHaveBeenCalledTimes(2);
483
- expect(effectFn).toHaveBeenLastCalledWith({
484
- type: "push",
485
- item: 0,
486
- });
487
-
488
- $array.push(1);
489
- expect(effectFn).toHaveBeenCalledTimes(3);
490
- expect(effectFn).toHaveBeenLastCalledWith({
491
- type: "push",
492
- item: 1,
493
- });
494
-
495
- $array.push(2);
496
- expect(effectFn).toHaveBeenCalledTimes(4);
497
- expect(effectFn).toHaveBeenLastCalledWith({
498
- type: "push",
499
- item: 2,
500
- });
501
-
502
- $array.pop();
503
- expect(effectFn).toHaveBeenCalledTimes(5);
504
- expect(effectFn).toHaveBeenLastCalledWith({
505
- type: "pop",
506
- });
507
-
508
- $array.pop();
509
- expect(effectFn).toHaveBeenCalledTimes(6);
510
- expect(effectFn).toHaveBeenLastCalledWith({
511
- type: "pop",
512
- });
513
-
514
- $array.pop();
515
- expect(effectFn).toHaveBeenCalledTimes(7);
516
- expect(effectFn).toHaveBeenLastCalledWith({
517
- type: "pop",
518
- });
519
- });
520
-
521
- test("called when updated (unshift/shift)", () => {
522
- const $array = array<number>();
523
- const effectFn = vi.fn();
524
- effect((get) => effectFn(get($array.$lastAction)));
525
-
526
- expect(effectFn).toHaveBeenCalledTimes(1);
527
- expect(effectFn).toHaveBeenLastCalledWith({
528
- type: "set",
529
- items: [],
530
- });
531
-
532
- $array.unshift(0);
533
- expect(effectFn).toHaveBeenCalledTimes(2);
534
- expect(effectFn).toHaveBeenLastCalledWith({
535
- type: "unshift",
536
- item: 0,
537
- });
538
-
539
- $array.unshift(1);
540
- expect(effectFn).toHaveBeenCalledTimes(3);
541
- expect(effectFn).toHaveBeenLastCalledWith({
542
- type: "unshift",
543
- item: 1,
544
- });
545
-
546
- $array.unshift(2);
547
- expect(effectFn).toHaveBeenCalledTimes(4);
548
- expect(effectFn).toHaveBeenLastCalledWith({
549
- type: "unshift",
550
- item: 2,
551
- });
552
-
553
- $array.shift();
554
- expect(effectFn).toHaveBeenCalledTimes(5);
555
- expect(effectFn).toHaveBeenLastCalledWith({
556
- type: "shift",
557
- });
558
-
559
- $array.shift();
560
- expect(effectFn).toHaveBeenCalledTimes(6);
561
- expect(effectFn).toHaveBeenLastCalledWith({
562
- type: "shift",
563
- });
564
-
565
- $array.shift();
566
- expect(effectFn).toHaveBeenCalledTimes(7);
567
- expect(effectFn).toHaveBeenLastCalledWith({
568
- type: "shift",
569
- });
570
- });
571
-
572
- test("called when updated (splice)", () => {
573
- const $array = array<number>([0, 1, 2, 3, 4]);
574
- const effectFn = vi.fn();
575
- effect((get) => effectFn(get($array.$lastAction)));
576
-
577
- expect(effectFn).toHaveBeenCalledTimes(1);
578
- expect(effectFn).toHaveBeenLastCalledWith({
579
- type: "set",
580
- items: [0, 1, 2, 3, 4],
581
- });
582
-
583
- $array.splice(1, 2);
584
- expect(effectFn).toHaveBeenCalledTimes(2);
585
- expect(effectFn).toHaveBeenLastCalledWith({
586
- type: "splice",
587
- start: 1,
588
- deleteCount: 2,
589
- items: [],
590
- });
591
-
592
- $array.splice(1, 0, 1, 2);
593
- expect(effectFn).toHaveBeenCalledTimes(3);
594
- expect(effectFn).toHaveBeenLastCalledWith({
595
- type: "splice",
596
- start: 1,
597
- deleteCount: 0,
598
- items: [1, 2],
599
- });
600
- });
601
-
602
- test("called when updated (clear)", () => {
603
- const $array = array<number>([0, 1, 2, 3, 4]);
604
- const effectFn = vi.fn();
605
- effect((get) => effectFn(get($array.$lastAction)));
606
-
607
- expect(effectFn).toHaveBeenCalledTimes(1);
608
- expect(effectFn).toHaveBeenLastCalledWith({
609
- type: "set",
610
- items: [0, 1, 2, 3, 4],
611
- });
612
-
613
- $array.clear();
614
- expect(effectFn).toHaveBeenCalledTimes(2);
615
- expect(effectFn).toHaveBeenLastCalledWith({
616
- type: "clear",
617
- });
618
- });
619
- });
206
+ test("called when initialized", () => {
207
+ const $array = array([state(1), state(2), state(3)]);
208
+ const effectFn = vi.fn();
209
+ effect((t) => effectFn($array.get(t).map((state) => state.get(t))));
210
+
211
+ expect(effectFn).toHaveBeenCalledTimes(1);
212
+ expect(effectFn).toHaveBeenLastCalledWith([1, 2, 3]);
213
+ });
214
+
215
+ test("called when updated (set)", () => {
216
+ const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
217
+ const effectFn = vi.fn();
218
+ effect((t) => effectFn($array.get(t).map((state) => state.get(t))));
219
+
220
+ expect(effectFn).toHaveBeenCalledTimes(1);
221
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2]);
222
+
223
+ $array.set([state(1), state(2), state(3)]);
224
+ expect(effectFn).toHaveBeenLastCalledWith([1, 2, 3]);
225
+ });
226
+
227
+ test("called when updated (push/pop)", () => {
228
+ const $array = array<FlowState<number>>();
229
+ const effectFn = vi.fn();
230
+ effect((t) => effectFn($array.get(t).map((state) => state.get(t))));
231
+
232
+ expect(effectFn).toHaveBeenCalledTimes(1);
233
+ expect(effectFn).toHaveBeenLastCalledWith([]);
234
+
235
+ $array.push(state(0));
236
+ expect(effectFn).toHaveBeenCalledTimes(2);
237
+ expect(effectFn).toHaveBeenLastCalledWith([0]);
238
+
239
+ $array.push(state(1));
240
+ expect(effectFn).toHaveBeenCalledTimes(3);
241
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1]);
242
+
243
+ $array.push(state(2));
244
+ expect(effectFn).toHaveBeenCalledTimes(4);
245
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2]);
246
+
247
+ $array.pop();
248
+ expect(effectFn).toHaveBeenCalledTimes(5);
249
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1]);
250
+
251
+ $array.pop();
252
+ expect(effectFn).toHaveBeenCalledTimes(6);
253
+ expect(effectFn).toHaveBeenLastCalledWith([0]);
254
+
255
+ $array.pop();
256
+ expect(effectFn).toHaveBeenCalledTimes(7);
257
+ expect(effectFn).toHaveBeenLastCalledWith([]);
258
+ });
259
+
260
+ test("called when updated (unshift/shift)", () => {
261
+ const $array = array<FlowState<number>>();
262
+ const effectFn = vi.fn();
263
+ effect((t) => effectFn($array.get(t).map((state) => state.get(t))));
264
+
265
+ expect(effectFn).toHaveBeenCalledTimes(1);
266
+ expect(effectFn).toHaveBeenLastCalledWith([]);
267
+
268
+ $array.unshift(state(0));
269
+ expect(effectFn).toHaveBeenCalledTimes(2);
270
+ expect(effectFn).toHaveBeenLastCalledWith([0]);
271
+
272
+ $array.unshift(state(1));
273
+ expect(effectFn).toHaveBeenCalledTimes(3);
274
+ expect(effectFn).toHaveBeenLastCalledWith([1, 0]);
275
+
276
+ $array.unshift(state(2));
277
+ expect(effectFn).toHaveBeenCalledTimes(4);
278
+ expect(effectFn).toHaveBeenLastCalledWith([2, 1, 0]);
279
+
280
+ $array.shift();
281
+ expect(effectFn).toHaveBeenCalledTimes(5);
282
+ expect(effectFn).toHaveBeenLastCalledWith([1, 0]);
283
+
284
+ $array.shift();
285
+ expect(effectFn).toHaveBeenCalledTimes(6);
286
+ expect(effectFn).toHaveBeenLastCalledWith([0]);
287
+
288
+ $array.shift();
289
+ expect(effectFn).toHaveBeenCalledTimes(7);
290
+ expect(effectFn).toHaveBeenLastCalledWith([]);
291
+ });
292
+
293
+ test("called when updated (splice)", () => {
294
+ const $array = array<FlowState<number>>([
295
+ state(0),
296
+ state(1),
297
+ state(2),
298
+ state(3),
299
+ state(4),
300
+ ]);
301
+ const effectFn = vi.fn();
302
+ effect((t) => effectFn($array.get(t).map((state) => state.get(t))));
303
+
304
+ expect(effectFn).toHaveBeenCalledTimes(1);
305
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2, 3, 4]);
306
+
307
+ $array.splice(1, 2);
308
+ expect(effectFn).toHaveBeenCalledTimes(2);
309
+ expect(effectFn).toHaveBeenLastCalledWith([0, 3, 4]);
310
+
311
+ $array.splice(1, 0, state(1), state(2));
312
+ expect(effectFn).toHaveBeenCalledTimes(3);
313
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2, 3, 4]);
314
+ });
315
+
316
+ test("called when updated (clear)", () => {
317
+ const $array = array<FlowState<number>>([
318
+ state(0),
319
+ state(1),
320
+ state(2),
321
+ state(3),
322
+ state(4),
323
+ ]);
324
+ const effectFn = vi.fn();
325
+ effect((t) => effectFn($array.get(t).map((state) => state.get(t))));
326
+
327
+ expect(effectFn).toHaveBeenCalledTimes(1);
328
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2, 3, 4]);
329
+
330
+ $array.clear();
331
+ expect(effectFn).toHaveBeenCalledTimes(2);
332
+ expect(effectFn).toHaveBeenLastCalledWith([]);
333
+ });
334
+
335
+ test("called when item updated", () => {
336
+ const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
337
+ const effectFn = vi.fn();
338
+ const effect0Fn = vi.fn();
339
+ const effect1Fn = vi.fn();
340
+ const effect2Fn = vi.fn();
341
+
342
+ effect((t) => effectFn($array.get(t).map((state) => state.get(t))));
343
+ effect((t) => effect0Fn($array.get(t)[0].get(t)));
344
+ effect((t) => effect1Fn($array.get(t)[1].get(t)));
345
+ effect((t) => effect2Fn($array.get(t)[2].get(t)));
346
+
347
+ expect(effectFn).toHaveBeenCalledTimes(1);
348
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2]);
349
+ expect(effect0Fn).toHaveBeenCalledTimes(1);
350
+ expect(effect0Fn).toHaveBeenLastCalledWith(0);
351
+ expect(effect1Fn).toHaveBeenCalledTimes(1);
352
+ expect(effect1Fn).toHaveBeenLastCalledWith(1);
353
+ expect(effect2Fn).toHaveBeenCalledTimes(1);
354
+ expect(effect2Fn).toHaveBeenLastCalledWith(2);
355
+
356
+ $array.pick()[0].set(1);
357
+ expect(effectFn).toHaveBeenCalledTimes(2);
358
+ expect(effectFn).toHaveBeenLastCalledWith([1, 1, 2]);
359
+ expect(effect0Fn).toHaveBeenCalledTimes(2);
360
+ expect(effect0Fn).toHaveBeenLastCalledWith(1);
361
+ expect(effect1Fn).toHaveBeenCalledTimes(1);
362
+ expect(effect1Fn).toHaveBeenLastCalledWith(1);
363
+ expect(effect2Fn).toHaveBeenCalledTimes(1);
364
+ expect(effect2Fn).toHaveBeenLastCalledWith(2);
365
+
366
+ $array.pick()[1].set(2);
367
+ expect(effectFn).toHaveBeenCalledTimes(3);
368
+ expect(effectFn).toHaveBeenLastCalledWith([1, 2, 2]);
369
+ expect(effect0Fn).toHaveBeenCalledTimes(2);
370
+ expect(effect0Fn).toHaveBeenLastCalledWith(1);
371
+ expect(effect1Fn).toHaveBeenCalledTimes(2);
372
+ expect(effect1Fn).toHaveBeenLastCalledWith(2);
373
+ expect(effect2Fn).toHaveBeenCalledTimes(1);
374
+ expect(effect2Fn).toHaveBeenLastCalledWith(2);
375
+
376
+ $array.pick()[2].set(3);
377
+ expect(effectFn).toHaveBeenCalledTimes(4);
378
+ expect(effectFn).toHaveBeenLastCalledWith([1, 2, 3]);
379
+ expect(effect0Fn).toHaveBeenCalledTimes(2);
380
+ expect(effect0Fn).toHaveBeenLastCalledWith(1);
381
+ expect(effect1Fn).toHaveBeenCalledTimes(2);
382
+ expect(effect1Fn).toHaveBeenLastCalledWith(2);
383
+ expect(effect2Fn).toHaveBeenCalledTimes(2);
384
+ expect(effect2Fn).toHaveBeenLastCalledWith(3);
385
+ });
386
+
387
+ test("called when item replaced", () => {
388
+ const $array = array<FlowState<number>>([state(0), state(1), state(2)]);
389
+ const effectFn = vi.fn();
390
+ const effect0Fn = vi.fn();
391
+
392
+ effect((t) => effectFn($array.get(t).map((state) => state.get(t))));
393
+ effect((t) => effect0Fn($array.get(t)[0].get(t)));
394
+
395
+ expect(effectFn).toHaveBeenCalledTimes(1);
396
+ expect(effectFn).toHaveBeenLastCalledWith([0, 1, 2]);
397
+ expect(effect0Fn).toHaveBeenCalledTimes(1);
398
+ expect(effect0Fn).toHaveBeenLastCalledWith(0);
399
+
400
+ $array.setItem(0, state(3));
401
+ expect(effectFn).toHaveBeenCalledTimes(2);
402
+ expect(effectFn).toHaveBeenLastCalledWith([3, 1, 2]);
403
+ expect(effect0Fn).toHaveBeenCalledTimes(2);
404
+ expect(effect0Fn).toHaveBeenLastCalledWith(3);
405
+
406
+ $array.shift();
407
+ expect(effectFn).toHaveBeenCalledTimes(3);
408
+ expect(effectFn).toHaveBeenLastCalledWith([1, 2]);
409
+ expect(effect0Fn).toHaveBeenCalledTimes(3);
410
+ expect(effect0Fn).toHaveBeenLastCalledWith(1);
411
+
412
+ $array.unshift(state(4));
413
+ expect(effectFn).toHaveBeenCalledTimes(4);
414
+ expect(effectFn).toHaveBeenLastCalledWith([4, 1, 2]);
415
+ expect(effect0Fn).toHaveBeenCalledTimes(4);
416
+ expect(effect0Fn).toHaveBeenLastCalledWith(4);
417
+ });
418
+
419
+ describe("lastAction", () => {
420
+ test("called when initialized", () => {
421
+ const $array = array([1, 2, 3]);
422
+ const effectFn = vi.fn();
423
+ effect((t) => effectFn($array.$lastAction.get(t)));
424
+
425
+ expect(effectFn).toHaveBeenCalledTimes(1);
426
+ expect(effectFn).toHaveBeenLastCalledWith({
427
+ type: "set",
428
+ items: [1, 2, 3],
429
+ });
430
+ });
431
+
432
+ test("called when updated (set)", () => {
433
+ const $array = array([0, 1, 2]);
434
+ const effectFn = vi.fn();
435
+ effect((t) => effectFn($array.$lastAction.get(t)));
436
+
437
+ expect(effectFn).toHaveBeenCalledTimes(1);
438
+ expect(effectFn).toHaveBeenLastCalledWith({
439
+ type: "set",
440
+ items: [0, 1, 2],
441
+ });
442
+ $array.set([1, 2, 3]);
443
+ expect(effectFn).toHaveBeenCalledTimes(2);
444
+ expect(effectFn).toHaveBeenLastCalledWith({
445
+ type: "set",
446
+ items: [1, 2, 3],
447
+ });
448
+ });
449
+
450
+ test("called when updated (push/pop)", () => {
451
+ const $array = array<number>();
452
+ const effectFn = vi.fn();
453
+ effect((t) => effectFn($array.$lastAction.get(t)));
454
+
455
+ expect(effectFn).toHaveBeenCalledTimes(1);
456
+ expect(effectFn).toHaveBeenLastCalledWith({
457
+ type: "set",
458
+ items: [],
459
+ });
460
+
461
+ $array.push(0);
462
+ expect(effectFn).toHaveBeenCalledTimes(2);
463
+ expect(effectFn).toHaveBeenLastCalledWith({
464
+ type: "push",
465
+ item: 0,
466
+ });
467
+
468
+ $array.push(1);
469
+ expect(effectFn).toHaveBeenCalledTimes(3);
470
+ expect(effectFn).toHaveBeenLastCalledWith({
471
+ type: "push",
472
+ item: 1,
473
+ });
474
+
475
+ $array.push(2);
476
+ expect(effectFn).toHaveBeenCalledTimes(4);
477
+ expect(effectFn).toHaveBeenLastCalledWith({
478
+ type: "push",
479
+ item: 2,
480
+ });
481
+
482
+ $array.pop();
483
+ expect(effectFn).toHaveBeenCalledTimes(5);
484
+ expect(effectFn).toHaveBeenLastCalledWith({
485
+ type: "pop",
486
+ });
487
+
488
+ $array.pop();
489
+ expect(effectFn).toHaveBeenCalledTimes(6);
490
+ expect(effectFn).toHaveBeenLastCalledWith({
491
+ type: "pop",
492
+ });
493
+
494
+ $array.pop();
495
+ expect(effectFn).toHaveBeenCalledTimes(7);
496
+ expect(effectFn).toHaveBeenLastCalledWith({
497
+ type: "pop",
498
+ });
499
+ });
500
+
501
+ test("called when updated (unshift/shift)", () => {
502
+ const $array = array<number>();
503
+ const effectFn = vi.fn();
504
+ effect((t) => effectFn($array.$lastAction.get(t)));
505
+
506
+ expect(effectFn).toHaveBeenCalledTimes(1);
507
+ expect(effectFn).toHaveBeenLastCalledWith({
508
+ type: "set",
509
+ items: [],
510
+ });
511
+
512
+ $array.unshift(0);
513
+ expect(effectFn).toHaveBeenCalledTimes(2);
514
+ expect(effectFn).toHaveBeenLastCalledWith({
515
+ type: "unshift",
516
+ item: 0,
517
+ });
518
+
519
+ $array.unshift(1);
520
+ expect(effectFn).toHaveBeenCalledTimes(3);
521
+ expect(effectFn).toHaveBeenLastCalledWith({
522
+ type: "unshift",
523
+ item: 1,
524
+ });
525
+
526
+ $array.unshift(2);
527
+ expect(effectFn).toHaveBeenCalledTimes(4);
528
+ expect(effectFn).toHaveBeenLastCalledWith({
529
+ type: "unshift",
530
+ item: 2,
531
+ });
532
+
533
+ $array.shift();
534
+ expect(effectFn).toHaveBeenCalledTimes(5);
535
+ expect(effectFn).toHaveBeenLastCalledWith({
536
+ type: "shift",
537
+ });
538
+
539
+ $array.shift();
540
+ expect(effectFn).toHaveBeenCalledTimes(6);
541
+ expect(effectFn).toHaveBeenLastCalledWith({
542
+ type: "shift",
543
+ });
544
+
545
+ $array.shift();
546
+ expect(effectFn).toHaveBeenCalledTimes(7);
547
+ expect(effectFn).toHaveBeenLastCalledWith({
548
+ type: "shift",
549
+ });
550
+ });
551
+
552
+ test("called when updated (splice)", () => {
553
+ const $array = array<number>([0, 1, 2, 3, 4]);
554
+ const effectFn = vi.fn();
555
+ effect((t) => effectFn($array.$lastAction.get(t)));
556
+
557
+ expect(effectFn).toHaveBeenCalledTimes(1);
558
+ expect(effectFn).toHaveBeenLastCalledWith({
559
+ type: "set",
560
+ items: [0, 1, 2, 3, 4],
561
+ });
562
+
563
+ $array.splice(1, 2);
564
+ expect(effectFn).toHaveBeenCalledTimes(2);
565
+ expect(effectFn).toHaveBeenLastCalledWith({
566
+ type: "splice",
567
+ start: 1,
568
+ deleteCount: 2,
569
+ items: [],
570
+ });
571
+
572
+ $array.splice(1, 0, 1, 2);
573
+ expect(effectFn).toHaveBeenCalledTimes(3);
574
+ expect(effectFn).toHaveBeenLastCalledWith({
575
+ type: "splice",
576
+ start: 1,
577
+ deleteCount: 0,
578
+ items: [1, 2],
579
+ });
580
+ });
581
+
582
+ test("called when updated (clear)", () => {
583
+ const $array = array<number>([0, 1, 2, 3, 4]);
584
+ const effectFn = vi.fn();
585
+ effect((t) => effectFn($array.$lastAction.get(t)));
586
+
587
+ expect(effectFn).toHaveBeenCalledTimes(1);
588
+ expect(effectFn).toHaveBeenLastCalledWith({
589
+ type: "set",
590
+ items: [0, 1, 2, 3, 4],
591
+ });
592
+
593
+ $array.clear();
594
+ expect(effectFn).toHaveBeenCalledTimes(2);
595
+ expect(effectFn).toHaveBeenLastCalledWith({
596
+ type: "clear",
597
+ });
598
+ });
599
+ });
620
600
  });