@livestore/livestore 0.0.54-dev.5 → 0.0.55-dev.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/MainDatabaseWrapper.d.ts +6 -5
- package/dist/MainDatabaseWrapper.d.ts.map +1 -1
- package/dist/MainDatabaseWrapper.js +3 -3
- package/dist/MainDatabaseWrapper.js.map +1 -1
- package/dist/QueryCache.d.ts +1 -1
- package/dist/QueryCache.d.ts.map +1 -1
- package/dist/QueryCache.js.map +1 -1
- package/dist/__tests__/react/fixture.d.ts +9 -27
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +12 -10
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/effect/LiveStore.d.ts +20 -12
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +23 -22
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/effect/index.d.ts +1 -1
- package/dist/effect/index.d.ts.map +1 -1
- package/dist/effect/index.js +1 -1
- package/dist/effect/index.js.map +1 -1
- package/dist/global-state.d.ts +1 -3
- package/dist/global-state.d.ts.map +1 -1
- package/dist/global-state.js +2 -3
- package/dist/global-state.js.map +1 -1
- package/dist/index.d.ts +6 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -6
- package/dist/index.js.map +1 -1
- package/dist/react/LiveStoreContext.d.ts +5 -2
- package/dist/react/LiveStoreContext.d.ts.map +1 -1
- package/dist/react/LiveStoreContext.js +3 -0
- package/dist/react/LiveStoreContext.js.map +1 -1
- package/dist/react/LiveStoreProvider.d.ts +8 -7
- package/dist/react/LiveStoreProvider.d.ts.map +1 -1
- package/dist/react/LiveStoreProvider.js +70 -43
- package/dist/react/LiveStoreProvider.js.map +1 -1
- package/dist/react/LiveStoreProvider.test.js +33 -12
- package/dist/react/LiveStoreProvider.test.js.map +1 -1
- package/dist/react/components/LiveList.d.ts.map +1 -1
- package/dist/react/useAtom.d.ts +1 -1
- package/dist/react/useAtom.d.ts.map +1 -1
- package/dist/react/useLocalId.d.ts.map +1 -1
- package/dist/react/useQuery.d.ts.map +1 -1
- package/dist/react/useQuery.js +2 -2
- package/dist/react/useQuery.js.map +1 -1
- package/dist/react/useRow.d.ts +2 -2
- package/dist/react/useRow.d.ts.map +1 -1
- package/dist/react/useRow.js +5 -5
- package/dist/react/useRow.js.map +1 -1
- package/dist/react/useRow.test.js +22 -22
- package/dist/react/useRow.test.js.map +1 -1
- package/dist/react/useTemporaryQuery.d.ts.map +1 -1
- package/dist/react/useTemporaryQuery.js +1 -1
- package/dist/react/useTemporaryQuery.js.map +1 -1
- package/dist/react/utils/useStateRefWithReactiveInput.d.ts.map +1 -1
- package/dist/reactive.d.ts +1 -1
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +4 -5
- package/dist/reactive.js.map +1 -1
- package/dist/reactiveQueries/base-class.d.ts +6 -6
- package/dist/reactiveQueries/base-class.d.ts.map +1 -1
- package/dist/reactiveQueries/base-class.js +3 -3
- package/dist/reactiveQueries/base-class.js.map +1 -1
- package/dist/reactiveQueries/graphql.d.ts +8 -8
- package/dist/reactiveQueries/graphql.d.ts.map +1 -1
- package/dist/reactiveQueries/graphql.js +10 -10
- package/dist/reactiveQueries/graphql.js.map +1 -1
- package/dist/reactiveQueries/js.d.ts +6 -6
- package/dist/reactiveQueries/js.d.ts.map +1 -1
- package/dist/reactiveQueries/js.js +8 -8
- package/dist/reactiveQueries/js.js.map +1 -1
- package/dist/reactiveQueries/sql.d.ts +9 -10
- package/dist/reactiveQueries/sql.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.js +12 -12
- package/dist/reactiveQueries/sql.js.map +1 -1
- package/dist/reactiveQueries/sql.test.js +6 -6
- package/dist/reactiveQueries/sql.test.js.map +1 -1
- package/dist/row-query.d.ts +2 -2
- package/dist/row-query.d.ts.map +1 -1
- package/dist/row-query.js +4 -38
- package/dist/row-query.js.map +1 -1
- package/dist/store.d.ts +41 -24
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +336 -223
- package/dist/store.js.map +1 -1
- package/dist/utils/otel.d.ts.map +1 -1
- package/package.json +10 -19
- package/src/MainDatabaseWrapper.ts +14 -8
- package/src/QueryCache.ts +1 -2
- package/src/__tests__/react/fixture.tsx +13 -11
- package/src/effect/LiveStore.ts +65 -54
- package/src/effect/index.ts +2 -1
- package/src/global-state.ts +2 -6
- package/src/index.ts +25 -7
- package/src/react/LiveStoreContext.ts +7 -2
- package/src/react/LiveStoreProvider.test.tsx +56 -14
- package/src/react/LiveStoreProvider.tsx +105 -46
- package/src/react/useQuery.ts +2 -2
- package/src/react/useRow.test.tsx +22 -22
- package/src/react/useRow.ts +7 -10
- package/src/react/useTemporaryQuery.ts +2 -2
- package/src/reactive.ts +6 -5
- package/src/reactiveQueries/base-class.ts +9 -9
- package/src/reactiveQueries/graphql.ts +19 -15
- package/src/reactiveQueries/js.ts +12 -12
- package/src/reactiveQueries/sql.test.ts +6 -6
- package/src/reactiveQueries/sql.ts +19 -21
- package/src/row-query.ts +8 -54
- package/src/store.ts +533 -284
- package/dist/utils/bounded-collections.d.ts +0 -34
- package/dist/utils/bounded-collections.d.ts.map +0 -1
- package/dist/utils/bounded-collections.js +0 -91
- package/dist/utils/bounded-collections.js.map +0 -1
- package/dist/utils/util.d.ts +0 -14
- package/dist/utils/util.d.ts.map +0 -1
- package/dist/utils/util.js +0 -19
- package/dist/utils/util.js.map +0 -1
- package/src/utils/util.ts +0 -31
|
@@ -5,11 +5,11 @@ import { Schema, TreeFormatter } from '@livestore/utils/effect'
|
|
|
5
5
|
import * as otel from '@opentelemetry/api'
|
|
6
6
|
import * as graphql from 'graphql'
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { globalReactivityGraph } from '../global-state.js'
|
|
9
9
|
import { isThunk, type Thunk } from '../reactive.js'
|
|
10
10
|
import type { BaseGraphQLContext, RefreshReason, Store } from '../store.js'
|
|
11
11
|
import { getDurationMsFromSpan } from '../utils/otel.js'
|
|
12
|
-
import type {
|
|
12
|
+
import type { GetAtomResult, LiveQuery, QueryContext, ReactivityGraph } from './base-class.js'
|
|
13
13
|
import { LiveStoreQueryBase, makeGetAtomResult } from './base-class.js'
|
|
14
14
|
|
|
15
15
|
export type MapResult<To, From> = ((res: From, get: GetAtomResult) => To) | Schema.Schema<To, From>
|
|
@@ -21,9 +21,13 @@ export const queryGraphQL = <
|
|
|
21
21
|
>(
|
|
22
22
|
document: DocumentNode<TResult, TVariableValues>,
|
|
23
23
|
genVariableValues: TVariableValues | ((get: GetAtomResult) => TVariableValues),
|
|
24
|
-
{
|
|
24
|
+
{
|
|
25
|
+
label,
|
|
26
|
+
reactivityGraph,
|
|
27
|
+
map,
|
|
28
|
+
}: { label?: string; reactivityGraph?: ReactivityGraph; map?: MapResult<TResultMapped, TResult> } = {},
|
|
25
29
|
): LiveQuery<TResultMapped, QueryInfoNone> =>
|
|
26
|
-
new LiveStoreGraphQLQuery({ document, genVariableValues, label,
|
|
30
|
+
new LiveStoreGraphQLQuery({ document, genVariableValues, label, reactivityGraph, map })
|
|
27
31
|
|
|
28
32
|
export class LiveStoreGraphQLQuery<
|
|
29
33
|
TResult extends Record<string, any>,
|
|
@@ -37,13 +41,13 @@ export class LiveStoreGraphQLQuery<
|
|
|
37
41
|
document: DocumentNode<TResult, TVariableValues>
|
|
38
42
|
|
|
39
43
|
/** A reactive thunk representing the query results */
|
|
40
|
-
results$: Thunk<TResultMapped,
|
|
44
|
+
results$: Thunk<TResultMapped, QueryContext, RefreshReason>
|
|
41
45
|
|
|
42
|
-
variableValues$: Thunk<TVariableValues,
|
|
46
|
+
variableValues$: Thunk<TVariableValues, QueryContext, RefreshReason> | undefined
|
|
43
47
|
|
|
44
48
|
label: string
|
|
45
49
|
|
|
46
|
-
protected
|
|
50
|
+
protected reactivityGraph: ReactivityGraph
|
|
47
51
|
|
|
48
52
|
queryInfo: QueryInfoNone = { _tag: 'None' }
|
|
49
53
|
|
|
@@ -53,13 +57,13 @@ export class LiveStoreGraphQLQuery<
|
|
|
53
57
|
document,
|
|
54
58
|
label,
|
|
55
59
|
genVariableValues,
|
|
56
|
-
|
|
60
|
+
reactivityGraph,
|
|
57
61
|
map,
|
|
58
62
|
}: {
|
|
59
63
|
document: DocumentNode<TResult, TVariableValues>
|
|
60
64
|
genVariableValues: TVariableValues | ((get: GetAtomResult) => TVariableValues)
|
|
61
65
|
label?: string
|
|
62
|
-
|
|
66
|
+
reactivityGraph?: ReactivityGraph
|
|
63
67
|
map?: MapResult<TResultMapped, TResult>
|
|
64
68
|
}) {
|
|
65
69
|
super()
|
|
@@ -69,7 +73,7 @@ export class LiveStoreGraphQLQuery<
|
|
|
69
73
|
this.label = labelWithDefault
|
|
70
74
|
this.document = document
|
|
71
75
|
|
|
72
|
-
this.
|
|
76
|
+
this.reactivityGraph = reactivityGraph ?? globalReactivityGraph
|
|
73
77
|
|
|
74
78
|
this.mapResult =
|
|
75
79
|
map === undefined
|
|
@@ -92,7 +96,7 @@ export class LiveStoreGraphQLQuery<
|
|
|
92
96
|
let variableValues$OrvariableValues
|
|
93
97
|
|
|
94
98
|
if (typeof genVariableValues === 'function') {
|
|
95
|
-
variableValues$OrvariableValues = this.
|
|
99
|
+
variableValues$OrvariableValues = this.reactivityGraph.makeThunk(
|
|
96
100
|
(get, _setDebugInfo, { rootOtelContext }, otelContext) => {
|
|
97
101
|
return genVariableValues(makeGetAtomResult(get, otelContext ?? rootOtelContext))
|
|
98
102
|
},
|
|
@@ -104,7 +108,7 @@ export class LiveStoreGraphQLQuery<
|
|
|
104
108
|
}
|
|
105
109
|
|
|
106
110
|
const resultsLabel = `${labelWithDefault}:results`
|
|
107
|
-
this.results$ = this.
|
|
111
|
+
this.results$ = this.reactivityGraph.makeThunk<TResultMapped>(
|
|
108
112
|
(get, setDebugInfo, { store, otelTracer, rootOtelContext }, otelContext) => {
|
|
109
113
|
const variableValues = isThunk(variableValues$OrvariableValues)
|
|
110
114
|
? (get(variableValues$OrvariableValues) as TVariableValues)
|
|
@@ -145,7 +149,7 @@ export class LiveStoreGraphQLQuery<
|
|
|
145
149
|
// },
|
|
146
150
|
// label: `${this.label}:js`,
|
|
147
151
|
// onDestroy: () => this.destroy(),
|
|
148
|
-
//
|
|
152
|
+
// reactivityGraph: this.reactivityGraph,
|
|
149
153
|
// })
|
|
150
154
|
|
|
151
155
|
queryOnce = ({
|
|
@@ -217,9 +221,9 @@ export class LiveStoreGraphQLQuery<
|
|
|
217
221
|
|
|
218
222
|
destroy = () => {
|
|
219
223
|
if (this.variableValues$ !== undefined) {
|
|
220
|
-
this.
|
|
224
|
+
this.reactivityGraph.destroyNode(this.variableValues$)
|
|
221
225
|
}
|
|
222
226
|
|
|
223
|
-
this.
|
|
227
|
+
this.reactivityGraph.destroyNode(this.results$)
|
|
224
228
|
}
|
|
225
229
|
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import type { QueryInfo, QueryInfoNone } from '@livestore/common'
|
|
2
2
|
import * as otel from '@opentelemetry/api'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { globalReactivityGraph } from '../global-state.js'
|
|
5
5
|
import type { Thunk } from '../reactive.js'
|
|
6
6
|
import type { RefreshReason } from '../store.js'
|
|
7
7
|
import { getDurationMsFromSpan } from '../utils/otel.js'
|
|
8
|
-
import type {
|
|
8
|
+
import type { GetAtomResult, LiveQuery, QueryContext, ReactivityGraph } from './base-class.js'
|
|
9
9
|
import { LiveStoreQueryBase, makeGetAtomResult } from './base-class.js'
|
|
10
10
|
|
|
11
11
|
export const computed = <TResult, TQueryInfo extends QueryInfo = QueryInfoNone>(
|
|
12
12
|
fn: (get: GetAtomResult) => TResult,
|
|
13
13
|
options?: {
|
|
14
14
|
label: string
|
|
15
|
-
|
|
15
|
+
reactivityGraph?: ReactivityGraph
|
|
16
16
|
queryInfo?: TQueryInfo
|
|
17
17
|
},
|
|
18
18
|
): LiveQuery<TResult, TQueryInfo> =>
|
|
19
19
|
new LiveStoreJSQuery<TResult, TQueryInfo>({
|
|
20
20
|
fn,
|
|
21
21
|
label: options?.label ?? fn.toString(),
|
|
22
|
-
|
|
22
|
+
reactivityGraph: options?.reactivityGraph,
|
|
23
23
|
queryInfo: options?.queryInfo,
|
|
24
24
|
})
|
|
25
25
|
|
|
@@ -30,11 +30,11 @@ export class LiveStoreJSQuery<TResult, TQueryInfo extends QueryInfo = QueryInfoN
|
|
|
30
30
|
_tag: 'js' = 'js'
|
|
31
31
|
|
|
32
32
|
/** A reactive thunk representing the query results */
|
|
33
|
-
results$: Thunk<TResult,
|
|
33
|
+
results$: Thunk<TResult, QueryContext, RefreshReason>
|
|
34
34
|
|
|
35
35
|
label: string
|
|
36
36
|
|
|
37
|
-
protected
|
|
37
|
+
protected reactivityGraph: ReactivityGraph
|
|
38
38
|
|
|
39
39
|
queryInfo: TQueryInfo
|
|
40
40
|
|
|
@@ -50,14 +50,14 @@ export class LiveStoreJSQuery<TResult, TQueryInfo extends QueryInfo = QueryInfoN
|
|
|
50
50
|
fn,
|
|
51
51
|
label,
|
|
52
52
|
onDestroy,
|
|
53
|
-
|
|
53
|
+
reactivityGraph,
|
|
54
54
|
queryInfo,
|
|
55
55
|
}: {
|
|
56
56
|
label: string
|
|
57
57
|
fn: (get: GetAtomResult) => TResult
|
|
58
58
|
/** Currently only used for "nested destruction" of piped queries */
|
|
59
59
|
onDestroy?: () => void
|
|
60
|
-
|
|
60
|
+
reactivityGraph?: ReactivityGraph
|
|
61
61
|
queryInfo?: TQueryInfo
|
|
62
62
|
}) {
|
|
63
63
|
super()
|
|
@@ -65,12 +65,12 @@ export class LiveStoreJSQuery<TResult, TQueryInfo extends QueryInfo = QueryInfoN
|
|
|
65
65
|
this.onDestroy = onDestroy
|
|
66
66
|
this.label = label
|
|
67
67
|
|
|
68
|
-
this.
|
|
68
|
+
this.reactivityGraph = reactivityGraph ?? globalReactivityGraph
|
|
69
69
|
this.queryInfo = queryInfo ?? ({ _tag: 'None' } as TQueryInfo)
|
|
70
70
|
|
|
71
71
|
const queryLabel = `${label}:results`
|
|
72
72
|
|
|
73
|
-
this.results$ = this.
|
|
73
|
+
this.results$ = this.reactivityGraph.makeThunk(
|
|
74
74
|
(get, setDebugInfo, { otelTracer, rootOtelContext }, otelContext) =>
|
|
75
75
|
otelTracer.startActiveSpan(`js:${label}`, {}, otelContext ?? rootOtelContext, (span) => {
|
|
76
76
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
@@ -98,11 +98,11 @@ export class LiveStoreJSQuery<TResult, TQueryInfo extends QueryInfo = QueryInfoN
|
|
|
98
98
|
// },
|
|
99
99
|
// label: `${this.label}:js`,
|
|
100
100
|
// onDestroy: () => this.destroy(),
|
|
101
|
-
//
|
|
101
|
+
// reactivityGraph: this.reactivityGraph,
|
|
102
102
|
// })
|
|
103
103
|
|
|
104
104
|
destroy = () => {
|
|
105
|
-
this.
|
|
105
|
+
this.reactivityGraph.destroyNode(this.results$)
|
|
106
106
|
this.onDestroy?.()
|
|
107
107
|
}
|
|
108
108
|
}
|
|
@@ -24,17 +24,17 @@ describe('otel', () => {
|
|
|
24
24
|
provider.addSpanProcessor(new SimpleSpanProcessor(exporter))
|
|
25
25
|
provider.register()
|
|
26
26
|
|
|
27
|
-
const
|
|
27
|
+
const otelTracer = otel.trace.getTracer('test')
|
|
28
28
|
|
|
29
|
-
const span =
|
|
29
|
+
const span = otelTracer.startSpan('test')
|
|
30
30
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
31
31
|
|
|
32
|
-
const { store } = await makeTodoMvc({ otelTracer
|
|
32
|
+
const { store } = await makeTodoMvc({ otelTracer, otelContext })
|
|
33
33
|
|
|
34
34
|
return {
|
|
35
35
|
[Symbol.dispose]: () => store.destroy(),
|
|
36
36
|
store,
|
|
37
|
-
|
|
37
|
+
otelTracer,
|
|
38
38
|
exporter,
|
|
39
39
|
span,
|
|
40
40
|
provider,
|
|
@@ -60,7 +60,7 @@ describe('otel', () => {
|
|
|
60
60
|
]
|
|
61
61
|
`)
|
|
62
62
|
|
|
63
|
-
store.destroy()
|
|
63
|
+
await store.destroy()
|
|
64
64
|
query.destroy()
|
|
65
65
|
span.end()
|
|
66
66
|
|
|
@@ -193,7 +193,7 @@ describe('otel', () => {
|
|
|
193
193
|
}
|
|
194
194
|
`)
|
|
195
195
|
|
|
196
|
-
store.destroy()
|
|
196
|
+
await store.destroy()
|
|
197
197
|
query.destroy()
|
|
198
198
|
span.end()
|
|
199
199
|
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Bindable, prepareBindValues, type QueryInfo, type QueryInfoNone } from '@livestore/common'
|
|
2
2
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
3
3
|
import { Schema, TreeFormatter } from '@livestore/utils/effect'
|
|
4
4
|
import * as otel from '@opentelemetry/api'
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { globalReactivityGraph } from '../global-state.js'
|
|
7
7
|
import type { Thunk } from '../reactive.js'
|
|
8
8
|
import type { RefreshReason } from '../store.js'
|
|
9
9
|
import { getDurationMsFromSpan } from '../utils/otel.js'
|
|
10
|
-
import type {
|
|
11
|
-
import { prepareBindValues } from '../utils/util.js'
|
|
12
|
-
import type { DbContext, DbGraph, GetAtomResult, LiveQuery } from './base-class.js'
|
|
10
|
+
import type { GetAtomResult, LiveQuery, QueryContext, ReactivityGraph } from './base-class.js'
|
|
13
11
|
import { LiveStoreQueryBase, makeGetAtomResult } from './base-class.js'
|
|
14
12
|
|
|
15
13
|
export type MapRows<TResult, TRaw = any> =
|
|
@@ -28,7 +26,7 @@ export const querySQL = <TResult, TRaw = any>(
|
|
|
28
26
|
queriedTables?: Set<string>
|
|
29
27
|
bindValues?: Bindable
|
|
30
28
|
label?: string
|
|
31
|
-
|
|
29
|
+
reactivityGraph?: ReactivityGraph
|
|
32
30
|
},
|
|
33
31
|
): LiveQuery<TResult, QueryInfoNone> =>
|
|
34
32
|
new LiveStoreSQLQuery<TResult, QueryInfoNone>({
|
|
@@ -36,7 +34,7 @@ export const querySQL = <TResult, TRaw = any>(
|
|
|
36
34
|
genQueryString: query,
|
|
37
35
|
queriedTables: options?.queriedTables,
|
|
38
36
|
bindValues: options?.bindValues,
|
|
39
|
-
|
|
37
|
+
reactivityGraph: options?.reactivityGraph,
|
|
40
38
|
map: options?.map,
|
|
41
39
|
queryInfo: { _tag: 'None' },
|
|
42
40
|
})
|
|
@@ -49,14 +47,14 @@ export class LiveStoreSQLQuery<TResult, TQueryInfo extends QueryInfo = QueryInfo
|
|
|
49
47
|
_tag: 'sql' = 'sql'
|
|
50
48
|
|
|
51
49
|
/** A reactive thunk representing the query text */
|
|
52
|
-
queryString$: Thunk<string,
|
|
50
|
+
queryString$: Thunk<string, QueryContext, RefreshReason> | undefined
|
|
53
51
|
|
|
54
52
|
/** A reactive thunk representing the query results */
|
|
55
|
-
results$: Thunk<TResult,
|
|
53
|
+
results$: Thunk<TResult, QueryContext, RefreshReason>
|
|
56
54
|
|
|
57
55
|
label: string
|
|
58
56
|
|
|
59
|
-
protected
|
|
57
|
+
protected reactivityGraph
|
|
60
58
|
|
|
61
59
|
/** Currently only used by `rowQuery` for lazy table migrations and eager default row insertion */
|
|
62
60
|
private execBeforeFirstRun
|
|
@@ -70,7 +68,7 @@ export class LiveStoreSQLQuery<TResult, TQueryInfo extends QueryInfo = QueryInfo
|
|
|
70
68
|
queriedTables,
|
|
71
69
|
bindValues,
|
|
72
70
|
label: label_,
|
|
73
|
-
|
|
71
|
+
reactivityGraph,
|
|
74
72
|
map,
|
|
75
73
|
execBeforeFirstRun,
|
|
76
74
|
queryInfo,
|
|
@@ -79,16 +77,16 @@ export class LiveStoreSQLQuery<TResult, TQueryInfo extends QueryInfo = QueryInfo
|
|
|
79
77
|
genQueryString: string | ((get: GetAtomResult) => string)
|
|
80
78
|
queriedTables?: Set<string>
|
|
81
79
|
bindValues?: Bindable
|
|
82
|
-
|
|
80
|
+
reactivityGraph?: ReactivityGraph
|
|
83
81
|
map?: MapRows<TResult>
|
|
84
|
-
execBeforeFirstRun?: (ctx:
|
|
82
|
+
execBeforeFirstRun?: (ctx: QueryContext) => void
|
|
85
83
|
queryInfo?: TQueryInfo
|
|
86
84
|
}) {
|
|
87
85
|
super()
|
|
88
86
|
|
|
89
87
|
const label = label_ ?? genQueryString.toString()
|
|
90
88
|
this.label = `sql(${label})`
|
|
91
|
-
this.
|
|
89
|
+
this.reactivityGraph = reactivityGraph ?? globalReactivityGraph
|
|
92
90
|
this.execBeforeFirstRun = execBeforeFirstRun
|
|
93
91
|
this.queryInfo = queryInfo ?? ({ _tag: 'None' } as TQueryInfo)
|
|
94
92
|
this.mapRows =
|
|
@@ -126,9 +124,9 @@ Result:`,
|
|
|
126
124
|
? map
|
|
127
125
|
: shouldNeverHappen(`Invalid map function ${map}`)
|
|
128
126
|
|
|
129
|
-
let queryString$OrQueryString: string | Thunk<string,
|
|
127
|
+
let queryString$OrQueryString: string | Thunk<string, QueryContext, RefreshReason>
|
|
130
128
|
if (typeof genQueryString === 'function') {
|
|
131
|
-
queryString$OrQueryString = this.
|
|
129
|
+
queryString$OrQueryString = this.reactivityGraph.makeThunk(
|
|
132
130
|
(get, setDebugInfo, { rootOtelContext }, otelContext) => {
|
|
133
131
|
const startMs = performance.now()
|
|
134
132
|
const queryString = genQueryString(makeGetAtomResult(get, otelContext ?? rootOtelContext))
|
|
@@ -148,7 +146,7 @@ Result:`,
|
|
|
148
146
|
|
|
149
147
|
const queriedTablesRef = { current: queriedTables }
|
|
150
148
|
|
|
151
|
-
const results$ = this.
|
|
149
|
+
const results$ = this.reactivityGraph.makeThunk<TResult>(
|
|
152
150
|
(get, setDebugInfo, { store, otelTracer, rootOtelContext }, otelContext) =>
|
|
153
151
|
otelTracer.startActiveSpan(
|
|
154
152
|
'sql:...', // NOTE span name will be overridden further down
|
|
@@ -219,7 +217,7 @@ Result:`,
|
|
|
219
217
|
// },
|
|
220
218
|
// label: `${this.label}:js`,
|
|
221
219
|
// onDestroy: () => this.destroy(),
|
|
222
|
-
//
|
|
220
|
+
// reactivityGraph: this.reactivityGraph,
|
|
223
221
|
// queryInfo: undefined,
|
|
224
222
|
// })
|
|
225
223
|
|
|
@@ -237,14 +235,14 @@ Result:`,
|
|
|
237
235
|
// },
|
|
238
236
|
// label: `${this.label}:first`,
|
|
239
237
|
// onDestroy: () => this.destroy(),
|
|
240
|
-
//
|
|
238
|
+
// reactivityGraph: this.reactivityGraph,
|
|
241
239
|
// })
|
|
242
240
|
|
|
243
241
|
destroy = () => {
|
|
244
242
|
if (this.queryString$ !== undefined) {
|
|
245
|
-
this.
|
|
243
|
+
this.reactivityGraph.destroyNode(this.queryString$)
|
|
246
244
|
}
|
|
247
245
|
|
|
248
|
-
this.
|
|
246
|
+
this.reactivityGraph.destroyNode(this.results$)
|
|
249
247
|
}
|
|
250
248
|
}
|
package/src/row-query.ts
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
import { DbSchema
|
|
1
|
+
import type { QueryInfoCol, QueryInfoNone, QueryInfoRow } from '@livestore/common'
|
|
2
|
+
import { sql } from '@livestore/common'
|
|
3
|
+
import { DbSchema } from '@livestore/common/schema'
|
|
4
4
|
import type { GetValForKey } from '@livestore/utils'
|
|
5
5
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
6
6
|
import { Schema, TreeFormatter } from '@livestore/utils/effect'
|
|
7
7
|
import type * as otel from '@opentelemetry/api'
|
|
8
8
|
import type { SqliteDsl } from 'effect-db-schema'
|
|
9
|
-
import { SqliteAst } from 'effect-db-schema'
|
|
10
9
|
|
|
11
|
-
import type {
|
|
12
|
-
import type { DbContext, DbGraph, LiveQuery, LiveQueryAny } from './reactiveQueries/base-class.js'
|
|
10
|
+
import type { LiveQuery, LiveQueryAny, QueryContext, ReactivityGraph } from './reactiveQueries/base-class.js'
|
|
13
11
|
import { computed } from './reactiveQueries/js.js'
|
|
14
12
|
import { LiveStoreSQLQuery } from './reactiveQueries/sql.js'
|
|
15
|
-
import type {
|
|
13
|
+
import type { Store } from './store.js'
|
|
16
14
|
|
|
17
15
|
export type RowQueryOptions = {
|
|
18
16
|
otelContext?: otel.Context
|
|
19
17
|
skipInsertDefaultRow?: boolean
|
|
20
|
-
|
|
18
|
+
reactivityGraph?: ReactivityGraph
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
export type RowQueryOptionsDefaulValues<TTableDef extends DbSchema.TableDef> = {
|
|
@@ -76,12 +74,11 @@ export const rowQuery: MakeRowQuery = <TTableDef extends DbSchema.TableDef>(
|
|
|
76
74
|
label: `rowQuery:query:${tableSchema.name}${id === undefined ? '' : `:${id}`}`,
|
|
77
75
|
genQueryString: queryStr,
|
|
78
76
|
queriedTables: new Set([tableName]),
|
|
79
|
-
|
|
77
|
+
reactivityGraph: options?.reactivityGraph,
|
|
80
78
|
// While this code-path is not needed for singleton tables, it's still needed for `useRow` with non-existing rows for a given ID
|
|
81
79
|
execBeforeFirstRun: makeExecBeforeFirstRun({
|
|
82
80
|
otelContext: options?.otelContext,
|
|
83
81
|
table,
|
|
84
|
-
tableName,
|
|
85
82
|
defaultValues,
|
|
86
83
|
id,
|
|
87
84
|
skipInsertDefaultRow: options?.skipInsertDefaultRow,
|
|
@@ -136,59 +133,16 @@ const makeExecBeforeFirstRun =
|
|
|
136
133
|
skipInsertDefaultRow,
|
|
137
134
|
otelContext: otelContext_,
|
|
138
135
|
table,
|
|
139
|
-
tableName,
|
|
140
136
|
}: {
|
|
141
137
|
id?: string
|
|
142
138
|
defaultValues?: any
|
|
143
139
|
skipInsertDefaultRow?: boolean
|
|
144
140
|
otelContext?: otel.Context
|
|
145
|
-
tableName: string
|
|
146
141
|
table: DbSchema.TableDef
|
|
147
142
|
}) =>
|
|
148
|
-
({ store }:
|
|
143
|
+
({ store }: QueryContext) => {
|
|
149
144
|
const otelContext = otelContext_ ?? store.otel.queriesSpanContext
|
|
150
145
|
|
|
151
|
-
// TODO we can remove this codepath again when Devtools v2 has landed
|
|
152
|
-
if (store.tableRefs[tableName] === undefined) {
|
|
153
|
-
const schemaHash = SqliteAst.hash(table.sqliteDef.ast)
|
|
154
|
-
const res = store.mainDbWrapper.select<{ schemaHash: number }>(
|
|
155
|
-
sql`SELECT schemaHash FROM ${SCHEMA_META_TABLE} WHERE tableName = '${tableName}'`,
|
|
156
|
-
)
|
|
157
|
-
if (res.length === 0 || res[0]!.schemaHash !== schemaHash) {
|
|
158
|
-
const db = {
|
|
159
|
-
...store.adapter.mainDb,
|
|
160
|
-
prepare: (query) => {
|
|
161
|
-
const mainStmt = store.adapter.mainDb.prepare(query)
|
|
162
|
-
return {
|
|
163
|
-
...mainStmt,
|
|
164
|
-
execute: (bindValues) => {
|
|
165
|
-
const getRowsChanged = mainStmt.execute(bindValues)
|
|
166
|
-
store.adapter.coordinator.execute(query, bindValues, undefined)
|
|
167
|
-
return getRowsChanged
|
|
168
|
-
},
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
} satisfies InMemoryDatabase
|
|
172
|
-
|
|
173
|
-
migrateTable({
|
|
174
|
-
db,
|
|
175
|
-
tableAst: table.sqliteDef.ast,
|
|
176
|
-
otelContext,
|
|
177
|
-
schemaHash,
|
|
178
|
-
behaviour: 'create-if-not-exists',
|
|
179
|
-
})
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const label = `tableRef:${tableName}`
|
|
183
|
-
|
|
184
|
-
// TODO find a better implementation for this
|
|
185
|
-
const existingTableRefFromGraph = Array.from(store.graph.atoms.values()).find(
|
|
186
|
-
(_) => _._tag === 'ref' && _.label === label,
|
|
187
|
-
) as Ref<null, DbContext, RefreshReason> | undefined
|
|
188
|
-
|
|
189
|
-
store.tableRefs[tableName] = existingTableRefFromGraph ?? store.makeTableRef(tableName)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
146
|
if (skipInsertDefaultRow !== true && table.options.isSingleton === false) {
|
|
193
147
|
insertRowWithDefaultValuesOrIgnore({
|
|
194
148
|
store,
|