@livestore/livestore 0.0.8 → 0.0.10

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 (41) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/__tests__/react/fixture.d.ts.map +1 -1
  3. package/dist/__tests__/react/fixture.js +1 -5
  4. package/dist/__tests__/react/fixture.js.map +1 -1
  5. package/dist/inMemoryDatabase.d.ts +2 -2
  6. package/dist/inMemoryDatabase.d.ts.map +1 -1
  7. package/dist/inMemoryDatabase.js +4 -4
  8. package/dist/inMemoryDatabase.js.map +1 -1
  9. package/dist/react/useGraphQL.d.ts.map +1 -1
  10. package/dist/react/useGraphQL.js +5 -6
  11. package/dist/react/useGraphQL.js.map +1 -1
  12. package/dist/react/useLiveStoreComponent.d.ts.map +1 -1
  13. package/dist/react/useLiveStoreComponent.js +36 -25
  14. package/dist/react/useLiveStoreComponent.js.map +1 -1
  15. package/dist/reactive.d.ts +5 -5
  16. package/dist/reactive.d.ts.map +1 -1
  17. package/dist/reactive.js +10 -10
  18. package/dist/reactive.js.map +1 -1
  19. package/dist/reactiveQueries/graphql.d.ts.map +1 -1
  20. package/dist/reactiveQueries/graphql.js +5 -1
  21. package/dist/reactiveQueries/graphql.js.map +1 -1
  22. package/dist/reactiveQueries/js.d.ts.map +1 -1
  23. package/dist/reactiveQueries/js.js +1 -1
  24. package/dist/reactiveQueries/js.js.map +1 -1
  25. package/dist/reactiveQueries/sql.d.ts.map +1 -1
  26. package/dist/reactiveQueries/sql.js +6 -2
  27. package/dist/reactiveQueries/sql.js.map +1 -1
  28. package/dist/store.d.ts +23 -6
  29. package/dist/store.d.ts.map +1 -1
  30. package/dist/store.js +13 -23
  31. package/dist/store.js.map +1 -1
  32. package/package.json +2 -2
  33. package/src/__tests__/react/fixture.tsx +1 -13
  34. package/src/inMemoryDatabase.ts +5 -5
  35. package/src/react/useGraphQL.ts +6 -7
  36. package/src/react/useLiveStoreComponent.ts +35 -47
  37. package/src/reactive.ts +10 -10
  38. package/src/reactiveQueries/graphql.ts +5 -3
  39. package/src/reactiveQueries/js.ts +1 -3
  40. package/src/reactiveQueries/sql.ts +6 -6
  41. package/src/store.ts +46 -32
