signalium 0.2.8 → 0.3.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 (161) hide show
  1. package/.turbo/turbo-build.log +12 -0
  2. package/CHANGELOG.md +12 -0
  3. package/dist/cjs/config.d.ts +14 -5
  4. package/dist/cjs/config.d.ts.map +1 -1
  5. package/dist/cjs/config.js +23 -14
  6. package/dist/cjs/config.js.map +1 -1
  7. package/dist/cjs/debug.d.ts +3 -0
  8. package/dist/cjs/debug.d.ts.map +1 -0
  9. package/dist/cjs/debug.js +16 -0
  10. package/dist/cjs/debug.js.map +1 -0
  11. package/dist/cjs/hooks.d.ts +45 -0
  12. package/dist/cjs/hooks.d.ts.map +1 -0
  13. package/dist/cjs/hooks.js +263 -0
  14. package/dist/cjs/hooks.js.map +1 -0
  15. package/dist/cjs/index.d.ts +5 -3
  16. package/dist/cjs/index.d.ts.map +1 -1
  17. package/dist/cjs/index.js +21 -8
  18. package/dist/cjs/index.js.map +1 -1
  19. package/dist/cjs/react/context.d.ts +4 -0
  20. package/dist/cjs/react/context.d.ts.map +1 -0
  21. package/dist/cjs/react/context.js +10 -0
  22. package/dist/cjs/react/context.js.map +1 -0
  23. package/dist/cjs/react/index.d.ts +5 -0
  24. package/dist/cjs/react/index.d.ts.map +1 -0
  25. package/dist/cjs/react/index.js +12 -0
  26. package/dist/cjs/react/index.js.map +1 -0
  27. package/dist/cjs/react/provider.d.ts +7 -0
  28. package/dist/cjs/react/provider.d.ts.map +1 -0
  29. package/dist/cjs/react/provider.js +13 -0
  30. package/dist/cjs/react/provider.js.map +1 -0
  31. package/dist/cjs/react/setup.d.ts +2 -0
  32. package/dist/cjs/react/setup.d.ts.map +1 -0
  33. package/dist/cjs/react/setup.js +13 -0
  34. package/dist/cjs/react/setup.js.map +1 -0
  35. package/dist/cjs/react/signal-value.d.ts +2 -0
  36. package/dist/cjs/react/signal-value.d.ts.map +1 -0
  37. package/dist/cjs/react/signal-value.js +35 -0
  38. package/dist/cjs/react/signal-value.js.map +1 -0
  39. package/dist/cjs/react/state.d.ts +3 -0
  40. package/dist/cjs/react/state.d.ts.map +1 -0
  41. package/dist/cjs/react/state.js +13 -0
  42. package/dist/cjs/react/state.js.map +1 -0
  43. package/dist/cjs/scheduling.d.ts +5 -0
  44. package/dist/cjs/scheduling.d.ts.map +1 -1
  45. package/dist/cjs/scheduling.js +59 -5
  46. package/dist/cjs/scheduling.js.map +1 -1
  47. package/dist/cjs/signals.d.ts +28 -68
  48. package/dist/cjs/signals.d.ts.map +1 -1
  49. package/dist/cjs/signals.js +223 -76
  50. package/dist/cjs/signals.js.map +1 -1
  51. package/dist/cjs/trace.d.ts +127 -0
  52. package/dist/cjs/trace.d.ts.map +1 -0
  53. package/dist/cjs/trace.js +319 -0
  54. package/dist/cjs/trace.js.map +1 -0
  55. package/dist/cjs/types.d.ts +66 -0
  56. package/dist/cjs/types.d.ts.map +1 -0
  57. package/dist/cjs/types.js +3 -0
  58. package/dist/cjs/types.js.map +1 -0
  59. package/dist/cjs/utils.d.ts +4 -0
  60. package/dist/cjs/utils.d.ts.map +1 -0
  61. package/dist/cjs/utils.js +80 -0
  62. package/dist/cjs/utils.js.map +1 -0
  63. package/dist/esm/config.d.ts +14 -5
  64. package/dist/esm/config.d.ts.map +1 -1
  65. package/dist/esm/config.js +19 -11
  66. package/dist/esm/config.js.map +1 -1
  67. package/dist/esm/debug.d.ts +3 -0
  68. package/dist/esm/debug.d.ts.map +1 -0
  69. package/dist/esm/debug.js +3 -0
  70. package/dist/esm/debug.js.map +1 -0
  71. package/dist/esm/hooks.d.ts +45 -0
  72. package/dist/esm/hooks.d.ts.map +1 -0
  73. package/dist/esm/hooks.js +246 -0
  74. package/dist/esm/hooks.js.map +1 -0
  75. package/dist/esm/index.d.ts +5 -3
  76. package/dist/esm/index.d.ts.map +1 -1
  77. package/dist/esm/index.js +4 -2
  78. package/dist/esm/index.js.map +1 -1
  79. package/dist/esm/react/context.d.ts +4 -0
  80. package/dist/esm/react/context.d.ts.map +1 -0
  81. package/dist/esm/react/context.js +6 -0
  82. package/dist/esm/react/context.js.map +1 -0
  83. package/dist/esm/react/index.d.ts +5 -0
  84. package/dist/esm/react/index.d.ts.map +1 -0
  85. package/dist/esm/react/index.js +5 -0
  86. package/dist/esm/react/index.js.map +1 -0
  87. package/dist/esm/react/provider.d.ts +7 -0
  88. package/dist/esm/react/provider.d.ts.map +1 -0
  89. package/dist/esm/react/provider.js +10 -0
  90. package/dist/esm/react/provider.js.map +1 -0
  91. package/dist/esm/react/setup.d.ts +2 -0
  92. package/dist/esm/react/setup.d.ts.map +1 -0
  93. package/dist/esm/react/setup.js +10 -0
  94. package/dist/esm/react/setup.js.map +1 -0
  95. package/dist/esm/react/signal-value.d.ts +2 -0
  96. package/dist/esm/react/signal-value.d.ts.map +1 -0
  97. package/dist/esm/react/signal-value.js +32 -0
  98. package/dist/esm/react/signal-value.js.map +1 -0
  99. package/dist/esm/react/state.d.ts +3 -0
  100. package/dist/esm/react/state.d.ts.map +1 -0
  101. package/dist/esm/react/state.js +10 -0
  102. package/dist/esm/react/state.js.map +1 -0
  103. package/dist/esm/scheduling.d.ts +5 -0
  104. package/dist/esm/scheduling.d.ts.map +1 -1
  105. package/dist/esm/scheduling.js +51 -1
  106. package/dist/esm/scheduling.js.map +1 -1
  107. package/dist/esm/signals.d.ts +28 -68
  108. package/dist/esm/signals.d.ts.map +1 -1
  109. package/dist/esm/signals.js +215 -72
  110. package/dist/esm/signals.js.map +1 -1
  111. package/dist/esm/trace.d.ts +127 -0
  112. package/dist/esm/trace.d.ts.map +1 -0
  113. package/dist/esm/trace.js +311 -0
  114. package/dist/esm/trace.js.map +1 -0
  115. package/dist/esm/types.d.ts +66 -0
  116. package/dist/esm/types.d.ts.map +1 -0
  117. package/dist/esm/types.js +2 -0
  118. package/dist/esm/types.js.map +1 -0
  119. package/dist/esm/utils.d.ts +4 -0
  120. package/dist/esm/utils.d.ts.map +1 -0
  121. package/dist/esm/utils.js +75 -0
  122. package/dist/esm/utils.js.map +1 -0
  123. package/package.json +43 -2
  124. package/src/__tests__/hooks/async-computed.test.ts +190 -0
  125. package/src/__tests__/hooks/async-task.test.ts +227 -0
  126. package/src/__tests__/hooks/computed.test.ts +126 -0
  127. package/src/__tests__/hooks/context.test.ts +527 -0
  128. package/src/__tests__/hooks/nesting.test.ts +303 -0
  129. package/src/__tests__/hooks/params-and-state.test.ts +168 -0
  130. package/src/__tests__/hooks/subscription.test.ts +97 -0
  131. package/src/__tests__/signals/async.test.ts +416 -0
  132. package/src/__tests__/signals/basic.test.ts +399 -0
  133. package/src/__tests__/signals/subscription.test.ts +632 -0
  134. package/src/__tests__/signals/watcher.test.ts +253 -0
  135. package/src/__tests__/utils/async.ts +6 -0
  136. package/src/__tests__/utils/builders.ts +22 -0
  137. package/src/__tests__/utils/instrumented-hooks.ts +309 -0
  138. package/src/__tests__/utils/instrumented-signals.ts +281 -0
  139. package/src/__tests__/utils/permute.ts +74 -0
  140. package/src/config.ts +32 -17
  141. package/src/debug.ts +14 -0
  142. package/src/hooks.ts +433 -0
  143. package/src/index.ts +28 -3
  144. package/src/react/__tests__/react.test.tsx +227 -0
  145. package/src/react/context.ts +8 -0
  146. package/src/react/index.ts +4 -0
  147. package/src/react/provider.tsx +18 -0
  148. package/src/react/setup.ts +10 -0
  149. package/src/react/signal-value.ts +49 -0
  150. package/src/react/state.ts +13 -0
  151. package/src/scheduling.ts +69 -1
  152. package/src/signals.ts +328 -169
  153. package/src/trace.ts +449 -0
  154. package/src/types.ts +86 -0
  155. package/src/utils.ts +83 -0
  156. package/tsconfig.json +2 -1
  157. package/vitest.workspace.ts +24 -0
  158. package/src/__tests__/async.test.ts +0 -426
  159. package/src/__tests__/basic.test.ts +0 -378
  160. package/src/__tests__/subscription.test.ts +0 -645
  161. package/src/__tests__/utils/instrumented.ts +0 -326
