@zeix/cause-effect 0.17.2 → 0.18.0

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 (94) hide show
  1. package/.ai-context.md +163 -226
  2. package/.cursorrules +41 -35
  3. package/.github/copilot-instructions.md +166 -116
  4. package/.zed/settings.json +3 -0
  5. package/ARCHITECTURE.md +274 -0
  6. package/CLAUDE.md +197 -202
  7. package/COLLECTION_REFACTORING.md +161 -0
  8. package/GUIDE.md +298 -0
  9. package/README.md +241 -220
  10. package/REQUIREMENTS.md +100 -0
  11. package/bench/reactivity.bench.ts +577 -0
  12. package/index.dev.js +1326 -1174
  13. package/index.js +1 -1
  14. package/index.ts +58 -85
  15. package/package.json +9 -6
  16. package/src/errors.ts +118 -70
  17. package/src/graph.ts +601 -0
  18. package/src/nodes/collection.ts +474 -0
  19. package/src/nodes/effect.ts +149 -0
  20. package/src/nodes/list.ts +588 -0
  21. package/src/nodes/memo.ts +120 -0
  22. package/src/nodes/sensor.ts +139 -0
  23. package/src/nodes/state.ts +135 -0
  24. package/src/nodes/store.ts +383 -0
  25. package/src/nodes/task.ts +146 -0
  26. package/src/signal.ts +112 -64
  27. package/src/util.ts +26 -57
  28. package/test/batch.test.ts +96 -69
  29. package/test/benchmark.test.ts +473 -485
  30. package/test/collection.test.ts +455 -955
  31. package/test/effect.test.ts +293 -696
  32. package/test/list.test.ts +332 -857
  33. package/test/memo.test.ts +380 -0
  34. package/test/regression.test.ts +156 -0
  35. package/test/scope.test.ts +191 -0
  36. package/test/sensor.test.ts +454 -0
  37. package/test/signal.test.ts +220 -213
  38. package/test/state.test.ts +217 -271
  39. package/test/store.test.ts +346 -898
  40. package/test/task.test.ts +395 -0
  41. package/test/untrack.test.ts +167 -0
  42. package/test/util/dependency-graph.ts +2 -2
  43. package/tsconfig.build.json +11 -0
  44. package/tsconfig.json +5 -7
  45. package/types/index.d.ts +13 -15
  46. package/types/src/errors.d.ts +73 -19
  47. package/types/src/graph.d.ts +208 -0
  48. package/types/src/nodes/collection.d.ts +64 -0
  49. package/types/src/nodes/effect.d.ts +48 -0
  50. package/types/src/nodes/list.d.ts +65 -0
  51. package/types/src/nodes/memo.d.ts +57 -0
  52. package/types/src/nodes/sensor.d.ts +75 -0
  53. package/types/src/nodes/state.d.ts +78 -0
  54. package/types/src/nodes/store.d.ts +51 -0
  55. package/types/src/nodes/task.d.ts +73 -0
  56. package/types/src/signal.d.ts +43 -28
  57. package/types/src/util.d.ts +9 -16
  58. package/archive/benchmark.ts +0 -688
  59. package/archive/collection.ts +0 -310
  60. package/archive/computed.ts +0 -198
  61. package/archive/list.ts +0 -544
  62. package/archive/memo.ts +0 -140
  63. package/archive/state.ts +0 -90
  64. package/archive/store.ts +0 -357
  65. package/archive/task.ts +0 -191
  66. package/src/classes/collection.ts +0 -298
  67. package/src/classes/composite.ts +0 -171
  68. package/src/classes/computed.ts +0 -392
  69. package/src/classes/list.ts +0 -310
  70. package/src/classes/ref.ts +0 -96
  71. package/src/classes/state.ts +0 -131
  72. package/src/classes/store.ts +0 -227
  73. package/src/diff.ts +0 -138
  74. package/src/effect.ts +0 -96
  75. package/src/match.ts +0 -45
  76. package/src/resolve.ts +0 -49
  77. package/src/system.ts +0 -275
  78. package/test/computed.test.ts +0 -1126
  79. package/test/diff.test.ts +0 -955
  80. package/test/match.test.ts +0 -388
  81. package/test/ref.test.ts +0 -381
  82. package/test/resolve.test.ts +0 -154
  83. package/types/src/classes/collection.d.ts +0 -47
  84. package/types/src/classes/composite.d.ts +0 -15
  85. package/types/src/classes/computed.d.ts +0 -114
  86. package/types/src/classes/list.d.ts +0 -41
  87. package/types/src/classes/ref.d.ts +0 -48
  88. package/types/src/classes/state.d.ts +0 -61
  89. package/types/src/classes/store.d.ts +0 -51
  90. package/types/src/diff.d.ts +0 -28
  91. package/types/src/effect.d.ts +0 -15
  92. package/types/src/match.d.ts +0 -21
  93. package/types/src/resolve.d.ts +0 -29
  94. package/types/src/system.d.ts +0 -81
