@livestore/livestore 0.0.46-dev.2 → 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.
- package/README.md +10 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/react/fixture.d.ts +17 -1
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +27 -3
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/__tests__/react/utils/otel.d.ts +10 -0
- package/dist/__tests__/react/utils/otel.d.ts.map +1 -0
- package/dist/__tests__/react/utils/otel.js +42 -0
- package/dist/__tests__/react/utils/otel.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react/LiveStoreProvider.js +39 -6
- package/dist/react/LiveStoreProvider.js.map +1 -1
- package/dist/react/LiveStoreProvider.test.d.ts +2 -0
- package/dist/react/LiveStoreProvider.test.d.ts.map +1 -0
- package/dist/react/LiveStoreProvider.test.js +51 -0
- package/dist/react/LiveStoreProvider.test.js.map +1 -0
- package/dist/react/components/DiffableList copy.d.ts +19 -0
- package/dist/react/components/DiffableList copy.d.ts.map +1 -0
- package/dist/react/components/DiffableList copy.js +62 -0
- package/dist/react/components/DiffableList copy.js.map +1 -0
- package/dist/react/components/DiffableList.d.ts +13 -0
- package/dist/react/components/DiffableList.d.ts.map +1 -0
- package/dist/react/components/DiffableList.js +21 -0
- package/dist/react/components/DiffableList.js.map +1 -0
- package/dist/react/components/DiffableList2.d.ts +20 -0
- package/dist/react/components/DiffableList2.d.ts.map +1 -0
- package/dist/react/components/DiffableList2.js +119 -0
- package/dist/react/components/DiffableList2.js.map +1 -0
- package/dist/react/components/DiffableList3.d.ts +19 -0
- package/dist/react/components/DiffableList3.d.ts.map +1 -0
- package/dist/react/components/DiffableList3.js +62 -0
- package/dist/react/components/DiffableList3.js.map +1 -0
- package/dist/react/components/LiveList.d.ts +21 -0
- package/dist/react/components/LiveList.d.ts.map +1 -0
- package/dist/react/components/LiveList.js +31 -0
- package/dist/react/components/LiveList.js.map +1 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/useAtom.d.ts +1 -1
- package/dist/react/useAtom.d.ts.map +1 -1
- package/dist/react/useAtom.js.map +1 -1
- package/dist/react/useQuery.d.ts +4 -1
- package/dist/react/useQuery.d.ts.map +1 -1
- package/dist/react/useQuery.js +24 -19
- package/dist/react/useQuery.js.map +1 -1
- package/dist/react/useQuery.test.js +11 -11
- package/dist/react/useQuery.test.js.map +1 -1
- package/dist/react/useRow.d.ts.map +1 -1
- package/dist/react/useRow.js +14 -69
- package/dist/react/useRow.js.map +1 -1
- package/dist/react/useRow.test.js +440 -28
- package/dist/react/useRow.test.js.map +1 -1
- package/dist/react/useRowOld.d.ts +40 -0
- package/dist/react/useRowOld.d.ts.map +1 -0
- package/dist/react/useRowOld.js +134 -0
- package/dist/react/useRowOld.js.map +1 -0
- package/dist/react/useTemporaryQuery.d.ts +15 -3
- package/dist/react/useTemporaryQuery.d.ts.map +1 -1
- package/dist/react/useTemporaryQuery.js +60 -27
- package/dist/react/useTemporaryQuery.js.map +1 -1
- package/dist/react/useTemporaryQuery.test.js +10 -9
- package/dist/react/useTemporaryQuery.test.js.map +1 -1
- package/dist/reactive.d.ts +23 -5
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +44 -11
- package/dist/reactive.js.map +1 -1
- package/dist/reactive.test.js +1 -1
- package/dist/reactive.test.js.map +1 -1
- package/dist/reactiveQueries/base-class.d.ts +1 -1
- package/dist/reactiveQueries/base-class.d.ts.map +1 -1
- package/dist/reactiveQueries/base-class.js.map +1 -1
- package/dist/reactiveQueries/graphql.d.ts +2 -2
- package/dist/reactiveQueries/graphql.d.ts.map +1 -1
- package/dist/reactiveQueries/graphql.js +16 -10
- package/dist/reactiveQueries/graphql.js.map +1 -1
- package/dist/reactiveQueries/sql.d.ts +1 -1
- package/dist/reactiveQueries/sql.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.js +15 -11
- package/dist/reactiveQueries/sql.js.map +1 -1
- package/dist/reactiveQueries/sql.test.js +1 -40
- package/dist/reactiveQueries/sql.test.js.map +1 -1
- package/dist/store.d.ts +2 -2
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +10 -7
- package/dist/store.js.map +1 -1
- package/package.json +6 -6
- package/src/__tests__/react/fixture.tsx +35 -2
- package/src/__tests__/react/utils/otel.ts +61 -0
- package/src/index.ts +12 -1
- package/src/react/LiveStoreProvider.test.tsx +82 -0
- package/src/react/LiveStoreProvider.tsx +42 -7
- package/src/react/components/LiveList.tsx +84 -0
- package/src/react/index.ts +2 -0
- package/src/react/useAtom.ts +1 -1
- package/src/react/useQuery.test.tsx +11 -11
- package/src/react/useQuery.ts +29 -22
- package/src/react/useRow.test.tsx +502 -30
- package/src/react/useRow.ts +19 -107
- package/src/react/useTemporaryQuery.test.tsx +17 -16
- package/src/react/useTemporaryQuery.ts +96 -28
- package/src/reactive.test.ts +1 -1
- package/src/reactive.ts +76 -15
- package/src/reactiveQueries/base-class.ts +2 -1
- package/src/reactiveQueries/graphql.ts +21 -15
- package/src/reactiveQueries/sql.test.ts +1 -54
- package/src/reactiveQueries/sql.ts +20 -14
- package/src/store.ts +12 -8
- package/tsconfig.json +6 -1
- package/src/react/utils/useCleanup.ts +0 -25
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api'
|
|
2
|
-
import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'
|
|
3
2
|
import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
|
4
3
|
import { describe, expect, it } from 'vitest'
|
|
5
4
|
|
|
6
5
|
import { makeTodoMvc, todos } from '../__tests__/react/fixture.js'
|
|
6
|
+
import { getSimplifiedRootSpan } from '../__tests__/react/utils/otel.js'
|
|
7
7
|
import { computed, ParseUtils, querySQL, rawSqlMutation, sql } from '../index.js'
|
|
8
8
|
|
|
9
9
|
/*
|
|
@@ -299,56 +299,3 @@ describe('otel', () => {
|
|
|
299
299
|
`)
|
|
300
300
|
})
|
|
301
301
|
})
|
|
302
|
-
|
|
303
|
-
const compareHrTime = (a: [number, number], b: [number, number]) => {
|
|
304
|
-
if (a[0] !== b[0]) return a[0] - b[0]
|
|
305
|
-
return a[1] - b[1]
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const omitEmpty = (obj: any) => {
|
|
309
|
-
const result: any = {}
|
|
310
|
-
for (const key in obj) {
|
|
311
|
-
if (
|
|
312
|
-
obj[key] !== undefined &&
|
|
313
|
-
!(Array.isArray(obj[key]) && obj[key].length === 0) &&
|
|
314
|
-
Object.keys(obj[key]).length > 0
|
|
315
|
-
) {
|
|
316
|
-
result[key] = obj[key]
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return result
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
const getSimplifiedRootSpan = (exporter: InMemorySpanExporter) => {
|
|
323
|
-
const spans = exporter.getFinishedSpans()
|
|
324
|
-
const spansMap = new Map<string, NestedSpan>(spans.map((span) => [span.spanContext().spanId, { span, children: [] }]))
|
|
325
|
-
|
|
326
|
-
spansMap.forEach((nestedSpan) => {
|
|
327
|
-
const parentSpan = nestedSpan.span.parentSpanId ? spansMap.get(nestedSpan.span.parentSpanId) : undefined
|
|
328
|
-
if (parentSpan) {
|
|
329
|
-
parentSpan.children.push(nestedSpan)
|
|
330
|
-
}
|
|
331
|
-
})
|
|
332
|
-
|
|
333
|
-
type NestedSpan = { span: ReadableSpan; children: NestedSpan[] }
|
|
334
|
-
const rootSpan = spansMap.get(spans.find((_) => _.name === 'test')!.spanContext().spanId)!
|
|
335
|
-
|
|
336
|
-
type SimplifiedNestedSpan = { _name: string; attributes: any; children: SimplifiedNestedSpan[] }
|
|
337
|
-
|
|
338
|
-
const simplifySpan = (span: NestedSpan): SimplifiedNestedSpan =>
|
|
339
|
-
omitEmpty({
|
|
340
|
-
_name: span.span.name,
|
|
341
|
-
attributes: span.span.attributes,
|
|
342
|
-
children: span.children
|
|
343
|
-
.filter((_) => _.span.name !== 'createStore')
|
|
344
|
-
.sort((a, b) => compareHrTime(a.span.startTime, b.span.startTime))
|
|
345
|
-
.map(simplifySpan),
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
// console.dir(
|
|
349
|
-
// spans.map((_) => [_.spanContext().spanId, _.name, _.attributes, _.parentSpanId]),
|
|
350
|
-
// { depth: 10 },
|
|
351
|
-
// )
|
|
352
|
-
|
|
353
|
-
return simplifySpan(rootSpan)
|
|
354
|
-
}
|
|
@@ -49,7 +49,7 @@ export class LiveStoreSQLQuery<TResult, TQueryInfo extends QueryInfo = QueryInfo
|
|
|
49
49
|
_tag: 'sql' = 'sql'
|
|
50
50
|
|
|
51
51
|
/** A reactive thunk representing the query text */
|
|
52
|
-
queryString$: Thunk<string, DbContext, RefreshReason>
|
|
52
|
+
queryString$: Thunk<string, DbContext, RefreshReason> | undefined
|
|
53
53
|
|
|
54
54
|
/** A reactive thunk representing the query results */
|
|
55
55
|
results$: Thunk<TResult, DbContext, RefreshReason>
|
|
@@ -126,23 +126,23 @@ Result:`,
|
|
|
126
126
|
? map
|
|
127
127
|
: shouldNeverHappen(`Invalid map function ${map}`)
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
let queryString$OrQueryString: string | Thunk<string, DbContext, RefreshReason>
|
|
130
|
+
if (typeof genQueryString === 'function') {
|
|
131
|
+
queryString$OrQueryString = this.dbGraph.makeThunk(
|
|
132
|
+
(get, setDebugInfo, { rootOtelContext }, otelContext) => {
|
|
133
133
|
const startMs = performance.now()
|
|
134
134
|
const queryString = genQueryString(makeGetAtomResult(get, otelContext ?? rootOtelContext))
|
|
135
135
|
const durationMs = performance.now() - startMs
|
|
136
136
|
setDebugInfo({ _tag: 'js', label: `${label}:queryString`, query: queryString, durationMs })
|
|
137
137
|
return queryString
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
},
|
|
142
|
-
{ label: `${label}:queryString`, meta: { liveStoreThunkType: 'sqlQueryString' } },
|
|
143
|
-
)
|
|
138
|
+
},
|
|
139
|
+
{ label: `${label}:queryString`, meta: { liveStoreThunkType: 'sqlQueryString' } },
|
|
140
|
+
)
|
|
144
141
|
|
|
145
|
-
|
|
142
|
+
this.queryString$ = queryString$OrQueryString
|
|
143
|
+
} else {
|
|
144
|
+
queryString$OrQueryString = genQueryString
|
|
145
|
+
}
|
|
146
146
|
|
|
147
147
|
const queryLabel = `${label}:results`
|
|
148
148
|
|
|
@@ -162,7 +162,10 @@ Result:`,
|
|
|
162
162
|
this.execBeforeFirstRun = undefined
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
const sqlString =
|
|
165
|
+
const sqlString =
|
|
166
|
+
typeof queryString$OrQueryString === 'string'
|
|
167
|
+
? queryString$OrQueryString
|
|
168
|
+
: get(queryString$OrQueryString, otelContext)
|
|
166
169
|
|
|
167
170
|
if (queriedTablesRef.current === undefined) {
|
|
168
171
|
queriedTablesRef.current = store.mainDbWrapper.getTablesUsed(sqlString)
|
|
@@ -238,7 +241,10 @@ Result:`,
|
|
|
238
241
|
// })
|
|
239
242
|
|
|
240
243
|
destroy = () => {
|
|
241
|
-
|
|
244
|
+
if (this.queryString$ !== undefined) {
|
|
245
|
+
this.dbGraph.destroyNode(this.queryString$)
|
|
246
|
+
}
|
|
247
|
+
|
|
242
248
|
this.dbGraph.destroyNode(this.results$)
|
|
243
249
|
}
|
|
244
250
|
}
|
package/src/store.ts
CHANGED
|
@@ -184,22 +184,23 @@ export class Store<
|
|
|
184
184
|
* Returns a function to cancel the subscription.
|
|
185
185
|
*/
|
|
186
186
|
subscribe = <TResult>(
|
|
187
|
-
query
|
|
187
|
+
query$: LiveQuery<TResult, any>,
|
|
188
188
|
onNewValue: (value: TResult) => void,
|
|
189
189
|
onUnsubsubscribe?: () => void,
|
|
190
190
|
options?: { label?: string; otelContext?: otel.Context; skipInitialRun?: boolean } | undefined,
|
|
191
191
|
): (() => void) =>
|
|
192
192
|
this.otel.tracer.startActiveSpan(
|
|
193
193
|
`LiveStore.subscribe`,
|
|
194
|
-
{ attributes: { label: options?.label, queryLabel: query
|
|
194
|
+
{ attributes: { label: options?.label, queryLabel: query$.label } },
|
|
195
195
|
options?.otelContext ?? this.otel.queriesSpanContext,
|
|
196
196
|
(span) => {
|
|
197
|
+
// console.log('store sub', query$.label)
|
|
197
198
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
198
199
|
|
|
199
200
|
const label = `subscribe:${options?.label}`
|
|
200
|
-
const effect = this.graph.makeEffect((get) => onNewValue(get(query
|
|
201
|
+
const effect = this.graph.makeEffect((get) => onNewValue(get(query$.results$)), { label })
|
|
201
202
|
|
|
202
|
-
this.activeQueries.add(query as LiveQuery<TResult>)
|
|
203
|
+
this.activeQueries.add(query$ as LiveQuery<TResult>)
|
|
203
204
|
|
|
204
205
|
// Running effect right away to get initial value (unless `skipInitialRun` is set)
|
|
205
206
|
if (options?.skipInitialRun !== true) {
|
|
@@ -207,9 +208,10 @@ export class Store<
|
|
|
207
208
|
}
|
|
208
209
|
|
|
209
210
|
const unsubscribe = () => {
|
|
211
|
+
// console.log('store unsub', query$.label)
|
|
210
212
|
try {
|
|
211
213
|
this.graph.destroyNode(effect)
|
|
212
|
-
this.activeQueries.remove(query as LiveQuery<TResult>)
|
|
214
|
+
this.activeQueries.remove(query$ as LiveQuery<TResult>)
|
|
213
215
|
onUnsubsubscribe?.()
|
|
214
216
|
} finally {
|
|
215
217
|
span.end()
|
|
@@ -225,7 +227,7 @@ export class Store<
|
|
|
225
227
|
*
|
|
226
228
|
* Currently only used when shutting down the app for debugging purposes (e.g. to close Otel spans).
|
|
227
229
|
*/
|
|
228
|
-
destroy = () => {
|
|
230
|
+
destroy = async () => {
|
|
229
231
|
for (const tableRef of Object.values(this.tableRefs)) {
|
|
230
232
|
for (const superComp of tableRef.super) {
|
|
231
233
|
this.graph.removeEdge(superComp, tableRef)
|
|
@@ -234,6 +236,8 @@ export class Store<
|
|
|
234
236
|
|
|
235
237
|
otel.trace.getSpan(this.otel.mutationsSpanContext)!.end()
|
|
236
238
|
otel.trace.getSpan(this.otel.queriesSpanContext)!.end()
|
|
239
|
+
|
|
240
|
+
await this.db.storageDb.shutdown()
|
|
237
241
|
}
|
|
238
242
|
|
|
239
243
|
mutate: {
|
|
@@ -540,11 +544,11 @@ export const createStore = async <
|
|
|
540
544
|
|
|
541
545
|
db.mainDb.execute('COMMIT', undefined)
|
|
542
546
|
|
|
543
|
-
db.storageDb.execute('BEGIN', undefined, undefined)
|
|
547
|
+
// db.storageDb.execute('BEGIN', undefined, undefined)
|
|
544
548
|
for (const [queryStr, bindValues] of txnExecuteStmnts) {
|
|
545
549
|
db.storageDb.execute(queryStr, bindValues, undefined)
|
|
546
550
|
}
|
|
547
|
-
db.storageDb.execute('COMMIT', undefined, undefined)
|
|
551
|
+
// db.storageDb.execute('COMMIT', undefined, undefined)
|
|
548
552
|
} catch (e: any) {
|
|
549
553
|
db.mainDb.execute('ROLLBACK', undefined)
|
|
550
554
|
throw e
|
package/tsconfig.json
CHANGED
|
@@ -9,5 +9,10 @@
|
|
|
9
9
|
"tsBuildInfoFile": "./dist/.tsbuildinfo"
|
|
10
10
|
},
|
|
11
11
|
"include": ["./src"],
|
|
12
|
-
"references": [
|
|
12
|
+
"references": [
|
|
13
|
+
{ "path": "../../effect-db-schema" },
|
|
14
|
+
{ "path": "../common" },
|
|
15
|
+
{ "path": "../web" },
|
|
16
|
+
{ "path": "../utils" }
|
|
17
|
+
]
|
|
13
18
|
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Like cleanup callback of `React.useEffect` but running as part of the render loop.
|
|
5
|
-
*
|
|
6
|
-
* NOTE: This hook should not be used with React strict mode.
|
|
7
|
-
*/
|
|
8
|
-
export const useCleanup = (
|
|
9
|
-
/** Needs to be a `React.useCallback` value */
|
|
10
|
-
cleanupCallback: () => void,
|
|
11
|
-
) => {
|
|
12
|
-
const callbackRef = React.useRef(cleanupCallback)
|
|
13
|
-
|
|
14
|
-
if (callbackRef.current !== cleanupCallback) {
|
|
15
|
-
callbackRef.current()
|
|
16
|
-
callbackRef.current = cleanupCallback
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
React.useEffect(
|
|
20
|
-
() => () => {
|
|
21
|
-
callbackRef.current()
|
|
22
|
-
},
|
|
23
|
-
[],
|
|
24
|
-
)
|
|
25
|
-
}
|