@livestore/react 0.2.0 → 0.3.0-dev.11
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/LiveStoreContext.d.ts +5 -3
- package/dist/LiveStoreContext.d.ts.map +1 -1
- package/dist/LiveStoreContext.js +7 -3
- package/dist/LiveStoreContext.js.map +1 -1
- package/dist/LiveStoreProvider.d.ts +6 -4
- package/dist/LiveStoreProvider.d.ts.map +1 -1
- package/dist/LiveStoreProvider.js +47 -45
- package/dist/LiveStoreProvider.js.map +1 -1
- package/dist/LiveStoreProvider.test.js +8 -2
- package/dist/LiveStoreProvider.test.js.map +1 -1
- package/dist/__tests__/fixture.d.ts +7 -10
- package/dist/__tests__/fixture.d.ts.map +1 -1
- package/dist/__tests__/fixture.js +10 -15
- package/dist/__tests__/fixture.js.map +1 -1
- package/dist/experimental/components/LiveList.d.ts +2 -2
- package/dist/experimental/components/LiveList.d.ts.map +1 -1
- package/dist/experimental/components/LiveList.js +5 -4
- package/dist/experimental/components/LiveList.js.map +1 -1
- package/dist/mod.d.ts +0 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +0 -1
- package/dist/mod.js.map +1 -1
- package/dist/useAtom.d.ts +4 -2
- package/dist/useAtom.d.ts.map +1 -1
- package/dist/useAtom.js +32 -28
- package/dist/useAtom.js.map +1 -1
- package/dist/useQuery.d.ts +26 -3
- package/dist/useQuery.d.ts.map +1 -1
- package/dist/useQuery.js +60 -45
- package/dist/useQuery.js.map +1 -1
- package/dist/useQuery.test.js +70 -16
- package/dist/useQuery.test.js.map +1 -1
- package/dist/useRcRef.d.ts +72 -0
- package/dist/useRcRef.d.ts.map +1 -0
- package/dist/useRcRef.js +146 -0
- package/dist/useRcRef.js.map +1 -0
- package/dist/useRcRef.test.d.ts +2 -0
- package/dist/useRcRef.test.d.ts.map +1 -0
- package/dist/useRcRef.test.js +128 -0
- package/dist/useRcRef.test.js.map +1 -0
- package/dist/useRcResource.d.ts +76 -0
- package/dist/useRcResource.d.ts.map +1 -0
- package/dist/useRcResource.js +150 -0
- package/dist/useRcResource.js.map +1 -0
- package/dist/useRcResource.test.d.ts +2 -0
- package/dist/useRcResource.test.d.ts.map +1 -0
- package/dist/useRcResource.test.js +122 -0
- package/dist/useRcResource.test.js.map +1 -0
- package/dist/useRow.d.ts +10 -7
- package/dist/useRow.d.ts.map +1 -1
- package/dist/useRow.js +16 -19
- package/dist/useRow.js.map +1 -1
- package/dist/useRow.test.js +74 -97
- package/dist/useRow.test.js.map +1 -1
- package/dist/useScopedQuery.d.ts +10 -4
- package/dist/useScopedQuery.d.ts.map +1 -1
- package/dist/useScopedQuery.js +97 -52
- package/dist/useScopedQuery.js.map +1 -1
- package/dist/useScopedQuery.test.js +13 -12
- package/dist/useScopedQuery.test.js.map +1 -1
- package/dist/utils/useStateRefWithReactiveInput.d.ts +1 -1
- package/dist/utils/useStateRefWithReactiveInput.d.ts.map +1 -1
- package/dist/utils/useStateRefWithReactiveInput.js.map +1 -1
- package/package.json +18 -17
- package/src/LiveStoreContext.ts +10 -6
- package/src/LiveStoreProvider.test.tsx +13 -2
- package/src/LiveStoreProvider.tsx +69 -53
- package/src/__snapshots__/useQuery.test.tsx.snap +2011 -0
- package/src/__snapshots__/useRow.test.tsx.snap +347 -151
- package/src/__tests__/fixture.tsx +11 -19
- package/src/experimental/components/LiveList.tsx +8 -7
- package/src/mod.ts +0 -1
- package/src/useAtom.ts +22 -11
- package/src/useQuery.test.tsx +165 -67
- package/src/useQuery.ts +84 -54
- package/src/useRcResource.test.tsx +167 -0
- package/src/useRcResource.ts +180 -0
- package/src/useRow.test.tsx +130 -164
- package/src/useRow.ts +32 -35
- package/src/utils/useStateRefWithReactiveInput.ts +1 -1
- package/dist/useTemporaryQuery.d.ts +0 -22
- package/dist/useTemporaryQuery.d.ts.map +0 -1
- package/dist/useTemporaryQuery.js +0 -75
- package/dist/useTemporaryQuery.js.map +0 -1
- package/src/useScopedQuery.test.tsx +0 -96
- package/src/useScopedQuery.ts +0 -142
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Adapter, BootStatus, IntentionalShutdownCause } from '@livestore/common'
|
|
2
|
-
import { UnexpectedError } from '@livestore/common'
|
|
2
|
+
import { provideOtel, UnexpectedError } from '@livestore/common'
|
|
3
3
|
import type { LiveStoreSchema } from '@livestore/common/schema'
|
|
4
4
|
import type {
|
|
5
5
|
BaseGraphQLContext,
|
|
@@ -7,11 +7,13 @@ import type {
|
|
|
7
7
|
GraphQLOptions,
|
|
8
8
|
LiveStoreContext as StoreContext_,
|
|
9
9
|
OtelOptions,
|
|
10
|
+
ShutdownDeferred,
|
|
10
11
|
Store,
|
|
11
12
|
} from '@livestore/livestore'
|
|
12
13
|
import { createStore, StoreAbort, StoreInterrupted } from '@livestore/livestore'
|
|
13
|
-
import { errorToString } from '@livestore/utils'
|
|
14
|
-
import {
|
|
14
|
+
import { errorToString, LS_DEV } from '@livestore/utils'
|
|
15
|
+
import type { OtelTracer } from '@livestore/utils/effect'
|
|
16
|
+
import { Deferred, Effect, Exit, identity, Logger, LogLevel, Schema, Scope, TaskTracing } from '@livestore/utils/effect'
|
|
15
17
|
import type * as otel from '@opentelemetry/api'
|
|
16
18
|
import type { ReactElement, ReactNode } from 'react'
|
|
17
19
|
import React from 'react'
|
|
@@ -26,7 +28,7 @@ interface LiveStoreProviderProps<GraphQLContext extends BaseGraphQLContext> {
|
|
|
26
28
|
*
|
|
27
29
|
* The `storeId` is also used for persistence.
|
|
28
30
|
*
|
|
29
|
-
* Make sure to also
|
|
31
|
+
* Make sure to also configure `storeId` in LiveStore Devtools (e.g. in Vite plugin).
|
|
30
32
|
*
|
|
31
33
|
* @default 'default'
|
|
32
34
|
*/
|
|
@@ -34,9 +36,9 @@ interface LiveStoreProviderProps<GraphQLContext extends BaseGraphQLContext> {
|
|
|
34
36
|
boot?: (
|
|
35
37
|
store: Store<GraphQLContext, LiveStoreSchema>,
|
|
36
38
|
parentSpan: otel.Span,
|
|
37
|
-
) => void | Promise<void> | Effect.Effect<void, unknown,
|
|
39
|
+
) => void | Promise<void> | Effect.Effect<void, unknown, OtelTracer.OtelTracer>
|
|
38
40
|
graphQLOptions?: GraphQLOptions<GraphQLContext>
|
|
39
|
-
otelOptions?: OtelOptions
|
|
41
|
+
otelOptions?: Partial<OtelOptions>
|
|
40
42
|
renderLoading: (status: BootStatus) => ReactElement
|
|
41
43
|
renderError?: (error: UnexpectedError | unknown) => ReactElement
|
|
42
44
|
renderShutdown?: (cause: IntentionalShutdownCause | StoreAbort) => ReactElement
|
|
@@ -69,7 +71,9 @@ const defaultRenderShutdown = (cause: IntentionalShutdownCause | StoreAbort) =>
|
|
|
69
71
|
? 'devtools import'
|
|
70
72
|
: cause.reason === 'devtools-reset'
|
|
71
73
|
? 'devtools reset'
|
|
72
|
-
:
|
|
74
|
+
: cause.reason === 'manual'
|
|
75
|
+
? 'manual shutdown'
|
|
76
|
+
: 'unknown reason'
|
|
73
77
|
|
|
74
78
|
return <>LiveStore Shutdown due to {reason}</>
|
|
75
79
|
}
|
|
@@ -88,7 +92,7 @@ export const LiveStoreProvider = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
88
92
|
batchUpdates,
|
|
89
93
|
disableDevtools,
|
|
90
94
|
signal,
|
|
91
|
-
}: LiveStoreProviderProps<GraphQLContext> & { children?: ReactNode }):
|
|
95
|
+
}: LiveStoreProviderProps<GraphQLContext> & { children?: ReactNode }): React.ReactElement => {
|
|
92
96
|
const storeCtx = useCreateStore({
|
|
93
97
|
storeId,
|
|
94
98
|
schema,
|
|
@@ -114,6 +118,9 @@ export const LiveStoreProvider = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
globalThis.__debugLiveStore ??= {}
|
|
121
|
+
if (Object.keys(globalThis.__debugLiveStore).length === 0) {
|
|
122
|
+
globalThis.__debugLiveStore['_'] = storeCtx.store
|
|
123
|
+
}
|
|
117
124
|
globalThis.__debugLiveStore[storeId] = storeCtx.store
|
|
118
125
|
|
|
119
126
|
return <LiveStoreContext.Provider value={storeCtx}>{children}</LiveStoreContext.Provider>
|
|
@@ -140,17 +147,21 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
140
147
|
adapter,
|
|
141
148
|
batchUpdates,
|
|
142
149
|
disableDevtools,
|
|
143
|
-
reactivityGraph,
|
|
144
150
|
signal,
|
|
145
|
-
}: CreateStoreOptions<GraphQLContext, LiveStoreSchema> & {
|
|
151
|
+
}: CreateStoreOptions<GraphQLContext, LiveStoreSchema> & {
|
|
152
|
+
signal?: AbortSignal
|
|
153
|
+
otelOptions?: Partial<OtelOptions>
|
|
154
|
+
}) => {
|
|
146
155
|
const [_, rerender] = React.useState(0)
|
|
147
156
|
const ctxValueRef = React.useRef<{
|
|
148
157
|
value: StoreContext_ | BootStatus
|
|
149
|
-
|
|
158
|
+
componentScope: Scope.CloseableScope | undefined
|
|
159
|
+
shutdownDeferred: ShutdownDeferred | undefined
|
|
150
160
|
counter: number
|
|
151
161
|
}>({
|
|
152
162
|
value: { stage: 'loading' },
|
|
153
|
-
|
|
163
|
+
componentScope: undefined,
|
|
164
|
+
shutdownDeferred: undefined,
|
|
154
165
|
counter: 0,
|
|
155
166
|
})
|
|
156
167
|
|
|
@@ -164,16 +175,20 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
164
175
|
adapter,
|
|
165
176
|
batchUpdates,
|
|
166
177
|
disableDevtools,
|
|
167
|
-
reactivityGraph,
|
|
168
178
|
signal,
|
|
169
179
|
})
|
|
170
180
|
|
|
171
|
-
const interrupt = (
|
|
181
|
+
const interrupt = (
|
|
182
|
+
componentScope: Scope.CloseableScope,
|
|
183
|
+
shutdownDeferred: ShutdownDeferred,
|
|
184
|
+
error: StoreAbort | StoreInterrupted,
|
|
185
|
+
) =>
|
|
172
186
|
Effect.gen(function* () {
|
|
173
|
-
|
|
174
|
-
yield*
|
|
187
|
+
// console.log('[@livestore/livestore/react] interupting', error)
|
|
188
|
+
yield* Scope.close(componentScope, Exit.fail(error))
|
|
189
|
+
yield* Deferred.fail(shutdownDeferred, error)
|
|
175
190
|
}).pipe(
|
|
176
|
-
Effect.tapErrorCause((cause) => Effect.logDebug(
|
|
191
|
+
Effect.tapErrorCause((cause) => Effect.logDebug('[@livestore/livestore/react] interupting', cause)),
|
|
177
192
|
Effect.runFork,
|
|
178
193
|
)
|
|
179
194
|
|
|
@@ -185,7 +200,6 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
185
200
|
inputPropsCacheRef.current.adapter !== adapter ||
|
|
186
201
|
inputPropsCacheRef.current.batchUpdates !== batchUpdates ||
|
|
187
202
|
inputPropsCacheRef.current.disableDevtools !== disableDevtools ||
|
|
188
|
-
inputPropsCacheRef.current.reactivityGraph !== reactivityGraph ||
|
|
189
203
|
inputPropsCacheRef.current.signal !== signal
|
|
190
204
|
) {
|
|
191
205
|
inputPropsCacheRef.current = {
|
|
@@ -196,14 +210,19 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
196
210
|
adapter,
|
|
197
211
|
batchUpdates,
|
|
198
212
|
disableDevtools,
|
|
199
|
-
reactivityGraph,
|
|
200
213
|
signal,
|
|
201
214
|
}
|
|
202
|
-
if (ctxValueRef.current.
|
|
203
|
-
interrupt(ctxValueRef.current.
|
|
204
|
-
ctxValueRef.current.
|
|
215
|
+
if (ctxValueRef.current.componentScope !== undefined && ctxValueRef.current.shutdownDeferred !== undefined) {
|
|
216
|
+
interrupt(ctxValueRef.current.componentScope, ctxValueRef.current.shutdownDeferred, new StoreInterrupted())
|
|
217
|
+
ctxValueRef.current.componentScope = undefined
|
|
218
|
+
ctxValueRef.current.shutdownDeferred = undefined
|
|
219
|
+
}
|
|
220
|
+
ctxValueRef.current = {
|
|
221
|
+
value: { stage: 'loading' },
|
|
222
|
+
componentScope: undefined,
|
|
223
|
+
shutdownDeferred: undefined,
|
|
224
|
+
counter: ctxValueRef.current.counter + 1,
|
|
205
225
|
}
|
|
206
|
-
ctxValueRef.current = { value: { stage: 'loading' }, fiberSet: undefined, counter: ctxValueRef.current.counter + 1 }
|
|
207
226
|
}
|
|
208
227
|
|
|
209
228
|
React.useEffect(() => {
|
|
@@ -216,47 +235,51 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
216
235
|
}
|
|
217
236
|
|
|
218
237
|
signal?.addEventListener('abort', () => {
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
ctxValueRef.current.
|
|
238
|
+
if (
|
|
239
|
+
ctxValueRef.current.componentScope !== undefined &&
|
|
240
|
+
ctxValueRef.current.shutdownDeferred !== undefined &&
|
|
241
|
+
ctxValueRef.current.counter === counter
|
|
242
|
+
) {
|
|
243
|
+
interrupt(ctxValueRef.current.componentScope, ctxValueRef.current.shutdownDeferred, new StoreAbort())
|
|
244
|
+
ctxValueRef.current.componentScope = undefined
|
|
245
|
+
ctxValueRef.current.shutdownDeferred = undefined
|
|
222
246
|
}
|
|
223
247
|
})
|
|
224
248
|
|
|
225
249
|
Effect.gen(function* () {
|
|
226
|
-
const
|
|
227
|
-
|
|
250
|
+
const componentScope = yield* Scope.make()
|
|
251
|
+
const shutdownDeferred = yield* Deferred.make<
|
|
252
|
+
void,
|
|
228
253
|
UnexpectedError | IntentionalShutdownCause | StoreAbort | StoreInterrupted
|
|
229
254
|
>()
|
|
230
255
|
|
|
231
|
-
ctxValueRef.current.
|
|
256
|
+
ctxValueRef.current.componentScope = componentScope
|
|
257
|
+
ctxValueRef.current.shutdownDeferred = shutdownDeferred
|
|
232
258
|
|
|
233
259
|
yield* Effect.gen(function* () {
|
|
234
260
|
const store = yield* createStore({
|
|
235
|
-
fiberSet,
|
|
236
261
|
schema,
|
|
237
262
|
storeId,
|
|
238
263
|
graphQLOptions,
|
|
239
|
-
otelOptions,
|
|
240
264
|
boot,
|
|
241
265
|
adapter,
|
|
242
|
-
reactivityGraph,
|
|
243
266
|
batchUpdates,
|
|
244
267
|
disableDevtools,
|
|
268
|
+
shutdownDeferred,
|
|
245
269
|
onBootStatus: (status) => {
|
|
246
270
|
if (ctxValueRef.current.value.stage === 'running' || ctxValueRef.current.value.stage === 'error') return
|
|
247
271
|
setContextValue(status)
|
|
248
272
|
},
|
|
249
|
-
})
|
|
273
|
+
}).pipe(Effect.tapErrorCause((cause) => Deferred.failCause(shutdownDeferred, cause)))
|
|
250
274
|
|
|
251
275
|
setContextValue({ stage: 'running', store })
|
|
252
|
-
|
|
253
|
-
yield* Effect.never
|
|
254
|
-
}).pipe(Effect.scoped, FiberSet.run(fiberSet))
|
|
276
|
+
}).pipe(Scope.extend(componentScope), Effect.forkIn(componentScope))
|
|
255
277
|
|
|
256
278
|
const shutdownContext = (cause: IntentionalShutdownCause | StoreAbort) =>
|
|
257
279
|
Effect.sync(() => setContextValue({ stage: 'shutdown', cause }))
|
|
258
280
|
|
|
259
|
-
yield*
|
|
281
|
+
yield* Deferred.await(shutdownDeferred).pipe(
|
|
282
|
+
Effect.tapErrorCause((cause) => Effect.logDebug('[@livestore/livestore/react] shutdown', cause)),
|
|
260
283
|
Effect.catchTag('LiveStore.IntentionalShutdownCause', (cause) => shutdownContext(cause)),
|
|
261
284
|
Effect.catchTag('LiveStore.StoreAbort', (cause) => shutdownContext(cause)),
|
|
262
285
|
Effect.tapError((error) => Effect.sync(() => setContextValue({ stage: 'error', error }))),
|
|
@@ -269,31 +292,24 @@ const useCreateStore = <GraphQLContext extends BaseGraphQLContext>({
|
|
|
269
292
|
// shutdown before a new one is created - especially when shutdown logic is async. You can't trust `React.useEffect`.
|
|
270
293
|
// Thank you to Mattia Manzati for this idea.
|
|
271
294
|
withSemaphore(storeId),
|
|
295
|
+
Effect.withSpan('@livestore/react:useCreateStore'),
|
|
296
|
+
LS_DEV ? TaskTracing.withAsyncTaggingTracing((name: string) => (console as any).createTask(name)) : identity,
|
|
297
|
+
provideOtel({ parentSpanContext: otelOptions?.rootSpanContext, otelTracer: otelOptions?.tracer }),
|
|
272
298
|
Effect.tapCauseLogPretty,
|
|
273
299
|
Effect.annotateLogs({ thread: 'window' }),
|
|
274
|
-
Effect.provide(Logger.
|
|
300
|
+
Effect.provide(Logger.prettyWithThread('window')),
|
|
275
301
|
Logger.withMinimumLogLevel(LogLevel.Debug),
|
|
276
302
|
Effect.runFork,
|
|
277
303
|
)
|
|
278
304
|
|
|
279
305
|
return () => {
|
|
280
|
-
if (ctxValueRef.current.
|
|
281
|
-
interrupt(ctxValueRef.current.
|
|
282
|
-
ctxValueRef.current.
|
|
306
|
+
if (ctxValueRef.current.componentScope !== undefined && ctxValueRef.current.shutdownDeferred !== undefined) {
|
|
307
|
+
interrupt(ctxValueRef.current.componentScope, ctxValueRef.current.shutdownDeferred, new StoreInterrupted())
|
|
308
|
+
ctxValueRef.current.componentScope = undefined
|
|
309
|
+
ctxValueRef.current.shutdownDeferred = undefined
|
|
283
310
|
}
|
|
284
311
|
}
|
|
285
|
-
}, [
|
|
286
|
-
schema,
|
|
287
|
-
graphQLOptions,
|
|
288
|
-
otelOptions,
|
|
289
|
-
boot,
|
|
290
|
-
adapter,
|
|
291
|
-
batchUpdates,
|
|
292
|
-
disableDevtools,
|
|
293
|
-
signal,
|
|
294
|
-
reactivityGraph,
|
|
295
|
-
storeId,
|
|
296
|
-
])
|
|
312
|
+
}, [schema, graphQLOptions, otelOptions, boot, adapter, batchUpdates, disableDevtools, signal, storeId])
|
|
297
313
|
|
|
298
314
|
return ctxValueRef.current.value
|
|
299
315
|
}
|