@@ -0,0 +1,395 @@
1
+ import { describe, expect, test } from 'bun:test'
2
+ import {
3
+ createEffect,
4
+ createMemo,
5
+ createState,
6
+ createTask,
7
+ isMemo,
8
+ isTask,
9
+ UnsetSignalValueError,
10
+ } from '../index.ts'
11
+
12
+ /* === Utility Functions === */
13
+
14
+ const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
15
+
16
+ /* === Tests === */
17
+
18
+ describe('Task', () => {
19
+ describe('createTask', () => {
20
+ test('should resolve async computation', async () => {
21
+ const task = createTask(
22
+ async () => {
23
+ await wait(50)
24
+ return 42
25
+ },
26
+ { value: 0 },
27
+ )
28
+ expect(task.get()).toBe(0)
29
+ await wait(60)
30
+ expect(task.get()).toBe(42)
31
+ })
32
+
33
+ test('should have Symbol.toStringTag of "Task"', () => {
34
+ const task = createTask(async () => 1, { value: 0 })
35
+ expect(task[Symbol.toStringTag]).toBe('Task')
36
+ })
37
+
38
+ test('should throw UnsetSignalValueError before resolution with no initial value', () => {
39
+ const task = createTask(async () => {
40
+ await wait(50)
41
+ return 42
42
+ })
43
+ expect(() => task.get()).toThrow(UnsetSignalValueError)
44
+ })
45
+ })
46
+
47
+ describe('isTask', () => {
48
+ test('should identify task signals', () => {
49
+ expect(isTask(createTask(async () => 1, { value: 0 }))).toBe(true)
50
+ })
51
+
52
+ test('should return false for non-task values', () => {
53
+ expect(isTask(42)).toBe(false)
54
+ expect(isTask(null)).toBe(false)
55
+ expect(isTask({})).toBe(false)
56
+ expect(isMemo(createTask(async () => 1, { value: 0 }))).toBe(false)
57
+ })
58
+ })
59
+
60
+ describe('isPending', () => {
61
+ test('should return true while computation is in-flight', async () => {
62
+ const task = createTask(
63
+ async () => {
64
+ await wait(50)
65
+ return 42
66
+ },
67
+ { value: 0 },
68
+ )
69
+ task.get() // trigger computation
70
+ expect(task.isPending()).toBe(true)
71
+ await wait(60)
72
+ task.get() // read resolved value
73
+ expect(task.isPending()).toBe(false)
74
+ })
75
+
76
+ test('should return false before first get()', () => {
77
+ const task = createTask(async () => 42, { value: 0 })
78
+ expect(task.isPending()).toBe(false)
79
+ })
80
+ })
81
+
82
+ describe('abort', () => {
83
+ test('should abort the current computation', async () => {
84
+ let completed = false
85
+ const task = createTask(
86
+ async (_prev, signal) => {
87
+ await wait(50)
88
+ if (!signal.aborted) completed = true
89
+ return 42
90
+ },
91
+ { value: 0 },
92
+ )
93
+ task.get() // trigger computation
94
+ expect(task.isPending()).toBe(true)
95
+ task.abort()
96
+ expect(task.isPending()).toBe(false)
97
+ await wait(60)
98
+ expect(completed).toBe(false)
99
+ })
100
+ })
101
+
102
+ describe('Dependency Tracking', () => {
103
+ test('should re-execute when dependencies change', async () => {
104
+ const source = createState(1)
105
+ const task = createTask(
106
+ async () => {
107
+ const val = source.get() // dependency tracked before await
108
+ await wait(50)
109
+ return val * 2
110
+ },
111
+ { value: 0 },
112
+ )
113
+
114
+ let result = 0
115
+ createEffect(() => {
116
+ result = task.get()
117
+ })
118
+ expect(result).toBe(0)
119
+ await wait(60)
120
+ expect(result).toBe(2)
121
+
122
+ source.set(5)
123
+ await wait(60)
124
+ expect(result).toBe(10)
125
+ })
126
+
127
+ test('should work with downstream memos', async () => {
128
+ const status = createState('pending')
129
+ const task = createTask(async () => {
130
+ await wait(50)
131
+ status.set('success')
132
+ return 42
133
+ })
134
+ const derived = createMemo(() => {
135
+ try {
136
+ return task.get() + 1
137
+ } catch {
138
+ return 0
139
+ }
140
+ })
141
+ expect(derived.get()).toBe(0)
142
+ expect(status.get()).toBe('pending')
143
+ await wait(60)
144
+ expect(derived.get()).toBe(43)
145
+ expect(status.get()).toBe('success')
146
+ })
147
+
148
+ test('should run tasks in parallel without waterfalls', async () => {
149
+ const a = createTask(
150
+ async () => {
151
+ await wait(80)
152
+ return 10
153
+ },
154
+ { value: 0 },
155
+ )
156
+ const b = createTask(
157
+ async () => {
158
+ await wait(80)
159
+ return 20
160
+ },
161
+ { value: 0 },
162
+ )
163
+ const sum = createMemo(() => a.get() + b.get(), { value: 0 })
164
+ expect(sum.get()).toBe(0)
165
+ await wait(90)
166
+ expect(sum.get()).toBe(30)
167
+ })
168
+ })
169
+
170
+ describe('AbortSignal', () => {
171
+ test('should signal abort when dependency changes during computation', async () => {
172
+ const source = createState(1)
173
+ let wasAborted = false
174
+ const task = createTask(
175
+ async (_prev, signal) => {
176
+ const val = source.get()
177
+ await wait(100)
178
+ if (signal.aborted) wasAborted = true
179
+ return val
180
+ },
181
+ { value: 0 },
182
+ )
183
+
184
+ task.get() // start computation
185
+ await wait(10)
186
+ source.set(2) // change dependency mid-flight
187
+
188
+ await wait(110)
189
+ expect(wasAborted).toBe(true)
190
+ })
191
+
192
+ test('should coalesce multiple rapid changes into one recomputation', async () => {
193
+ const source = createState(1)
194
+ let computationCount = 0
195
+ const task = createTask(
196
+ async () => {
197
+ computationCount++
198
+ await wait(100)
199
+ return source.get()
200
+ },
201
+ { value: 0 },
202
+ )
203
+
204
+ task.get()
205
+ expect(computationCount).toBe(1)
206
+
207
+ source.set(2)
208
+ source.set(3)
209
+ source.set(4)
210
+ await wait(210)
211
+
212
+ expect(task.get()).toBe(4)
213
+ expect(computationCount).toBe(1)
214
+ })
215
+ })
216
+
217
+ describe('Error Handling', () => {
218
+ test('should propagate async errors on get()', async () => {
219
+ const task = createTask(
220
+ async () => {
221
+ await wait(50)
222
+ throw new Error('async failure')
223
+ },
224
+ { value: 0 },
225
+ )
226
+ task.get()
227
+ await wait(60)
228
+ expect(() => task.get()).toThrow('async failure')
229
+ })
230
+
231
+ test('should recover from errors when dependency changes', async () => {
232
+ const source = createState(1)
233
+ const task = createTask(
234
+ async () => {
235
+ const value = source.get()
236
+ await wait(50)
237
+ if (value === 2) throw new Error('bad value')
238
+ return value
239
+ },
240
+ { value: 0 },
241
+ )
242
+
243
+ task.get()
244
+ await wait(60)
245
+ expect(task.get()).toBe(1)
246
+
247
+ source.set(2)
248
+ task.get()
249
+ await wait(60)
250
+ expect(() => task.get()).toThrow('bad value')
251
+
252
+ source.set(3)
253
+ task.get()
254
+ await wait(60)
255
+ expect(task.get()).toBe(3)
256
+ })
257
+ })
258
+
259
+ describe('options.value (prev)', () => {
260
+ test('should return initial value before resolution', () => {
261
+ const task = createTask(
262
+ async () => {
263
+ await wait(50)
264
+ return 42
265
+ },
266
+ { value: 10 },
267
+ )
268
+ expect(task.get()).toBe(10)
269
+ })
270
+
271
+ test('should pass initial value as prev to first computation', async () => {
272
+ let receivedPrev: number | undefined
273
+ const task = createTask(
274
+ async prev => {
275
+ receivedPrev = prev
276
+ await wait(50)
277
+ return prev + 5
278
+ },
279
+ { value: 10 },
280
+ )
281
+
282
+ expect(task.get()).toBe(10)
283
+ await wait(60)
284
+ expect(task.get()).toBe(15)
285
+ expect(receivedPrev).toBe(10)
286
+ })
287
+
288
+ test('should pass previous resolved value on recomputation', async () => {
289
+ const source = createState(1)
290
+ const receivedPrevs: number[] = []
291
+ const task = createTask(
292
+ async prev => {
293
+ const val = source.get() // dependency tracked before await
294
+ receivedPrevs.push(prev)
295
+ await wait(50)
296
+ return val + prev
297
+ },
298
+ { value: 0 },
299
+ )
300
+
301
+ let result = 0
302
+ createEffect(() => {
303
+ result = task.get()
304
+ })
305
+ await wait(60)
306
+ expect(result).toBe(1) // 0 + 1
307
+
308
+ source.set(2)
309
+ await wait(60)
310
+ expect(result).toBe(3) // 1 + 2
311
+ expect(receivedPrevs).toEqual([0, 1])
312
+ })
313
+ })
314
+
315
+ describe('options.equals', () => {
316
+ test('should use custom equality to skip propagation after resolution', async () => {
317
+ const source = createState(1)
318
+ let effectCount = 0
319
+ const task = createTask(
320
+ async () => {
321
+ const val = source.get() // dependency tracked before await
322
+ await wait(50)
323
+ return { x: val % 2 }
324
+ },
325
+ {
326
+ value: { x: -1 },
327
+ equals: (a, b) => a.x === b.x,
328
+ },
329
+ )
330
+
331
+ createEffect(() => {
332
+ task.get()
333
+ effectCount++
334
+ })
335
+ await wait(60) // first resolution: { x: 1 }
336
+
337
+ source.set(3) // still odd — result will be { x: 1 }, structurally equal
338
+ await wait(60)
339
+ const countAfterEqual = effectCount
340
+
341
+ source.set(2) // now even — result will be { x: 0 }, different
342
+ await wait(60)
343
+
344
+ // After the structurally different result resolves, effect should run again
345
+ expect(effectCount).toBeGreaterThan(countAfterEqual)
346
+ })
347
+ })
348
+
349
+ describe('options.guard', () => {
350
+ test('should validate initial value against guard', () => {
351
+ expect(() => {
352
+ createTask(async () => 42, {
353
+ // @ts-expect-error - Testing invalid input
354
+ value: 'foo',
355
+ guard: (v): v is number => typeof v === 'number',
356
+ })
357
+ }).toThrow('[Task] Signal value "foo" is invalid')
358
+ })
359
+
360
+ test('should accept initial value that passes guard', () => {
361
+ const task = createTask(async () => 42, {
362
+ value: 10,
363
+ guard: (v): v is number => typeof v === 'number',
364
+ })
365
+ expect(task.get()).toBe(10)
366
+ })
367
+ })
368
+
369
+ describe('Input Validation', () => {
370
+ test('should throw InvalidCallbackError for sync callback', () => {
371
+ expect(() => {
372
+ // @ts-expect-error - Testing invalid input
373
+ createTask((_a: unknown) => 42)
374
+ }).toThrow('[Task] Callback (_a) => 42 is invalid')
375
+ })
376
+
377
+ test('should throw InvalidCallbackError for non-function callback', () => {
378
+ // @ts-expect-error - Testing invalid input
379
+ expect(() => createTask(null)).toThrow(
380
+ '[Task] Callback null is invalid',
381
+ )
382
+ // @ts-expect-error - Testing invalid input
383
+ expect(() => createTask(42)).toThrow(
384
+ '[Task] Callback 42 is invalid',
385
+ )
386
+ })
387
+
388
+ test('should throw NullishSignalValueError for null initial value', () => {
389
+ expect(() => {
390
+ // @ts-expect-error - Testing invalid input
391
+ createTask(async () => 42, { value: null })
392
+ }).toThrow('[Task] Signal value cannot be null or undefined')
393
+ })
394
+ })
395
+ })
@@ -0,0 +1,167 @@
1
+ import { describe, expect, test } from 'bun:test'
2
+ import {
3
+ createEffect,
4
+ createMemo,
5
+ createScope,
6
+ createState,
7
+ untrack,
8
+ } from '../index.ts'
9
+
10
+ /* === Tests === */
11
+
12
+ describe('untrack', () => {
13
+ test('should return the value of the callback', () => {
14
+ const result = untrack(() => 42)
15
+ expect(result).toBe(42)
16
+ })
17
+
18
+ test('should read a signal without tracking it', () => {
19
+ const tracked = createState('tracked')
20
+ const untracked = createState('untracked')
21
+ let count = 0
22
+ createEffect((): undefined => {
23
+ tracked.get()
24
+ untrack(() => untracked.get())
25
+ count++
26
+ })
27
+ expect(count).toBe(1)
28
+
29
+ // changing tracked signal should re-run the effect
30
+ tracked.set('changed')
31
+ expect(count).toBe(2)
32
+
33
+ // changing untracked signal should not re-run the effect
34
+ untracked.set('changed')
35
+ expect(count).toBe(2)
36
+ })
37
+
38
+ test('should not track dependencies in memos', () => {
39
+ const a = createState(1)
40
+ const b = createState(2)
41
+ const sum = createMemo(() => a.get() + untrack(() => b.get()))
42
+ expect(sum.get()).toBe(3)
43
+
44
+ // changing a should recompute
45
+ a.set(10)
46
+ expect(sum.get()).toBe(12)
47
+
48
+ // changing b should not recompute (stale value of b used)
49
+ b.set(20)
50
+ expect(sum.get()).toBe(12)
51
+ })
52
+
53
+ test('should prevent dependency pollution from subcomponent creation', () => {
54
+ const parentSignal = createState('parent')
55
+ let parentRuns = 0
56
+ let childRuns = 0
57
+
58
+ const dispose = createScope(() => {
59
+ createEffect((): undefined => {
60
+ parentSignal.get()
61
+ parentRuns++
62
+
63
+ // Simulate subcomponent: create local state + effect
64
+ // Without untrack, childSignal.get() in the child effect
65
+ // would link to the parent effect during initial run
66
+ untrack(() => {
67
+ const childSignal = createState('child')
68
+ createEffect((): undefined => {
69
+ childSignal.get()
70
+ childRuns++
71
+ })
72
+ childSignal.set('updated')
73
+ })
74
+ })
75
+ })
76
+
77
+ expect(parentRuns).toBe(1)
78
+ expect(childRuns).toBe(2) // initial + update
79
+
80
+ // parent should re-run when its own signal changes
81
+ parentSignal.set('changed')
82
+ expect(parentRuns).toBe(2)
83
+
84
+ dispose()
85
+ })
86
+
87
+ test('should prevent parent effect from re-running on child signal changes', () => {
88
+ const show = createState(true)
89
+ let parentRuns = 0
90
+ let childValue = ''
91
+
92
+ const dispose = createScope(() => {
93
+ createEffect((): undefined => {
94
+ parentRuns++
95
+ if (show.get()) {
96
+ // Subcomponent with its own reactive state
97
+ untrack(() => {
98
+ const label = createState('hello')
99
+ createEffect((): undefined => {
100
+ childValue = label.get()
101
+ })
102
+ label.set('world')
103
+ })
104
+ }
105
+ })
106
+ })
107
+
108
+ expect(parentRuns).toBe(1)
109
+ expect(childValue).toBe('world')
110
+
111
+ // toggling show re-runs parent (it's tracked)
112
+ show.set(false)
113
+ expect(parentRuns).toBe(2)
114
+
115
+ dispose()
116
+ })
117
+
118
+ test('should nest correctly', () => {
119
+ const a = createState(1)
120
+ const b = createState(2)
121
+ const c = createState(3)
122
+ let count = 0
123
+ createEffect((): undefined => {
124
+ a.get()
125
+ untrack(() => {
126
+ b.get()
127
+ untrack(() => {
128
+ c.get()
129
+ })
130
+ })
131
+ count++
132
+ })
133
+ expect(count).toBe(1)
134
+
135
+ a.set(10)
136
+ expect(count).toBe(2)
137
+
138
+ b.set(20)
139
+ expect(count).toBe(2)
140
+
141
+ c.set(30)
142
+ expect(count).toBe(2)
143
+ })
144
+
145
+ test('should restore tracking after untrack completes', () => {
146
+ const before = createState('before')
147
+ const during = createState('during')
148
+ const after = createState('after')
149
+ let count = 0
150
+ createEffect((): undefined => {
151
+ before.get()
152
+ untrack(() => during.get())
153
+ after.get()
154
+ count++
155
+ })
156
+ expect(count).toBe(1)
157
+
158
+ before.set('x')
159
+ expect(count).toBe(2)
160
+
161
+ during.set('x')
162
+ expect(count).toBe(2)
163
+
164
+ after.set('x')
165
+ expect(count).toBe(3)
166
+ })
167
+ })
@@ -124,7 +124,7 @@ function makeDependentRows(
124
124
  ): Computed<number>[][] {
125
125
  let prevRow = sources
126
126
  const rand = new Random('seed')
127
- const rows = []
127
+ const rows: Computed<number>[][] = []
128
128
  for (let l = 0; l < numRows; l++) {
129
129
  const row = makeRow(
130
130
  prevRow,
@@ -135,7 +135,7 @@ function makeDependentRows(
135
135
  l,
136
136
  rand,
137
137
  )
138
- rows.push(row as never)
138
+ rows.push(row)
139
139
  prevRow = row
140
140
  }
141
141
  return rows
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": false,
5
+ "declaration": true,
6
+ "declarationDir": "./types",
7
+ "emitDeclarationOnly": true,
8
+ },
9
+ "include": ["./index.ts", "./src/**/*.ts"],
10
+ "exclude": ["node_modules", "types", "test", "archive"],
11
+ }
package/tsconfig.json CHANGED
@@ -13,6 +13,9 @@
13
13
  "allowImportingTsExtensions": true,