@@ -1,426 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { state, asyncComputed, computed } from './utils/instrumented.js';
3
- import { AsyncResult } from '../signals';
4
-
5
- const sleep = (ms = 0) => new Promise(r => setTimeout(r, ms));
6
- const nextTick = () => new Promise(r => setTimeout(r, 0));
7
-
8
- const result = <T>(
9
- value: T | undefined,
10
- promiseState: 'pending' | 'error' | 'success',
11
- readyState: 'initial' | 'ready' | 'resolved',
12
- error?: any,
13
- ): AsyncResult<T> =>
14
- ({
15
- result: value,
16
- error,
17
- isPending: promiseState === 'pending',
18
- isError: promiseState === 'error',
19
- isSuccess: promiseState === 'success',
20
-
21
- isReady: readyState === 'ready' || readyState === 'resolved',
22
- didResolve: readyState === 'resolved',
23
-
24
- await: expect.any(Function),
25
- invalidate: expect.any(Function),
26
- }) as AsyncResult<T>;
27
-
28
- describe('Async Signal functionality', () => {
29
- test('Can run basic computed', async () => {
30
- const a = state(1);
31
- const b = state(2);
32
-
33
- const c = asyncComputed(async () => {
34
- return a.get() + b.get();
35
- });
36
-
37
- expect(c).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
38
- compute: 1,
39
- resolve: 0,
40
- });
41
-
42
- await nextTick();
43
-
44
- expect(c).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
45
- compute: 1,
46
- resolve: 1,
47
- });
48
-
49
- // stability
50
- expect(c).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
51
- compute: 1,
52
- resolve: 1,
53
- });
54
- });
55
-
56
- test('Computeds can be updated', async () => {
57
- const a = state(1);
58
- const b = state(2);
59
-
60
- const c = asyncComputed(async () => {
61
- return a.get() + b.get();
62
- });
63
-
64
- expect(c).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
65
- compute: 1,
66
- resolve: 0,
67
- });
68
-
69
- await nextTick();
70
-
71
- expect(c).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
72
- compute: 1,
73
- resolve: 1,
74
- });
75
-
76
- a.set(2);
77
-
78
- expect(c).toHaveValueAndCounts(result(3, 'pending', 'resolved'), {
79
- compute: 2,
80
- resolve: 1,
81
- });
82
-
83
- await nextTick();
84
-
85
- expect(c).toHaveValueAndCounts(result(4, 'success', 'resolved'), {
86
- compute: 2,
87
- resolve: 2,
88
- });
89
- });
90
-
91
- test('Does not update if value is the same', async () => {
92
- const a = state(1);
93
- const b = state(2);
94
-
95
- const c = asyncComputed(async () => {
96
- return a.get() + b.get();
97
- });
98
-
99
- expect(c).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
100
- compute: 1,
101
- resolve: 0,
102
- });
103
-
104
- await nextTick();
105
-
106
- expect(c).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
107
- compute: 1,
108
- resolve: 1,
109
- });
110
-
111
- a.set(1);
112
-
113
- expect(c).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
114
- compute: 1,
115
- resolve: 1,
116
- });
117
-
118
- await nextTick();
119
-
120
- expect(c).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
121
- compute: 1,
122
- resolve: 1,
123
- });
124
- });
125
-
126
- test('Skips resolution if value is updated multiple times', async () => {
127
- const a = state(1);
128
- const b = state(2);
129
-
130
- const c = asyncComputed(async () => {
131
- const result = a.get() + b.get();
132
-
133
- if (result === 4) {
134
- await sleep(10);
135
- }
136
-
137
- return result;
138
- });
139
-
140
- expect(c).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
141
- compute: 1,
142
- resolve: 0,
143
- });
144
-
145
- await nextTick();
146
-
147
- expect(c).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
148
- compute: 1,
149
- resolve: 1,
150
- });
151
-
152
- a.set(2);
153
-
154
- expect(c).toHaveValueAndCounts(result(3, 'pending', 'resolved'), {
155
- compute: 2,
156
- resolve: 1,
157
- });
158
-
159
- a.set(3);
160
-
161
- expect(c).toHaveValueAndCounts(result(3, 'pending', 'resolved'), {
162
- compute: 3,
163
- resolve: 1,
164
- });
165
-
166
- await sleep(20);
167
-
168
- expect(c).toHaveValueAndCounts(result(5, 'success', 'resolved'), {
169
- compute: 3,
170
- resolve: 3,
171
- });
172
- });
173
-
174
- test('Can have initial value', async () => {
175
- const a = state(1);
176
- const b = state(2);
177
-
178
- const c = asyncComputed(
179
- async () => {
180
- const result = a.get() + b.get();
181
-
182
- await sleep(10);
183
-
184
- return result;
185
- },
186
- {
187
- initValue: 5,
188
- },
189
- );
190
-
191
- expect(c).toHaveValueAndCounts(result(5, 'pending', 'ready'), {
192
- compute: 1,
193
- resolve: 0,
194
- });
195
-
196
- await nextTick();
197
-
198
- expect(c).toHaveValueAndCounts(result(5, 'pending', 'ready'), {
199
- compute: 1,
200
- resolve: 0,
201
- });
202
-
203
- await sleep(20);
204
-
205
- expect(c).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
206
- compute: 1,
207
- resolve: 1,
208
- });
209
- });
210
-
211
- describe('Awaiting', () => {
212
- test('Awaiting a computed will resolve the value', async () => {
213
- const compA = asyncComputed(async () => {
214
- await sleep(10);
215
-
216
- return 1;
217
- });
218
-
219
- const compB = asyncComputed(async () => {
220
- await sleep(10);
221
-
222
- return 2;
223
- });
224
-
225
- const compC = asyncComputed(async () => {
226
- const a = compA.get().await();
227
- const b = compB.get().await();
228
-
229
- return a + b;
230
- });
231
-
232
- // Pull once to start the computation, trigger the computation
233
- expect(compC).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
234
- compute: 1,
235
- resolve: 0,
236
- });
237
-
238
- await nextTick();
239
-
240
- // Check after a tick to make sure we didn't resolve early
241
- expect(compC).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
242
- compute: 1,
243
- resolve: 0,
244
- });
245
-
246
- await sleep(20);
247
-
248
- // Check to make sure we don't resolve early after the first task completes
249
- expect(compC).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
250
- compute: 2,
251
- resolve: 0,
252
- });
253
-
254
- await sleep(20);
255
-
256
- expect(compC).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
257
- compute: 3,
258
- resolve: 1,
259
- });
260
- });
261
-
262
- test('Awaiting a computed can handle errors', async () => {
263
- const compA = asyncComputed(async () => {
264
- await sleep(10);
265
-
266
- throw 'error';
267
- });
268
-
269
- const compB = asyncComputed(async () => {
270
- await sleep(20);
271
-
272
- return 2;
273
- });
274
-
275
- const compC = asyncComputed(async () => {
276
- const a = compA.get().await();
277
- const b = compB.get().await();
278
-
279
- return a + b;
280
- });
281
-
282
- // Pull once to start the computation, trigger the computation
283
- expect(compC).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
284
- compute: 1,
285
- resolve: 0,
286
- });
287
-
288
- await sleep(15);
289
-
290
- expect(compC).toHaveValueAndCounts(result(undefined, 'error', 'initial', 'error'), {
291
- compute: 2,
292
- resolve: 0,
293
- });
294
- });
295
-
296
- test('Awaiting a computed does not let valid values override errors', async () => {
297
- const compA = asyncComputed(async () => {
298
- await sleep(10);
299
-
300
- throw 'error';
301
- });
302
-
303
- const compB = asyncComputed(async () => {
304
- await sleep(20);
305
-
306
- return 2;
307
- });
308
-
309
- const compC = asyncComputed(async () => {
310
- const aResult = compA.get();
311
- const bResult = compB.get();
312
-
313
- const b = bResult.await();
314
- const a = aResult.await();
315
-
316
- return a + b;
317
- });
318
-
319
- // Pull once to start the computation, trigger the computation
320
- expect(compC).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
321
- compute: 1,
322
- resolve: 0,
323
- });
324
-
325
- await sleep(40);
326
-
327
- expect(compC).toHaveValueAndCounts(result(undefined, 'error', 'initial', 'error'), {
328
- compute: 2,
329
- resolve: 0,
330
- });
331
- });
332
-
333
- test('Await can be composed and nested', async () => {
334
- const compA = asyncComputed('compA', async () => {
335
- await sleep(20);
336
- return 1;
337
- });
338
-
339
- const compB = asyncComputed('compB', async () => {
340
- await sleep(20);
341
- return 2;
342
- });
343
-
344
- const compC = computed('compC', () => {
345
- const resultA = compA.get();
346
- const resultB = compB.get();
347
-
348
- return {
349
- awaitA: resultA.await,
350
- awaitB: resultB.await,
351
- };
352
- });
353
-
354
- const compD = asyncComputed('compD', async () => {
355
- const { awaitA, awaitB } = compC.get();
356
- const a = awaitA();
357
- const b = awaitB();
358
-
359
- return a + b;
360
- });
361
-
362
- // Pull once to start the computation, trigger the computation
363
- expect(compD).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
364
- compute: 1,
365
- resolve: 0,
366
- });
367
-
368
- await sleep(30);
369
-
370
- expect(compD).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
371
- compute: 2,
372
- resolve: 1,
373
- });
374
- });
375
-
376
- test('Await works with intermediate state', async () => {
377
- const compA = asyncComputed('compA', async () => {
378
- await sleep(20);
379
- return 1;
380
- });
381
-
382
- const compB = asyncComputed('compB', async () => {
383
- await sleep(40);
384
- return 2;
385
- });
386
-
387
- const compC = computed('compC', () => {
388
- const resultA = compA.get();
389
- const resultB = compB.get();
390
-
391
- return {
392
- awaitA: resultA.await,
393
- awaitB: resultB.await,
394
- };
395
- });
396
-
397
- const compD = asyncComputed('compD', async () => {
398
- const { awaitA, awaitB } = compC.get();
399
- const a = awaitA();
400
- const b = awaitB();
401
-
402
- return a + b;
403
- });
404
-
405
- // Pull once to start the computation, trigger the computation
406
- expect(compD).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
407
- compute: 1,
408
- resolve: 0,
409
- });
410
-
411
- await sleep(30);
412
-
413
- expect(compD).toHaveValueAndCounts(result(undefined, 'pending', 'initial'), {
414
- compute: 2,
415
- resolve: 0,
416
- });
417
-
418
- await sleep(30);
419
-
420
- expect(compD).toHaveValueAndCounts(result(3, 'success', 'resolved'), {
421
- compute: 3,
422
- resolve: 1,
423
- });
424
- });
425
- });
426
- });