@livestore/livestore 0.0.19 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -22
- package/dist/.tsbuildinfo +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 +5 -4
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +3 -5
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/__tests__/react/useComponentState.test.d.ts +2 -0
- package/dist/__tests__/react/useComponentState.test.d.ts.map +1 -0
- package/dist/__tests__/react/useComponentState.test.js +68 -0
- package/dist/__tests__/react/useComponentState.test.js.map +1 -0
- package/dist/__tests__/react/useLQuery.test.d.ts +2 -0
- package/dist/__tests__/react/useLQuery.test.d.ts.map +1 -0
- package/dist/__tests__/react/useLQuery.test.js +38 -0
- package/dist/__tests__/react/useLQuery.test.js.map +1 -0
- package/dist/__tests__/react/useLiveStoreComponent.test.js +4 -9
- package/dist/__tests__/react/useLiveStoreComponent.test.js.map +1 -1
- package/dist/__tests__/react/useQuery.test.d.ts +2 -0
- package/dist/__tests__/react/useQuery.test.d.ts.map +1 -0
- package/dist/__tests__/react/useQuery.test.js +33 -0
- package/dist/__tests__/react/useQuery.test.js.map +1 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.d.ts +2 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.d.ts.map +1 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.js +38 -0
- package/dist/__tests__/react/utils/extractStackInfoFromStackTrace.test.js.map +1 -0
- package/dist/__tests__/react/utils/stack-info.test.d.ts +2 -0
- package/dist/__tests__/react/utils/stack-info.test.d.ts.map +1 -0
- package/dist/__tests__/react/utils/stack-info.test.js +43 -0
- package/dist/__tests__/react/utils/stack-info.test.js.map +1 -0
- package/dist/__tests__/reactive.test.js +179 -93
- package/dist/__tests__/reactive.test.js.map +1 -1
- package/dist/__tests__/reactiveQueries/sql.test.d.ts +2 -0
- package/dist/__tests__/reactiveQueries/sql.test.d.ts.map +1 -0
- package/dist/__tests__/reactiveQueries/sql.test.js +337 -0
- package/dist/__tests__/reactiveQueries/sql.test.js.map +1 -0
- package/dist/inMemoryDatabase.d.ts +4 -3
- package/dist/inMemoryDatabase.d.ts.map +1 -1
- package/dist/inMemoryDatabase.js +3 -2
- package/dist/inMemoryDatabase.js.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.ts +4 -3
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +3 -2
- package/dist/react/index.js.map +1 -1
- package/dist/react/useComponentState.d.ts +50 -0
- package/dist/react/useComponentState.d.ts.map +1 -0
- package/dist/react/useComponentState.js +240 -0
- package/dist/react/useComponentState.js.map +1 -0
- package/dist/react/useGlobalQuery.d.ts +3 -0
- package/dist/react/useGlobalQuery.d.ts.map +1 -0
- package/dist/react/useGlobalQuery.js +26 -0
- package/dist/react/useGlobalQuery.js.map +1 -0
- package/dist/react/useGraphQL.d.ts +3 -3
- package/dist/react/useGraphQL.d.ts.map +1 -1
- package/dist/react/useGraphQL.js +10 -8
- package/dist/react/useGraphQL.js.map +1 -1
- package/dist/react/useLiveStoreComponent.d.ts +6 -6
- package/dist/react/useLiveStoreComponent.d.ts.map +1 -1
- package/dist/react/useLiveStoreComponent.js +143 -99
- package/dist/react/useLiveStoreComponent.js.map +1 -1
- package/dist/react/useQuery.d.ts +2 -2
- package/dist/react/useQuery.d.ts.map +1 -1
- package/dist/react/useQuery.js +54 -30
- package/dist/react/useQuery.js.map +1 -1
- package/dist/react/useTemporaryQuery.d.ts +8 -0
- package/dist/react/useTemporaryQuery.d.ts.map +1 -0
- package/dist/react/useTemporaryQuery.js +19 -0
- package/dist/react/useTemporaryQuery.js.map +1 -0
- package/dist/react/utils/extractNamesFromStackTrace.d.ts +3 -0
- package/dist/react/utils/extractNamesFromStackTrace.d.ts.map +1 -0
- package/dist/react/utils/extractNamesFromStackTrace.js +40 -0
- package/dist/react/utils/extractNamesFromStackTrace.js.map +1 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.d.ts +7 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.d.ts.map +1 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.js +40 -0
- package/dist/react/utils/extractStackInfoFromStackTrace.js.map +1 -0
- package/dist/react/utils/stack-info.d.ts +11 -0
- package/dist/react/utils/stack-info.d.ts.map +1 -0
- package/dist/react/utils/stack-info.js +49 -0
- package/dist/react/utils/stack-info.js.map +1 -0
- package/dist/reactive.d.ts +51 -67
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +138 -220
- package/dist/reactive.js.map +1 -1
- package/dist/reactiveQueries/base-class.d.ts +28 -21
- package/dist/reactiveQueries/base-class.d.ts.map +1 -1
- package/dist/reactiveQueries/base-class.js +22 -18
- package/dist/reactiveQueries/base-class.js.map +1 -1
- package/dist/reactiveQueries/graph.d.ts +10 -0
- package/dist/reactiveQueries/graph.d.ts.map +1 -0
- package/dist/reactiveQueries/graph.js +6 -0
- package/dist/reactiveQueries/graph.js.map +1 -0
- package/dist/reactiveQueries/graphql.d.ts +35 -17
- package/dist/reactiveQueries/graphql.d.ts.map +1 -1
- package/dist/reactiveQueries/graphql.js +86 -10
- package/dist/reactiveQueries/graphql.js.map +1 -1
- package/dist/reactiveQueries/js.d.ts +17 -12
- package/dist/reactiveQueries/js.d.ts.map +1 -1
- package/dist/reactiveQueries/js.js +30 -8
- package/dist/reactiveQueries/js.js.map +1 -1
- package/dist/reactiveQueries/sql.d.ts +28 -18
- package/dist/reactiveQueries/sql.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.js +79 -16
- package/dist/reactiveQueries/sql.js.map +1 -1
- package/dist/store.d.ts +35 -61
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +77 -272
- package/dist/store.js.map +1 -1
- package/package.json +4 -3
- package/src/QueryCache.ts +1 -1
- package/src/__tests__/react/fixture.tsx +10 -8
- package/src/__tests__/react/{useLiveStoreComponent.test.tsx → useComponentState.test.tsx} +9 -20
- package/src/__tests__/react/useQuery.test.tsx +48 -0
- package/src/__tests__/react/utils/stack-info.test.ts +45 -0
- package/src/__tests__/reactive.test.ts +212 -140
- package/src/__tests__/reactiveQueries/sql.test.ts +372 -0
- package/src/inMemoryDatabase.ts +11 -8
- package/src/index.ts +7 -11
- package/src/react/index.ts +4 -7
- package/src/react/{useLiveStoreComponent.ts → useComponentState.ts} +90 -253
- package/src/react/useQuery.ts +74 -40
- package/src/react/useTemporaryQuery.ts +23 -0
- package/src/react/utils/stack-info.ts +63 -0
- package/src/reactive.ts +234 -308
- package/src/reactiveQueries/base-class.ts +59 -42
- package/src/reactiveQueries/graph.ts +15 -0
- package/src/reactiveQueries/graphql.ts +143 -29
- package/src/reactiveQueries/js.ts +57 -20
- package/src/reactiveQueries/sql.ts +136 -36
- package/src/store.ts +121 -426
- package/src/react/useGraphQL.ts +0 -138
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import * as otel from '@opentelemetry/api'
|
|
2
|
+
import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'
|
|
3
|
+
import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
|
4
|
+
import { describe, expect, it } from 'vitest'
|
|
5
|
+
|
|
6
|
+
import { queryJS, querySQL, sql } from '../../index.js'
|
|
7
|
+
import { makeTodoMvc } from '../react/fixture.js'
|
|
8
|
+
|
|
9
|
+
describe('otel', () => {
|
|
10
|
+
let cachedProvider: BasicTracerProvider | undefined
|
|
11
|
+
|
|
12
|
+
const makeQuery = async () => {
|
|
13
|
+
const exporter = new InMemorySpanExporter()
|
|
14
|
+
|
|
15
|
+
const provider = cachedProvider ?? new BasicTracerProvider()
|
|
16
|
+
cachedProvider = provider
|
|
17
|
+
provider.addSpanProcessor(new SimpleSpanProcessor(exporter))
|
|
18
|
+
provider.register()
|
|
19
|
+
|
|
20
|
+
const tracer = otel.trace.getTracer('test')
|
|
21
|
+
|
|
22
|
+
const span = tracer.startSpan('test')
|
|
23
|
+
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
24
|
+
|
|
25
|
+
const { store } = await makeTodoMvc({ otelTracer: tracer, otelContext })
|
|
26
|
+
|
|
27
|
+
return { store, tracer, exporter, span, provider }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
it('otel', async () => {
|
|
31
|
+
const { store, exporter, span } = await makeQuery()
|
|
32
|
+
|
|
33
|
+
const query = querySQL(`select * from todos`, { queriedTables: ['todos'] })
|
|
34
|
+
expect(query.run()).toMatchInlineSnapshot('[]')
|
|
35
|
+
|
|
36
|
+
store.applyEvent('RawSql', {
|
|
37
|
+
sql: sql`INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);`,
|
|
38
|
+
bindValues: {},
|
|
39
|
+
writeTables: ['todos'],
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
expect(query.run()).toMatchInlineSnapshot(`
|
|
43
|
+
[
|
|
44
|
+
{
|
|
45
|
+
"completed": 0,
|
|
46
|
+
"id": "t1",
|
|
47
|
+
"text": "buy milk",
|
|
48
|
+
},
|
|
49
|
+
]
|
|
50
|
+
`)
|
|
51
|
+
|
|
52
|
+
store.destroy()
|
|
53
|
+
query.destroy()
|
|
54
|
+
span.end()
|
|
55
|
+
|
|
56
|
+
expect(getSimplifiedRootSpan(exporter)).toMatchInlineSnapshot(`
|
|
57
|
+
{
|
|
58
|
+
"_name": "test",
|
|
59
|
+
"children": [
|
|
60
|
+
{
|
|
61
|
+
"_name": "livestore.in-memory-db:execute",
|
|
62
|
+
"attributes": {
|
|
63
|
+
"sql.query": "
|
|
64
|
+
PRAGMA page_size=32768;
|
|
65
|
+
PRAGMA cache_size=10000;
|
|
66
|
+
PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
|
|
67
|
+
PRAGMA synchronous='OFF';
|
|
68
|
+
PRAGMA temp_store='MEMORY';
|
|
69
|
+
PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
|
|
70
|
+
",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"_name": "sql-in-memory-select",
|
|
75
|
+
"attributes": {
|
|
76
|
+
"sql.cached": false,
|
|
77
|
+
"sql.query": "SELECT * FROM __livestore_schema",
|
|
78
|
+
"sql.rowsCount": 0,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"_name": "livestore.in-memory-db:execute",
|
|
83
|
+
"attributes": {
|
|
84
|
+
"sql.query": "INSERT OR IGNORE INTO app (id, newTodoText, filter) VALUES ('static', '', 'all');",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"_name": "LiveStore:applyEvents",
|
|
89
|
+
"children": [
|
|
90
|
+
{
|
|
91
|
+
"_name": "LiveStore:applyEvent",
|
|
92
|
+
"children": [
|
|
93
|
+
{
|
|
94
|
+
"_name": "LiveStore:applyEventWithoutRefresh",
|
|
95
|
+
"attributes": {
|
|
96
|
+
"livestore.actionType": "RawSql",
|
|
97
|
+
"livestore.args": "{
|
|
98
|
+
\\"sql\\": \\"INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);\\",
|
|
99
|
+
\\"bindValues\\": {},
|
|
100
|
+
\\"writeTables\\": [
|
|
101
|
+
\\"todos\\"
|
|
102
|
+
]
|
|
103
|
+
}",
|
|
104
|
+
},
|
|
105
|
+
"children": [
|
|
106
|
+
{
|
|
107
|
+
"_name": "livestore.in-memory-db:execute",
|
|
108
|
+
"attributes": {
|
|
109
|
+
"sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);",
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"_name": "LiveStore:queries",
|
|
120
|
+
"children": [
|
|
121
|
+
{
|
|
122
|
+
"_name": "sql:select * from todos",
|
|
123
|
+
"attributes": {
|
|
124
|
+
"sql.query": "select * from todos",
|
|
125
|
+
"sql.rowsCount": 0,
|
|
126
|
+
},
|
|
127
|
+
"children": [
|
|
128
|
+
{
|
|
129
|
+
"_name": "sql-in-memory-select",
|
|
130
|
+
"attributes": {
|
|
131
|
+
"sql.cached": false,
|
|
132
|
+
"sql.query": "select * from todos",
|
|
133
|
+
"sql.rowsCount": 0,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"_name": "sql:select * from todos",
|
|
140
|
+
"attributes": {
|
|
141
|
+
"sql.query": "select * from todos",
|
|
142
|
+
"sql.rowsCount": 1,
|
|
143
|
+
},
|
|
144
|
+
"children": [
|
|
145
|
+
{
|
|
146
|
+
"_name": "sql-in-memory-select",
|
|
147
|
+
"attributes": {
|
|
148
|
+
"sql.cached": false,
|
|
149
|
+
"sql.query": "select * from todos",
|
|
150
|
+
"sql.rowsCount": 1,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
}
|
|
159
|
+
`)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('with thunks', async () => {
|
|
163
|
+
const { store, exporter, span } = await makeQuery()
|
|
164
|
+
|
|
165
|
+
const defaultTodo = { id: '', text: '', completed: 0 }
|
|
166
|
+
|
|
167
|
+
const filter = queryJS(() => `where completed = 0`, { label: 'where-filter' })
|
|
168
|
+
const query = querySQL((get) => `select * from todos ${get(filter)}`, {
|
|
169
|
+
// queriedTables: ['todos'],
|
|
170
|
+
label: 'all todos',
|
|
171
|
+
}).getFirstRow({
|
|
172
|
+
defaultValue: defaultTodo,
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
expect(query.run()).toMatchInlineSnapshot(`
|
|
176
|
+
{
|
|
177
|
+
"completed": 0,
|
|
178
|
+
"id": "",
|
|
179
|
+
"text": "",
|
|
180
|
+
}
|
|
181
|
+
`)
|
|
182
|
+
|
|
183
|
+
store.applyEvent('RawSql', {
|
|
184
|
+
sql: sql`INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);`,
|
|
185
|
+
bindValues: {},
|
|
186
|
+
writeTables: ['todos'],
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
expect(query.run()).toMatchInlineSnapshot(`
|
|
190
|
+
{
|
|
191
|
+
"completed": 0,
|
|
192
|
+
"id": "t1",
|
|
193
|
+
"text": "buy milk",
|
|
194
|
+
}
|
|
195
|
+
`)
|
|
196
|
+
|
|
197
|
+
store.destroy()
|
|
198
|
+
query.destroy()
|
|
199
|
+
span.end()
|
|
200
|
+
|
|
201
|
+
expect(getSimplifiedRootSpan(exporter)).toMatchInlineSnapshot(`
|
|
202
|
+
{
|
|
203
|
+
"_name": "test",
|
|
204
|
+
"children": [
|
|
205
|
+
{
|
|
206
|
+
"_name": "livestore.in-memory-db:execute",
|
|
207
|
+
"attributes": {
|
|
208
|
+
"sql.query": "
|
|
209
|
+
PRAGMA page_size=32768;
|
|
210
|
+
PRAGMA cache_size=10000;
|
|
211
|
+
PRAGMA journal_mode='MEMORY'; -- we don't flush to disk before committing a write
|
|
212
|
+
PRAGMA synchronous='OFF';
|
|
213
|
+
PRAGMA temp_store='MEMORY';
|
|
214
|
+
PRAGMA foreign_keys='ON'; -- we want foreign key constraints to be enforced
|
|
215
|
+
",
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"_name": "sql-in-memory-select",
|
|
220
|
+
"attributes": {
|
|
221
|
+
"sql.cached": false,
|
|
222
|
+
"sql.query": "SELECT * FROM __livestore_schema",
|
|
223
|
+
"sql.rowsCount": 0,
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"_name": "livestore.in-memory-db:execute",
|
|
228
|
+
"attributes": {
|
|
229
|
+
"sql.query": "INSERT OR IGNORE INTO app (id, newTodoText, filter) VALUES ('static', '', 'all');",
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"_name": "LiveStore:applyEvents",
|
|
234
|
+
"children": [
|
|
235
|
+
{
|
|
236
|
+
"_name": "LiveStore:applyEvent",
|
|
237
|
+
"children": [
|
|
238
|
+
{
|
|
239
|
+
"_name": "LiveStore:applyEventWithoutRefresh",
|
|
240
|
+
"attributes": {
|
|
241
|
+
"livestore.actionType": "RawSql",
|
|
242
|
+
"livestore.args": "{
|
|
243
|
+
\\"sql\\": \\"INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);\\",
|
|
244
|
+
\\"bindValues\\": {},
|
|
245
|
+
\\"writeTables\\": [
|
|
246
|
+
\\"todos\\"
|
|
247
|
+
]
|
|
248
|
+
}",
|
|
249
|
+
},
|
|
250
|
+
"children": [
|
|
251
|
+
{
|
|
252
|
+
"_name": "livestore.in-memory-db:execute",
|
|
253
|
+
"attributes": {
|
|
254
|
+
"sql.query": "INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0);",
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"_name": "LiveStore:queries",
|
|
265
|
+
"children": [
|
|
266
|
+
{
|
|
267
|
+
"_name": "js:sql(all todos):first",
|
|
268
|
+
"children": [
|
|
269
|
+
{
|
|
270
|
+
"_name": "sql:select * from todos where completed = 0",
|
|
271
|
+
"attributes": {
|
|
272
|
+
"sql.query": "select * from todos where completed = 0",
|
|
273
|
+
"sql.rowsCount": 0,
|
|
274
|
+
},
|
|
275
|
+
"children": [
|
|
276
|
+
{
|
|
277
|
+
"_name": "js:where-filter",
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"_name": "sql-in-memory-select",
|
|
281
|
+
"attributes": {
|
|
282
|
+
"sql.cached": false,
|
|
283
|
+
"sql.query": "select * from todos where completed = 0",
|
|
284
|
+
"sql.rowsCount": 0,
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"_name": "js:sql(all todos):first",
|
|
293
|
+
"children": [
|
|
294
|
+
{
|
|
295
|
+
"_name": "sql:select * from todos where completed = 0",
|
|
296
|
+
"attributes": {
|
|
297
|
+
"sql.query": "select * from todos where completed = 0",
|
|
298
|
+
"sql.rowsCount": 1,
|
|
299
|
+
},
|
|
300
|
+
"children": [
|
|
301
|
+
{
|
|
302
|
+
"_name": "sql-in-memory-select",
|
|
303
|
+
"attributes": {
|
|
304
|
+
"sql.cached": false,
|
|
305
|
+
"sql.query": "select * from todos where completed = 0",
|
|
306
|
+
"sql.rowsCount": 1,
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
},
|
|
313
|
+
],
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
}
|
|
317
|
+
`)
|
|
318
|
+
})
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
const compareHrTime = (a: [number, number], b: [number, number]) => {
|
|
322
|
+
if (a[0] !== b[0]) return a[0] - b[0]
|
|
323
|
+
return a[1] - b[1]
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const omitEmpty = (obj: any) => {
|
|
327
|
+
const result: any = {}
|
|
328
|
+
for (const key in obj) {
|
|
329
|
+
if (
|
|
330
|
+
obj[key] !== undefined &&
|
|
331
|
+
!(Array.isArray(obj[key]) && obj[key].length === 0) &&
|
|
332
|
+
Object.keys(obj[key]).length > 0
|
|
333
|
+
) {
|
|
334
|
+
result[key] = obj[key]
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return result
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const getSimplifiedRootSpan = (exporter: InMemorySpanExporter) => {
|
|
341
|
+
const spans = exporter.getFinishedSpans()
|
|
342
|
+
const spansMap = new Map<string, NestedSpan>(spans.map((span) => [span.spanContext().spanId, { span, children: [] }]))
|
|
343
|
+
|
|
344
|
+
spansMap.forEach((nestedSpan) => {
|
|
345
|
+
const parentSpan = nestedSpan.span.parentSpanId ? spansMap.get(nestedSpan.span.parentSpanId) : undefined
|
|
346
|
+
if (parentSpan) {
|
|
347
|
+
parentSpan.children.push(nestedSpan)
|
|
348
|
+
}
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
type NestedSpan = { span: ReadableSpan; children: NestedSpan[] }
|
|
352
|
+
const rootSpan = spansMap.get(spans.find((_) => _.name === 'test')!.spanContext().spanId)!
|
|
353
|
+
|
|
354
|
+
type SimplifiedNestedSpan = { _name: string; attributes: any; children: SimplifiedNestedSpan[] }
|
|
355
|
+
|
|
356
|
+
const simplifySpan = (span: NestedSpan): SimplifiedNestedSpan =>
|
|
357
|
+
omitEmpty({
|
|
358
|
+
_name: span.span.name,
|
|
359
|
+
attributes: span.span.attributes,
|
|
360
|
+
children: span.children
|
|
361
|
+
.filter((_) => _.span.name !== 'createStore')
|
|
362
|
+
.sort((a, b) => compareHrTime(a.span.startTime, b.span.startTime))
|
|
363
|
+
.map(simplifySpan),
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
// console.dir(
|
|
367
|
+
// spans.map((_) => [_.spanContext().spanId, _.name, _.attributes, _.parentSpanId]),
|
|
368
|
+
// { depth: 10 },
|
|
369
|
+
// )
|
|
370
|
+
|
|
371
|
+
return simplifySpan(rootSpan)
|
|
372
|
+
}
|
package/src/inMemoryDatabase.ts
CHANGED
|
@@ -25,7 +25,7 @@ export type SlowQueryInfo = [
|
|
|
25
25
|
bindValues: PreparedBindValues | undefined,
|
|
26
26
|
durationMs: number,
|
|
27
27
|
rowsCount: number | undefined,
|
|
28
|
-
queriedTables: string
|
|
28
|
+
queriedTables: ReadonlyArray<string>,
|
|
29
29
|
startTimePerfNow: DOMHighResTimeStamp,
|
|
30
30
|
]
|
|
31
31
|
|
|
@@ -41,6 +41,7 @@ export class InMemoryDatabase {
|
|
|
41
41
|
private cachedStmts = new BoundMap<string, Sqlite.PreparedStatement>(200)
|
|
42
42
|
private tablesUsedCache = new BoundMap<string, string[]>(200)
|
|
43
43
|
private resultCache = new QueryCache()
|
|
44
|
+
private tablesUsedStmt
|
|
44
45
|
public debugInfo: DebugInfo = emptyDebugInfo()
|
|
45
46
|
|
|
46
47
|
constructor(
|
|
@@ -48,7 +49,11 @@ export class InMemoryDatabase {
|
|
|
48
49
|
private otelTracer: otel.Tracer,
|
|
49
50
|
private otelRootSpanContext: otel.Context,
|
|
50
51
|
public SQL: Sqlite.Sqlite3Static,
|
|
51
|
-
) {
|
|
52
|
+
) {
|
|
53
|
+
this.tablesUsedStmt = this.db.prepare(
|
|
54
|
+
`SELECT tbl_name FROM tables_used(?) AS u JOIN sqlite_master ON sqlite_master.name = u.name WHERE u.schema = 'main';`,
|
|
55
|
+
)
|
|
56
|
+
}
|
|
52
57
|
|
|
53
58
|
static load({
|
|
54
59
|
data,
|
|
@@ -113,9 +118,7 @@ export class InMemoryDatabase {
|
|
|
113
118
|
if (cached) {
|
|
114
119
|
return cached
|
|
115
120
|
}
|
|
116
|
-
const stmt = this.
|
|
117
|
-
`SELECT tbl_name FROM tables_used(?) AS u JOIN sqlite_master ON sqlite_master.name = u.name WHERE u.schema = 'main';`,
|
|
118
|
-
)
|
|
121
|
+
const stmt = this.tablesUsedStmt
|
|
119
122
|
const tablesUsed = []
|
|
120
123
|
try {
|
|
121
124
|
stmt.bind([query])
|
|
@@ -123,7 +126,7 @@ export class InMemoryDatabase {
|
|
|
123
126
|
tablesUsed.push(stmt.get(0))
|
|
124
127
|
}
|
|
125
128
|
} finally {
|
|
126
|
-
stmt.
|
|
129
|
+
stmt.reset()
|
|
127
130
|
}
|
|
128
131
|
this.tablesUsedCache.set(query, tablesUsed as string[])
|
|
129
132
|
return tablesUsed as string[]
|
|
@@ -133,7 +136,7 @@ export class InMemoryDatabase {
|
|
|
133
136
|
query: string,
|
|
134
137
|
bindValues?: PreparedBindValues,
|
|
135
138
|
writeTables?: string[],
|
|
136
|
-
options?: { hasNoEffects?: boolean; otelContext
|
|
139
|
+
options?: { hasNoEffects?: boolean; otelContext?: otel.Context },
|
|
137
140
|
): { durationMs: number } {
|
|
138
141
|
return this.otelTracer.startActiveSpan(
|
|
139
142
|
'livestore.in-memory-db:execute',
|
|
@@ -202,7 +205,7 @@ export class InMemoryDatabase {
|
|
|
202
205
|
select<T = any>(
|
|
203
206
|
query: string,
|
|
204
207
|
options?: {
|
|
205
|
-
queriedTables?: string
|
|
208
|
+
queriedTables?: ReadonlyArray<string>
|
|
206
209
|
bindValues?: PreparedBindValues
|
|
207
210
|
skipCache?: boolean
|
|
208
211
|
otelContext?: otel.Context
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
export { Store, createStore } from './store.js'
|
|
2
|
-
export type {
|
|
3
|
-
LiveStoreQuery,
|
|
4
|
-
GetAtomResult,
|
|
5
|
-
BaseGraphQLContext,
|
|
6
|
-
QueryResult,
|
|
7
|
-
QueryDebugInfo,
|
|
8
|
-
RefreshReason,
|
|
9
|
-
} from './store.js'
|
|
2
|
+
export type { LiveStoreQuery, BaseGraphQLContext, QueryResult, QueryDebugInfo, RefreshReason } from './store.js'
|
|
10
3
|
|
|
11
4
|
export type { QueryDefinition, LiveStoreCreateStoreOptions, LiveStoreContext } from './effect/LiveStore.js'
|
|
12
5
|
|
|
@@ -27,10 +20,13 @@ export type {
|
|
|
27
20
|
RefreshReasonWithGenericReasons,
|
|
28
21
|
SerializedAtom,
|
|
29
22
|
SerializedEffect,
|
|
23
|
+
Atom,
|
|
30
24
|
} from './reactive.js'
|
|
31
|
-
export type
|
|
32
|
-
export type
|
|
33
|
-
export type
|
|
25
|
+
export { type LiveStoreJSQuery, queryJS } from './reactiveQueries/js.js'
|
|
26
|
+
export { type LiveStoreSQLQuery, querySQL } from './reactiveQueries/sql.js'
|
|
27
|
+
export { type LiveStoreGraphQLQuery, queryGraphQL } from './reactiveQueries/graphql.js'
|
|
28
|
+
export { type GetAtomResult } from './reactiveQueries/base-class.js'
|
|
29
|
+
export { dbGraph } from './reactiveQueries/graph.js'
|
|
34
30
|
|
|
35
31
|
export { labelForKey } from './componentKey.js'
|
|
36
32
|
export type { ComponentKey } from './componentKey.js'
|
package/src/react/index.ts
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
export type {
|
|
2
|
-
UseLiveStoreComponentProps as LiveStoreComponentConfig,
|
|
3
|
-
ReactiveGraphQL,
|
|
4
|
-
ReactiveSQL,
|
|
5
2
|
Setters,
|
|
6
3
|
ComponentKeyConfig,
|
|
7
|
-
QueryResults,
|
|
8
4
|
QueryDefinitions,
|
|
9
5
|
ComponentColumns,
|
|
10
6
|
GetStateType,
|
|
11
7
|
GetStateTypeEncoded,
|
|
12
|
-
} from './
|
|
8
|
+
} from './useComponentState.js'
|
|
13
9
|
export { LiveStoreContext, useStore } from './LiveStoreContext.js'
|
|
14
10
|
export { LiveStoreProvider } from './LiveStoreProvider.js'
|
|
15
|
-
export {
|
|
16
|
-
export { useGraphQL } from './useGraphQL.js'
|
|
11
|
+
export { useComponentState } from './useComponentState.js'
|
|
17
12
|
export { useQuery } from './useQuery.js'
|
|
13
|
+
export { useTemporaryQuery } from './useTemporaryQuery.js'
|
|
14
|
+
export { useStackInfo } from './utils/stack-info.js'
|
|
18
15
|
|
|
19
16
|
// Needed to make TS happy
|
|
20
17
|
export type { TypedDocumentNode } from '@graphql-typed-document-node/core'
|