@@ -81,7 +81,7 @@ type ComponentState = {
81
81
  * so we need to "cache" the fact that we've already started a span for this component.
82
82
  * The map entry is being removed again in the `React.useEffect` call below.
83
83
  */
84
- const spanAlreadyStartedCache = new Map<string, { span: otel.Span; otelCtx: otel.Context }>()
84
+ const spanAlreadyStartedCache = new Map<string, { span: otel.Span; otelContext: otel.Context }>()
85
85
 
86
86
  type UseLiveStoreJsonState<TState> = <TResult>(
87
87
  jsonStringKey: keyof TState,
@@ -118,7 +118,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
118
118
  const componentKeyLabel = React.useMemo(() => labelForKey(componentKey), [componentKey])
119
119
 
120
120
  // 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, otelCtx } = React.useMemo(() => {
121
+ const { span, otelContext } = React.useMemo(() => {
122
122
  const existingSpan = spanAlreadyStartedCache.get(componentKeyLabel)
123
123
  if (existingSpan !== undefined) return existingSpan
124
124
 
@@ -128,11 +128,11 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
128
128
  store.otel.queriesSpanContext,
129
129
  )
130
130
 
131
- const otelCtx = otel.trace.setSpan(otel.context.active(), span)
131
+ const otelContext = otel.trace.setSpan(otel.context.active(), span)
132
132
 
133
- spanAlreadyStartedCache.set(componentKeyLabel, { span, otelCtx })
133
+ spanAlreadyStartedCache.set(componentKeyLabel, { span, otelContext })
134
134
 
135
- return { span, otelCtx }
135
+ return { span, otelContext }
136
136
  }, [componentKeyLabel, store.otel.queriesSpanContext, store.otel.tracer])
137
137
 
138
138
  React.useEffect(
@@ -146,23 +146,23 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
146
146
  const generateQueries = React.useCallback(
147
147
  ({
148
148
  state$,
149
- otelCtx,
149
+ otelContext,
150
150
  registerSubscription,
151
151
  isTemporaryQuery,
152
152
  }: {
153
153
  state$: LiveStoreJSQuery<TComponentState>
154
- otelCtx: otel.Context
154
+ otelContext: otel.Context
155
155
  registerSubscription: RegisterSubscription
156
156
  isTemporaryQuery: boolean
157
157
  }) =>
158
158
  queries({
159
159
  rxSQL: <T>(genQuery: (get: GetAtom) => string, queriedTables: string[]) =>
160
- store.querySQL<T>(genQuery, queriedTables, undefined, componentKey, undefined, otelCtx),
160
+ store.querySQL<T>(genQuery, { queriedTables, otelContext }),
161
161
  rxGraphQL: <Result extends Record<string, any>, Variables extends Record<string, any>>(
162
162
  query: DocumentNode<Result, Variables>,
163
163
  genVariableValues: (get: GetAtom) => Variables,
164
164
  label?: string,
165
- ) => store.queryGraphQL(query, genVariableValues, { componentKey, label }, otelCtx),
165
+ ) => store.queryGraphQL(query, genVariableValues, { componentKey, label, otelContext }),
166
166
  globalQueries,
167
167
  state$,
168
168
  subscribe: registerSubscription,
@@ -193,8 +193,8 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
193
193
  // We do this in a temporary query context which cleans up after itself, making it idempotent
194
194
  // TODO get rid of the temporary query workaround
195
195
  const { initialComponentState, initialQueryResults } = React.useMemo(() => {
196
- return store.otel.tracer.startActiveSpan('LiveStore:useLiveStoreComponent:initial', {}, otelCtx, (span) => {
197
- const otelCtx = otel.trace.setSpan(otel.context.active(), span)
196
+ return store.otel.tracer.startActiveSpan('LiveStore:useLiveStoreComponent:initial', {}, otelContext, (span) => {
197
+ const otelContext = otel.trace.setSpan(otel.context.active(), span)
198
198
 
199
199
  return store.inTempQueryContext(() => {
200
200
  try {
@@ -202,31 +202,27 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
202
202
  let stateQuery: LiveStoreJSQuery<TComponentState>
203
203
  if (stateSchema === undefined) {
204
204
  // TODO don't set up a query if there's no state schema (keeps the graph more clean)
205
- stateQuery = store.queryJS(
206
- () => ({}),
205
+ stateQuery = store.queryJS(() => ({}), {
207
206
  componentKey,
208
- undefined,
209
- otelCtx,
210
- ) as unknown as LiveStoreJSQuery<TComponentState>
207
+ otelContext,
208
+ }) as unknown as LiveStoreJSQuery<TComponentState>
211
209
  } else {
212
210
  const componentTableName = tableNameForComponentKey(componentKey)
213
211
  const whereClause = componentKey._tag === 'singleton' ? '' : `where id = '${componentKey.id}'`
214
212
  stateQuery = store
215
- .querySQL<TComponentState>(
216
- () => sql`select * from ${componentTableName} ${whereClause} limit 1`,
217
- [componentTableName],
218
- undefined,
213
+ .querySQL<TComponentState>(() => sql`select * from ${componentTableName} ${whereClause} limit 1`, {
214
+ queriedTables: [componentTableName],
219
215
  componentKey,
220
- `localState:query:${componentKeyLabel}`,
221
- otelCtx,
222
- )
216
+ label: `localState:query:${componentKeyLabel}`,
217
+ otelContext,
218
+ })
223
219
  .getFirstRow({ defaultValue: defaultComponentState })
224
220
  }
225
221
  const initialComponentState = stateQuery.results$.result
226
222
 
227
223
  const queries = generateQueries({
228
224
  state$: stateQuery,
229
- otelCtx,
225
+ otelContext,
230
226
  registerSubscription: () => {},
231
227
  isTemporaryQuery: true,
232
228
  })
@@ -241,7 +237,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
241
237
  }
242
238
  })
243
239
  })
244
- }, [store, otelCtx, stateSchema, generateQueries, componentKey, componentKeyLabel, defaultComponentState])
240
+ }, [store, otelContext, stateSchema, generateQueries, componentKey, componentKeyLabel, defaultComponentState])
245
241
 
246
242
  // Now that we've computed the initial state synchronously,
247
243
  // we can set up our useState calls w/ a default value populated...
@@ -287,48 +283,40 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
287
283
  return store.otel.tracer.startActiveSpan(
288
284
  'LiveStore:useLiveStoreComponent:long-running',
289
285
  { attributes: {} },
290
- otelCtx,
286
+ otelContext,
291
287
  (span) => {
292
- const otelCtx = otel.trace.setSpan(otel.context.active(), span)
288
+ const otelContext = otel.trace.setSpan(otel.context.active(), span)
293
289
  const unsubs: (() => void)[] = []
294
290
 
295
291
  // create state query
296
- let stateQuery: LiveStoreJSQuery<TComponentState>
292
+ let state$: LiveStoreJSQuery<TComponentState>
297
293
  if (stateSchema === undefined) {
298
- stateQuery = store.queryJS(
299
- () => ({}),
300
- componentKey,
301
- undefined,
302
- otelCtx,
303
- ) as unknown as LiveStoreJSQuery<TComponentState>
294
+ state$ = store.queryJS(() => ({}) as TComponentState, { componentKey, otelContext })
304
295
  } else {
305
296
  const componentTableName = tableNameForComponentKey(componentKey)
306
297
  insertRowForComponentInstance({ store, componentKey, stateSchema })
307
298
 
308
299
  const whereClause = componentKey._tag === 'singleton' ? '' : `where id = '${componentKey.id}'`
309
- stateQuery = store
310
- .querySQL<TComponentState>(
311
- () => sql`select * from ${componentTableName} ${whereClause} limit 1`,
312
- [componentTableName],
313
- undefined,
300
+ state$ = store
301
+ .querySQL<TComponentState>(() => sql`select * from ${componentTableName} ${whereClause} limit 1`, {
302
+ queriedTables: [componentTableName],
314
303
  componentKey,
315
- // TODO introduce a refresh "grouping" concept to associate related refreshes in the debugger UI
316
- `localState:query:${componentKeyLabel}`,
317
- otelCtx,
318
- )
304
+ label: `localState:query:${componentKeyLabel}`,
305
+ otelContext,
306
+ })
319
307
  .getFirstRow({ defaultValue: defaultComponentState })
320
308
  }
321
309
 
322
310
  unsubs.push(
323
311
  store.subscribe(
324
- stateQuery,
312
+ state$,
325
313
  (results) => {
326
314
  if (isEqual(results, componentStateRef.current) === false) {
327
315
  setComponentState_(results as TComponentState)
328
316
  }
329
317
  },
330
318
  undefined,
331
- { label: `useLiveStoreComponent:localState:subscribe:${stateQuery.label}` },
319
+ { label: `useLiveStoreComponent:localState:subscribe:${state$.label}` },
332
320
  ),
333
321
  )
334
322
 
@@ -345,7 +333,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
345
333
  )
346
334
  }
347
335
 
348
- const queries = generateQueries({ state$: stateQuery, otelCtx, registerSubscription, isTemporaryQuery: false })
336
+ const queries = generateQueries({ state$, otelContext, registerSubscription, isTemporaryQuery: false })
349
337
  // Use the name given to this query in the useQueries hook as its label
350
338
  for (const [name, query] of Object.entries(queries)) {
351
339
  query.label = name
@@ -384,7 +372,7 @@ export const useLiveStoreComponent = <TComponentState extends ComponentState, TQ
384
372
  stateSchema,
385
373
  defaultComponentState,
386
374
  generateQueries,
387
- otelCtx,
375
+ otelContext,
388
376
  componentStateRef,
389
377
  // setComponentState_,
390
378
  // 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
- parentSpanContext: otel.Context,
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
- parentSpanContext,
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
- parentSpanContext: otel.Context,
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
- parentSpanContext,
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
- parentSpanContext: otel.Context,
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 }, parentSpanContext)
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
- parentSpanContext: otel.Context,
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 }, parentSpanContext)
336
+ this.refresh({ otelHint, debugRefreshReason }, otelContext)
337
337
  }
