@livestore/livestore 0.0.46-dev.4 → 0.0.46

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 (115) hide show
  1. package/README.md +10 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/react/fixture.d.ts +18 -2
  4. package/dist/__tests__/react/fixture.d.ts.map +1 -1
  5. package/dist/__tests__/react/fixture.js +27 -3
  6. package/dist/__tests__/react/fixture.js.map +1 -1
  7. package/dist/__tests__/react/utils/otel.d.ts +10 -0
  8. package/dist/__tests__/react/utils/otel.d.ts.map +1 -0
  9. package/dist/__tests__/react/utils/otel.js +42 -0
  10. package/dist/__tests__/react/utils/otel.js.map +1 -0
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/react/LiveStoreProvider.js +39 -6
  15. package/dist/react/LiveStoreProvider.js.map +1 -1
  16. package/dist/react/LiveStoreProvider.test.d.ts +2 -0
  17. package/dist/react/LiveStoreProvider.test.d.ts.map +1 -0
  18. package/dist/react/LiveStoreProvider.test.js +51 -0
  19. package/dist/react/LiveStoreProvider.test.js.map +1 -0
  20. package/dist/react/components/DiffableList copy.d.ts +19 -0
  21. package/dist/react/components/DiffableList copy.d.ts.map +1 -0
  22. package/dist/react/components/DiffableList copy.js +62 -0
  23. package/dist/react/components/DiffableList copy.js.map +1 -0
  24. package/dist/react/components/DiffableList.d.ts +2 -9
  25. package/dist/react/components/DiffableList.d.ts.map +1 -1
  26. package/dist/react/components/DiffableList.js +10 -102
  27. package/dist/react/components/DiffableList.js.map +1 -1
  28. package/dist/react/components/DiffableList2.d.ts +20 -0
  29. package/dist/react/components/DiffableList2.d.ts.map +1 -0
  30. package/dist/react/components/DiffableList2.js +119 -0
  31. package/dist/react/components/DiffableList2.js.map +1 -0
  32. package/dist/react/components/DiffableList3.d.ts +19 -0
  33. package/dist/react/components/DiffableList3.d.ts.map +1 -0
  34. package/dist/react/components/DiffableList3.js +62 -0
  35. package/dist/react/components/DiffableList3.js.map +1 -0
  36. package/dist/react/components/LiveList.d.ts +21 -0
  37. package/dist/react/components/LiveList.d.ts.map +1 -0
  38. package/dist/react/components/LiveList.js +31 -0
  39. package/dist/react/components/LiveList.js.map +1 -0
  40. package/dist/react/index.d.ts +1 -1
  41. package/dist/react/index.d.ts.map +1 -1
  42. package/dist/react/index.js +1 -1
  43. package/dist/react/index.js.map +1 -1
  44. package/dist/react/useAtom.d.ts +1 -1
  45. package/dist/react/useAtom.d.ts.map +1 -1
  46. package/dist/react/useAtom.js.map +1 -1
  47. package/dist/react/useQuery.d.ts +4 -1
  48. package/dist/react/useQuery.d.ts.map +1 -1
  49. package/dist/react/useQuery.js +24 -19
  50. package/dist/react/useQuery.js.map +1 -1
  51. package/dist/react/useQuery.test.js +11 -11
  52. package/dist/react/useQuery.test.js.map +1 -1
  53. package/dist/react/useRow.d.ts.map +1 -1
  54. package/dist/react/useRow.js +14 -69
  55. package/dist/react/useRow.js.map +1 -1
  56. package/dist/react/useRow.test.js +440 -28
  57. package/dist/react/useRow.test.js.map +1 -1
  58. package/dist/react/useRowOld.d.ts +40 -0
  59. package/dist/react/useRowOld.d.ts.map +1 -0
  60. package/dist/react/useRowOld.js +134 -0
  61. package/dist/react/useRowOld.js.map +1 -0
  62. package/dist/react/useTemporaryQuery.d.ts +15 -3
  63. package/dist/react/useTemporaryQuery.d.ts.map +1 -1
  64. package/dist/react/useTemporaryQuery.js +60 -27
  65. package/dist/react/useTemporaryQuery.js.map +1 -1
  66. package/dist/react/useTemporaryQuery.test.js +10 -9
  67. package/dist/react/useTemporaryQuery.test.js.map +1 -1
  68. package/dist/reactive.d.ts +23 -5
  69. package/dist/reactive.d.ts.map +1 -1
  70. package/dist/reactive.js +44 -11
  71. package/dist/reactive.js.map +1 -1
  72. package/dist/reactive.test.js +1 -1
  73. package/dist/reactive.test.js.map +1 -1
  74. package/dist/reactiveQueries/base-class.d.ts +1 -1
  75. package/dist/reactiveQueries/base-class.d.ts.map +1 -1
  76. package/dist/reactiveQueries/base-class.js.map +1 -1
  77. package/dist/reactiveQueries/graphql.d.ts +2 -2
  78. package/dist/reactiveQueries/graphql.d.ts.map +1 -1
  79. package/dist/reactiveQueries/graphql.js +16 -10
  80. package/dist/reactiveQueries/graphql.js.map +1 -1
  81. package/dist/reactiveQueries/sql.d.ts +1 -1
  82. package/dist/reactiveQueries/sql.d.ts.map +1 -1
  83. package/dist/reactiveQueries/sql.js +15 -11
  84. package/dist/reactiveQueries/sql.js.map +1 -1
  85. package/dist/reactiveQueries/sql.test.js +1 -40
  86. package/dist/reactiveQueries/sql.test.js.map +1 -1
  87. package/dist/store.d.ts +2 -2
  88. package/dist/store.d.ts.map +1 -1
  89. package/dist/store.js +10 -7
  90. package/dist/store.js.map +1 -1
  91. package/package.json +6 -8
  92. package/src/__tests__/react/fixture.tsx +35 -2
  93. package/src/__tests__/react/utils/otel.ts +61 -0
  94. package/src/index.ts +12 -1
  95. package/src/react/LiveStoreProvider.test.tsx +82 -0
  96. package/src/react/LiveStoreProvider.tsx +42 -7
  97. package/src/react/components/LiveList.tsx +84 -0
  98. package/src/react/index.ts +1 -1
  99. package/src/react/useAtom.ts +1 -1
  100. package/src/react/useQuery.test.tsx +11 -11
  101. package/src/react/useQuery.ts +29 -22
  102. package/src/react/useRow.test.tsx +502 -30
  103. package/src/react/useRow.ts +19 -107
  104. package/src/react/useTemporaryQuery.test.tsx +17 -16
  105. package/src/react/useTemporaryQuery.ts +96 -28
  106. package/src/reactive.test.ts +1 -1
  107. package/src/reactive.ts +76 -15
  108. package/src/reactiveQueries/base-class.ts +2 -1
  109. package/src/reactiveQueries/graphql.ts +21 -15
  110. package/src/reactiveQueries/sql.test.ts +1 -54
  111. package/src/reactiveQueries/sql.ts +20 -14
  112. package/src/store.ts +12 -8
  113. package/tsconfig.json +0 -1
  114. package/src/react/components/DiffableList.tsx +0 -192
  115. package/src/react/utils/useCleanup.ts +0 -25
