signalium 0.3.8 → 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 (287) hide show
  1. package/.turbo/turbo-build.log +3 -3
  2. package/CHANGELOG.md +21 -0
  3. package/build/react.js +19 -0
  4. package/build/transform.js +19 -0
  5. package/dist/cjs/config.d.ts +8 -3
  6. package/dist/cjs/config.d.ts.map +1 -1
  7. package/dist/cjs/config.js +14 -8
  8. package/dist/cjs/config.js.map +1 -1
  9. package/dist/cjs/debug.d.ts +2 -2
  10. package/dist/cjs/debug.d.ts.map +1 -1
  11. package/dist/cjs/debug.js +3 -3
  12. package/dist/cjs/debug.js.map +1 -1
  13. package/dist/cjs/hooks.d.ts +14 -42
  14. package/dist/cjs/hooks.d.ts.map +1 -1
  15. package/dist/cjs/hooks.js +19 -240
  16. package/dist/cjs/hooks.js.map +1 -1
  17. package/dist/cjs/index.d.ts +5 -3
  18. package/dist/cjs/index.d.ts.map +1 -1
  19. package/dist/cjs/index.js +18 -18
  20. package/dist/cjs/index.js.map +1 -1
  21. package/dist/cjs/internals/async.d.ts +52 -0
  22. package/dist/cjs/internals/async.d.ts.map +1 -0
  23. package/dist/cjs/internals/async.js +394 -0
  24. package/dist/cjs/internals/async.js.map +1 -0
  25. package/dist/cjs/internals/connect.d.ts +4 -0
  26. package/dist/cjs/internals/connect.d.ts.map +1 -0
  27. package/dist/cjs/internals/connect.js +37 -0
  28. package/dist/cjs/internals/connect.js.map +1 -0
  29. package/dist/cjs/internals/consumer.d.ts +6 -0
  30. package/dist/cjs/internals/consumer.d.ts.map +1 -0
  31. package/dist/cjs/internals/consumer.js +13 -0
  32. package/dist/cjs/internals/consumer.js.map +1 -0
  33. package/dist/cjs/internals/contexts.d.ts +33 -0
  34. package/dist/cjs/internals/contexts.d.ts.map +1 -0
  35. package/dist/cjs/internals/contexts.js +103 -0
  36. package/dist/cjs/internals/contexts.js.map +1 -0
  37. package/dist/cjs/internals/derived.d.ts +66 -0
  38. package/dist/cjs/internals/derived.d.ts.map +1 -0
  39. package/dist/cjs/internals/derived.js +128 -0
  40. package/dist/cjs/internals/derived.js.map +1 -0
  41. package/dist/cjs/internals/dirty.d.ts +5 -0
  42. package/dist/cjs/internals/dirty.d.ts.map +1 -0
  43. package/dist/cjs/internals/dirty.js +79 -0
  44. package/dist/cjs/internals/dirty.js.map +1 -0
  45. package/dist/cjs/internals/edge.d.ts +32 -0
  46. package/dist/cjs/internals/edge.d.ts.map +1 -0
  47. package/dist/cjs/internals/edge.js +59 -0
  48. package/dist/cjs/internals/edge.js.map +1 -0
  49. package/dist/cjs/internals/get.d.ts +10 -0
  50. package/dist/cjs/internals/get.d.ts.map +1 -0
  51. package/dist/cjs/internals/get.js +255 -0
  52. package/dist/cjs/internals/get.js.map +1 -0
  53. package/dist/cjs/internals/scheduling.d.ts +12 -0
  54. package/dist/cjs/internals/scheduling.d.ts.map +1 -0
  55. package/dist/cjs/internals/scheduling.js +117 -0
  56. package/dist/cjs/internals/scheduling.js.map +1 -0
  57. package/dist/cjs/internals/state.d.ts +18 -0
  58. package/dist/cjs/internals/state.d.ts.map +1 -0
  59. package/dist/cjs/internals/state.js +88 -0
  60. package/dist/cjs/internals/state.js.map +1 -0
  61. package/dist/cjs/internals/utils/debug-name.d.ts +2 -0
  62. package/dist/cjs/internals/utils/debug-name.d.ts.map +1 -0
  63. package/dist/cjs/internals/utils/debug-name.js +14 -0
  64. package/dist/cjs/internals/utils/debug-name.js.map +1 -0
  65. package/dist/cjs/internals/utils/equals.d.ts +3 -0
  66. package/dist/cjs/internals/utils/equals.d.ts.map +1 -0
  67. package/dist/cjs/internals/utils/equals.js +13 -0
  68. package/dist/cjs/internals/utils/equals.js.map +1 -0
  69. package/dist/cjs/internals/utils/hash.d.ts +7 -0
  70. package/dist/cjs/internals/utils/hash.d.ts.map +1 -0
  71. package/dist/cjs/internals/utils/hash.js +181 -0
  72. package/dist/cjs/internals/utils/hash.js.map +1 -0
  73. package/dist/cjs/internals/utils/stringify.d.ts +3 -0
  74. package/dist/cjs/internals/utils/stringify.d.ts.map +1 -0
  75. package/dist/cjs/{utils.js → internals/utils/stringify.js} +5 -27
  76. package/dist/cjs/internals/utils/stringify.js.map +1 -0
  77. package/dist/cjs/internals/utils/type-utils.d.ts +6 -0
  78. package/dist/cjs/internals/utils/type-utils.d.ts.map +1 -0
  79. package/dist/cjs/internals/utils/type-utils.js +22 -0
  80. package/dist/cjs/internals/utils/type-utils.js.map +1 -0
  81. package/dist/cjs/react/context.d.ts +1 -1
  82. package/dist/cjs/react/context.d.ts.map +1 -1
  83. package/dist/cjs/react/provider.d.ts +4 -3
  84. package/dist/cjs/react/provider.d.ts.map +1 -1
  85. package/dist/cjs/react/provider.js +7 -3
  86. package/dist/cjs/react/provider.js.map +1 -1
  87. package/dist/cjs/react/setup.d.ts.map +1 -1
  88. package/dist/cjs/react/setup.js +2 -1
  89. package/dist/cjs/react/setup.js.map +1 -1
  90. package/dist/cjs/react/signal-value.d.ts +5 -1
  91. package/dist/cjs/react/signal-value.d.ts.map +1 -1
  92. package/dist/cjs/react/signal-value.js +35 -45
  93. package/dist/cjs/react/signal-value.js.map +1 -1
  94. package/dist/cjs/trace.d.ts +32 -28
  95. package/dist/cjs/trace.d.ts.map +1 -1
  96. package/dist/cjs/trace.js +14 -16
  97. package/dist/cjs/trace.js.map +1 -1
  98. package/dist/cjs/transform.d.ts +6 -0
  99. package/dist/cjs/transform.d.ts.map +1 -0
  100. package/dist/cjs/transform.js +92 -0
  101. package/dist/cjs/transform.js.map +1 -0
  102. package/dist/cjs/types.d.ts +32 -40
  103. package/dist/cjs/types.d.ts.map +1 -1
  104. package/dist/esm/config.d.ts +8 -3
  105. package/dist/esm/config.d.ts.map +1 -1
  106. package/dist/esm/config.js +12 -7
  107. package/dist/esm/config.js.map +1 -1
  108. package/dist/esm/debug.d.ts +2 -2
  109. package/dist/esm/debug.d.ts.map +1 -1
  110. package/dist/esm/debug.js +2 -2
  111. package/dist/esm/debug.js.map +1 -1
  112. package/dist/esm/hooks.d.ts +14 -42
  113. package/dist/esm/hooks.d.ts.map +1 -1
  114. package/dist/esm/hooks.js +17 -226
  115. package/dist/esm/hooks.js.map +1 -1
  116. package/dist/esm/index.d.ts +5 -3
  117. package/dist/esm/index.d.ts.map +1 -1
  118. package/dist/esm/index.js +5 -3
  119. package/dist/esm/index.js.map +1 -1
  120. package/dist/esm/internals/async.d.ts +52 -0
  121. package/dist/esm/internals/async.d.ts.map +1 -0
  122. package/dist/esm/internals/async.js +387 -0
  123. package/dist/esm/internals/async.js.map +1 -0
  124. package/dist/esm/internals/connect.d.ts +4 -0
  125. package/dist/esm/internals/connect.d.ts.map +1 -0
  126. package/dist/esm/internals/connect.js +33 -0
  127. package/dist/esm/internals/connect.js.map +1 -0
  128. package/dist/esm/internals/consumer.d.ts +6 -0
  129. package/dist/esm/internals/consumer.d.ts.map +1 -0
  130. package/dist/esm/internals/consumer.js +9 -0
  131. package/dist/esm/internals/consumer.js.map +1 -0
  132. package/dist/esm/internals/contexts.d.ts +33 -0
  133. package/dist/esm/internals/contexts.d.ts.map +1 -0
  134. package/dist/esm/internals/contexts.js +92 -0
  135. package/dist/esm/internals/contexts.js.map +1 -0
  136. package/dist/esm/internals/derived.d.ts +66 -0
  137. package/dist/esm/internals/derived.d.ts.map +1 -0
  138. package/dist/esm/internals/derived.js +118 -0
  139. package/dist/esm/internals/derived.js.map +1 -0
  140. package/dist/esm/internals/dirty.d.ts +5 -0
  141. package/dist/esm/internals/dirty.d.ts.map +1 -0
  142. package/dist/esm/internals/dirty.js +75 -0
  143. package/dist/esm/internals/dirty.js.map +1 -0
  144. package/dist/esm/internals/edge.d.ts +32 -0
  145. package/dist/esm/internals/edge.d.ts.map +1 -0
  146. package/dist/esm/internals/edge.js +54 -0
  147. package/dist/esm/internals/edge.js.map +1 -0
  148. package/dist/esm/internals/get.d.ts +10 -0
  149. package/dist/esm/internals/get.d.ts.map +1 -0
  150. package/dist/esm/internals/get.js +247 -0
  151. package/dist/esm/internals/get.js.map +1 -0
  152. package/dist/esm/internals/scheduling.d.ts +12 -0
  153. package/dist/esm/internals/scheduling.d.ts.map +1 -0
  154. package/dist/esm/internals/scheduling.js +106 -0
  155. package/dist/esm/internals/scheduling.js.map +1 -0
  156. package/dist/esm/internals/state.d.ts +18 -0
  157. package/dist/esm/internals/state.d.ts.map +1 -0
  158. package/dist/esm/internals/state.js +82 -0
  159. package/dist/esm/internals/state.js.map +1 -0
  160. package/dist/esm/internals/utils/debug-name.d.ts +2 -0
  161. package/dist/esm/internals/utils/debug-name.d.ts.map +1 -0
  162. package/dist/esm/internals/utils/debug-name.js +11 -0
  163. package/dist/esm/internals/utils/debug-name.js.map +1 -0
  164. package/dist/esm/internals/utils/equals.d.ts +3 -0
  165. package/dist/esm/internals/utils/equals.d.ts.map +1 -0
  166. package/dist/esm/internals/utils/equals.js +9 -0
  167. package/dist/esm/internals/utils/equals.js.map +1 -0
  168. package/dist/esm/internals/utils/hash.d.ts +7 -0
  169. package/dist/esm/internals/utils/hash.d.ts.map +1 -0
  170. package/dist/esm/internals/utils/hash.js +174 -0
  171. package/dist/esm/internals/utils/hash.js.map +1 -0
  172. package/dist/esm/internals/utils/stringify.d.ts +3 -0
  173. package/dist/esm/internals/utils/stringify.d.ts.map +1 -0
  174. package/dist/esm/{utils.js → internals/utils/stringify.js} +4 -25
  175. package/dist/esm/internals/utils/stringify.js.map +1 -0
  176. package/dist/esm/internals/utils/type-utils.d.ts +6 -0
  177. package/dist/esm/internals/utils/type-utils.d.ts.map +1 -0
  178. package/dist/esm/internals/utils/type-utils.js +15 -0
  179. package/dist/esm/internals/utils/type-utils.js.map +1 -0
  180. package/dist/esm/react/context.d.ts +1 -1
  181. package/dist/esm/react/context.d.ts.map +1 -1
  182. package/dist/esm/react/provider.d.ts +4 -3
  183. package/dist/esm/react/provider.d.ts.map +1 -1
  184. package/dist/esm/react/provider.js +6 -2
  185. package/dist/esm/react/provider.js.map +1 -1
  186. package/dist/esm/react/setup.d.ts.map +1 -1
  187. package/dist/esm/react/setup.js +3 -2
  188. package/dist/esm/react/setup.js.map +1 -1
  189. package/dist/esm/react/signal-value.d.ts +5 -1
  190. package/dist/esm/react/signal-value.d.ts.map +1 -1
  191. package/dist/esm/react/signal-value.js +34 -45
  192. package/dist/esm/react/signal-value.js.map +1 -1
  193. package/dist/esm/trace.d.ts +32 -28
  194. package/dist/esm/trace.d.ts.map +1 -1
  195. package/dist/esm/trace.js +13 -15
  196. package/dist/esm/trace.js.map +1 -1
  197. package/dist/esm/transform.d.ts +6 -0
  198. package/dist/esm/transform.d.ts.map +1 -0
  199. package/dist/esm/transform.js +89 -0
  200. package/dist/esm/transform.js.map +1 -0
  201. package/dist/esm/types.d.ts +32 -40
  202. package/dist/esm/types.d.ts.map +1 -1
  203. package/package.json +23 -4
  204. package/src/__tests__/__snapshots__/context.test.ts.snap +2101 -0
  205. package/src/__tests__/__snapshots__/nesting.test.ts.snap +16201 -0
  206. package/src/__tests__/__snapshots__/params-and-state.test.ts.snap +1879 -0
  207. package/src/__tests__/async-task.test.ts +327 -0
  208. package/src/__tests__/context.test.ts +517 -0
  209. package/src/__tests__/nesting.test.ts +298 -0
  210. package/src/__tests__/params-and-state.test.ts +230 -0
  211. package/src/__tests__/reactive-async.test.ts +548 -0
  212. package/src/__tests__/reactive-sync.test.ts +130 -0
  213. package/src/__tests__/subscription.test.ts +510 -0
  214. package/src/__tests__/utils/async.ts +1 -1
  215. package/src/__tests__/utils/instrumented-hooks.ts +229 -124
  216. package/src/__tests__/utils/permute.ts +25 -14
  217. package/src/config.ts +19 -9
  218. package/src/debug.ts +2 -2
  219. package/src/hooks.ts +46 -380
  220. package/src/index.ts +7 -24
  221. package/src/internals/async.ts +558 -0
  222. package/src/internals/connect.ts +41 -0
  223. package/src/internals/consumer.ts +13 -0
  224. package/src/internals/contexts.ts +133 -0
  225. package/src/internals/derived.ts +208 -0
  226. package/src/internals/dirty.ts +91 -0
  227. package/src/internals/edge.ts +109 -0
  228. package/src/internals/get.ts +298 -0
  229. package/src/internals/scheduling.ts +140 -0
  230. package/src/internals/state.ts +111 -0
  231. package/src/internals/utils/debug-name.ts +14 -0
  232. package/src/internals/utils/equals.ts +12 -0
  233. package/src/internals/utils/hash.ts +221 -0
  234. package/src/{utils.ts → internals/utils/stringify.ts} +3 -29
  235. package/src/internals/utils/type-utils.ts +19 -0
  236. package/src/react/__tests__/async.test.tsx +704 -0
  237. package/src/react/__tests__/basic.test.tsx +95 -0
  238. package/src/react/__tests__/contexts.test.tsx +99 -0
  239. package/src/react/__tests__/subscriptions.test.tsx +49 -0
  240. package/src/react/__tests__/utils.tsx +40 -0
  241. package/src/react/context.ts +1 -1
  242. package/src/react/provider.tsx +12 -4
  243. package/src/react/setup.ts +3 -2
  244. package/src/react/signal-value.ts +47 -67
  245. package/src/trace.ts +43 -38
  246. package/src/transform.ts +113 -0
  247. package/src/types.ts +56 -46
  248. package/transform.js +19 -0
  249. package/vitest.workspace.ts +38 -2
  250. package/dist/cjs/scheduling.d.ts +0 -11
  251. package/dist/cjs/scheduling.d.ts.map +0 -1
  252. package/dist/cjs/scheduling.js +0 -108
  253. package/dist/cjs/scheduling.js.map +0 -1
  254. package/dist/cjs/signals.d.ts +0 -73
  255. package/dist/cjs/signals.d.ts.map +0 -1
  256. package/dist/cjs/signals.js +0 -632
  257. package/dist/cjs/signals.js.map +0 -1
  258. package/dist/cjs/utils.d.ts +0 -4
  259. package/dist/cjs/utils.d.ts.map +0 -1
  260. package/dist/cjs/utils.js.map +0 -1
  261. package/dist/esm/scheduling.d.ts +0 -11
  262. package/dist/esm/scheduling.d.ts.map +0 -1
  263. package/dist/esm/scheduling.js +0 -97
  264. package/dist/esm/scheduling.js.map +0 -1
  265. package/dist/esm/signals.d.ts +0 -73
  266. package/dist/esm/signals.d.ts.map +0 -1
  267. package/dist/esm/signals.js +0 -614
  268. package/dist/esm/signals.js.map +0 -1
  269. package/dist/esm/utils.d.ts +0 -4
  270. package/dist/esm/utils.d.ts.map +0 -1
  271. package/dist/esm/utils.js.map +0 -1
  272. package/src/__tests__/hooks/async-computed.test.ts +0 -190
  273. package/src/__tests__/hooks/async-task.test.ts +0 -334
  274. package/src/__tests__/hooks/computed.test.ts +0 -126
  275. package/src/__tests__/hooks/context.test.ts +0 -527
  276. package/src/__tests__/hooks/nesting.test.ts +0 -303
  277. package/src/__tests__/hooks/params-and-state.test.ts +0 -168
  278. package/src/__tests__/hooks/subscription.test.ts +0 -97
  279. package/src/__tests__/signals/async.test.ts +0 -416
  280. package/src/__tests__/signals/basic.test.ts +0 -399
  281. package/src/__tests__/signals/subscription.test.ts +0 -632
  282. package/src/__tests__/signals/watcher.test.ts +0 -253
  283. package/src/__tests__/utils/builders.ts +0 -22
  284. package/src/__tests__/utils/instrumented-signals.ts +0 -291
  285. package/src/react/__tests__/react.test.tsx +0 -227
  286. package/src/scheduling.ts +0 -130
  287. package/src/signals.ts +0 -824