338
338
 
339
339
  get<T>(atom: Atom<T>, context: Atom<any> | Effect): T {
@@ -367,7 +367,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
367
367
  debugRefreshReason?: RefreshReasonWithGenericReasons<TDebugRefreshReason>
368
368
  }
369
369
  | undefined,
370
- parentSpanContext: otel.Context,
370
+ otelContext: otel.Context,
371
371
  ): void {
372
372
  const otelHint = options?.otelHint ?? ''
373
373
  const debugRefreshReason = options?.debugRefreshReason
@@ -380,7 +380,7 @@ export class ReactiveGraph<TDebugRefreshReason extends Taggable, TDebugThunkInfo
380
380
  // console.log('refresh', otelHint, { shouldTrace })
381
381
  // }
382
382
 
383
- this.otelTracer.startActiveSpan(`LiveStore.refresh:${otelHint}`, {}, parentSpanContext, (span) => {
383
+ this.otelTracer.startActiveSpan(`LiveStore.refresh:${otelHint}`, {}, otelContext, (span) => {
384
384
  const atomsToRefresh = roots.filter(isAtom)
385
385
  const effectsToRun = new Set(roots.filter(isEffect))
386
386
 
@@ -45,8 +45,10 @@ export class LiveStoreGraphQLQuery<
45
45
  const results = get(this.results$)
46
46
  return f(results, get)
47
47
  },
48
- this.componentKey,
49
- `${this.label}:js`,
50
- this.otelContext,
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
- this.componentKey,
46
- `${this.label}:js`,
47
- this.otelContext,
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
  }
package/src/store.ts CHANGED
@@ -4,7 +4,7 @@ import * as otel from '@opentelemetry/api'
4
4
  import type { GraphQLSchema } from 'graphql'
5
5
  import * as graphql from 'graphql'
6
6
  import { uniqueId } from 'lodash-es'
7
- import ReactDOM from 'react-dom'
7
+ import * as ReactDOM from 'react-dom'
8
8
  import { v4 as uuid } from 'uuid'
9
9
 
10
10
  import type { Backend, BackendOptions } from './backends/index.js'
@@ -32,7 +32,7 @@ export type LiveStoreQuery<TResult extends Record<string, any> = any> =
32
32
  export type BaseGraphQLContext = {
33
33
  queriedTables: Set<string>
34
34
  /** Needed by Pothos Otel plugin for resolver tracing to work */
35
- parentSpanContext?: otel.Context
35
+ otelContext?: otel.Context
36
36
  }
37
37
 
38
38
  export const RESET_DB_LOCAL_STORAGE_KEY = 'livestore-reset'
@@ -124,6 +124,7 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
124
124
  }: StoreOptions<TGraphQLContext>) {
125
125
  this.inMemoryDB = db
126
126
  this.graph = new ReactiveGraph({
127
+ // TODO move this into React module
127
128
  // Do all our updates inside a single React setState batch to avoid multiple UI re-renders
128
129
  effectsWrapper: (run) => ReactDOM.unstable_batchedUpdates(() => run()),
129
130
  otelTracer,
@@ -186,21 +187,30 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
186
187
  */
187
188
  querySQL = <TResult>(
188
189
  genQueryString: (get: GetAtom) => string,
189
- /**
190
- * List of tables that are queried in this query;
191
- * used to determine reactive dependencies.
192
- * In the future we want to auto-generate this via parsing the query
193
- */
194
- queriedTables: string[],
195
- bindValues: Bindable | undefined,
196
- componentKey: ComponentKey | undefined,
197
- label: string | undefined,
198
- parentSpanContext: otel.Context,
190
+ {
191
+ queriedTables,
192
+ bindValues,
193
+ componentKey,
194
+ label,
195
+ otelContext = otel.context.active(),
196
+ }: {
197
+ /**
198
+ * List of tables that are queried in this query;
199
+ * used to determine reactive dependencies.
200
+ *
201
+ * NOTE In the future we want to auto-generate this via parsing the query
202
+ */
203
+ queriedTables: string[]
204
+ bindValues?: Bindable | undefined
205
+ componentKey?: ComponentKey | undefined
206
+ label?: string | undefined
207
+ otelContext?: otel.Context
208
+ },
199
209
  ): LiveStoreSQLQuery<TResult> =>
200
210
  this.otel.tracer.startActiveSpan(
201
211
  'querySQL', // NOTE span name will be overridden further down
202
212
  { attributes: { label } },
203
- parentSpanContext,
213
+ otelContext,
204
214
  (span) => {
205
215
  const otelContext = otel.trace.setSpan(otel.context.active(), span)
206
216
 
@@ -240,11 +250,7 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
240
250
  span.setAttribute('sql.query', sqlString)
241
251
  span.updateName(`sql:${sqlString.slice(0, 50)}`)
242
252
 
243
- const results = this.inMemoryDB.select(sqlString, {
244
- queriedTables,
245
- bindValues,
246
- parentSpanContext: otelContext,
247
- })
253
+ const results = this.inMemoryDB.select(sqlString, { queriedTables, bindValues, otelContext })
248
254
 
249
255
  span.setAttribute('sql.rowsCount', results.length)
250
256
  addDebugInfo({ _tag: 'sql', label: label ?? '', query: sqlString })
@@ -282,11 +288,13 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
282
288
 
283
289
  queryJS = <TResult>(
284
290
  genResults: (get: GetAtom) => TResult,
285
- componentKey: ComponentKey,
286
- label = `js${uniqueId()}`,
287
- parentSpanContext: otel.Context,
291
+ {
292
+ componentKey = globalComponentKey,
293
+ label = `js${uniqueId()}`,
294
+ otelContext = otel.context.active(),
295
+ }: { componentKey?: ComponentKey; label?: string; otelContext?: otel.Context },
288
296
  ): LiveStoreJSQuery<TResult> =>
289
- this.otel.tracer.startActiveSpan(`queryJS:${label}`, { attributes: { label } }, parentSpanContext, (span) => {
297
+ this.otel.tracer.startActiveSpan(`queryJS:${label}`, { attributes: { label } }, otelContext, (span) => {
290
298
  const otelContext = otel.trace.setSpan(otel.context.active(), span)
291
299
  const queryLabel = `${label}:results` + (this.temporaryQueries ? ':temp' : '')
292
300
  const results$ = this.graph.makeThunk(
@@ -320,13 +328,20 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
320
328
  queryGraphQL = <TResult extends Record<string, any>, TVariableValues extends Record<string, any>>(
321
329
  document: DocumentNode<TResult, TVariableValues>,
322
330
  genVariableValues: (get: GetAtom) => TVariableValues,
323
- { componentKey, label }: { componentKey: ComponentKey; label?: string },
324
- parentSpanContext: otel.Context,
331
+ {
332
+ componentKey,
333
+ label,
334
+ otelContext = otel.context.active(),
335
+ }: {
336
+ componentKey: ComponentKey
337
+ label?: string
338
+ otelContext?: otel.Context
339
+ },
325
340
  ): LiveStoreGraphQLQuery<TResult, TVariableValues, TGraphQLContext> =>
326
341
  this.otel.tracer.startActiveSpan(
327
- `queryGraphQL`, // NOTE span name will be overridden further down
342
+ `queryGraphQL:`, // NOTE span name will be overridden further down
328
343
  {},
329
- parentSpanContext,
344
+ otelContext,
330
345
  (span) => {
331
346
  const otelContext = otel.trace.setSpan(otel.context.active(), span)
332
347
 
@@ -390,25 +405,24 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
390
405
  queryGraphQLOnce = <TResult extends Record<string, any>, TVariableValues extends Record<string, any>>(
391
406
  document: DocumentNode<TResult, TVariableValues>,
392
407
  variableValues: TVariableValues,
393
- parentSpanContext?: otel.Context,
408
+ otelContext: otel.Context = this.otel.queriesSpanContext,
394
409
  ): { result: TResult; queriedTables: string[] } => {
395
410
  const schema =
396
411
  this.graphQLSchema ?? shouldNeverHappen("Can't run a GraphQL query on a store without GraphQL schema")
397
412
  const context =
398
413
  this.graphQLContext ?? shouldNeverHappen("Can't run a GraphQL query on a store without GraphQL context")
399
414
  const tracer = this.otel.tracer
400
- const spanContext = parentSpanContext ?? this.otel.queriesSpanContext
401
415
 
402
416
  const operationName = graphql.getOperationAST(document)?.name?.value
403
417
 
404
- return tracer.startActiveSpan(`executeGraphQLQuery: ${operationName}`, {}, spanContext, (span) => {
418
+ return tracer.startActiveSpan(`executeGraphQLQuery: ${operationName}`, {}, otelContext, (span) => {
405
419
  try {
406
420
  span.setAttribute('graphql.variables', JSON.stringify(variableValues))
407
421
  span.setAttribute('graphql.query', graphql.print(document))
408
422
 
409
423
  context.queriedTables.clear()
410
424
 
411
- context.parentSpanContext = otel.trace.setSpan(otel.context.active(), span)
425
+ context.otelContext = otel.trace.setSpan(otel.context.active(), span)
412
426
 
413
427
  const res = graphql.executeSync({
414
428
  document,
@@ -713,7 +727,7 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
713
727
  private applyEventWithoutRefresh = (
714
728
  eventType: string,
715
729
  args: any = {},
716
- parentSpanContext: otel.Context,
730
+ otelContext: otel.Context,
717
731
  ): { writeTables: string[]; durationMs: number } => {
718
732
  return this.otel.tracer.startActiveSpan(
719
733
  'LiveStore:applyEventWithoutRefresh',
@@ -723,7 +737,7 @@ export class Store<TGraphQLContext extends BaseGraphQLContext> {
723
737
  'livestore.args': JSON.stringify(args, null, 2),
724
738
  },
725
739
  },
726
- parentSpanContext,
740
+ otelContext,
727
741
  (span) => {
728
742
  const otelContext = otel.trace.setSpan(otel.context.active(), span)
729
743