@@ -1,22 +1,30 @@
1
+ import { ReadonlyRecord } from '@livestore/utils/effect'
2
+ import * as otel from '@opentelemetry/api'
3
+ import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
1
4
  import { act, render, renderHook } from '@testing-library/react'
2
5
  import React from 'react'
3
6
  import { describe, expect, it } from 'vitest'
4
7
 
5
8
  import type { Todo } from '../__tests__/react/fixture.js'
6
9
  import { makeTodoMvc, todos } from '../__tests__/react/fixture.js'
10
+ import { getSimplifiedRootSpan } from '../__tests__/react/utils/otel.js'
7
11
  import * as LiveStore from '../index.js'
8
12
  import { mutationForQueryInfo } from '../query-info.js'
9
13
  import * as LiveStoreReact from './index.js'
14
+ import type { StackInfo } from './utils/stack-info.js'
10
15
 
11
- describe('useRow', () => {
16
+ // NOTE running tests concurrently doesn't work with the default global db graph
17
+ describe.concurrent('useRow', () => {
12
18
  it('should update the data based on component key', async () => {
13
- let renderCount = 0
19
+ using inputs = await makeTodoMvc({ useGlobalDbGraph: false })
14
20
 
15
- const { wrapper, AppComponentSchema, store, dbGraph } = await makeTodoMvc({ useGlobalDbGraph: false })
21
+ const { wrapper, AppComponentSchema, store, dbGraph, makeRenderCount } = inputs
22
+
23
+ const renderCount = makeRenderCount()
16
24
 
17
25
  const { result, rerender } = renderHook(
18
26
  (userId: string) => {
19
- renderCount++
27
+ renderCount.inc()
20
28
 
21
29
  const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { dbGraph })
22
30
  return { state, setState }
@@ -26,25 +34,33 @@ describe('useRow', () => {
26
34
 
27
35
  expect(result.current.state.id).toBe('u1')
28
36
  expect(result.current.state.username).toBe('')
29
- expect(renderCount).toBe(1)
37
+ expect(renderCount.val).toBe(1)
30
38
 
31
- act(() => store.execute(LiveStore.sql`INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`))
39
+ act(() =>
40
+ store.mutate(
41
+ LiveStore.rawSqlMutation({
42
+ sql: LiveStore.sql`INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`,
43
+ }),
44
+ ),
45
+ )
32
46
 
33
47
  rerender('u2')
34
48
 
35
49
  expect(result.current.state.id).toBe('u2')
36
50
  expect(result.current.state.username).toBe('username_u2')
37
- expect(renderCount).toBe(2)
51
+ expect(renderCount.val).toBe(2)
38
52
  })
39
53
 
40
54
  it('should update the data reactively - via setState', async () => {
41
- let renderCount = 0
55
+ using inputs = await makeTodoMvc({ useGlobalDbGraph: false })
42
56
 
43
- const { wrapper, AppComponentSchema, dbGraph } = await makeTodoMvc({ useGlobalDbGraph: false })
57
+ const { wrapper, AppComponentSchema, dbGraph, makeRenderCount } = inputs
58
+
59
+ const renderCount = makeRenderCount()
44
60
 
45
61
  const { result } = renderHook(
46
62
  (userId: string) => {
47
- renderCount++
63
+ renderCount.inc()
48
64
 
49
65
  const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { dbGraph })
50
66
  return { state, setState }
@@ -54,23 +70,25 @@ describe('useRow', () => {
54
70
 
55
71
  expect(result.current.state.id).toBe('u1')
56
72
  expect(result.current.state.username).toBe('')
57
- expect(renderCount).toBe(1)
73
+ expect(renderCount.val).toBe(1)
58
74
 
59
75
  act(() => result.current.setState.username('username_u1_hello'))
60
76
 
61
77
  expect(result.current.state.id).toBe('u1')
62
78
  expect(result.current.state.username).toBe('username_u1_hello')
63
- expect(renderCount).toBe(2)
79
+ expect(renderCount.val).toBe(2)
64
80
  })
65
81
 
66
- it('should update the data reactively - via raw store update', async () => {
67
- let renderCount = 0
82
+ it('should update the data reactively - via raw store mutation', async () => {
83
+ using inputs = await makeTodoMvc({ useGlobalDbGraph: false })
84
+
85
+ const { wrapper, AppComponentSchema, store, dbGraph, makeRenderCount } = inputs
68
86
 
69
- const { wrapper, AppComponentSchema, store, dbGraph } = await makeTodoMvc({ useGlobalDbGraph: false })
87
+ const renderCount = makeRenderCount()
70
88
 
71
89
  const { result } = renderHook(
72
90
  (userId: string) => {
73
- renderCount++
91
+ renderCount.inc()
74
92
 
75
93
  const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { dbGraph })
76
94
  return { state, setState }
@@ -80,19 +98,24 @@ describe('useRow', () => {
80
98
 
81
99
  expect(result.current.state.id).toBe('u1')
82
100
  expect(result.current.state.username).toBe('')
83
- expect(renderCount).toBe(1)
84
-
85
- act(() => result.current.setState.username('username_u1_hello'))
101
+ expect(renderCount.val).toBe(1)
86
102
 
87
- act(() => store.execute(LiveStore.sql`UPDATE UserInfo SET username = 'username_u1_hello' WHERE id = 'u1';`))
103
+ act(() =>
104
+ store.mutate(
105
+ LiveStore.rawSqlMutation({
106
+ sql: LiveStore.sql`UPDATE UserInfo SET username = 'username_u1_hello' WHERE id = 'u1';`,
107
+ }),
108
+ ),
109
+ )
88
110
 
89
111
  expect(result.current.state.id).toBe('u1')
90
112
  expect(result.current.state.username).toBe('username_u1_hello')
91
- expect(renderCount).toBe(2)
113
+ expect(renderCount.val).toBe(2)
92
114
  })
93
115
 
94
116
  it('should work for a larger app', async () => {
95
- const { wrapper, store, dbGraph } = await makeTodoMvc({ useGlobalDbGraph: false })
117
+ using inputs = await makeTodoMvc({ useGlobalDbGraph: false })
118
+ const { wrapper, store, dbGraph, makeRenderCount } = inputs
96
119
 
97
120
  const allTodos$ = LiveStore.querySQL<Todo[]>(`select * from todos`, { label: 'allTodos', dbGraph })
98
121
 
@@ -104,10 +127,10 @@ describe('useRow', () => {
104
127
  { isSingleton: true },
105
128
  )
106
129
 
107
- let appRouterRenderCount = 0
130
+ const appRouterRenderCount = makeRenderCount()
108
131
  let globalSetState: LiveStoreReact.StateSetters<typeof AppRouterSchema> | undefined
109
132
  const AppRouter: React.FC = () => {
110
- appRouterRenderCount++
133
+ appRouterRenderCount.inc()
111
134
 
112
135
  const [state, setState] = LiveStoreReact.useRow(AppRouterSchema, { dbGraph })
113
136
 
@@ -143,7 +166,7 @@ describe('useRow', () => {
143
166
 
144
167
  const renderResult = render(<AppRouter />, { wrapper })
145
168
 
146
- expect(appRouterRenderCount).toBe(1)
169
+ expect(appRouterRenderCount.val).toBe(1)
147
170
 
148
171
  act(() =>
149
172
  store.mutate(
@@ -153,12 +176,12 @@ describe('useRow', () => {
153
176
  ),
154
177
  )
155
178
 
156
- expect(appRouterRenderCount).toBe(1)
179
+ expect(appRouterRenderCount.val).toBe(1)
157
180
  expect(renderResult.getByRole('current-id').innerHTML).toMatchInlineSnapshot('"Current Task Id: -"')
158
181
 
159
182
  act(() => globalSetState!.currentTaskId('t1'))
160
183
 
161
- expect(appRouterRenderCount).toBe(2)
184
+ expect(appRouterRenderCount.val).toBe(2)
162
185
  expect(renderResult.getByRole('content').innerHTML).toMatchInlineSnapshot(
163
186
  `"{"id":"t1","text":"buy milk","completed":false}"`,
164
187
  )
@@ -177,9 +200,458 @@ describe('useRow', () => {
177
200
  ),
178
201
  )
179
202
 
180
- expect(appRouterRenderCount).toBe(3)
203
+ expect(appRouterRenderCount.val).toBe(3)
181
204
  expect(renderResult.getByRole('current-id').innerHTML).toMatchInlineSnapshot('"Current Task Id: t2"')
182
205
  })
183
- })
184
206
 
185
- // TODO add otel tests
207
+ it('should work for a useRow query chained with a useTemporary query', async () => {
208
+ using inputs = await makeTodoMvc({ useGlobalDbGraph: false })
209
+ const { store, wrapper, AppComponentSchema, dbGraph, makeRenderCount, cud } = inputs
210
+ const renderCount = makeRenderCount()
211
+
212
+ store.mutate(
213
+ cud.todos.insert({ id: 't1', text: 'buy milk', completed: false }),
214
+ cud.todos.insert({ id: 't2', text: 'buy bread', completed: false }),
215
+ )
216
+
217
+ const { result, unmount, rerender } = renderHook(
218
+ (userId: string) => {
219
+ renderCount.inc()
220
+
221
+ const [_row, _setRow, rowState$] = LiveStoreReact.useRow(AppComponentSchema, userId, { dbGraph })
222
+ const todos = LiveStoreReact.useTemporaryQuery(
223
+ () =>
224
+ LiveStore.querySQL<any[]>(
225
+ (get) => LiveStore.sql`select * from todos where text like '%${get(rowState$).text}%'`,
226
+ { dbGraph, label: 'todosFiltered' },
227
+ ),
228
+ userId,
229
+ )
230
+
231
+ return { todos }
232
+ },
233
+ { wrapper, initialProps: 'u1' },
234
+ )
235
+
236
+ act(() =>
237
+ store.mutate(
238
+ LiveStore.rawSqlMutation({
239
+ sql: LiveStore.sql`INSERT INTO UserInfo (id, username, text) VALUES ('u2', 'username_u2', 'milk')`,
240
+ }),
241
+ ),
242
+ )
243
+
244
+ expect(result.current.todos.length).toBe(2)
245
+ // expect(result.current.state.username).toBe('')
246
+ expect(renderCount.val).toBe(1)
247
+
248
+ rerender('u2')
249
+
250
+ expect(result.current.todos.length).toBe(1)
251
+ expect(renderCount.val).toBe(2)
252
+
253
+ unmount()
254
+ })
255
+
256
+ let cachedProvider: BasicTracerProvider | undefined
257
+
258
+ describe('otel', () => {
259
+ const exporter = new InMemorySpanExporter()
260
+
261
+ const provider = cachedProvider ?? new BasicTracerProvider()
262
+ cachedProvider = provider
263
+ provider.addSpanProcessor(new SimpleSpanProcessor(exporter))
264
+ provider.register()
265
+
266
+ const otelTracer = otel.trace.getTracer('test')
267
+
268
+ const span = otelTracer.startSpan('test')
269
+ const otelContext = otel.trace.setSpan(otel.context.active(), span)
270
+
271
+ it('should update the data based on component key', async () => {
272
+ using inputs = await makeTodoMvc({ useGlobalDbGraph: false, otelContext, otelTracer })
273
+
274
+ const { wrapper, AppComponentSchema, store, dbGraph, makeRenderCount, strictMode } = inputs
275
+
276
+ const renderCount = makeRenderCount()
277
+
278
+ const { result, rerender, unmount } = renderHook(
279
+ (userId: string) => {
280
+ renderCount.inc()
281
+
282
+ const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { dbGraph })
283
+ return { state, setState }
284
+ },
285
+ { wrapper, initialProps: 'u1' },
286
+ )
287
+
288
+ expect(result.current.state.id).toBe('u1')
289
+ expect(result.current.state.username).toBe('')
290
+ expect(renderCount.val).toBe(1)
291
+
292
+ act(() =>
293
+ store.mutate(
294
+ LiveStore.rawSqlMutation({
295
+ sql: LiveStore.sql`INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`,
296
+ }),
297
+ ),
298
+ )
299
+
300
+ rerender('u2')
301
+
302
+ expect(result.current.state.id).toBe('u2')
303
+ expect(result.current.state.username).toBe('username_u2')
304
+ expect(renderCount.val).toBe(2)
305
+
306
+ unmount()
307
+ store.destroy()
308
+ span.end()
309
+
310
+ const mapAttributes = (attributes: otel.Attributes) => {
311
+ return ReadonlyRecord.map(attributes, (val, key) => {
312
+ if (key === 'stackInfo') {
313
+ const stackInfo = JSON.parse(val as string) as StackInfo
314
+ // stackInfo.frames.shift() // Removes `renderHook.wrapper` from the stack
315
+ stackInfo.frames.forEach((_) => {
316
+ if (_.name.includes('renderHook.wrapper')) {
317
+ _.name = 'renderHook.wrapper'
318
+ }
319
+ _.filePath = '__REPLACED_FOR_SNAPSHOT__'
320
+ })
321
+ return JSON.stringify(stackInfo)
322
+ }
323
+ return val
324
+ })
325
+ }
326
+
327
+ if (strictMode) {
328
+ expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchInlineSnapshot(`
329
+ {
330
+ "_name": "test",
331
+ "children": [
332
+ {
333
+ "_name": "livestore.in-memory-db:execute",
334
+ "attributes": {
335
+ "sql.query": "
336
+ PRAGMA page_size=32768;
337
+ PRAGMA cache_size=10000;
338
+ PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
339
+ PRAGMA synchronous='OFF';
340
+ PRAGMA temp_store='MEMORY';
341
+ PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
342
+ ",
343
+ },
344
+ },
345
+ {
346
+ "_name": "sql-in-memory-select",
347
+ "attributes": {
348
+ "sql.cached": false,
349
+ "sql.query": "SELECT schemaHash FROM __livestore_schema WHERE tableName = 'UserInfo'",
350
+ "sql.rowsCount": 0,
351
+ },
352
+ },
353
+ {
354
+ "_name": "LiveStore:mutations",
355
+ "children": [
356
+ {
357
+ "_name": "LiveStore:mutate",
358
+ "attributes": {
359
+ "livestore.mutateLabel": "mutate",
360
+ },
361
+ "children": [
362
+ {
363
+ "_name": "LiveStore:processWrites",
364
+ "attributes": {
365
+ "livestore.mutateLabel": "mutate",
366
+ },
367
+ "children": [
368
+ {
369
+ "_name": "LiveStore:mutatetWithoutRefresh",
370
+ "attributes": {
371
+ "livestore.args": "{
372
+ "sql": "INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')"
373
+ }",
374
+ "livestore.mutation": "livestore.RawSql",
375
+ },
376
+ "children": [
377
+ {
378
+ "_name": "livestore.in-memory-db:execute",
379
+ "attributes": {
380
+ "sql.query": "INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')",
381
+ },
382
+ },
383
+ ],
384
+ },
385
+ ],
386
+ },
387
+ ],
388
+ },
389
+ ],
390
+ },
391
+ {
392
+ "_name": "LiveStore:queries",
393
+ "children": [
394
+ {
395
+ "_name": "sql:select * from UserInfo where id = 'u1' limit 1",
396
+ "attributes": {
397
+ "sql.query": "select * from UserInfo where id = 'u1' limit 1",
398
+ "sql.rowsCount": 1,
399
+ },
400
+ "children": [
401
+ {
402
+ "_name": "sql-in-memory-select",
403
+ "attributes": {
404
+ "sql.cached": false,
405
+ "sql.query": "select * from UserInfo where id = 'u1' limit 1",
406
+ "sql.rowsCount": 1,
407
+ },
408
+ },
409
+ ],
410
+ },
411
+ {
412
+ "_name": "LiveStore:useRow:UserInfo:u1",
413
+ "attributes": {
414
+ "id": "u1",
415
+ },
416
+ "children": [
417
+ {
418
+ "_name": "livestore.in-memory-db:execute",
419
+ "attributes": {
420
+ "sql.query": "insert into UserInfo (username, text, id) select $username, $text, $id where not exists(select 1 from UserInfo where id = 'u1')",
421
+ },
422
+ },
423
+ {
424
+ "_name": "LiveStore:useQuery:sql(rowQuery:query:UserInfo:u1)",
425
+ "attributes": {
426
+ "label": "sql(rowQuery:query:UserInfo:u1)",
427
+ "stackInfo": "{"frames":[{"name":"renderHook.wrapper","filePath":"__REPLACED_FOR_SNAPSHOT__"},{"name":"useRow","filePath":"__REPLACED_FOR_SNAPSHOT__"}]}",
428
+ },
429
+ "children": [
430
+ {
431
+ "_name": "sql:select * from UserInfo where id = 'u1' limit 1",
432
+ "attributes": {
433
+ "sql.query": "select * from UserInfo where id = 'u1' limit 1",
434
+ "sql.rowsCount": 1,
435
+ },
436
+ "children": [
437
+ {
438
+ "_name": "sql-in-memory-select",
439
+ "attributes": {
440
+ "sql.cached": false,
441
+ "sql.query": "select * from UserInfo where id = 'u1' limit 1",
442
+ "sql.rowsCount": 1,
443
+ },
444
+ },
445
+ ],
446
+ },
447
+ {
448
+ "_name": "LiveStore.subscribe",
449
+ "attributes": {
450
+ "label": "sql(rowQuery:query:UserInfo:u1)",
451
+ "queryLabel": "sql(rowQuery:query:UserInfo:u1)",
452
+ },
453
+ },
454
+ {
455
+ "_name": "LiveStore.subscribe",
456
+ "attributes": {
457
+ "label": "sql(rowQuery:query:UserInfo:u1)",
458
+ "queryLabel": "sql(rowQuery:query:UserInfo:u1)",
459
+ },
460
+ },
461
+ ],
462
+ },
463
+ ],
464
+ },
465
+ ],
466
+ },
467
+ ],
468
+ }
469
+ `)
470
+ // Below: Strict mode disabled
471
+ } else {
472
+ expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchInlineSnapshot(`
473
+ {
474
+ "_name": "test",
475
+ "children": [
476
+ {
477
+ "_name": "livestore.in-memory-db:execute",
478
+ "attributes": {
479
+ "sql.query": "
480
+ PRAGMA page_size=32768;
481
+ PRAGMA cache_size=10000;
482
+ PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
483
+ PRAGMA synchronous='OFF';
484
+ PRAGMA temp_store='MEMORY';
485
+ PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
486
+ ",
487
+ },
488
+ },
489
+ {
490
+ "_name": "sql-in-memory-select",
491
+ "attributes": {
492
+ "sql.cached": false,
493
+ "sql.query": "SELECT schemaHash FROM __livestore_schema WHERE tableName = 'UserInfo'",
494
+ "sql.rowsCount": 0,
495
+ },
496
+ },
497
+ {
498
+ "_name": "LiveStore:mutations",
499
+ "children": [
500
+ {
501
+ "_name": "LiveStore:mutate",
502
+ "attributes": {
503
+ "livestore.mutateLabel": "mutate",
504
+ },
505
+ "children": [
506
+ {
507
+ "_name": "LiveStore:processWrites",
508
+ "attributes": {
509
+ "livestore.mutateLabel": "mutate",
510
+ },
511
+ "children": [
512
+ {
513
+ "_name": "LiveStore:mutatetWithoutRefresh",
514
+ "attributes": {
515
+ "livestore.args": "{
516
+ "sql": "INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')"
517
+ }",
518
+ "livestore.mutation": "livestore.RawSql",
519
+ },
520
+ "children": [
521
+ {
522
+ "_name": "livestore.in-memory-db:execute",
523
+ "attributes": {
524
+ "sql.query": "INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')",
525
+ },
526
+ },
527
+ ],
528
+ },
529
+ ],
530
+ },
531
+ ],
532
+ },
533
+ ],
534
+ },
535
+ {
536
+ "_name": "LiveStore:queries",
537
+ "children": [
538
+ {
539
+ "_name": "sql:select * from UserInfo where id = 'u1' limit 1",
540
+ "attributes": {
541
+ "sql.query": "select * from UserInfo where id = 'u1' limit 1",
542
+ "sql.rowsCount": 1,
543
+ },
544
+ "children": [
545
+ {
546
+ "_name": "sql-in-memory-select",
547
+ "attributes": {
548
+ "sql.cached": false,
549
+ "sql.query": "select * from UserInfo where id = 'u1' limit 1",
550
+ "sql.rowsCount": 1,
551
+ },
552
+ },
553
+ ],
554
+ },
555
+ {
556
+ "_name": "LiveStore:useRow:UserInfo:u1",
557
+ "attributes": {
558
+ "id": "u1",
559
+ },
560
+ "children": [
561
+ {
562
+ "_name": "livestore.in-memory-db:execute",
563
+ "attributes": {
564
+ "sql.query": "insert into UserInfo (username, text, id) select $username, $text, $id where not exists(select 1 from UserInfo where id = 'u1')",
565
+ },
566
+ },
567
+ {
568
+ "_name": "LiveStore:useQuery:sql(rowQuery:query:UserInfo:u1)",
569
+ "attributes": {
570
+ "label": "sql(rowQuery:query:UserInfo:u1)",
571
+ "stackInfo": "{"frames":[{"name":"renderHook.wrapper","filePath":"__REPLACED_FOR_SNAPSHOT__"},{"name":"useRow","filePath":"__REPLACED_FOR_SNAPSHOT__"}]}",
572
+ },
573
+ "children": [
574
+ {
575
+ "_name": "sql:select * from UserInfo where id = 'u1' limit 1",
576
+ "attributes": {
577
+ "sql.query": "select * from UserInfo where id = 'u1' limit 1",
578
+ "sql.rowsCount": 1,
579
+ },
580
+ "children": [
581
+ {
582
+ "_name": "sql-in-memory-select",
583
+ "attributes": {
584
+ "sql.cached": false,
585
+ "sql.query": "select * from UserInfo where id = 'u1' limit 1",
586
+ "sql.rowsCount": 1,
587
+ },
588
+ },
589
+ ],
590
+ },
591
+ {
592
+ "_name": "LiveStore.subscribe",
593
+ "attributes": {
594
+ "label": "sql(rowQuery:query:UserInfo:u1)",
595
+ "queryLabel": "sql(rowQuery:query:UserInfo:u1)",
596
+ },
597
+ },
598
+ ],
599
+ },
600
+ ],
601
+ },
602
+ {
603
+ "_name": "LiveStore:useRow:UserInfo:u2",
604
+ "attributes": {
605
+ "id": "u2",
606
+ },
607
+ "children": [
608
+ {
609
+ "_name": "livestore.in-memory-db:execute",
610
+ "attributes": {
611
+ "sql.query": "insert into UserInfo (username, text, id) select $username, $text, $id where not exists(select 1 from UserInfo where id = 'u2')",
612
+ },
613
+ },
614
+ {
615
+ "_name": "LiveStore:useQuery:sql(rowQuery:query:UserInfo:u2)",
616
+ "attributes": {
617
+ "label": "sql(rowQuery:query:UserInfo:u2)",
618
+ "stackInfo": "{"frames":[{"name":"renderHook.wrapper","filePath":"__REPLACED_FOR_SNAPSHOT__"},{"name":"useRow","filePath":"__REPLACED_FOR_SNAPSHOT__"}]}",
619
+ },
620
+ "children": [
621
+ {
622
+ "_name": "sql:select * from UserInfo where id = 'u2' limit 1",
623
+ "attributes": {
624
+ "sql.query": "select * from UserInfo where id = 'u2' limit 1",
625
+ "sql.rowsCount": 1,
626
+ },
627
+ "children": [
628
+ {
629
+ "_name": "sql-in-memory-select",
630
+ "attributes": {
631
+ "sql.cached": false,
632
+ "sql.query": "select * from UserInfo where id = 'u2' limit 1",
633
+ "sql.rowsCount": 1,
634
+ },
635
+ },
636
+ ],
637
+ },
638
+ {
639
+ "_name": "LiveStore.subscribe",
640
+ "attributes": {
641
+ "label": "sql(rowQuery:query:UserInfo:u2)",
642
+ "queryLabel": "sql(rowQuery:query:UserInfo:u2)",
643
+ },
644
+ },
645
+ ],
646
+ },
647
+ ],
648
+ },
649
+ ],
650
+ },
651
+ ],
652
+ }
653
+ `)
654
+ }
655
+ })
656
+ })
657
+ })