14
14
  "verbatimModuleSyntax": true,
15
15
 
16
+ // Editor-only mode - no emit
17
+ "noEmit": true,
18
+
16
19
  // Best practices
17
20
  "strict": true,
18
21
  "skipLibCheck": true,
@@ -22,12 +25,7 @@
22
25
  "noUnusedLocals": false,
23
26
  "noUnusedParameters": false,
24
27
  "noPropertyAccessFromIndexSignature": false,
25
-
26
- // Declarations
27
- "declaration": true,
28
- "declarationDir": "./types",
29
- "emitDeclarationOnly": true
30
28
  },
31
- "include": ["./*.ts", "./src/*.ts"],
32
- "exclude": ["node_modules", "test", "types"]
29
+ "include": ["./**/*.ts"],
30
+ "exclude": ["node_modules", "types"],
33
31
  }
package/types/index.d.ts CHANGED
@@ -1,19 +1,17 @@
1
1
  /**
2
2
  * @name Cause & Effect
3
- * @version 0.17.2
3
+ * @version 0.18.0
4
4
  * @author Esther Brunner
5
5
  */
6
- export { type Collection, type CollectionCallback, type CollectionSource, DerivedCollection, isCollection, TYPE_COLLECTION, } from './src/classes/collection';
7
- export { type Computed, createComputed, isComputed, isMemoCallback, isTaskCallback, Memo, type MemoCallback, Task, type TaskCallback, TYPE_COMPUTED, } from './src/classes/computed';
8
- export { type ArrayToRecord, isList, type KeyConfig, List, TYPE_LIST, } from './src/classes/list';
9
- export { isRef, Ref, TYPE_REF } from './src/classes/ref';
10
- export { isState, State, TYPE_STATE } from './src/classes/state';
11
- export { BaseStore, createStore, isStore, type Store, TYPE_STORE, } from './src/classes/store';
12
- export { type DiffResult, diff, isEqual, type UnknownArray, type UnknownRecord, } from './src/diff';
13
- export { createEffect, type EffectCallback, type MaybeCleanup, } from './src/effect';
14
- export { CircularDependencyError, createError, DuplicateKeyError, type Guard, guardMutableSignal, InvalidCallbackError, InvalidCollectionSourceError, InvalidSignalValueError, NullishSignalValueError, ReadonlySignalError, validateCallback, validateSignalValue, } from './src/errors';
15
- export { type MatchHandlers, match } from './src/match';
16
- export { type ResolveResult, resolve } from './src/resolve';
17
- export { createSignal, isMutableSignal, isSignal, type Signal, type SignalValues, type UnknownSignalRecord, } from './src/signal';
18
- export { batchSignalWrites, type Cleanup, createWatcher, flushPendingReactions, HOOK_ADD, HOOK_CHANGE, HOOK_CLEANUP, HOOK_REMOVE, HOOK_SORT, HOOK_WATCH, type Hook, type CleanupHook, type WatchHook, type HookCallback, type HookCallbacks, isHandledHook, notifyWatchers, subscribeActiveWatcher, trackSignalReads, triggerHook, UNSET, type Watcher, } from './src/system';
19
- export { isAbortError, isAsyncFunction, isFunction, isNumber, isObjectOfType, isRecord, isRecordOrArray, isString, isSymbol, valueString, } from './src/util';
6
+ export { CircularDependencyError, type Guard, InvalidCallbackError, InvalidSignalValueError, NullishSignalValueError, RequiredOwnerError, UnsetSignalValueError, } from './src/errors';
7
+ export { batch, type Cleanup, type ComputedOptions, createScope, type EffectCallback, type MemoCallback, type Signal, type SignalOptions, SKIP_EQUALITY, type TaskCallback, untrack, } from './src/graph';
8
+ export { type Collection, type CollectionCallback, type CollectionOptions, createCollection, type DeriveCollectionCallback, isCollection, } from './src/nodes/collection';
9
+ export { createEffect, type MatchHandlers, type MaybePromise, match, } from './src/nodes/effect';
10
+ export { createList, type DiffResult, isEqual, isList, type KeyConfig, type List, type ListOptions, } from './src/nodes/list';
11
+ export { createMemo, isMemo, type Memo } from './src/nodes/memo';
12
+ export { createSensor, isSensor, type Sensor, type SensorCallback, } from './src/nodes/sensor';
13
+ export { createState, isState, type State, type UpdateCallback, } from './src/nodes/state';
14
+ export { createStore, isStore, type Store, type StoreOptions, } from './src/nodes/store';
15
+ export { createTask, isTask, type Task } from './src/nodes/task';
16
+ export { createComputed, createMutableSignal, createSignal, isComputed, isMutableSignal, isSignal, type MutableSignal, } from './src/signal';
17
+ export { isAsyncFunction, isFunction, isObjectOfType, isRecord, valueString, } from './src/util';