@livestore/livestore 0.0.12 → 0.0.14
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.
- package/README.md +25 -28
- package/dist/.tsbuildinfo +1 -0
- package/dist/QueryCache.d.ts +20 -0
- package/dist/QueryCache.d.ts.map +1 -0
- package/dist/QueryCache.js +71 -0
- package/dist/QueryCache.js.map +1 -0
- package/dist/__tests__/react/fixture.d.ts +26 -0
- package/dist/__tests__/react/fixture.d.ts.map +1 -0
- package/dist/__tests__/react/fixture.js +60 -0
- package/dist/__tests__/react/fixture.js.map +1 -0
- package/dist/__tests__/react/useComponentState.test.d.ts +2 -0
- package/dist/__tests__/react/useComponentState.test.d.ts.map +1 -0
- package/dist/__tests__/react/useComponentState.test.js +68 -0
- package/dist/__tests__/react/useComponentState.test.js.map +1 -0
- package/dist/__tests__/react/useLQuery.test.d.ts +2 -0
- package/dist/__tests__/react/useLQuery.test.d.ts.map +1 -0
- package/dist/__tests__/react/useLQuery.test.js +38 -0
- package/dist/__tests__/react/useLQuery.test.js.map +1 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.d.ts +2 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.d.ts.map +1 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.js +73 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.js.map +1 -0
- package/dist/__tests__/react/useQuery.test.d.ts +2 -0
- package/dist/__tests__/react/useQuery.test.d.ts.map +1 -0
- package/dist/__tests__/react/useQuery.test.js +33 -0
- package/dist/__tests__/react/useQuery.test.js.map +1 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.d.ts +2 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.d.ts.map +1 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.js +38 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.js.map +1 -0
- package/dist/__tests__/reactive.test.d.ts +2 -0
- package/dist/__tests__/reactive.test.d.ts.map +1 -0
- package/dist/__tests__/reactive.test.js +271 -0
- package/dist/__tests__/reactive.test.js.map +1 -0
- package/dist/__tests__/reactiveQueries/sql.test.d.ts +2 -0
- package/dist/__tests__/reactiveQueries/sql.test.d.ts.map +1 -0
- package/dist/__tests__/reactiveQueries/sql.test.js +337 -0
- package/dist/__tests__/reactiveQueries/sql.test.js.map +1 -0
- package/dist/bounded-collections.d.ts +34 -0
- package/dist/bounded-collections.d.ts.map +1 -0
- package/dist/bounded-collections.js +103 -0
- package/dist/bounded-collections.js.map +1 -0
- package/dist/componentKey.d.ts +20 -0
- package/dist/componentKey.d.ts.map +1 -0
- package/dist/componentKey.js +3 -0
- package/dist/componentKey.js.map +1 -0
- package/dist/effect/LiveStore.d.ts +36 -0
- package/dist/effect/LiveStore.d.ts.map +1 -0
- package/dist/effect/LiveStore.js +41 -0
- package/dist/effect/LiveStore.js.map +1 -0
- package/dist/effect/index.d.ts +2 -0
- package/dist/effect/index.d.ts.map +1 -0
- package/dist/effect/index.js +2 -0
- package/dist/effect/index.js.map +1 -0
- package/dist/events.d.ts +7 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +2 -0
- package/dist/events.js.map +1 -0
- package/dist/inMemoryDatabase.d.ts +56 -0
- package/dist/inMemoryDatabase.d.ts.map +1 -0
- package/dist/inMemoryDatabase.js +223 -0
- package/dist/inMemoryDatabase.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations.d.ts +16 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +67 -0
- package/dist/migrations.js.map +1 -0
- package/dist/otel.d.ts +4 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +6 -0
- package/dist/otel.js.map +1 -0
- package/dist/react/LiveStoreContext.d.ts +11 -0
- package/dist/react/LiveStoreContext.d.ts.map +1 -0
- package/dist/react/LiveStoreContext.js +10 -0
- package/dist/react/LiveStoreContext.js.map +1 -0
- package/dist/react/LiveStoreProvider.d.ts +20 -0
- package/dist/react/LiveStoreProvider.d.ts.map +1 -0
- package/dist/react/LiveStoreProvider.js +52 -0
- package/dist/react/LiveStoreProvider.js.map +1 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +6 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/useComponentState.d.ts +50 -0
- package/dist/react/useComponentState.d.ts.map +1 -0
- package/dist/react/useComponentState.js +248 -0
- package/dist/react/useComponentState.js.map +1 -0
- package/dist/react/useGlobalQuery.d.ts +3 -0
- package/dist/react/useGlobalQuery.d.ts.map +1 -0
- package/dist/react/useGlobalQuery.js +26 -0
- package/dist/react/useGlobalQuery.js.map +1 -0
- package/dist/react/useGraphQL.d.ts +13 -0
- package/dist/react/useGraphQL.d.ts.map +1 -0
- package/dist/react/useGraphQL.js +87 -0
- package/dist/react/useGraphQL.js.map +1 -0
- package/dist/react/useLiveStoreComponent.d.ts +75 -0
- package/dist/react/useLiveStoreComponent.d.ts.map +1 -0
- package/dist/react/useLiveStoreComponent.js +361 -0
- package/dist/react/useLiveStoreComponent.js.map +1 -0
- package/dist/react/useQuery.d.ts +3 -0
- package/dist/react/useQuery.d.ts.map +1 -0
- package/dist/react/useQuery.js +42 -0
- package/dist/react/useQuery.js.map +1 -0
- package/dist/react/useTemporaryQuery.d.ts +8 -0
- package/dist/react/useTemporaryQuery.d.ts.map +1 -0
- package/dist/react/useTemporaryQuery.js +17 -0
- package/dist/react/useTemporaryQuery.js.map +1 -0
- package/dist/react/utils/extractNamesFromStackTrace.d.ts +3 -0
- package/dist/react/utils/extractNamesFromStackTrace.d.ts.map +1 -0
- package/dist/react/utils/extractNamesFromStackTrace.js +40 -0
- package/dist/react/utils/extractNamesFromStackTrace.js.map +1 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.d.ts +7 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.d.ts.map +1 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.js +40 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.js.map +1 -0
- package/dist/react/utils/useStateRefWithReactiveInput.d.ts +13 -0
- package/dist/react/utils/useStateRefWithReactiveInput.d.ts.map +1 -0
- package/dist/react/utils/useStateRefWithReactiveInput.js +38 -0
- package/dist/react/utils/useStateRefWithReactiveInput.js.map +1 -0
- package/dist/reactive.d.ts +134 -0
- package/dist/reactive.d.ts.map +1 -0
- package/dist/reactive.js +409 -0
- package/dist/reactive.js.map +1 -0
- package/dist/reactiveQueries/base-class.d.ts +32 -0
- package/dist/reactiveQueries/base-class.d.ts.map +1 -0
- package/dist/reactiveQueries/base-class.js +30 -0
- package/dist/reactiveQueries/base-class.js.map +1 -0
- package/dist/reactiveQueries/graph.d.ts +10 -0
- package/dist/reactiveQueries/graph.d.ts.map +1 -0
- package/dist/reactiveQueries/graph.js +6 -0
- package/dist/reactiveQueries/graph.js.map +1 -0
- package/dist/reactiveQueries/graphql.d.ts +42 -0
- package/dist/reactiveQueries/graphql.d.ts.map +1 -0
- package/dist/reactiveQueries/graphql.js +99 -0
- package/dist/reactiveQueries/graphql.js.map +1 -0
- package/dist/reactiveQueries/js.d.ts +23 -0
- package/dist/reactiveQueries/js.d.ts.map +1 -0
- package/dist/reactiveQueries/js.js +36 -0
- package/dist/reactiveQueries/js.js.map +1 -0
- package/dist/reactiveQueries/sql.d.ts +35 -0
- package/dist/reactiveQueries/sql.d.ts.map +1 -0
- package/dist/reactiveQueries/sql.js +97 -0
- package/dist/reactiveQueries/sql.js.map +1 -0
- package/dist/schema.d.ts +81 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +46 -0
- package/dist/schema.js.map +1 -0
- package/dist/storage/in-memory/index.d.ts +15 -0
- package/dist/storage/in-memory/index.d.ts.map +1 -0
- package/dist/storage/in-memory/index.js +14 -0
- package/dist/storage/in-memory/index.js.map +1 -0
- package/dist/storage/index.d.ts +14 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +9 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/tauri/index.d.ts +19 -0
- package/dist/storage/tauri/index.d.ts.map +1 -0
- package/dist/storage/tauri/index.js +38 -0
- package/dist/storage/tauri/index.js.map +1 -0
- package/dist/storage/utils/idb.d.ts +10 -0
- package/dist/storage/utils/idb.d.ts.map +1 -0
- package/dist/storage/utils/idb.js +58 -0
- package/dist/storage/utils/idb.js.map +1 -0
- package/dist/storage/web-worker/index.d.ts +27 -0
- package/dist/storage/web-worker/index.d.ts.map +1 -0
- package/dist/storage/web-worker/index.js +74 -0
- package/dist/storage/web-worker/index.js.map +1 -0
- package/dist/storage/web-worker/worker.d.ts +13 -0
- package/dist/storage/web-worker/worker.d.ts.map +1 -0
- package/dist/storage/web-worker/worker.js +110 -0
- package/dist/storage/web-worker/worker.js.map +1 -0
- package/dist/store.d.ts +159 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +626 -0
- package/dist/store.js.map +1 -0
- package/dist/util.d.ts +28 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +55 -0
- package/dist/util.js.map +1 -0
- package/package.json +47 -19
- package/src/QueryCache.ts +1 -1
- package/src/__tests__/react/fixture.tsx +35 -39
- package/src/__tests__/react/{useLiveStoreComponent.test.tsx → useComponentState.test.tsx} +9 -20
- package/src/__tests__/react/useQuery.test.tsx +48 -0
- package/src/__tests__/react/utils/extractStackInfoFromStackTrace.test.ts +40 -0
- package/src/__tests__/reactive.test.ts +194 -142
- package/src/__tests__/reactiveQueries/sql.test.ts +372 -0
- package/src/effect/LiveStore.ts +22 -31
- package/src/events.ts +1 -1
- package/src/inMemoryDatabase.ts +117 -142
- package/src/index.ts +18 -22
- package/src/migrations.ts +119 -0
- package/src/otel.ts +0 -11
- package/src/react/LiveStoreProvider.tsx +24 -23
- package/src/react/index.ts +12 -7
- package/src/react/useComponentState.ts +409 -0
- package/src/react/useQuery.ts +58 -0
- package/src/react/useTemporaryQuery.ts +21 -0
- package/src/react/utils/extractStackInfoFromStackTrace.ts +47 -0
- package/src/reactive.ts +386 -267
- package/src/reactiveQueries/base-class.ts +61 -39
- package/src/reactiveQueries/graph.ts +15 -0
- package/src/reactiveQueries/graphql.ts +147 -31
- package/src/reactiveQueries/js.ts +54 -21
- package/src/reactiveQueries/sql.ts +128 -37
- package/src/schema.ts +69 -145
- package/src/storage/in-memory/index.ts +21 -0
- package/src/storage/index.ts +27 -0
- package/src/{backends/tauri.ts → storage/tauri/index.ts} +14 -28
- package/src/storage/web-worker/index.ts +116 -0
- package/src/{backends/web-worker.ts → storage/web-worker/worker.ts} +17 -52
- package/src/store.ts +466 -457
- package/src/util.ts +13 -3
- package/tsconfig.json +1 -3
- package/src/backends/base.ts +0 -67
- package/src/backends/index.ts +0 -98
- package/src/backends/noop.ts +0 -32
- package/src/backends/web-in-memory.ts +0 -65
- package/src/backends/web.ts +0 -97
- package/src/react/useGlobalQuery.ts +0 -40
- package/src/react/useGraphQL.ts +0 -112
- package/src/react/useLiveStoreComponent.ts +0 -483
- /package/src/{backends → storage}/utils/idb.ts +0 -0
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
import { makeNoopTracer } from '@livestore/utils'
|
|
2
|
-
import * as otel from '@opentelemetry/api'
|
|
3
1
|
import { describe, expect, it } from 'vitest'
|
|
4
2
|
|
|
5
3
|
import { ReactiveGraph } from '../reactive.js'
|
|
6
4
|
|
|
7
|
-
const mockOtelCtx = otel.context.active()
|
|
8
|
-
|
|
9
5
|
describe('a trivial graph', () => {
|
|
10
6
|
const makeGraph = () => {
|
|
11
|
-
const graph = new ReactiveGraph({
|
|
12
|
-
|
|
13
|
-
const
|
|
7
|
+
const graph = new ReactiveGraph({})
|
|
8
|
+
graph.context = {}
|
|
9
|
+
const a = graph.makeRef(1, { label: 'a' })
|
|
10
|
+
const b = graph.makeRef(2, { label: 'b' })
|
|
14
11
|
const numberOfRunsForC = { runs: 0 }
|
|
15
12
|
const c = graph.makeThunk(
|
|
16
13
|
(get) => {
|
|
17
14
|
numberOfRunsForC.runs++
|
|
18
15
|
return get(a) + get(b)
|
|
19
16
|
},
|
|
20
|
-
|
|
21
|
-
mockOtelCtx,
|
|
17
|
+
{ label: 'c' },
|
|
22
18
|
)
|
|
23
|
-
const d = graph.makeRef(3)
|
|
24
|
-
const e = graph.makeThunk((get) => get(c) + get(d),
|
|
19
|
+
const d = graph.makeRef(3, { label: 'd' })
|
|
20
|
+
const e = graph.makeThunk((get) => get(c) + get(d), { label: 'e' })
|
|
25
21
|
|
|
26
22
|
// a(1) b(2)
|
|
27
23
|
// \ /
|
|
@@ -39,158 +35,216 @@ describe('a trivial graph', () => {
|
|
|
39
35
|
|
|
40
36
|
it('has the right initial values', () => {
|
|
41
37
|
const { c, e } = makeGraph()
|
|
42
|
-
expect(c.
|
|
43
|
-
expect(e.
|
|
38
|
+
expect(c.computeResult()).toBe(3)
|
|
39
|
+
expect(e.computeResult()).toBe(6)
|
|
44
40
|
})
|
|
45
41
|
|
|
46
42
|
it('propagates change through the graph', () => {
|
|
47
43
|
const { graph, a, c, e } = makeGraph()
|
|
48
|
-
graph.setRef(a, 5
|
|
49
|
-
expect(c.
|
|
50
|
-
expect(e.
|
|
44
|
+
graph.setRef(a, 5)
|
|
45
|
+
expect(c.computeResult()).toBe(7)
|
|
46
|
+
expect(e.computeResult()).toBe(10)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('does not rerun downstream computations eagerly when an upstream dep changes', () => {
|
|
50
|
+
const { graph, a, c, numberOfRunsForC } = makeGraph()
|
|
51
|
+
expect(numberOfRunsForC.runs).toBe(0)
|
|
52
|
+
graph.setRef(a, 5)
|
|
53
|
+
expect(numberOfRunsForC.runs).toBe(0)
|
|
54
|
+
c.computeResult()
|
|
55
|
+
expect(numberOfRunsForC.runs).toBe(1)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('does not rerun c when d is edited and e is rerun', () => {
|
|
59
|
+
const { graph, c, d, e, numberOfRunsForC } = makeGraph()
|
|
60
|
+
expect(numberOfRunsForC.runs).toBe(0)
|
|
61
|
+
expect(e.computeResult()).toBe(3 + 3)
|
|
62
|
+
expect(numberOfRunsForC.runs).toBe(1)
|
|
63
|
+
graph.setRef(d, 4)
|
|
64
|
+
expect(e.computeResult()).toBe(4 + 3)
|
|
65
|
+
expect(numberOfRunsForC.runs).toBe(1)
|
|
51
66
|
})
|
|
52
67
|
|
|
53
68
|
it('cuts off reactive propagation when a thunk evaluates to same result as before', () => {
|
|
54
69
|
const { graph, a, c, d } = makeGraph()
|
|
55
70
|
|
|
56
71
|
let numberOfRuns = 0
|
|
57
|
-
const f = graph.makeThunk(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
)
|
|
65
|
-
expect(numberOfRuns).toBe(1) // initializing f should run it once
|
|
72
|
+
const f = graph.makeThunk((get) => {
|
|
73
|
+
numberOfRuns++
|
|
74
|
+
return get(c) + get(d)
|
|
75
|
+
})
|
|
76
|
+
expect(numberOfRuns).toBe(0) // defining f shouldn't run it yet
|
|
77
|
+
f.computeResult()
|
|
78
|
+
expect(numberOfRuns).toBe(1) // refreshing should run it once
|
|
66
79
|
|
|
67
80
|
// f doesn't run because a is set to same value as before
|
|
68
|
-
graph.setRef(a, 1
|
|
69
|
-
expect(f.
|
|
70
|
-
expect(numberOfRuns).toBe(1)
|
|
81
|
+
graph.setRef(a, 1)
|
|
82
|
+
expect(f.computeResult()).toBe(6)
|
|
83
|
+
// expect(numberOfRuns).toBe(1) // TODO comp caching
|
|
71
84
|
|
|
72
85
|
// f runs because a is set to a different value
|
|
73
|
-
graph.setRef(a, 5
|
|
74
|
-
expect(f.
|
|
75
|
-
expect(numberOfRuns).toBe(2)
|
|
86
|
+
graph.setRef(a, 5)
|
|
87
|
+
expect(f.computeResult()).toBe(10)
|
|
88
|
+
// expect(numberOfRuns).toBe(2) // TODO comp caching
|
|
76
89
|
|
|
77
90
|
// f runs again when d is set to a different value
|
|
78
|
-
graph.setRef(d, 4
|
|
79
|
-
expect(f.
|
|
80
|
-
expect(numberOfRuns).toBe(3)
|
|
91
|
+
graph.setRef(d, 4)
|
|
92
|
+
expect(f.computeResult()).toBe(11)
|
|
93
|
+
// expect(numberOfRuns).toBe(3) // TODO comp caching
|
|
81
94
|
|
|
82
95
|
// f only runs one time if we set two refs together
|
|
83
|
-
graph.setRefs(
|
|
84
|
-
[
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
mockOtelCtx,
|
|
90
|
-
)
|
|
91
|
-
expect(f.result).toBe(13)
|
|
92
|
-
expect(numberOfRuns).toBe(4)
|
|
96
|
+
graph.setRefs([
|
|
97
|
+
[a, 6],
|
|
98
|
+
[d, 5],
|
|
99
|
+
])
|
|
100
|
+
expect(f.computeResult()).toBe(13)
|
|
101
|
+
// expect(numberOfRuns).toBe(4) // TODO comp caching
|
|
93
102
|
})
|
|
94
103
|
|
|
95
104
|
it('only runs a thunk once when two upstream refs are updated together', () => {
|
|
96
105
|
const { graph, a, b, c, numberOfRunsForC } = makeGraph()
|
|
106
|
+
graph.setRefs([
|
|
107
|
+
[a, 5],
|
|
108
|
+
[b, 6],
|
|
109
|
+
])
|
|
110
|
+
expect(numberOfRunsForC.runs).toBe(0)
|
|
111
|
+
expect(c.computeResult()).toBe(11)
|
|
97
112
|
expect(numberOfRunsForC.runs).toBe(1)
|
|
98
|
-
graph.setRefs(
|
|
99
|
-
[
|
|
100
|
-
[a, 5],
|
|
101
|
-
[b, 6],
|
|
102
|
-
],
|
|
103
|
-
undefined,
|
|
104
|
-
mockOtelCtx,
|
|
105
|
-
)
|
|
106
|
-
expect(numberOfRunsForC.runs).toBe(2)
|
|
107
|
-
expect(c.result).toBe(11)
|
|
108
113
|
})
|
|
109
114
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
describe('effects', () => {
|
|
116
|
+
// TODO TBD whether we want to keep this as intended behavior
|
|
117
|
+
it(`doesn't run on initial definition`, () => {
|
|
118
|
+
const { graph, c, numberOfRunsForC } = makeGraph()
|
|
119
|
+
expect(numberOfRunsForC.runs).toBe(0)
|
|
120
|
+
c.computeResult()
|
|
121
|
+
expect(numberOfRunsForC.runs).toBe(1)
|
|
122
|
+
|
|
123
|
+
let numberOfEffectRuns = 0
|
|
124
|
+
const effect = graph.makeEffect((get) => {
|
|
125
|
+
// establish a dependency on thunk c and mutate an outside value
|
|
126
|
+
expect(get(c)).toBe(3)
|
|
127
|
+
numberOfEffectRuns++
|
|
128
|
+
})
|
|
129
|
+
expect(numberOfEffectRuns).toBe(0)
|
|
130
|
+
expect(numberOfRunsForC.runs).toBe(1)
|
|
131
|
+
|
|
132
|
+
effect.doEffect()
|
|
133
|
+
expect(numberOfEffectRuns).toBe(1)
|
|
134
|
+
})
|
|
113
135
|
|
|
114
|
-
|
|
136
|
+
it('only reruns an effect if the thunk value changed', () => {
|
|
137
|
+
const { graph, a, c } = makeGraph()
|
|
138
|
+
let numberOfEffectRuns = 0
|
|
139
|
+
let aHasChanged = true
|
|
140
|
+
expect(numberOfEffectRuns).toBe(0)
|
|
141
|
+
const effect = graph.makeEffect((get) => {
|
|
142
|
+
// establish a dependency on thunk c and mutate an outside value
|
|
143
|
+
expect(get(c)).toBe(aHasChanged ? 3 : 4)
|
|
144
|
+
numberOfEffectRuns++
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
expect(numberOfEffectRuns).toBe(0)
|
|
148
|
+
effect.doEffect()
|
|
149
|
+
expect(numberOfEffectRuns).toBe(1)
|
|
115
150
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
151
|
+
// if we set a to the same value, the effect should not run again
|
|
152
|
+
graph.setRef(a, 1)
|
|
153
|
+
// expect(numberOfCallsToC).toBe(1) // TODO comp caching
|
|
154
|
+
|
|
155
|
+
aHasChanged = false
|
|
119
156
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
expect(c.result).toBe(7)
|
|
157
|
+
graph.setRef(a, 2)
|
|
158
|
+
// expect(numberOfCallsToC).toBe(2) // TODO comp caching
|
|
159
|
+
})
|
|
124
160
|
})
|
|
161
|
+
})
|
|
125
162
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
163
|
+
describe('a dynamic graph', () => {
|
|
164
|
+
const makeGraph = () => {
|
|
165
|
+
const graph = new ReactiveGraph({})
|
|
166
|
+
graph.context = {}
|
|
129
167
|
|
|
130
|
-
graph.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
168
|
+
const a = graph.makeRef(1, { label: 'a' })
|
|
169
|
+
const b = graph.makeRef(2, { label: 'b' })
|
|
170
|
+
const c = graph.makeRef<'a' | 'b'>('a', { label: 'c' })
|
|
171
|
+
const numberOfRunsForD = { runs: 0 }
|
|
172
|
+
const d = graph.makeThunk(
|
|
173
|
+
(get) => {
|
|
174
|
+
numberOfRunsForD.runs++
|
|
175
|
+
return get(c) === 'a' ? get(a) : get(b)
|
|
176
|
+
},
|
|
177
|
+
{ label: 'd' },
|
|
137
178
|
)
|
|
179
|
+
const e = graph.makeRef(2, { label: 'e' })
|
|
180
|
+
const f = graph.makeThunk((get) => get(d) * get(e), { label: 'f' })
|
|
138
181
|
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
182
|
+
// a(1) b(2) c('a')
|
|
183
|
+
// \ / /
|
|
184
|
+
// \ / /
|
|
185
|
+
// d = a or b depending on c
|
|
186
|
+
// \
|
|
187
|
+
// \
|
|
188
|
+
// e(2) \
|
|
189
|
+
// \ \
|
|
190
|
+
// \ \
|
|
191
|
+
// f = d * e
|
|
142
192
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
expect(numberOfRunsForC.runs).toBe(2)
|
|
146
|
-
expect(c.result).toBe(11)
|
|
147
|
-
})
|
|
193
|
+
return { graph, a, b, c, d, e, f, numberOfRunsForD }
|
|
194
|
+
}
|
|
148
195
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
(get) => {
|
|
155
|
-
// establish a dependency on thunk c and mutate an outside value
|
|
156
|
-
get(c)
|
|
157
|
-
numberOfCallsToC++
|
|
158
|
-
},
|
|
159
|
-
undefined,
|
|
160
|
-
mockOtelCtx,
|
|
161
|
-
)
|
|
162
|
-
expect(numberOfCallsToC).toBe(1)
|
|
196
|
+
it('has the right initial values', () => {
|
|
197
|
+
const { d, f } = makeGraph()
|
|
198
|
+
expect(d.computeResult()).toBe(1)
|
|
199
|
+
expect(f.computeResult()).toBe(2)
|
|
200
|
+
})
|
|
163
201
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
202
|
+
it('dynamically adjusts d when a, b or c changes', () => {
|
|
203
|
+
const { graph, c, d, e, f, numberOfRunsForD } = makeGraph()
|
|
204
|
+
expect(numberOfRunsForD.runs).toBe(0)
|
|
205
|
+
expect(d.computeResult()).toBe(1)
|
|
206
|
+
expect(f.computeResult()).toBe(2)
|
|
207
|
+
expect(numberOfRunsForD.runs).toBe(1)
|
|
208
|
+
graph.setRef(c, 'b')
|
|
209
|
+
expect(d.computeResult()).toBe(2)
|
|
210
|
+
expect(f.computeResult()).toBe(4)
|
|
211
|
+
expect(numberOfRunsForD.runs).toBe(2)
|
|
212
|
+
graph.setRef(e, 3)
|
|
213
|
+
expect(f.computeResult()).toBe(6)
|
|
214
|
+
expect(numberOfRunsForD.runs).toBe(2)
|
|
215
|
+
})
|
|
167
216
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
217
|
+
it('runs d only when a changes, not b', () => {
|
|
218
|
+
const { graph, a, b, d, numberOfRunsForD } = makeGraph()
|
|
219
|
+
numberOfRunsForD.runs = 0
|
|
220
|
+
d.computeResult()
|
|
221
|
+
expect(numberOfRunsForD.runs).toBe(1)
|
|
222
|
+
graph.setRef(a, 3)
|
|
223
|
+
expect(d.computeResult()).toBe(3)
|
|
224
|
+
expect(numberOfRunsForD.runs).toBe(2)
|
|
225
|
+
graph.setRef(b, 4)
|
|
226
|
+
expect(d.computeResult()).toBe(3)
|
|
227
|
+
expect(numberOfRunsForD.runs).toBe(2)
|
|
171
228
|
})
|
|
172
229
|
})
|
|
173
230
|
|
|
174
231
|
describe('a diamond shaped graph', () => {
|
|
175
232
|
const makeGraph = () => {
|
|
176
|
-
const graph = new ReactiveGraph({
|
|
233
|
+
const graph = new ReactiveGraph({})
|
|
234
|
+
graph.context = {}
|
|
177
235
|
const a = graph.makeRef(1)
|
|
178
|
-
const b = graph.makeThunk((get) => get(a) + 1
|
|
179
|
-
const c = graph.makeThunk((get) => get(a) + 1
|
|
236
|
+
const b = graph.makeThunk((get) => get(a) + 1)
|
|
237
|
+
const c = graph.makeThunk((get) => get(a) + 1)
|
|
180
238
|
|
|
181
239
|
// track the number of times d has run in an object so we can mutate it
|
|
182
240
|
const dRuns = { runs: 0 }
|
|
183
241
|
|
|
184
242
|
// normally thunks aren't supposed to side effect;
|
|
185
243
|
// we do it here to track the number of times d has run
|
|
186
|
-
const d = graph.makeThunk(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
},
|
|
191
|
-
undefined,
|
|
192
|
-
mockOtelCtx,
|
|
193
|
-
)
|
|
244
|
+
const d = graph.makeThunk((get) => {
|
|
245
|
+
dRuns.runs++
|
|
246
|
+
return get(b) + get(c)
|
|
247
|
+
})
|
|
194
248
|
|
|
195
249
|
// a(1)
|
|
196
250
|
// / \
|
|
@@ -203,48 +257,46 @@ describe('a diamond shaped graph', () => {
|
|
|
203
257
|
|
|
204
258
|
it('has the right initial values', () => {
|
|
205
259
|
const { b, c, d } = makeGraph()
|
|
206
|
-
expect(b.
|
|
207
|
-
expect(c.
|
|
208
|
-
expect(d.
|
|
260
|
+
expect(b.computeResult()).toBe(2)
|
|
261
|
+
expect(c.computeResult()).toBe(2)
|
|
262
|
+
expect(d.computeResult()).toBe(4)
|
|
209
263
|
})
|
|
210
264
|
|
|
211
265
|
it('propagates change through the graph', () => {
|
|
212
266
|
const { graph, a, b, c, d } = makeGraph()
|
|
213
|
-
graph.setRef(a, 5
|
|
214
|
-
expect(b.
|
|
215
|
-
expect(c.
|
|
216
|
-
expect(d.
|
|
267
|
+
graph.setRef(a, 5)
|
|
268
|
+
expect(b.computeResult()).toBe(6)
|
|
269
|
+
expect(c.computeResult()).toBe(6)
|
|
270
|
+
expect(d.computeResult()).toBe(12)
|
|
217
271
|
})
|
|
218
272
|
|
|
219
273
|
// if we're being efficient, we should update b and c before updating d,
|
|
220
274
|
// so d only needs to update one time
|
|
221
275
|
it('only runs d once when a changes', () => {
|
|
222
|
-
const { graph, a, dRuns } = makeGraph()
|
|
276
|
+
const { graph, a, d, dRuns } = makeGraph()
|
|
277
|
+
expect(dRuns.runs).toBe(0)
|
|
278
|
+
d.computeResult()
|
|
223
279
|
expect(dRuns.runs).toBe(1)
|
|
224
|
-
graph.setRef(a, 5
|
|
280
|
+
graph.setRef(a, 5)
|
|
281
|
+
d.computeResult()
|
|
282
|
+
d.computeResult() // even extra calls to computeResult should not run d again
|
|
225
283
|
expect(dRuns.runs).toBe(2)
|
|
226
284
|
})
|
|
227
285
|
})
|
|
228
286
|
|
|
229
|
-
|
|
230
|
-
describe.todo('a trivial graph with undefined', () => {
|
|
287
|
+
describe('a trivial graph with undefined', () => {
|
|
231
288
|
const makeGraph = () => {
|
|
232
|
-
const graph = new ReactiveGraph({
|
|
233
|
-
|
|
234
|
-
const
|
|
235
|
-
const
|
|
236
|
-
const c = graph.makeThunk(
|
|
237
|
-
(get)
|
|
238
|
-
|
|
239
|
-
return (get(a) ?? 0) + get(b)
|
|
240
|
-
},
|
|
241
|
-
undefined,
|
|
242
|
-
mockOtelCtx,
|
|
243
|
-
)
|
|
289
|
+
const graph = new ReactiveGraph({})
|
|
290
|
+
graph.context = {}
|
|
291
|
+
const a = graph.makeRef(1)
|
|
292
|
+
const b = graph.makeRef(undefined)
|
|
293
|
+
const c = graph.makeThunk((get) => {
|
|
294
|
+
return get(a) + (get(b) ?? 0)
|
|
295
|
+
})
|
|
244
296
|
const d = graph.makeRef(3)
|
|
245
|
-
const e = graph.makeThunk((get) => get(c) + get(d)
|
|
297
|
+
const e = graph.makeThunk((get) => get(c) + get(d))
|
|
246
298
|
|
|
247
|
-
// a(1) b(
|
|
299
|
+
// a(1) b(undefined)
|
|
248
300
|
// \ /
|
|
249
301
|
// \ /
|
|
250
302
|
// c = a + b
|
|
@@ -255,12 +307,12 @@ describe.todo('a trivial graph with undefined', () => {
|
|
|
255
307
|
// \ \
|
|
256
308
|
// e = c + d
|
|
257
309
|
|
|
258
|
-
return { graph, a, b, c, d, e
|
|
310
|
+
return { graph, a, b, c, d, e }
|
|
259
311
|
}
|
|
260
312
|
|
|
261
313
|
it('has the right initial values', () => {
|
|
262
314
|
const { c, e } = makeGraph()
|
|
263
|
-
expect(c.
|
|
264
|
-
expect(e.
|
|
315
|
+
expect(c.computeResult()).toBe(1)
|
|
316
|
+
expect(e.computeResult()).toBe(4)
|
|
265
317
|
})
|
|
266
318
|
})
|