@livestore/livestore 0.0.54-dev.26 → 0.0.54-dev.28
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/dist/.tsbuildinfo +1 -1
- package/dist/QueryCache.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.d.ts +5 -15
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +2 -2
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/effect/LiveStore.d.ts +15 -8
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +15 -16
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/effect/index.d.ts +1 -1
- package/dist/effect/index.d.ts.map +1 -1
- package/dist/effect/index.js +1 -1
- package/dist/effect/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react/LiveStoreContext.d.ts +5 -2
- package/dist/react/LiveStoreContext.d.ts.map +1 -1
- package/dist/react/LiveStoreContext.js.map +1 -1
- package/dist/react/LiveStoreProvider.d.ts +3 -2
- package/dist/react/LiveStoreProvider.d.ts.map +1 -1
- package/dist/react/LiveStoreProvider.js +63 -39
- package/dist/react/LiveStoreProvider.js.map +1 -1
- package/dist/react/LiveStoreProvider.test.js +28 -9
- package/dist/react/LiveStoreProvider.test.js.map +1 -1
- package/dist/react/components/LiveList.d.ts.map +1 -1
- package/dist/react/useAtom.d.ts +1 -1
- package/dist/react/useAtom.d.ts.map +1 -1
- package/dist/react/useLocalId.d.ts.map +1 -1
- package/dist/react/useQuery.d.ts.map +1 -1
- package/dist/react/useQuery.js +2 -2
- package/dist/react/useQuery.js.map +1 -1
- package/dist/react/useRow.d.ts.map +1 -1
- package/dist/react/useRow.js +2 -2
- package/dist/react/useRow.js.map +1 -1
- package/dist/react/useRow.test.js +1 -1
- package/dist/react/useRow.test.js.map +1 -1
- package/dist/react/useTemporaryQuery.d.ts.map +1 -1
- package/dist/react/utils/useStateRefWithReactiveInput.d.ts.map +1 -1
- package/dist/reactive.d.ts +1 -1
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +3 -4
- package/dist/reactive.js.map +1 -1
- package/dist/reactiveQueries/base-class.d.ts.map +1 -1
- package/dist/reactiveQueries/graphql.d.ts.map +1 -1
- package/dist/reactiveQueries/js.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.test.js +6 -6
- package/dist/reactiveQueries/sql.test.js.map +1 -1
- package/dist/store.d.ts +12 -5
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +59 -122
- package/dist/store.js.map +1 -1
- package/dist/utils/otel.d.ts.map +1 -1
- package/package.json +8 -10
- package/src/__tests__/react/fixture.tsx +2 -2
- package/src/effect/LiveStore.ts +50 -43
- package/src/effect/index.ts +2 -1
- package/src/index.ts +7 -3
- package/src/react/LiveStoreContext.ts +3 -2
- package/src/react/LiveStoreProvider.test.tsx +47 -10
- package/src/react/LiveStoreProvider.tsx +95 -38
- package/src/react/useQuery.ts +2 -2
- package/src/react/useRow.test.tsx +1 -1
- package/src/react/useRow.ts +2 -5
- package/src/reactive.ts +3 -4
- package/src/reactiveQueries/sql.test.ts +6 -6
- package/src/store.ts +243 -286
package/src/effect/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
export { Store, createStore } from './store.js'
|
|
1
|
+
export { Store, createStorePromise, createStore } from './store.js'
|
|
2
2
|
export type { BaseGraphQLContext, QueryDebugInfo, RefreshReason } from './store.js'
|
|
3
3
|
|
|
4
|
-
export type {
|
|
4
|
+
export type {
|
|
5
|
+
QueryDefinition,
|
|
6
|
+
LiveStoreCreateStoreOptions,
|
|
7
|
+
LiveStoreContextRunning as LiveStoreContext,
|
|
8
|
+
} from './effect/LiveStore.js'
|
|
5
9
|
|
|
6
10
|
export { MainDatabaseWrapper, emptyDebugInfo } from './MainDatabaseWrapper.js'
|
|
7
11
|
|
|
@@ -46,7 +50,7 @@ export {
|
|
|
46
50
|
|
|
47
51
|
export { SqliteAst, SqliteDsl } from 'effect-db-schema'
|
|
48
52
|
|
|
49
|
-
export {
|
|
53
|
+
export { deepEqual } from '@livestore/utils'
|
|
50
54
|
|
|
51
55
|
export type {
|
|
52
56
|
StoreAdapter as DatabaseImpl,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, { useContext } from 'react'
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { LiveStoreContextRunning as LiveStoreContext_ } from '../effect/LiveStore.js'
|
|
4
|
+
import type { Store } from '../store.js'
|
|
4
5
|
|
|
5
6
|
export const LiveStoreContext = React.createContext<LiveStoreContext_ | undefined>(undefined)
|
|
6
7
|
|
|
7
|
-
export const useStore = ():
|
|
8
|
+
export const useStore = (): { store: Store } => {
|
|
8
9
|
const storeContext = useContext(LiveStoreContext)
|
|
9
10
|
|
|
10
11
|
if (storeContext === undefined) {
|
|
@@ -7,27 +7,25 @@ import { describe, expect, it } from 'vitest'
|
|
|
7
7
|
|
|
8
8
|
import { parseTodos, schema } from '../__tests__/react/fixture.js'
|
|
9
9
|
import { querySQL } from '../reactiveQueries/sql.js'
|
|
10
|
-
import type { Store } from '../store.js'
|
|
11
10
|
import * as LiveStoreReact from './index.js'
|
|
12
11
|
import { LiveStoreProvider } from './LiveStoreProvider.js'
|
|
13
12
|
|
|
14
13
|
describe('LiveStoreProvider', () => {
|
|
15
14
|
it('simple', async () => {
|
|
16
|
-
let
|
|
15
|
+
let appRenderCount = 0
|
|
17
16
|
|
|
18
17
|
const allTodos$ = querySQL(`select * from todos`, { map: parseTodos })
|
|
19
|
-
let latestStoreCtx: { store: Store } | undefined = undefined
|
|
20
18
|
|
|
21
19
|
const App = () => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
latestStoreCtx = LiveStoreReact.useStore()
|
|
20
|
+
appRenderCount++
|
|
25
21
|
|
|
26
22
|
const todos = LiveStoreReact.useQuery(allTodos$)
|
|
27
23
|
|
|
28
24
|
return <div>{JSON.stringify(todos)}</div>
|
|
29
25
|
}
|
|
30
26
|
|
|
27
|
+
const abortController = new AbortController()
|
|
28
|
+
|
|
31
29
|
const Root = ({ forceUpdate }: { forceUpdate: number }) => {
|
|
32
30
|
const bootCb = React.useCallback(
|
|
33
31
|
(db: BootDb) =>
|
|
@@ -42,6 +40,7 @@ describe('LiveStoreProvider', () => {
|
|
|
42
40
|
renderLoading={(status) => <div>Loading LiveStore: {status.stage}</div>}
|
|
43
41
|
adapter={adapterMemo}
|
|
44
42
|
boot={bootCb}
|
|
43
|
+
signal={abortController.signal}
|
|
45
44
|
>
|
|
46
45
|
<App />
|
|
47
46
|
</LiveStoreProvider>
|
|
@@ -50,19 +49,57 @@ describe('LiveStoreProvider', () => {
|
|
|
50
49
|
|
|
51
50
|
const { rerender } = render(<Root forceUpdate={1} />)
|
|
52
51
|
|
|
53
|
-
expect(
|
|
52
|
+
expect(appRenderCount).toBe(0)
|
|
54
53
|
|
|
55
54
|
await waitForElementToBeRemoved(() => screen.getByText((_) => _.startsWith('Loading LiveStore')))
|
|
56
55
|
|
|
57
|
-
expect(
|
|
56
|
+
expect(appRenderCount).toBe(1)
|
|
58
57
|
|
|
59
58
|
rerender(<Root forceUpdate={2} />)
|
|
60
59
|
|
|
61
60
|
await waitFor(() => screen.getByText('Loading LiveStore: loading'))
|
|
62
61
|
await waitForElementToBeRemoved(() => screen.getByText((_) => _.startsWith('Loading LiveStore')))
|
|
63
62
|
|
|
64
|
-
expect(
|
|
63
|
+
expect(appRenderCount).toBe(2)
|
|
64
|
+
|
|
65
|
+
abortController.abort()
|
|
66
|
+
|
|
67
|
+
await waitFor(() => screen.getByText('LiveStore Shutdown'))
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('error during boot', async () => {
|
|
71
|
+
let appRenderCount = 0
|
|
72
|
+
|
|
73
|
+
const App = () => {
|
|
74
|
+
appRenderCount++
|
|
75
|
+
|
|
76
|
+
return <div>hello world</div>
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const Root = ({ forceUpdate }: { forceUpdate: number }) => {
|
|
80
|
+
const bootCb = React.useCallback(
|
|
81
|
+
(db: BootDb) =>
|
|
82
|
+
db.execute(sql`INSERT INTO todos_mising_table (id, text, completed) VALUES ('t1', 'buy milk', 0);`),
|
|
83
|
+
[],
|
|
84
|
+
)
|
|
85
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
86
|
+
const adapterMemo = React.useMemo(() => makeInMemoryAdapter(), [forceUpdate])
|
|
87
|
+
return (
|
|
88
|
+
<LiveStoreProvider
|
|
89
|
+
schema={schema}
|
|
90
|
+
renderLoading={(status) => <div>Loading LiveStore: {status.stage}</div>}
|
|
91
|
+
adapter={adapterMemo}
|
|
92
|
+
boot={bootCb}
|
|
93
|
+
>
|
|
94
|
+
<App />
|
|
95
|
+
</LiveStoreProvider>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
render(<Root forceUpdate={1} />)
|
|
100
|
+
|
|
101
|
+
expect(appRenderCount).toBe(0)
|
|
65
102
|
|
|
66
|
-
await
|
|
103
|
+
await waitFor(() => screen.getByText((_) => _.startsWith('LiveStore.UnexpectedError')))
|
|
67
104
|
})
|
|
68
105
|
})
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type BootDb, type BootStatus, type StoreAdapterFactory, UnexpectedError } from '@livestore/common'
|
|
2
2
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
3
|
-
import {
|
|
3
|
+
import { errorToString } from '@livestore/utils'
|
|
4
|
+
import { Effect, Exit, Logger, LogLevel, Schema, Scope } from '@livestore/utils/effect'
|
|
4
5
|
import type * as otel from '@opentelemetry/api'
|
|
5
6
|
import type { ReactElement, ReactNode } from 'react'
|
|
6
7
|
import React from 'react'
|
|
7
8
|
|
|
8
9
|
// TODO refactor so the `react` module doesn't depend on `effect` module
|
|
9
10
|
import type { LiveStoreContext as StoreContext_, LiveStoreCreateStoreOptions } from '../effect/LiveStore.js'
|
|
10
|
-
import type { BaseGraphQLContext, GraphQLOptions, OtelOptions
|
|
11
|
+
import type { BaseGraphQLContext, GraphQLOptions, OtelOptions } from '../store.js'
|
|
11
12
|
import { createStore } from '../store.js'
|
|
12
13
|
import { LiveStoreContext } from './LiveStoreContext.js'
|
|
13
14
|
|
|
@@ -20,6 +21,7 @@ interface LiveStoreProviderProps<GraphQLContext> {
|
|
|
20
21
|
adapter: StoreAdapterFactory
|
|
21
22
|
batchUpdates?: (run: () => void) => void
|
|
22
23
|
disableDevtools?: boolean
|
|
24
|
+
signal?: AbortSignal
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export const LiveStoreProvider = <GraphQLContext extends BaseGraphQLContext>({
|
|
@@ -32,6 +34,7 @@ export const LiveStoreProvider = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
32
34
|
adapter,
|
|
33
35
|
batchUpdates,
|
|
34
36
|
disableDevtools,
|
|
37
|
+
signal,
|
|
35
38
|
}: LiveStoreProviderProps<GraphQLContext> & { children?: ReactNode }): JSX.Element => {
|
|
36
39
|
const storeCtx = useCreateStore({
|
|
37
40
|
schema,
|
|
@@ -41,8 +44,21 @@ export const LiveStoreProvider = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
41
44
|
adapter,
|
|
42
45
|
batchUpdates,
|
|
43
46
|
disableDevtools,
|
|
47
|
+
signal,
|
|
44
48
|
})
|
|
45
49
|
|
|
50
|
+
if (storeCtx.stage === 'error') {
|
|
51
|
+
return (
|
|
52
|
+
<div>
|
|
53
|
+
{Schema.is(UnexpectedError)(storeCtx.error) ? storeCtx.error.toString() : errorToString(storeCtx.error)}
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (storeCtx.stage === 'shutdown') {
|
|
59
|
+
return <div>LiveStore Shutdown</div>
|
|
60
|
+
}
|
|
61
|
+
|
|
46
62
|
if (storeCtx.stage !== 'running') {
|
|
47
63
|
return <div>{renderLoading(storeCtx)}</div>
|
|
48
64
|
}
|
|
@@ -60,9 +76,21 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
60
76
|
adapter,
|
|
61
77
|
batchUpdates,
|
|
62
78
|
disableDevtools,
|
|
79
|
+
signal,
|
|
63
80
|
}: LiveStoreCreateStoreOptions<GraphQLContext>) => {
|
|
64
81
|
const [_, rerender] = React.useState(0)
|
|
65
|
-
const ctxValueRef = React.useRef<
|
|
82
|
+
const ctxValueRef = React.useRef<{
|
|
83
|
+
value: StoreContext_ | BootStatus
|
|
84
|
+
scope: Scope.CloseableScope | undefined
|
|
85
|
+
counter: number
|
|
86
|
+
}>({
|
|
87
|
+
value: { stage: 'loading' },
|
|
88
|
+
scope: undefined,
|
|
89
|
+
counter: 0,
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
// console.debug(`useCreateStore (${ctxValueRef.current.counter})`, ctxValueRef.current.value.stage)
|
|
93
|
+
|
|
66
94
|
const inputPropsCacheRef = React.useRef({
|
|
67
95
|
schema,
|
|
68
96
|
graphQLOptions,
|
|
@@ -70,8 +98,9 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
70
98
|
boot,
|
|
71
99
|
adapter,
|
|
72
100
|
batchUpdates,
|
|
101
|
+
disableDevtools,
|
|
102
|
+
signal,
|
|
73
103
|
})
|
|
74
|
-
const oldStoreAlreadyDestroyedRef = React.useRef(false)
|
|
75
104
|
|
|
76
105
|
if (
|
|
77
106
|
inputPropsCacheRef.current.schema !== schema ||
|
|
@@ -79,7 +108,9 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
79
108
|
inputPropsCacheRef.current.otelOptions !== otelOptions ||
|
|
80
109
|
inputPropsCacheRef.current.boot !== boot ||
|
|
81
110
|
inputPropsCacheRef.current.adapter !== adapter ||
|
|
82
|
-
inputPropsCacheRef.current.batchUpdates !== batchUpdates
|
|
111
|
+
inputPropsCacheRef.current.batchUpdates !== batchUpdates ||
|
|
112
|
+
inputPropsCacheRef.current.disableDevtools !== disableDevtools ||
|
|
113
|
+
inputPropsCacheRef.current.signal !== signal
|
|
83
114
|
) {
|
|
84
115
|
inputPropsCacheRef.current = {
|
|
85
116
|
schema,
|
|
@@ -88,47 +119,73 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
88
119
|
boot,
|
|
89
120
|
adapter,
|
|
90
121
|
batchUpdates,
|
|
122
|
+
disableDevtools,
|
|
123
|
+
signal,
|
|
91
124
|
}
|
|
92
|
-
if (ctxValueRef.current.
|
|
93
|
-
ctxValueRef.current.
|
|
94
|
-
oldStoreAlreadyDestroyedRef.current = true
|
|
95
|
-
ctxValueRef.current = { stage: 'loading' }
|
|
125
|
+
if (ctxValueRef.current.scope !== undefined) {
|
|
126
|
+
Scope.close(ctxValueRef.current.scope, Exit.void).pipe(Effect.tapCauseLogPretty, Effect.runFork)
|
|
96
127
|
}
|
|
128
|
+
ctxValueRef.current = { value: { stage: 'loading' }, scope: undefined, counter: ctxValueRef.current.counter + 1 }
|
|
97
129
|
}
|
|
98
130
|
|
|
99
131
|
React.useEffect(() => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
} catch (e) {
|
|
122
|
-
shouldNeverHappen(`Error creating LiveStore store: ${e}`)
|
|
132
|
+
const storeScope = Scope.make().pipe(Effect.runSync)
|
|
133
|
+
|
|
134
|
+
const counter = ctxValueRef.current.counter
|
|
135
|
+
|
|
136
|
+
const setContextValue = (value: StoreContext_ | BootStatus) => {
|
|
137
|
+
if (ctxValueRef.current.counter !== counter) return
|
|
138
|
+
ctxValueRef.current.value = value
|
|
139
|
+
rerender((c) => c + 1)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
Scope.addFinalizer(
|
|
143
|
+
storeScope,
|
|
144
|
+
Effect.sync(() => setContextValue({ stage: 'shutdown' })),
|
|
145
|
+
).pipe(Effect.runSync)
|
|
146
|
+
|
|
147
|
+
ctxValueRef.current.scope = storeScope
|
|
148
|
+
|
|
149
|
+
signal?.addEventListener('abort', () => {
|
|
150
|
+
if (ctxValueRef.current.scope !== undefined && ctxValueRef.current.counter === counter) {
|
|
151
|
+
Scope.close(ctxValueRef.current.scope, Exit.void).pipe(Effect.tapCauseLogPretty, Effect.runFork)
|
|
152
|
+
ctxValueRef.current.scope = undefined
|
|
123
153
|
}
|
|
124
|
-
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
createStore({
|
|
157
|
+
storeScope,
|
|
158
|
+
schema,
|
|
159
|
+
graphQLOptions,
|
|
160
|
+
otelOptions,
|
|
161
|
+
boot,
|
|
162
|
+
adapter,
|
|
163
|
+
batchUpdates,
|
|
164
|
+
disableDevtools,
|
|
165
|
+
onBootStatus: (status) => {
|
|
166
|
+
if (ctxValueRef.current.value.stage === 'running' || ctxValueRef.current.value.stage === 'error') return
|
|
167
|
+
setContextValue(status)
|
|
168
|
+
},
|
|
169
|
+
}).pipe(
|
|
170
|
+
Effect.tapSync((store) => setContextValue({ stage: 'running', store })),
|
|
171
|
+
Effect.tapError((error) => Effect.sync(() => setContextValue({ stage: 'error', error }))),
|
|
172
|
+
Effect.tapDefect((defect) => Effect.sync(() => setContextValue({ stage: 'error', error: defect }))),
|
|
173
|
+
Scope.extend(storeScope),
|
|
174
|
+
Effect.forkIn(storeScope),
|
|
175
|
+
Effect.tapCauseLogPretty,
|
|
176
|
+
Effect.annotateLogs({ thread: 'window' }),
|
|
177
|
+
Effect.provide(Logger.pretty),
|
|
178
|
+
Logger.withMinimumLogLevel(LogLevel.Debug),
|
|
179
|
+
Effect.runFork,
|
|
180
|
+
)
|
|
125
181
|
|
|
126
182
|
return () => {
|
|
127
|
-
if (
|
|
128
|
-
|
|
183
|
+
if (ctxValueRef.current.scope !== undefined) {
|
|
184
|
+
Scope.close(ctxValueRef.current.scope, Exit.void).pipe(Effect.tapCauseLogPretty, Effect.runFork)
|
|
185
|
+
ctxValueRef.current.scope = undefined
|
|
129
186
|
}
|
|
130
187
|
}
|
|
131
|
-
}, [schema, graphQLOptions, otelOptions, boot, adapter, batchUpdates, disableDevtools])
|
|
188
|
+
}, [schema, graphQLOptions, otelOptions, boot, adapter, batchUpdates, disableDevtools, signal])
|
|
132
189
|
|
|
133
|
-
return ctxValueRef.current
|
|
190
|
+
return ctxValueRef.current.value
|
|
134
191
|
}
|
package/src/react/useQuery.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { deepEqual } from '@livestore/utils'
|
|
1
2
|
import * as otel from '@opentelemetry/api'
|
|
2
|
-
import { isEqual } from 'lodash-es'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
|
|
5
5
|
import type { GetResult, LiveQueryAny } from '../reactiveQueries/base-class.js'
|
|
@@ -90,7 +90,7 @@ export const useQueryRef = <TQuery extends LiveQueryAny>(
|
|
|
90
90
|
// NOTE: we return a reference to the result object within LiveStore;
|
|
91
91
|
// this implies that app code must not mutate the results, or else
|
|
92
92
|
// there may be weird reactivity bugs.
|
|
93
|
-
if (
|
|
93
|
+
if (deepEqual(newValue, valueRef.current) === false) {
|
|
94
94
|
setValue(newValue)
|
|
95
95
|
}
|
|
96
96
|
},
|
package/src/react/useRow.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { QueryInfo } from '@livestore/common'
|
|
2
|
-
import {} from // deriveCreateMutationDef as deriveCreateMutationDef_,
|
|
3
|
-
// updateMutationForQueryInfo as updateMutationForQueryInfo_,
|
|
4
|
-
'@livestore/common'
|
|
5
2
|
import { DbSchema } from '@livestore/common/schema'
|
|
6
3
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
4
|
+
import { ReadonlyRecord } from '@livestore/utils/effect'
|
|
7
5
|
import type { SqliteDsl } from 'effect-db-schema'
|
|
8
|
-
import { mapValues } from 'lodash-es'
|
|
9
6
|
import React from 'react'
|
|
10
7
|
|
|
11
8
|
import type { LiveQuery, ReactivityGraph } from '../index.js'
|
|
@@ -133,7 +130,7 @@ export const useRow: {
|
|
|
133
130
|
}
|
|
134
131
|
} else {
|
|
135
132
|
const setState = // TODO: do we have a better type for the values that can go in SQLite?
|
|
136
|
-
|
|
133
|
+
ReadonlyRecord.map(sqliteTableDef.columns, (column, columnName) => (newValueOrFn: any) => {
|
|
137
134
|
const newValue =
|
|
138
135
|
// @ts-expect-error TODO fix typing
|
|
139
136
|
typeof newValueOrFn === 'function' ? newValueOrFn(query$Ref.current[columnName]) : newValueOrFn
|
package/src/reactive.ts
CHANGED
|
@@ -25,9 +25,8 @@
|
|
|
25
25
|
|
|
26
26
|
import { BoundArray } from '@livestore/common'
|
|
27
27
|
import type { PrettifyFlat } from '@livestore/utils'
|
|
28
|
-
import { shouldNeverHappen } from '@livestore/utils'
|
|
28
|
+
import { deepEqual, shouldNeverHappen } from '@livestore/utils'
|
|
29
29
|
import type * as otel from '@opentelemetry/api'
|
|
30
|
-
import { isEqual } from 'lodash-es'
|
|
31
30
|
// import { getDurationMsFromSpan } from './otel.js'
|
|
32
31
|
|
|
33
32
|
export const NOT_REFRESHED_YET = Symbol.for('NOT_REFRESHED_YET')
|
|
@@ -234,7 +233,7 @@ export class ReactiveGraph<
|
|
|
234
233
|
super: new Set(),
|
|
235
234
|
label: options?.label,
|
|
236
235
|
meta: options?.meta,
|
|
237
|
-
equal: options?.equal ??
|
|
236
|
+
equal: options?.equal ?? deepEqual,
|
|
238
237
|
refreshes: 0,
|
|
239
238
|
}
|
|
240
239
|
|
|
@@ -331,7 +330,7 @@ export class ReactiveGraph<
|
|
|
331
330
|
recomputations: 0,
|
|
332
331
|
label: options?.label,
|
|
333
332
|
meta: options?.meta,
|
|
334
|
-
equal: options?.equal ??
|
|
333
|
+
equal: options?.equal ?? deepEqual,
|
|
335
334
|
__getResult: getResult,
|
|
336
335
|
}
|
|
337
336
|
|
|
@@ -24,17 +24,17 @@ describe('otel', () => {
|
|
|
24
24
|
provider.addSpanProcessor(new SimpleSpanProcessor(exporter))
|
|
25
25
|
provider.register()
|
|
26
26
|
|
|
27
|
-
const
|
|
27
|
+
const otelTracer = otel.trace.getTracer('test')
|
|
28
28
|
|
|
29
|
-
const span =
|
|
29
|
+
const span = otelTracer.startSpan('test')
|
|
30
30
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
31
31
|
|
|
32
|
-
const { store } = await makeTodoMvc({ otelTracer
|
|
32
|
+
const { store } = await makeTodoMvc({ otelTracer, otelContext })
|
|
33
33
|
|
|
34
34
|
return {
|
|
35
35
|
[Symbol.dispose]: () => store.destroy(),
|
|
36
36
|
store,
|
|
37
|
-
|
|
37
|
+
otelTracer,
|
|
38
38
|
exporter,
|
|
39
39
|
span,
|
|
40
40
|
provider,
|
|
@@ -60,7 +60,7 @@ describe('otel', () => {
|
|
|
60
60
|
]
|
|
61
61
|
`)
|
|
62
62
|
|
|
63
|
-
store.destroy()
|
|
63
|
+
await store.destroy()
|
|
64
64
|
query.destroy()
|
|
65
65
|
span.end()
|
|
66
66
|
|
|
@@ -193,7 +193,7 @@ describe('otel', () => {
|
|
|
193
193
|
}
|
|
194
194
|
`)
|
|
195
195
|
|
|
196
|
-
store.destroy()
|
|
196
|
+
await store.destroy()
|
|
197
197
|
query.destroy()
|
|
198
198
|
span.end()
|
|
199
199
|
|