@livestore/livestore 0.0.9 → 0.0.12
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/package.json +7 -7
- package/src/__tests__/react/fixture.tsx +1 -13
- package/src/__tests__/reactive.test.ts +39 -0
- package/src/inMemoryDatabase.ts +5 -5
- package/src/react/useGraphQL.ts +6 -7
- package/src/react/useLiveStoreComponent.ts +38 -48
- package/src/reactive.ts +12 -11
- package/src/reactiveQueries/graphql.ts +5 -3
- package/src/reactiveQueries/js.ts +1 -3
- package/src/reactiveQueries/sql.ts +6 -6
- package/src/store.ts +45 -31
- package/dist/.tsbuildinfo +0 -1
- package/dist/QueryCache.d.ts +0 -20
- package/dist/QueryCache.d.ts.map +0 -1
- package/dist/QueryCache.js +0 -71
- package/dist/QueryCache.js.map +0 -1
- package/dist/__tests__/react/fixture.d.ts +0 -141
- package/dist/__tests__/react/fixture.d.ts.map +0 -1
- package/dist/__tests__/react/fixture.js +0 -72
- package/dist/__tests__/react/fixture.js.map +0 -1
- package/dist/__tests__/react/useLiveStoreComponent.test.d.ts +0 -2
- package/dist/__tests__/react/useLiveStoreComponent.test.d.ts.map +0 -1
- package/dist/__tests__/react/useLiveStoreComponent.test.js +0 -78
- package/dist/__tests__/react/useLiveStoreComponent.test.js.map +0 -1
- package/dist/__tests__/reactive.test.d.ts +0 -2
- package/dist/__tests__/reactive.test.d.ts.map +0 -1
- package/dist/__tests__/reactive.test.js +0 -167
- package/dist/__tests__/reactive.test.js.map +0 -1
- package/dist/backends/base.d.ts +0 -13
- package/dist/backends/base.d.ts.map +0 -1
- package/dist/backends/base.js +0 -53
- package/dist/backends/base.js.map +0 -1
- package/dist/backends/index.d.ts +0 -45
- package/dist/backends/index.d.ts.map +0 -1
- package/dist/backends/index.js +0 -38
- package/dist/backends/index.js.map +0 -1
- package/dist/backends/noop.d.ts +0 -18
- package/dist/backends/noop.d.ts.map +0 -1
- package/dist/backends/noop.js +0 -21
- package/dist/backends/noop.js.map +0 -1
- package/dist/backends/tauri.d.ts +0 -22
- package/dist/backends/tauri.d.ts.map +0 -1
- package/dist/backends/tauri.js +0 -48
- package/dist/backends/tauri.js.map +0 -1
- package/dist/backends/utils/idb.d.ts +0 -10
- package/dist/backends/utils/idb.d.ts.map +0 -1
- package/dist/backends/utils/idb.js +0 -58
- package/dist/backends/utils/idb.js.map +0 -1
- package/dist/backends/web-in-memory.d.ts +0 -22
- package/dist/backends/web-in-memory.d.ts.map +0 -1
- package/dist/backends/web-in-memory.js +0 -45
- package/dist/backends/web-in-memory.js.map +0 -1
- package/dist/backends/web-worker.d.ts +0 -17
- package/dist/backends/web-worker.d.ts.map +0 -1
- package/dist/backends/web-worker.js +0 -139
- package/dist/backends/web-worker.js.map +0 -1
- package/dist/backends/web.d.ts +0 -27
- package/dist/backends/web.d.ts.map +0 -1
- package/dist/backends/web.js +0 -63
- package/dist/backends/web.js.map +0 -1
- package/dist/bounded-collections.d.ts +0 -34
- package/dist/bounded-collections.d.ts.map +0 -1
- package/dist/bounded-collections.js +0 -103
- package/dist/bounded-collections.js.map +0 -1
- package/dist/componentKey.d.ts +0 -20
- package/dist/componentKey.d.ts.map +0 -1
- package/dist/componentKey.js +0 -3
- package/dist/componentKey.js.map +0 -1
- package/dist/effect/LiveStore.d.ts +0 -42
- package/dist/effect/LiveStore.d.ts.map +0 -1
- package/dist/effect/LiveStore.js +0 -40
- package/dist/effect/LiveStore.js.map +0 -1
- package/dist/effect/index.d.ts +0 -2
- package/dist/effect/index.d.ts.map +0 -1
- package/dist/effect/index.js +0 -2
- package/dist/effect/index.js.map +0 -1
- package/dist/events.d.ts +0 -7
- package/dist/events.d.ts.map +0 -1
- package/dist/events.js +0 -2
- package/dist/events.js.map +0 -1
- package/dist/inMemoryDatabase.d.ts +0 -65
- package/dist/inMemoryDatabase.d.ts.map +0 -1
- package/dist/inMemoryDatabase.js +0 -241
- package/dist/inMemoryDatabase.js.map +0 -1
- package/dist/index.d.ts +0 -20
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -10
- package/dist/index.js.map +0 -1
- package/dist/otel.d.ts +0 -5
- package/dist/otel.d.ts.map +0 -1
- package/dist/otel.js +0 -17
- package/dist/otel.js.map +0 -1
- package/dist/react/LiveStoreContext.d.ts +0 -11
- package/dist/react/LiveStoreContext.d.ts.map +0 -1
- package/dist/react/LiveStoreContext.js +0 -10
- package/dist/react/LiveStoreContext.js.map +0 -1
- package/dist/react/LiveStoreProvider.d.ts +0 -21
- package/dist/react/LiveStoreProvider.d.ts.map +0 -1
- package/dist/react/LiveStoreProvider.js +0 -48
- package/dist/react/LiveStoreProvider.js.map +0 -1
- package/dist/react/index.d.ts +0 -7
- package/dist/react/index.d.ts.map +0 -1
- package/dist/react/index.js +0 -6
- package/dist/react/index.js.map +0 -1
- package/dist/react/useGlobalQuery.d.ts +0 -3
- package/dist/react/useGlobalQuery.d.ts.map +0 -1
- package/dist/react/useGlobalQuery.js +0 -25
- package/dist/react/useGlobalQuery.js.map +0 -1
- package/dist/react/useGraphQL.d.ts +0 -11
- package/dist/react/useGraphQL.d.ts.map +0 -1
- package/dist/react/useGraphQL.js +0 -68
- package/dist/react/useGraphQL.js.map +0 -1
- package/dist/react/useLiveStoreComponent.d.ts +0 -70
- package/dist/react/useLiveStoreComponent.d.ts.map +0 -1
- package/dist/react/useLiveStoreComponent.js +0 -261
- package/dist/react/useLiveStoreComponent.js.map +0 -1
- package/dist/react/utils/useStateRefWithReactiveInput.d.ts +0 -13
- package/dist/react/utils/useStateRefWithReactiveInput.d.ts.map +0 -1
- package/dist/react/utils/useStateRefWithReactiveInput.js +0 -38
- package/dist/react/utils/useStateRefWithReactiveInput.js.map +0 -1
- package/dist/reactive.d.ts +0 -140
- package/dist/reactive.d.ts.map +0 -1
- package/dist/reactive.js +0 -301
- package/dist/reactive.js.map +0 -1
- package/dist/reactiveQueries/base-class.d.ts +0 -24
- package/dist/reactiveQueries/base-class.d.ts.map +0 -1
- package/dist/reactiveQueries/base-class.js +0 -22
- package/dist/reactiveQueries/base-class.js.map +0 -1
- package/dist/reactiveQueries/graphql.d.ts +0 -25
- package/dist/reactiveQueries/graphql.d.ts.map +0 -1
- package/dist/reactiveQueries/graphql.js +0 -14
- package/dist/reactiveQueries/graphql.js.map +0 -1
- package/dist/reactiveQueries/js.d.ts +0 -19
- package/dist/reactiveQueries/js.d.ts.map +0 -1
- package/dist/reactiveQueries/js.js +0 -13
- package/dist/reactiveQueries/js.js.map +0 -1
- package/dist/reactiveQueries/sql.d.ts +0 -31
- package/dist/reactiveQueries/sql.d.ts.map +0 -1
- package/dist/reactiveQueries/sql.js +0 -28
- package/dist/reactiveQueries/sql.js.map +0 -1
- package/dist/schema.d.ts +0 -163
- package/dist/schema.d.ts.map +0 -1
- package/dist/schema.js +0 -92
- package/dist/schema.js.map +0 -1
- package/dist/store.d.ts +0 -175
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -549
- package/dist/store.js.map +0 -1
- package/dist/util.d.ts +0 -24
- package/dist/util.d.ts.map +0 -1
- package/dist/util.js +0 -51
- package/dist/util.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/livestore",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@graphql-typed-document-node/core": "^3.2.0",
|
|
34
|
-
"@livestore/utils": "
|
|
34
|
+
"@livestore/utils": "workspace:*",
|
|
35
35
|
"@opentelemetry/api": "^1.6.0",
|
|
36
36
|
"comlink": "^4.4.1",
|
|
37
|
-
"graphql": "^16.8.
|
|
37
|
+
"graphql": "^16.8.1",
|
|
38
38
|
"lodash-es": "^4.17.21",
|
|
39
39
|
"sqlite-esm": "3.42.0-build6",
|
|
40
|
-
"uuid": "^9.0.
|
|
40
|
+
"uuid": "^9.0.1"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@tauri-apps/api": "^1.4.0",
|
|
@@ -53,12 +53,12 @@
|
|
|
53
53
|
"@tauri-apps/api": "^1.4.0",
|
|
54
54
|
"@testing-library/react": "^14.0.0",
|
|
55
55
|
"@types/lodash-es": "^4.17.9",
|
|
56
|
-
"@types/uuid": "^9.0.
|
|
56
|
+
"@types/uuid": "^9.0.4",
|
|
57
57
|
"jsdom": "^22.1.0",
|
|
58
58
|
"react": "^18.2.0",
|
|
59
59
|
"react-dom": "^18.2.0",
|
|
60
60
|
"typescript": "5.2.2",
|
|
61
61
|
"vite": "4.4.9",
|
|
62
|
-
"vitest": "^0.34.
|
|
62
|
+
"vitest": "^0.34.6"
|
|
63
63
|
}
|
|
64
|
-
}
|
|
64
|
+
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { mapObjectValues } from '@livestore/utils'
|
|
2
|
-
import * as otel from '@opentelemetry/api'
|
|
3
2
|
import React from 'react'
|
|
4
3
|
|
|
5
4
|
import * as LiveStore from '../../index.js'
|
|
6
5
|
import { sql } from '../../index.js'
|
|
7
6
|
import * as LiveStoreReact from '../../react/index.js'
|
|
8
7
|
|
|
9
|
-
const mockOtelCtx = otel.context.active()
|
|
10
|
-
|
|
11
8
|
export type Todo = {
|
|
12
9
|
id: string
|
|
13
10
|
text: string | null
|
|
@@ -22,16 +19,7 @@ export type AppState = {
|
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
const appState: LiveStore.QueryDefinition = (store) =>
|
|
25
|
-
store
|
|
26
|
-
.querySQL<AppState>(
|
|
27
|
-
() => `select newTodoText, filter from app;`,
|
|
28
|
-
['app'],
|
|
29
|
-
undefined,
|
|
30
|
-
undefined,
|
|
31
|
-
undefined,
|
|
32
|
-
mockOtelCtx,
|
|
33
|
-
)
|
|
34
|
-
.getFirstRow()
|
|
22
|
+
store.querySQL<AppState>(() => `select newTodoText, filter from app;`, { queriedTables: ['app'] }).getFirstRow()
|
|
35
23
|
|
|
36
24
|
export const globalQueryDefs = {
|
|
37
25
|
appState,
|
|
@@ -225,3 +225,42 @@ describe('a diamond shaped graph', () => {
|
|
|
225
225
|
expect(dRuns.runs).toBe(2)
|
|
226
226
|
})
|
|
227
227
|
})
|
|
228
|
+
|
|
229
|
+
// TODO handle `undefined` in the graph
|
|
230
|
+
describe.todo('a trivial graph with undefined', () => {
|
|
231
|
+
const makeGraph = () => {
|
|
232
|
+
const graph = new ReactiveGraph({ otelTracer: makeNoopTracer() })
|
|
233
|
+
const a = graph.makeRef(undefined)
|
|
234
|
+
const b = graph.makeRef(2)
|
|
235
|
+
const numberOfRunsForC = { runs: 0 }
|
|
236
|
+
const c = graph.makeThunk(
|
|
237
|
+
(get) => {
|
|
238
|
+
numberOfRunsForC.runs++
|
|
239
|
+
return (get(a) ?? 0) + get(b)
|
|
240
|
+
},
|
|
241
|
+
undefined,
|
|
242
|
+
mockOtelCtx,
|
|
243
|
+
)
|
|
244
|
+
const d = graph.makeRef(3)
|
|
245
|
+
const e = graph.makeThunk((get) => get(c) + get(d), undefined, mockOtelCtx)
|
|
246
|
+
|
|
247
|
+
// a(1) b(2)
|
|
248
|
+
// \ /
|
|
249
|
+
// \ /
|
|
250
|
+
// c = a + b
|
|
251
|
+
// \
|
|
252
|
+
// \
|
|
253
|
+
// d(3) \
|
|
254
|
+
// \ \
|
|
255
|
+
// \ \
|
|
256
|
+
// e = c + d
|
|
257
|
+
|
|
258
|
+
return { graph, a, b, c, d, e, numberOfRunsForC }
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
it('has the right initial values', () => {
|
|
262
|
+
const { c, e } = makeGraph()
|
|
263
|
+
expect(c.result).toBe(3)
|
|
264
|
+
expect(e.result).toBe(6)
|
|
265
|
+
})
|
|
266
|
+
})
|
package/src/inMemoryDatabase.ts
CHANGED
|
@@ -192,14 +192,14 @@ export class InMemoryDatabase {
|
|
|
192
192
|
queriedTables?: string[]
|
|
193
193
|
bindValues?: Bindable
|
|
194
194
|
skipCache?: boolean
|
|
195
|
-
|
|
195
|
+
otelContext?: otel.Context
|
|
196
196
|
},
|
|
197
197
|
): ReadonlyArray<T> {
|
|
198
|
-
const { queriedTables, bindValues, skipCache = false,
|
|
198
|
+
const { queriedTables, bindValues, skipCache = false, otelContext } = options ?? {}
|
|
199
199
|
return this.otelTracer.startActiveSpan(
|
|
200
200
|
'sql-in-memory-select',
|
|
201
201
|
{},
|
|
202
|
-
|
|
202
|
+
otelContext ?? this.otelRootSpanContext,
|
|
203
203
|
(span) => {
|
|
204
204
|
try {
|
|
205
205
|
span.setAttribute('sql.query', query)
|
|
@@ -279,9 +279,9 @@ export class InMemoryDatabase {
|
|
|
279
279
|
applyEvent(
|
|
280
280
|
event: LiveStoreEvent,
|
|
281
281
|
eventDefinition: ActionDefinition,
|
|
282
|
-
|
|
282
|
+
otelContext: otel.Context,
|
|
283
283
|
): { durationMs: number } {
|
|
284
|
-
return this.otelTracer.startActiveSpan('livestore.in-memory-db:applyEvent', {},
|
|
284
|
+
return this.otelTracer.startActiveSpan('livestore.in-memory-db:applyEvent', {}, otelContext, (span) => {
|
|
285
285
|
// TODO: in the future, we'll do more CRDT-style stuff here to decide whether to run effects of the event
|
|
286
286
|
|
|
287
287
|
// NOTE: These two updates should happen transactionally;
|
package/src/react/useGraphQL.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type UseLiveStoreComponentProps<TResult extends Record<string, any>, TVar
|
|
|
20
20
|
* so we need to "cache" the fact that we've already started a span for this component.
|
|
21
21
|
* The map entry is being removed again in the `React.useEffect` call below.
|
|
22
22
|
*/
|
|
23
|
-
const spanAlreadyStartedCache = new Map<string, { span: otel.Span;
|
|
23
|
+
const spanAlreadyStartedCache = new Map<string, { span: otel.Span; otelContext: otel.Context }>()
|
|
24
24
|
|
|
25
25
|
// TODO 1) figure out a way to make `variables` optional if the query doesn't have any variables (probably requires positional args)
|
|
26
26
|
// TODO 2) allow `.pipe` on the resulting query (possibly as a separate optional prop)
|
|
@@ -36,7 +36,7 @@ export const useGraphQL = <TResult extends Record<string, any>, TVariables exten
|
|
|
36
36
|
const componentKeyLabel = React.useMemo(() => labelForKey(componentKey), [componentKey])
|
|
37
37
|
|
|
38
38
|
// The following `React.useMemo` and `React.useEffect` calls are used to start and end a span for the lifetime of this component.
|
|
39
|
-
const { span,
|
|
39
|
+
const { span, otelContext } = React.useMemo(() => {
|
|
40
40
|
const existingSpan = spanAlreadyStartedCache.get(componentKeyLabel)
|
|
41
41
|
if (existingSpan !== undefined) return existingSpan
|
|
42
42
|
|
|
@@ -46,11 +46,11 @@ export const useGraphQL = <TResult extends Record<string, any>, TVariables exten
|
|
|
46
46
|
store.otel.queriesSpanContext,
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
-
const
|
|
49
|
+
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
50
50
|
|
|
51
|
-
spanAlreadyStartedCache.set(componentKeyLabel, { span,
|
|
51
|
+
spanAlreadyStartedCache.set(componentKeyLabel, { span, otelContext })
|
|
52
52
|
|
|
53
|
-
return { span,
|
|
53
|
+
return { span, otelContext }
|
|
54
54
|
}, [componentKeyLabel, store.otel.queriesSpanContext, store.otel.tracer])
|
|
55
55
|
|
|
56
56
|
React.useEffect(
|
|
@@ -62,7 +62,7 @@ export const useGraphQL = <TResult extends Record<string, any>, TVariables exten
|
|
|
62
62
|
)
|
|
63
63
|
|
|
64
64
|
const makeLiveStoreQuery = React.useCallback(
|
|
65
|
-
() => store.queryGraphQL(query, () => variables ?? ({} as TVariables), { componentKey }
|
|
65
|
+
() => store.queryGraphQL(query, () => variables ?? ({} as TVariables), { componentKey, otelContext }),
|
|
66
66
|
// NOTE: we don't include the queries function passed in by the user here;
|
|
67
67
|
// the reason is that we don't want to force them to memoize that function.
|
|
68
68
|
// Instead, we just assume that the function always has the same contents.
|
|
@@ -100,7 +100,6 @@ export const useGraphQL = <TResult extends Record<string, any>, TVariables exten
|
|
|
100
100
|
// This should probably be improved
|
|
101
101
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
102
102
|
}, [
|
|
103
|
-
otelCtx,
|
|
104
103
|
makeLiveStoreQuery,
|
|
105
104
|
// setQueryResults_,
|
|
106
105
|
store,
|
|
@@ -14,6 +14,7 @@ import type { LiveStoreJSQuery } from '../reactiveQueries/js.js'
|
|
|
14
14
|
import type { LiveStoreSQLQuery } from '../reactiveQueries/sql.js'
|
|
15
15
|
import type { ComponentStateSchema } from '../schema.js'
|
|
16
16
|
import type { BaseGraphQLContext, LiveStoreQuery, QueryResult, Store } from '../store.js'
|
|
17
|
+
import type { Bindable } from '../util.js'
|
|
17
18
|
import { sql } from '../util.js'
|
|
18
19
|
import { useStore } from './LiveStoreContext.js'
|
|
19
20
|
import { useStateRefWithReactiveInput } from './utils/useStateRefWithReactiveInput.js'
|
|
@@ -26,6 +27,7 @@ export type QueryResults<TQuery> = { [queryName in keyof TQuery]: QueryResult<TQ
|
|
|
26
27
|
export type ReactiveSQL = <TResult>(
|
|
27
28
|
genQuery: (get: GetAtom) => string,
|
|
28
29
|
queriedTables: string[],
|
|
30
|
+
bindValues?: Bindable | undefined,
|
|
29
31
|
) => LiveStoreSQLQuery<TResult>
|
|
30
32
|
export type ReactiveGraphQL = <
|
|
31
33
|
TResult extends Record<string, any>,
|
|
@@ -81,7 +83,7 @@ type ComponentState = {
|
|
|
81
83
|
* so we need to "cache" the fact that we've already started a span for this component.
|
|
82
84
|
* The map entry is being removed again in the `React.useEffect` call below.
|
|
83
85
|
*/
|
|
84
|
-
const spanAlreadyStartedCache = new Map<string, { span: otel.Span;
|
|
86
|
+
const spanAlreadyStartedCache = new Map<string, { span: otel.Span; otelContext: otel.Context }>()
|
|
85
87
|
|
|
86
88
|
type UseLiveStoreJsonState<TState> = <TResult>(
|
|
87
89
|
jsonStringKey: keyof TState,
|
|
@@ -118,7 +120,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
118
120
|
const componentKeyLabel = React.useMemo(() => labelForKey(componentKey), [componentKey])
|
|
119
121
|
|
|
120
122
|
// The following `React.useMemo` and `React.useEffect` calls are used to start and end a span for the lifetime of this component.
|
|
121
|
-
const { span,
|
|
123
|
+
const { span, otelContext } = React.useMemo(() => {
|
|
122
124
|
const existingSpan = spanAlreadyStartedCache.get(componentKeyLabel)
|
|
123
125
|
if (existingSpan !== undefined) return existingSpan
|
|
124
126
|
|
|
@@ -128,11 +130,11 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
128
130
|
store.otel.queriesSpanContext,
|
|
129
131
|
)
|
|
130
132
|
|
|
131
|
-
const
|
|
133
|
+
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
132
134
|
|
|
133
|
-
spanAlreadyStartedCache.set(componentKeyLabel, { span,
|
|
135
|
+
spanAlreadyStartedCache.set(componentKeyLabel, { span, otelContext })
|
|
134
136
|
|
|
135
|
-
return { span,
|
|
137
|
+
return { span, otelContext }
|
|
136
138
|
}, [componentKeyLabel, store.otel.queriesSpanContext, store.otel.tracer])
|
|
137
139
|
|
|
138
140
|
React.useEffect(
|
|
@@ -146,23 +148,23 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
146
148
|
const generateQueries = React.useCallback(
|
|
147
149
|
({
|
|
148
150
|
state$,
|
|
149
|
-
|
|
151
|
+
otelContext,
|
|
150
152
|
registerSubscription,
|
|
151
153
|
isTemporaryQuery,
|
|
152
154
|
}: {
|
|
153
155
|
state$: LiveStoreJSQuery<TComponentState>
|
|
154
|
-
|
|
156
|
+
otelContext: otel.Context
|
|
155
157
|
registerSubscription: RegisterSubscription
|
|
156
158
|
isTemporaryQuery: boolean
|
|
157
159
|
}) =>
|
|
158
160
|
queries({
|
|
159
|
-
rxSQL: <T>(genQuery: (get: GetAtom) => string, queriedTables: string[]) =>
|
|
160
|
-
store.querySQL<T>(genQuery, queriedTables,
|
|
161
|
+
rxSQL: <T>(genQuery: (get: GetAtom) => string, queriedTables: string[], bindValues?: Bindable) =>
|
|
162
|
+
store.querySQL<T>(genQuery, { queriedTables, bindValues, otelContext }),
|
|
161
163
|
rxGraphQL: <Result extends Record<string, any>, Variables extends Record<string, any>>(
|
|
162
164
|
query: DocumentNode<Result, Variables>,
|
|
163
165
|
genVariableValues: (get: GetAtom) => Variables,
|
|
164
166
|
label?: string,
|
|
165
|
-
) => store.queryGraphQL(query, genVariableValues, { componentKey, label }
|
|
167
|
+
) => store.queryGraphQL(query, genVariableValues, { componentKey, label, otelContext }),
|
|
166
168
|
globalQueries,
|
|
167
169
|
state$,
|
|
168
170
|
subscribe: registerSubscription,
|
|
@@ -193,8 +195,8 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
193
195
|
// We do this in a temporary query context which cleans up after itself, making it idempotent
|
|
194
196
|
// TODO get rid of the temporary query workaround
|
|
195
197
|
const { initialComponentState, initialQueryResults } = React.useMemo(() => {
|
|
196
|
-
return store.otel.tracer.startActiveSpan('LiveStore:useLiveStoreComponent:initial', {},
|
|
197
|
-
const
|
|
198
|
+
return store.otel.tracer.startActiveSpan('LiveStore:useLiveStoreComponent:initial', {}, otelContext, (span) => {
|
|
199
|
+
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
198
200
|
|
|
199
201
|
return store.inTempQueryContext(() => {
|
|
200
202
|
try {
|
|
@@ -202,31 +204,27 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
202
204
|
let stateQuery: LiveStoreJSQuery<TComponentState>
|
|
203
205
|
if (stateSchema === undefined) {
|
|
204
206
|
// TODO don't set up a query if there's no state schema (keeps the graph more clean)
|
|
205
|
-
stateQuery = store.queryJS(
|
|
206
|
-
() => ({}),
|
|
207
|
+
stateQuery = store.queryJS(() => ({}), {
|
|
207
208
|
componentKey,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
) as unknown as LiveStoreJSQuery<TComponentState>
|
|
209
|
+
otelContext,
|
|
210
|
+
}) as unknown as LiveStoreJSQuery<TComponentState>
|
|
211
211
|
} else {
|
|
212
212
|
const componentTableName = tableNameForComponentKey(componentKey)
|
|
213
213
|
const whereClause = componentKey._tag === 'singleton' ? '' : `where id = '${componentKey.id}'`
|
|
214
214
|
stateQuery = store
|
|
215
|
-
.querySQL<TComponentState>(
|
|
216
|
-
|
|
217
|
-
[componentTableName],
|
|
218
|
-
undefined,
|
|
215
|
+
.querySQL<TComponentState>(() => sql`select * from ${componentTableName} ${whereClause} limit 1`, {
|
|
216
|
+
queriedTables: [componentTableName],
|
|
219
217
|
componentKey,
|
|
220
|
-
`localState:query:${componentKeyLabel}`,
|
|
221
|
-
|
|
222
|
-
)
|
|
218
|
+
label: `localState:query:${componentKeyLabel}`,
|
|
219
|
+
otelContext,
|
|
220
|
+
})
|
|
223
221
|
.getFirstRow({ defaultValue: defaultComponentState })
|
|
224
222
|
}
|
|
225
223
|
const initialComponentState = stateQuery.results$.result
|
|
226
224
|
|
|
227
225
|
const queries = generateQueries({
|
|
228
226
|
state$: stateQuery,
|
|
229
|
-
|
|
227
|
+
otelContext,
|
|
230
228
|
registerSubscription: () => {},
|
|
231
229
|
isTemporaryQuery: true,
|
|
232
230
|
})
|
|
@@ -241,7 +239,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
241
239
|
}
|
|
242
240
|
})
|
|
243
241
|
})
|
|
244
|
-
}, [store,
|
|
242
|
+
}, [store, otelContext, stateSchema, generateQueries, componentKey, componentKeyLabel, defaultComponentState])
|
|
245
243
|
|
|
246
244
|
// Now that we've computed the initial state synchronously,
|
|
247
245
|
// we can set up our useState calls w/ a default value populated...
|
|
@@ -287,48 +285,40 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
287
285
|
return store.otel.tracer.startActiveSpan(
|
|
288
286
|
'LiveStore:useLiveStoreComponent:long-running',
|
|
289
287
|
{ attributes: {} },
|
|
290
|
-
|
|
288
|
+
otelContext,
|
|
291
289
|
(span) => {
|
|
292
|
-
const
|
|
290
|
+
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
293
291
|
const unsubs: (() => void)[] = []
|
|
294
292
|
|
|
295
293
|
// create state query
|
|
296
|
-
let
|
|
294
|
+
let state$: LiveStoreJSQuery<TComponentState>
|
|
297
295
|
if (stateSchema === undefined) {
|
|
298
|
-
|
|
299
|
-
() => ({}),
|
|
300
|
-
componentKey,
|
|
301
|
-
undefined,
|
|
302
|
-
otelCtx,
|
|
303
|
-
) as unknown as LiveStoreJSQuery<TComponentState>
|
|
296
|
+
state$ = store.queryJS(() => ({}) as TComponentState, { componentKey, otelContext })
|
|
304
297
|
} else {
|
|
305
298
|
const componentTableName = tableNameForComponentKey(componentKey)
|
|
306
299
|
insertRowForComponentInstance({ store, componentKey, stateSchema })
|
|
307
300
|
|
|
308
301
|
const whereClause = componentKey._tag === 'singleton' ? '' : `where id = '${componentKey.id}'`
|
|
309
|
-
|
|
310
|
-
.querySQL<TComponentState>(
|
|
311
|
-
|
|
312
|
-
[componentTableName],
|
|
313
|
-
undefined,
|
|
302
|
+
state$ = store
|
|
303
|
+
.querySQL<TComponentState>(() => sql`select * from ${componentTableName} ${whereClause} limit 1`, {
|
|
304
|
+
queriedTables: [componentTableName],
|
|
314
305
|
componentKey,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
)
|
|
306
|
+
label: `localState:query:${componentKeyLabel}`,
|
|
307
|
+
otelContext,
|
|
308
|
+
})
|
|
319
309
|
.getFirstRow({ defaultValue: defaultComponentState })
|
|
320
310
|
}
|
|
321
311
|
|
|
322
312
|
unsubs.push(
|
|
323
313
|
store.subscribe(
|
|
324
|
-
|
|
314
|
+
state$,
|
|
325
315
|
(results) => {
|
|
326
316
|
if (isEqual(results, componentStateRef.current) === false) {
|
|
327
317
|
setComponentState_(results as TComponentState)
|
|
328
318
|
}
|
|
329
319
|
},
|
|
330
320
|
undefined,
|
|
331
|
-
{ label: `useLiveStoreComponent:localState:subscribe:${
|
|
321
|
+
{ label: `useLiveStoreComponent:localState:subscribe:${state$.label}` },
|
|
332
322
|
),
|
|
333
323
|
)
|
|
334
324
|
|
|
@@ -345,7 +335,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
345
335
|
)
|
|
346
336
|
}
|
|
347
337
|
|
|
348
|
-
const queries = generateQueries({ state
|
|
338
|
+
const queries = generateQueries({ state$, otelContext, registerSubscription, isTemporaryQuery: false })
|
|
349
339
|
// Use the name given to this query in the useQueries hook as its label
|
|
350
340
|
for (const [name, query] of Object.entries(queries)) {
|
|
351
341
|
query.label = name
|
|
@@ -384,7 +374,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
|
|
|
384
374
|
stateSchema,
|
|
385
375
|
defaultComponentState,
|
|
386
376
|
generateQueries,
|
|
387
|
-
|
|
377
|
+
otelContext,
|
|
388
378
|
componentStateRef,
|
|
389
379
|
// setComponentState_,
|
|
390
380
|
// setQueryResults_,
|
package/src/reactive.ts
CHANGED
|
@@ -196,7 +196,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
196
196
|
debugRefreshReason?: RefreshReasonWithGenericReasons<TDebugRefreshReason>
|
|
197
197
|
}
|
|
198
198
|
| undefined,
|
|
199
|
-
|
|
199
|
+
otelContext: otel.Context,
|
|
200
200
|
): Thunk<T> {
|
|
201
201
|
const thunk: UnevaluatedThunk<T> = {
|
|
202
202
|
_tag: 'thunk',
|
|
@@ -218,7 +218,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
218
218
|
otelHint: options?.label ?? 'makeThunk',
|
|
219
219
|
debugRefreshReason: options?.debugRefreshReason ?? { _tag: 'makeThunk', label: options?.label },
|
|
220
220
|
},
|
|
221
|
-
|
|
221
|
+
otelContext,
|
|
222
222
|
)
|
|
223
223
|
|
|
224
224
|
// Manually tell the typesystem this thunk is guaranteed to have a result at this point
|
|
@@ -248,7 +248,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
248
248
|
makeEffect(
|
|
249
249
|
doEffect: (get: GetAtom) => void,
|
|
250
250
|
options: { label?: string } | undefined,
|
|
251
|
-
|
|
251
|
+
otelContext: otel.Context,
|
|
252
252
|
): Effect {
|
|
253
253
|
const effect: Effect = {
|
|
254
254
|
_tag: 'effect',
|
|
@@ -261,7 +261,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
261
261
|
this.dirtyNodes.add(effect)
|
|
262
262
|
this.refresh(
|
|
263
263
|
{ otelHint: 'makeEffect', debugRefreshReason: { _tag: 'makeEffect', label: options?.label } },
|
|
264
|
-
|
|
264
|
+
otelContext,
|
|
265
265
|
)
|
|
266
266
|
|
|
267
267
|
return effect
|
|
@@ -277,7 +277,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
277
277
|
debugRefreshReason?: TDebugRefreshReason
|
|
278
278
|
}
|
|
279
279
|
| undefined,
|
|
280
|
-
|
|
280
|
+
otelContext: otel.Context,
|
|
281
281
|
) {
|
|
282
282
|
const { otelHint, skipRefresh, debugRefreshReason } = options ?? {}
|
|
283
283
|
ref.result = val
|
|
@@ -297,7 +297,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
297
297
|
return
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
this.refresh({ otelHint, debugRefreshReason },
|
|
300
|
+
this.refresh({ otelHint, debugRefreshReason }, otelContext)
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
setRefs<T>(
|
|
@@ -309,7 +309,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
309
309
|
debugRefreshReason?: TDebugRefreshReason
|
|
310
310
|
}
|
|
311
311
|
| undefined,
|
|
312
|
-
|
|
312
|
+
otelContext: otel.Context,
|
|
313
313
|
) {
|
|
314
314
|
const otelHint = options?.otelHint ?? ''
|
|
315
315
|
const skipRefresh = options?.skipRefresh ?? false
|
|
@@ -333,7 +333,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
333
333
|
return
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
-
this.refresh({ otelHint, debugRefreshReason },
|
|
336
|
+
this.refresh({ otelHint, debugRefreshReason }, otelContext)
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
get<T>(atom: Atom<T>, context: Atom<any> | Effect): T {
|
|
@@ -350,7 +350,8 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
350
350
|
)
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
|
|
353
|
+
// TODO handle case when `atom.result` is undefined
|
|
354
|
+
return atom.result
|
|
354
355
|
}
|
|
355
356
|
|
|
356
357
|
/**
|
|
@@ -367,7 +368,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
367
368
|
debugRefreshReason?: RefreshReasonWithGenericReasons<TDebugRefreshReason>
|
|
368
369
|
}
|
|
369
370
|
| undefined,
|
|
370
|
-
|
|
371
|
+
otelContext: otel.Context,
|
|
371
372
|
): void {
|
|
372
373
|
const otelHint = options?.otelHint ?? ''
|
|
373
374
|
const debugRefreshReason = options?.debugRefreshReason
|
|
@@ -380,7 +381,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
|
|
|
380
381
|
// console.log('refresh', otelHint, { shouldTrace })
|
|
381
382
|
// }
|
|
382
383
|
|
|
383
|
-
this.otelTracer.startActiveSpan(`LiveStore.refresh:${otelHint}`, {},
|
|
384
|
+
this.otelTracer.startActiveSpan(`LiveStore.refresh:${otelHint}`, {}, otelContext, (span) => {
|
|
384
385
|
const atomsToRefresh = roots.filter(isAtom)
|
|
385
386
|
const effectsToRun = new Set(roots.filter(isEffect))
|
|
386
387
|
|
|
@@ -45,8 +45,10 @@ export class LiveStoreGraphQLQuery<
|
|
|
45
45
|
const results = get(this.results$)
|
|
46
46
|
return f(results, get)
|
|
47
47
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
{
|
|
49
|
+
componentKey: this.componentKey,
|
|
50
|
+
label: `${this.label}:js`,
|
|
51
|
+
otelContext: this.otelContext,
|
|
52
|
+
},
|
|
51
53
|
)
|
|
52
54
|
}
|
|
@@ -31,8 +31,6 @@ export class LiveStoreJSQuery<TResult> extends LiveStoreQueryBase {
|
|
|
31
31
|
const results = get(this.results$)
|
|
32
32
|
return f(results, get)
|
|
33
33
|
},
|
|
34
|
-
this.componentKey,
|
|
35
|
-
`${this.label}:js`,
|
|
36
|
-
this.otelContext,
|
|
34
|
+
{ componentKey: this.componentKey, label: `${this.label}:js`, otelContext: this.otelContext },
|
|
37
35
|
)
|
|
38
36
|
}
|
|
@@ -42,9 +42,11 @@ export class LiveStoreSQLQuery<Row> extends LiveStoreQueryBase {
|
|
|
42
42
|
const results = get(this.results$)
|
|
43
43
|
return f(results, get)
|
|
44
44
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
{
|
|
46
|
+
componentKey: this.componentKey,
|
|
47
|
+
label: `${this.label}:js`,
|
|
48
|
+
otelContext: this.otelContext,
|
|
49
|
+
},
|
|
48
50
|
)
|
|
49
51
|
|
|
50
52
|
/** Returns a reactive query */
|
|
@@ -58,8 +60,6 @@ export class LiveStoreSQLQuery<Row> extends LiveStoreQueryBase {
|
|
|
58
60
|
}
|
|
59
61
|
return (results[0] ?? args?.defaultValue) as Row
|
|
60
62
|
},
|
|
61
|
-
this.componentKey,
|
|
62
|
-
`${this.label}:first`,
|
|
63
|
-
this.otelContext,
|
|
63
|
+
{ componentKey: this.componentKey, label: `${this.label}:first`, otelContext: this.otelContext },
|
|
64
64
|
)
|
|
65
65
|
}
|