@@ -1,190 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { state } from '../../index.js';
3
- import { asyncComputed } from '../utils/instrumented-hooks.js';
4
- import { nextTick } from '../utils/async.js';
5
-
6
- describe('async computeds', () => {
7
- test('Basic async computed works', async () => {
8
- const getC = asyncComputed(async (a: number, b: number) => {
9
- return a + b;
10
- });
11
-
12
- const result1 = getC(1, 2);
13
- expect(result1.isPending).toBe(true);
14
- expect(result1.result).toBe(undefined);
15
- await nextTick();
16
- expect(result1.isSuccess).toBe(true);
17
- expect(result1.result).toBe(3);
18
-
19
- const result2 = getC(2, 2);
20
- expect(result2.isPending).toBe(true);
21
- expect(result2.result).toBe(undefined);
22
- await nextTick();
23
- expect(result2.isSuccess).toBe(true);
24
- expect(result2.result).toBe(4);
25
- });
26
-
27
- test('Async computed is not recomputed when the same arguments are passed', async () => {
28
- let computeCount = 0;
29
- const getC = asyncComputed(async (a: number, b: number) => {
30
- computeCount++;
31
- return a + b;
32
- });
33
-
34
- const result1 = getC(1, 2);
35
- await nextTick();
36
- expect(result1.result).toBe(3);
37
- expect(computeCount).toBe(1);
38
-
39
- const result2 = getC(1, 2);
40
- await nextTick();
41
- expect(result2.result).toBe(3);
42
- expect(computeCount).toBe(1);
43
- });
44
-
45
- test('Async computed is recomputed when the arguments change', async () => {
46
- let computeCount = 0;
47
- const getC = asyncComputed(async (a: number, b: number) => {
48
- computeCount++;
49
- return a + b;
50
- });
51
-
52
- const result1 = getC(1, 2);
53
- await nextTick();
54
- expect(result1.result).toBe(3);
55
- expect(computeCount).toBe(1);
56
-
57
- const result2 = getC(2, 2);
58
- await nextTick();
59
- expect(result2.result).toBe(4);
60
- expect(computeCount).toBe(2);
61
- });
62
-
63
- test('Async computed is recomputed when state changes', async () => {
64
- let computeCount = 0;
65
- const stateValue = state(1);
66
-
67
- const getC = asyncComputed(async (a: number) => {
68
- computeCount++;
69
- return a + stateValue.get();
70
- });
71
-
72
- const result1 = getC(1);
73
- await nextTick();
74
- expect(result1.result).toBe(2);
75
- expect(computeCount).toBe(1);
76
-
77
- stateValue.set(2);
78
- const result2 = getC(1);
79
- await nextTick();
80
- expect(result2.result).toBe(3);
81
- expect(computeCount).toBe(2);
82
- });
83
-
84
- test('Async computed handles errors', async () => {
85
- const getC = asyncComputed(async (shouldError: boolean) => {
86
- if (shouldError) {
87
- throw new Error('Test error');
88
- }
89
- return 'success';
90
- });
91
-
92
- const result1 = getC(false);
93
- await nextTick();
94
- expect(result1.isSuccess).toBe(true);
95
- expect(result1.result).toBe('success');
96
-
97
- const result2 = getC(true);
98
- await nextTick();
99
- expect(result2.isError).toBe(true);
100
- expect(result2.error as Error).toBeInstanceOf(Error);
101
- expect((result2.error as Error).message).toBe('Test error');
102
- });
103
-
104
- test('Async computed with init value starts ready', () => {
105
- const getC = asyncComputed(async () => 'updated', { initValue: 'initial' });
106
-
107
- const result = getC();
108
- expect(result.isReady).toBe(true);
109
- expect(result.result).toBe('initial');
110
- expect(result.isPending).toBe(true);
111
- });
112
-
113
- test('Nested async computeds work correctly', async () => {
114
- let innerCount = 0;
115
- let outerCount = 0;
116
-
117
- const inner = asyncComputed(async (x: number) => {
118
- innerCount++;
119
- await nextTick();
120
- return x * 2;
121
- });
122
-
123
- const outer = asyncComputed(async (x: number) => {
124
- outerCount++;
125
- const innerResult = inner(x);
126
- const result = innerResult.await();
127
- return result + 1;
128
- });
129
-
130
- const result1 = outer(2);
131
- expect(result1.result).toBe(undefined);
132
- expect(innerCount).toBe(1);
133
- expect(outerCount).toBe(1);
134
-
135
- await new Promise(resolve => setTimeout(resolve, 10));
136
- const result2 = outer(2);
137
- expect(result2.result).toBe(5);
138
- expect(innerCount).toBe(1);
139
- expect(outerCount).toBe(2);
140
- });
141
-
142
- test('Nested async computeds handle errors correctly', async () => {
143
- const inner = asyncComputed(async (shouldError: boolean) => {
144
- if (shouldError) throw new Error('Inner error');
145
- await nextTick();
146
- return 'inner success';
147
- });
148
-
149
- const outer = asyncComputed(async (shouldError: boolean) => {
150
- const innerResult = inner(shouldError);
151
- await innerResult.await();
152
- return 'outer: ' + innerResult.result;
153
- });
154
-
155
- // Test success case
156
- const successResult = outer(false);
157
- await new Promise(resolve => setTimeout(resolve, 10));
158
- expect(successResult.isSuccess).toBe(true);
159
- expect(successResult.result).toBe('outer: inner success');
160
-
161
- // Test error case
162
- const errorResult = outer(true);
163
- await new Promise(resolve => setTimeout(resolve, 10));
164
- expect(errorResult.isError).toBe(true);
165
- expect(errorResult.error).toBeInstanceOf(Error);
166
- expect((errorResult.error as Error).message).toBe('Inner error');
167
- });
168
-
169
- test('Nested async computeds with init values work correctly', async () => {
170
- const inner = asyncComputed(async (x: number) => x * 2, { initValue: 0 });
171
- const outer = asyncComputed(
172
- async (x: number) => {
173
- const innerResult = inner(x);
174
- await innerResult.await();
175
- return innerResult.result! + 1;
176
- },
177
- { initValue: -1 },
178
- );
179
-
180
- const result = outer(2);
181
- expect(result.isReady).toBe(true);
182
- expect(result.result).toBe(-1); // Initial value
183
- expect(result.isPending).toBe(true);
184
-
185
- await new Promise(resolve => setTimeout(resolve, 10));
186
- expect(result.result).toBe(5); // (2 * 2) + 1
187
- expect(result.isPending).toBe(false);
188
- expect(result.isSuccess).toBe(true);
189
- });
190
- });
@@ -1,334 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { asyncTask, computed } from '../utils/instrumented-hooks.js';
3
- import { nextTick } from '../utils/async.js';
4
-
5
- describe('async tasks', () => {
6
- test('Basic async task works', async () => {
7
- const getC = asyncTask(async (a: number, b: number) => {
8
- return a + b;
9
- });
10
-
11
- // First set of args
12
- const task1 = getC(1, 2);
13
- expect(task1.isPending).toBe(false);
14
- expect(task1.result).toBe(undefined);
15
- expect(getC).toHaveCounts({ compute: 0 });
16
-
17
- await nextTick();
18
- expect(task1.isPending).toBe(false);
19
- expect(task1.result).toBe(undefined);
20
- expect(getC).toHaveCounts({ compute: 0 });
21
-
22
- const result1 = task1.run();
23
- expect(task1.isPending).toBe(true);
24
- expect(task1.result).toBe(undefined);
25
- expect(getC).toHaveCounts({ compute: 1 });
26
-
27
- expect(await result1).toBe(3);
28
- expect(task1.isSuccess).toBe(true);
29
- expect(task1.result).toBe(3);
30
- expect(getC).toHaveCounts({ compute: 1 });
31
-
32
- const result2 = task1.run();
33
- expect(task1.isPending).toBe(true);
34
- expect(task1.result).toBe(3);
35
- expect(getC).toHaveCounts({ compute: 2 });
36
-
37
- expect(await result2).toBe(3);
38
- expect(task1.isSuccess).toBe(true);
39
- expect(task1.result).toBe(3);
40
- expect(getC).toHaveCounts({ compute: 2 });
41
-
42
- // Second set of args
43
- const task2 = getC(2, 2);
44
- expect(task2.isPending).toBe(false);
45
- expect(task2.result).toBe(undefined);
46
- expect(getC).toHaveCounts({ compute: 2 });
47
-
48
- await nextTick();
49
- expect(task2.isPending).toBe(false);
50
- expect(task2.result).toBe(undefined);
51
- expect(getC).toHaveCounts({ compute: 2 });
52
-
53
- const result3 = task2.run();
54
- expect(task2.isPending).toBe(true);
55
- expect(task2.result).toBe(undefined);
56
- expect(getC).toHaveCounts({ compute: 3 });
57
-
58
- expect(await result3).toBe(4);
59
- expect(task2.isSuccess).toBe(true);
60
- expect(task2.result).toBe(4);
61
- expect(getC).toHaveCounts({ compute: 3 });
62
-
63
- const result4 = task2.run();
64
- expect(task2.isPending).toBe(true);
65
- expect(task2.result).toBe(4);
66
- expect(getC).toHaveCounts({ compute: 4 });
67
-
68
- expect(await result4).toBe(4);
69
- expect(task2.isSuccess).toBe(true);
70
- expect(task2.result).toBe(4);
71
- expect(getC).toHaveCounts({ compute: 4 });
72
- });
73
-
74
- test('Separate tasks are created for different arguments', async () => {
75
- const getC = asyncTask(async (a: number, b: number) => {
76
- return a + b;
77
- });
78
-
79
- const task1 = getC(1, 2);
80
- const task2 = getC(2, 2);
81
-
82
- expect(task1.isPending).toBe(false);
83
- expect(task1.result).toBe(undefined);
84
- expect(task2.isPending).toBe(false);
85
- expect(task2.result).toBe(undefined);
86
- expect(getC).toHaveCounts({ compute: 0 });
87
-
88
- await nextTick();
89
- expect(task1.isPending).toBe(false);
90
- expect(task1.result).toBe(undefined);
91
- expect(task2.isPending).toBe(false);
92
- expect(task2.result).toBe(undefined);
93
- expect(getC).toHaveCounts({ compute: 0 });
94
-
95
- const result1 = task1.run();
96
- expect(task1.isPending).toBe(true);
97
- expect(task1.result).toBe(undefined);
98
- expect(task2.isPending).toBe(false);
99
- expect(task2.result).toBe(undefined);
100
- expect(getC).toHaveCounts({ compute: 1 });
101
-
102
- expect(await result1).toBe(3);
103
- expect(task1.isSuccess).toBe(true);
104
- expect(task1.result).toBe(3);
105
- expect(task2.isPending).toBe(false);
106
- expect(task2.result).toBe(undefined);
107
- expect(getC).toHaveCounts({ compute: 1 });
108
-
109
- const result2 = task2.run();
110
- expect(task2.isPending).toBe(true);
111
- expect(task2.result).toBe(undefined);
112
- expect(task1.isPending).toBe(false);
113
- expect(task1.result).toBe(3);
114
- expect(getC).toHaveCounts({ compute: 2 });
115
-
116
- expect(await result2).toBe(4);
117
- expect(task1.isPending).toBe(false);
118
- expect(task1.result).toBe(3);
119
- expect(task2.isSuccess).toBe(true);
120
- expect(task2.result).toBe(4);
121
- expect(getC).toHaveCounts({ compute: 2 });
122
- });
123
-
124
- test('Separate tasks notify separately', async () => {
125
- const getC = asyncTask(async (a: number, b: number) => {
126
- return a + b;
127
- });
128
-
129
- const computed1 = computed(() => getC(1, 2));
130
- const computed2 = computed(() => getC(2, 2));
131
-
132
- const task1 = computed1();
133
- const task2 = computed2();
134
-
135
- expect(task1.isPending).toBe(false);
136
- expect(task1.result).toBe(undefined);
137
- expect(task2.isPending).toBe(false);
138
- expect(task2.result).toBe(undefined);
139
- expect(getC).toHaveCounts({ compute: 0 });
140
- expect(computed1).toHaveCounts({ compute: 1 });
141
- expect(computed2).toHaveCounts({ compute: 1 });
142
-
143
- await nextTick();
144
- expect(task1.isPending).toBe(false);
145
- expect(task1.result).toBe(undefined);
146
- expect(task2.isPending).toBe(false);
147
- expect(task2.result).toBe(undefined);
148
- expect(getC).toHaveCounts({ compute: 0 });
149
- expect(computed1).toHaveCounts({ compute: 1 });
150
- expect(computed2).toHaveCounts({ compute: 1 });
151
-
152
- const result1 = task1.run();
153
-
154
- computed1();
155
- computed2();
156
-
157
- expect(task1.isPending).toBe(true);
158
- expect(task1.result).toBe(undefined);
159
- expect(task2.isPending).toBe(false);
160
- expect(task2.result).toBe(undefined);
161
- expect(getC).toHaveCounts({ compute: 1 });
162
- expect(computed1).toHaveCounts({ compute: 2 });
163
- expect(computed2).toHaveCounts({ compute: 1 });
164
-
165
- computed1();
166
- computed2();
167
-
168
- expect(await result1).toBe(3);
169
- expect(task1.isSuccess).toBe(true);
170
- expect(task1.result).toBe(3);
171
- expect(task2.isPending).toBe(false);
172
- expect(task2.result).toBe(undefined);
173
- expect(getC).toHaveCounts({ compute: 1 });
174
-
175
- computed1();
176
- computed2();
177
-
178
- expect(computed1).toHaveCounts({ compute: 3 });
179
- expect(computed2).toHaveCounts({ compute: 1 });
180
-
181
- const result2 = task2.run();
182
- expect(task2.isPending).toBe(true);
183
- expect(task2.result).toBe(undefined);
184
- expect(task1.isPending).toBe(false);
185
- expect(task1.result).toBe(3);
186
- expect(getC).toHaveCounts({ compute: 2 });
187
-
188
- computed1();
189
- computed2();
190
-
191
- expect(computed1).toHaveCounts({ compute: 3 });
192
- expect(computed2).toHaveCounts({ compute: 2 });
193
-
194
- expect(await result2).toBe(4);
195
- expect(task1.isPending).toBe(false);
196
- expect(task1.result).toBe(3);
197
- expect(task2.isSuccess).toBe(true);
198
- expect(task2.result).toBe(4);
199
- expect(getC).toHaveCounts({ compute: 2 });
200
-
201
- computed1();
202
- computed2();
203
-
204
- expect(computed1).toHaveCounts({ compute: 3 });
205
- expect(computed2).toHaveCounts({ compute: 3 });
206
- });
207
-
208
- test('Basic async task works with run args', async () => {
209
- const getC = asyncTask(async (a: number, b: number, c: number, d: number) => {
210
- return a + b + c + d;
211
- });
212
-
213
- // First set of args
214
- const task1 = getC(1, 2);
215
- expect(task1.isPending).toBe(false);
216
- expect(task1.result).toBe(undefined);
217
- expect(getC).toHaveCounts({ compute: 0 });
218
-
219
- await nextTick();
220
- expect(task1.isPending).toBe(false);
221
- expect(task1.result).toBe(undefined);
222
- expect(getC).toHaveCounts({ compute: 0 });
223
-
224
- const result1 = task1.run(3, 4);
225
- expect(task1.isPending).toBe(true);
226
- expect(task1.result).toBe(undefined);
227
- expect(getC).toHaveCounts({ compute: 1 });
228
-
229
- expect(await result1).toBe(10);
230
- expect(task1.isSuccess).toBe(true);
231
- expect(task1.result).toBe(10);
232
- expect(getC).toHaveCounts({ compute: 1 });
233
-
234
- const result2 = task1.run(5, 6);
235
- expect(task1.isPending).toBe(true);
236
- expect(task1.result).toBe(10);
237
- expect(getC).toHaveCounts({ compute: 2 });
238
-
239
- expect(await result2).toBe(14);
240
- expect(task1.isSuccess).toBe(true);
241
- expect(task1.result).toBe(14);
242
- expect(getC).toHaveCounts({ compute: 2 });
243
-
244
- // Second set of args
245
- const task2 = getC(2, 2);
246
- expect(task2.isPending).toBe(false);
247
- expect(task2.result).toBe(undefined);
248
- expect(getC).toHaveCounts({ compute: 2 });
249
-
250
- await nextTick();
251
- expect(task2.isPending).toBe(false);
252
- expect(task2.result).toBe(undefined);
253
- expect(getC).toHaveCounts({ compute: 2 });
254
-
255
- const result3 = task2.run(7, 8);
256
- expect(task2.isPending).toBe(true);
257
- expect(task2.result).toBe(undefined);
258
- expect(getC).toHaveCounts({ compute: 3 });
259
-
260
- expect(await result3).toBe(19);
261
- expect(task2.isSuccess).toBe(true);
262
- expect(task2.result).toBe(19);
263
- expect(getC).toHaveCounts({ compute: 3 });
264
-
265
- const result4 = task2.run(9, 10);
266
- expect(task2.isPending).toBe(true);
267
- expect(task2.result).toBe(19);
268
- expect(getC).toHaveCounts({ compute: 4 });
269
-
270
- expect(await result4).toBe(23);
271
- expect(task2.isSuccess).toBe(true);
272
- expect(task2.result).toBe(23);
273
- expect(getC).toHaveCounts({ compute: 4 });
274
- });
275
-
276
- test('Task can be defined with rest params', async () => {
277
- const getC = asyncTask(async (...nums: number[]) => {
278
- return nums.reduce((acc, num) => acc + num, 0);
279
- });
280
-
281
- // First set of args
282
- const task1 = getC(1, 2);
283
- expect(task1.isPending).toBe(false);
284
- expect(task1.result).toBe(undefined);
285
- expect(getC).toHaveCounts({ compute: 0 });
286
-
287
- await nextTick();
288
- expect(task1.isPending).toBe(false);
289
- expect(task1.result).toBe(undefined);
290
- expect(getC).toHaveCounts({ compute: 0 });
291
-
292
- const result1 = task1.run(3, 4);
293
- expect(task1.isPending).toBe(true);
294
- expect(task1.result).toBe(undefined);
295
- expect(getC).toHaveCounts({ compute: 1 });
296
-
297
- expect(await result1).toBe(10);
298
- expect(task1.isSuccess).toBe(true);
299
- expect(task1.result).toBe(10);
300
- expect(getC).toHaveCounts({ compute: 1 });
301
-
302
- const result2 = task1.run(5, 6, 7);
303
- expect(task1.isPending).toBe(true);
304
- expect(task1.result).toBe(10);
305
- expect(getC).toHaveCounts({ compute: 2 });
306
-
307
- expect(await result2).toBe(21);
308
- expect(task1.isSuccess).toBe(true);
309
- expect(task1.result).toBe(21);
310
- expect(getC).toHaveCounts({ compute: 2 });
311
- });
312
-
313
- test('Async task handles errors', async () => {
314
- const getC = asyncTask(async (shouldError: boolean) => {
315
- if (shouldError) {
316
- throw new Error('Test error');
317
- }
318
- return 'success';
319
- });
320
-
321
- const result1 = getC(false);
322
- await expect(result1.run()).resolves.toBe('success');
323
- await nextTick();
324
- expect(result1.isSuccess).toBe(true);
325
- expect(result1.result).toBe('success');
326
-
327
- const result2 = getC(true);
328
- await expect(result2.run()).rejects.toThrow('Test error');
329
- await nextTick();
330
- expect(result2.isError).toBe(true);
331
- expect(result2.error as Error).toBeInstanceOf(Error);
332
- expect((result2.error as Error).message).toBe('Test error');
333
- });
334
- });
@@ -1,126 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { state } from '../../index.js';
3
- import { computed } from '../utils/instrumented-hooks.js';
4
-
5
- describe('computeds', () => {
6
- test('Basic computed works', () => {
7
- const getC = computed((a: number, b: number) => {
8
- return a + b;
9
- });
10
-
11
- expect(getC).withParams(1, 2).toHaveValueAndCounts(3, { compute: 1 });
12
- expect(getC).withParams(2, 2).toHaveValueAndCounts(4, { compute: 2 });
13
- });
14
-
15
- test('Computed can throw errors', () => {
16
- const getC = computed((a: number) => {
17
- if (a < 0) throw new Error('negative number');
18
- return a * 2;
19
- });
20
-
21
- expect(getC).withParams(2).toHaveValueAndCounts(4, { compute: 1 });
22
- expect(() => getC(-1)).toThrow('negative number');
23
- });
24
-
25
- describe('nesting behavior', () => {
26
- test('Nested computeds work', () => {
27
- const getInner = computed((a: number, b: number) => {
28
- return a + b;
29
- });
30
-
31
- const getOuter = computed((x: number) => {
32
- return getInner(x, 2) * 2;
33
- });
34
-
35
- expect(getOuter).withParams(1).toHaveValueAndCounts(6, { compute: 1 });
36
- expect(getOuter).withParams(1).toHaveValueAndCounts(6, { compute: 1 });
37
- expect(getOuter).withParams(2).toHaveValueAndCounts(8, { compute: 2 });
38
- });
39
-
40
- test('Nested computeds with shared state', () => {
41
- const sharedState = state(1);
42
-
43
- const getInner = computed((a: number) => {
44
- return a + sharedState.get();
45
- });
46
-
47
- const getOuter = computed((x: number) => {
48
- return getInner(x) * 2;
49
- });
50
-
51
- expect(getOuter).withParams(1).toHaveValueAndCounts(4, { compute: 1 });
52
- sharedState.set(2);
53
- expect(getOuter).withParams(1).toHaveValueAndCounts(6, { compute: 2 });
54
- });
55
-
56
- test('Deeply nested computeds maintain independence', () => {
57
- const getA = computed((x: number) => {
58
- return x + 1;
59
- });
60
-
61
- const getB = computed((x: number) => {
62
- return getA(x) * 2 + getA(x * 2);
63
- });
64
-
65
- const getC = computed((x: number) => {
66
- return getB(x) + getA(x);
67
- });
68
-
69
- expect(getC).withParams(1).toHaveValueAndCounts(9, { compute: 1 });
70
- expect(getC).withParams(1).toHaveValueAndCounts(9, { compute: 1 });
71
- expect(getC).withParams(2).toHaveValueAndCounts(14, { compute: 2 });
72
- });
73
-
74
- test('Nested computeds work with state signals', () => {
75
- const stateA = state(1);
76
- const stateB = state(2);
77
-
78
- const getInner = computed((x: number) => {
79
- return x + stateA.get();
80
- });
81
-
82
- const getOuter = computed((x: number) => {
83
- return getInner(x) * stateB.get();
84
- });
85
-
86
- expect(getOuter).withParams(3).toHaveValueAndCounts(8, { compute: 1 });
87
-
88
- stateA.set(2);
89
- expect(getOuter).withParams(3).toHaveValueAndCounts(10, { compute: 2 });
90
-
91
- stateB.set(3);
92
- expect(getOuter).withParams(3).toHaveValueAndCounts(15, { compute: 3 });
93
-
94
- expect(getOuter).withParams(3).toHaveValueAndCounts(15, { compute: 3 });
95
- });
96
-
97
- test('Nested computeds work with both state and arguments', () => {
98
- const stateA = state(1);
99
- const stateB = state(2);
100
-
101
- const getInner = computed((x: number, y: number) => {
102
- return x + y + stateA.get();
103
- });
104
-
105
- const getMiddle = computed((x: number) => {
106
- return getInner(x, stateB.get()) * 2;
107
- });
108
-
109
- const getOuter = computed((x: number, y: number) => {
110
- return getMiddle(x) + y;
111
- });
112
-
113
- expect(getOuter).withParams(1, 3).toHaveValueAndCounts(11, { compute: 1 });
114
-
115
- stateB.set(3);
116
- expect(getOuter).withParams(1, 3).toHaveValueAndCounts(13, { compute: 2 });
117
-
118
- stateA.set(2);
119
- expect(getOuter).withParams(1, 3).toHaveValueAndCounts(15, { compute: 3 });
120
-
121
- expect(getOuter).withParams(1, 4).toHaveValueAndCounts(16, { compute: 4 });
122
-
123
- expect(getOuter).withParams(1, 4).toHaveValueAndCounts(16, { compute: 4 });
124
- });
125
- });
126
- });