@livestore/react 0.4.0-dev.2 → 0.4.0-dev.21
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 +27 -0
- package/dist/LiveStoreContext.d.ts.map +1 -1
- package/dist/LiveStoreContext.js +18 -0
- package/dist/LiveStoreContext.js.map +1 -1
- package/dist/LiveStoreProvider.d.ts +14 -8
- package/dist/LiveStoreProvider.d.ts.map +1 -1
- package/dist/LiveStoreProvider.js +40 -24
- package/dist/LiveStoreProvider.js.map +1 -1
- package/dist/LiveStoreProvider.test.js +7 -7
- package/dist/LiveStoreProvider.test.js.map +1 -1
- package/dist/__tests__/fixture.d.ts +34 -12
- package/dist/__tests__/fixture.d.ts.map +1 -1
- package/dist/__tests__/fixture.js +13 -5
- package/dist/__tests__/fixture.js.map +1 -1
- package/dist/experimental/components/LiveList.js +1 -1
- package/dist/experimental/mod.d.ts +1 -0
- package/dist/experimental/mod.d.ts.map +1 -1
- package/dist/experimental/mod.js +1 -0
- package/dist/experimental/mod.js.map +1 -1
- package/dist/experimental/multi-store/StoreRegistry.d.ts +105 -0
- package/dist/experimental/multi-store/StoreRegistry.d.ts.map +1 -0
- package/dist/experimental/multi-store/StoreRegistry.js +184 -0
- package/dist/experimental/multi-store/StoreRegistry.js.map +1 -0
- package/dist/experimental/multi-store/StoreRegistry.test.d.ts +2 -0
- package/dist/experimental/multi-store/StoreRegistry.test.d.ts.map +1 -0
- package/dist/experimental/multi-store/StoreRegistry.test.js +381 -0
- package/dist/experimental/multi-store/StoreRegistry.test.js.map +1 -0
- package/dist/experimental/multi-store/StoreRegistryContext.d.ts +10 -0
- package/dist/experimental/multi-store/StoreRegistryContext.d.ts.map +1 -0
- package/dist/experimental/multi-store/StoreRegistryContext.js +15 -0
- package/dist/experimental/multi-store/StoreRegistryContext.js.map +1 -0
- package/dist/experimental/multi-store/mod.d.ts +6 -0
- package/dist/experimental/multi-store/mod.d.ts.map +1 -0
- package/dist/experimental/multi-store/mod.js +6 -0
- package/dist/experimental/multi-store/mod.js.map +1 -0
- package/dist/experimental/multi-store/storeOptions.d.ts +4 -0
- package/dist/experimental/multi-store/storeOptions.d.ts.map +1 -0
- package/dist/experimental/multi-store/storeOptions.js +4 -0
- package/dist/experimental/multi-store/storeOptions.js.map +1 -0
- package/dist/experimental/multi-store/types.d.ts +25 -0
- package/dist/experimental/multi-store/types.d.ts.map +1 -0
- package/dist/experimental/multi-store/types.js +2 -0
- package/dist/experimental/multi-store/types.js.map +1 -0
- package/dist/experimental/multi-store/useStore.d.ts +11 -0
- package/dist/experimental/multi-store/useStore.d.ts.map +1 -0
- package/dist/experimental/multi-store/useStore.js +16 -0
- package/dist/experimental/multi-store/useStore.js.map +1 -0
- package/dist/experimental/multi-store/useStore.test.d.ts +2 -0
- package/dist/experimental/multi-store/useStore.test.d.ts.map +1 -0
- package/dist/experimental/multi-store/useStore.test.js +198 -0
- package/dist/experimental/multi-store/useStore.test.js.map +1 -0
- package/dist/mod.d.ts +1 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js.map +1 -1
- package/dist/useClientDocument.d.ts +43 -13
- package/dist/useClientDocument.d.ts.map +1 -1
- package/dist/useClientDocument.js +4 -5
- package/dist/useClientDocument.js.map +1 -1
- package/dist/useClientDocument.test.js +29 -7
- package/dist/useClientDocument.test.js.map +1 -1
- package/dist/useQuery.d.ts +28 -6
- package/dist/useQuery.d.ts.map +1 -1
- package/dist/useQuery.js +63 -18
- package/dist/useQuery.js.map +1 -1
- package/dist/useQuery.test.js +35 -11
- package/dist/useQuery.test.js.map +1 -1
- package/dist/useRcResource.test.js +1 -1
- package/dist/useStore.d.ts +53 -1
- package/dist/useStore.d.ts.map +1 -1
- package/dist/useStore.js +52 -1
- package/dist/useStore.js.map +1 -1
- package/package.json +14 -14
- package/src/LiveStoreContext.ts +27 -0
- package/src/LiveStoreProvider.test.tsx +7 -7
- package/src/LiveStoreProvider.tsx +67 -45
- package/src/__snapshots__/useClientDocument.test.tsx.snap +208 -100
- package/src/__snapshots__/useQuery.test.tsx.snap +400 -128
- package/src/__tests__/fixture.tsx +23 -24
- package/src/experimental/components/LiveList.tsx +1 -1
- package/src/experimental/mod.ts +1 -0
- package/src/experimental/multi-store/StoreRegistry.test.ts +518 -0
- package/src/experimental/multi-store/StoreRegistry.ts +253 -0
- package/src/experimental/multi-store/StoreRegistryContext.tsx +23 -0
- package/src/experimental/multi-store/mod.ts +5 -0
- package/src/experimental/multi-store/storeOptions.ts +8 -0
- package/src/experimental/multi-store/types.ts +37 -0
- package/src/experimental/multi-store/useStore.test.tsx +269 -0
- package/src/experimental/multi-store/useStore.ts +26 -0
- package/src/mod.ts +2 -1
- package/src/useClientDocument.test.tsx +105 -75
- package/src/useClientDocument.ts +58 -13
- package/src/useQuery.test.tsx +62 -11
- package/src/useQuery.ts +98 -27
- package/src/useRcResource.test.tsx +1 -1
- package/src/useStore.ts +55 -3
package/dist/useQuery.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isQueryBuilder } from '@livestore/common';
|
|
2
|
+
import { extractStackInfoFromStackTrace, isQueryable, queryDb, StoreInternalsSymbol, stackInfoToString, } from '@livestore/livestore';
|
|
2
3
|
import { deepEqual, indent, shouldNeverHappen } from '@livestore/utils';
|
|
3
4
|
import * as otel from '@opentelemetry/api';
|
|
4
5
|
import React from 'react';
|
|
@@ -17,16 +18,56 @@ import { useStateRefWithReactiveInput } from "./utils/useStateRefWithReactiveInp
|
|
|
17
18
|
* }
|
|
18
19
|
* ```
|
|
19
20
|
*/
|
|
20
|
-
export const useQuery = (
|
|
21
|
+
export const useQuery = (queryable, options) => useQueryRef(queryable, options).valueRef.current;
|
|
21
22
|
/**
|
|
23
|
+
* Like `useQuery`, but also returns a reference to the underlying LiveQuery instance.
|
|
24
|
+
*
|
|
25
|
+
* Usage
|
|
26
|
+
* - Accepts any `Queryable<TResult>`: a `LiveQueryDef`, `SignalDef`, a `LiveQuery` instance
|
|
27
|
+
* or a SQL `QueryBuilder`. Unions of queryables are supported and the result type is
|
|
28
|
+
* inferred via `Queryable.Result<TQueryable>`.
|
|
29
|
+
* - Creates an OpenTelemetry span per unique query, reusing it while the ref-counted
|
|
30
|
+
* resource is alive. The span name is updated once the dynamic label is known.
|
|
31
|
+
* - Manages a reference-counted resource under-the-hood so query instances are shared
|
|
32
|
+
* across re-renders and properly disposed once no longer referenced.
|
|
33
|
+
*
|
|
34
|
+
* Parameters
|
|
35
|
+
* - `queryable`: The query definition/instance/builder to run and subscribe to.
|
|
36
|
+
* - `options.store`: Optional store to use; by default the store from `LiveStoreContext` is used.
|
|
37
|
+
* - `options.otelContext`: Optional parent otel context for the query span.
|
|
38
|
+
* - `options.otelSpanName`: Optional explicit span name; otherwise derived from the query label.
|
|
39
|
+
*
|
|
40
|
+
* Returns
|
|
41
|
+
* - `valueRef`: A React ref whose `current` holds the latest query result. The type is
|
|
42
|
+
* `Queryable.Result<TQueryable>` with full inference for unions.
|
|
43
|
+
* - `queryRcRef`: The underlying reference-counted `LiveQuery` instance used by the store.
|
|
22
44
|
*/
|
|
23
|
-
export const useQueryRef = (
|
|
24
|
-
const store = options?.store ??
|
|
25
|
-
// biome-ignore lint/correctness/useHookAtTopLevel: store is stable
|
|
45
|
+
export const useQueryRef = (queryable, options) => {
|
|
46
|
+
const store = options?.store ?? // biome-ignore lint/correctness/useHookAtTopLevel: store is stable
|
|
26
47
|
React.useContext(LiveStoreContext)?.store ??
|
|
27
48
|
shouldNeverHappen(`No store provided to useQuery`);
|
|
49
|
+
const normalized = React.useMemo(() => {
|
|
50
|
+
if (!isQueryable(queryable)) {
|
|
51
|
+
return shouldNeverHappen('useQuery expected a Queryable value');
|
|
52
|
+
}
|
|
53
|
+
if (isQueryBuilder(queryable)) {
|
|
54
|
+
return { _tag: 'definition', def: queryDb(queryable) };
|
|
55
|
+
}
|
|
56
|
+
if (queryable._tag === 'def' ||
|
|
57
|
+
queryable._tag === 'signal-def') {
|
|
58
|
+
return { _tag: 'definition', def: queryable };
|
|
59
|
+
}
|
|
60
|
+
return { _tag: 'live-query', query$: queryable };
|
|
61
|
+
}, [queryable]);
|
|
28
62
|
// It's important to use all "aspects" of a store instance here, otherwise we get unexpected cache mappings
|
|
29
|
-
const rcRefKey =
|
|
63
|
+
const rcRefKey = React.useMemo(() => {
|
|
64
|
+
const base = `${store.storeId}_${store.clientId}_${store.sessionId}`;
|
|
65
|
+
if (normalized._tag === 'definition') {
|
|
66
|
+
return `${base}:def:${normalized.def.hash}`;
|
|
67
|
+
}
|
|
68
|
+
return `${base}:instance:${normalized.query$.id}`;
|
|
69
|
+
}, [normalized, store.clientId, store.sessionId, store.storeId]);
|
|
70
|
+
const resourceLabel = normalized._tag === 'definition' ? normalized.def.label : normalized.query$.label;
|
|
30
71
|
const stackInfo = React.useMemo(() => {
|
|
31
72
|
Error.stackTraceLimit = 10;
|
|
32
73
|
const stack = new Error().stack;
|
|
@@ -34,10 +75,15 @@ export const useQueryRef = (queryDef, options) => {
|
|
|
34
75
|
return extractStackInfoFromStackTrace(stack);
|
|
35
76
|
}, []);
|
|
36
77
|
const { queryRcRef, span, otelContext } = useRcResource(rcRefKey, () => {
|
|
37
|
-
const
|
|
38
|
-
const span = store.otel.tracer.startSpan(options?.otelSpanName ?? `LiveStore:useQuery:${queryDefLabel}`, { attributes: { label: queryDefLabel, firstStackInfo: JSON.stringify(stackInfo) } }, options?.otelContext ?? store.otel.queriesSpanContext);
|
|
78
|
+
const span = store[StoreInternalsSymbol].otel.tracer.startSpan(options?.otelSpanName ?? `LiveStore:useQuery:${resourceLabel}`, { attributes: { label: resourceLabel, firstStackInfo: JSON.stringify(stackInfo) } }, options?.otelContext ?? store[StoreInternalsSymbol].otel.queriesSpanContext);
|
|
39
79
|
const otelContext = otel.trace.setSpan(otel.context.active(), span);
|
|
40
|
-
const queryRcRef =
|
|
80
|
+
const queryRcRef = normalized._tag === 'definition'
|
|
81
|
+
? normalized.def.make(store[StoreInternalsSymbol].reactivityGraph.context, otelContext)
|
|
82
|
+
: {
|
|
83
|
+
value: normalized.query$,
|
|
84
|
+
deref: () => { },
|
|
85
|
+
rc: Number.POSITIVE_INFINITY,
|
|
86
|
+
};
|
|
41
87
|
return { queryRcRef, span, otelContext };
|
|
42
88
|
},
|
|
43
89
|
// We need to keep the queryRcRef alive a bit longer, so we have a second `useRcResource` below
|
|
@@ -87,15 +133,14 @@ Stack trace:
|
|
|
87
133
|
// Dynamic queries only set their actual label after they've been run the first time,
|
|
88
134
|
// so we're also updating the span name here.
|
|
89
135
|
span.updateName(options?.otelSpanName ?? `LiveStore:useQuery:${query$.label}`);
|
|
90
|
-
return store.subscribe(query$, {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
},
|
|
136
|
+
return store.subscribe(query$, (newValue) => {
|
|
137
|
+
// NOTE: we return a reference to the result object within LiveStore;
|
|
138
|
+
// this implies that app code must not mutate the results, or else
|
|
139
|
+
// there may be weird reactivity bugs.
|
|
140
|
+
if (deepEqual(newValue, valueRef.current) === false) {
|
|
141
|
+
setValue(newValue);
|
|
142
|
+
}
|
|
143
|
+
}, {
|
|
99
144
|
onUnsubsubscribe: () => {
|
|
100
145
|
query$.activeSubscriptions.delete(stackInfo);
|
|
101
146
|
},
|
package/dist/useQuery.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useQuery.js","sourceRoot":"","sources":["../src/useQuery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useQuery.js","sourceRoot":"","sources":["../src/useQuery.ts"],"names":[],"mappings":"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"}
|
package/dist/useQuery.test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/** biome-ignore-all lint/a11y: test */
|
|
3
3
|
import * as LiveStore from '@livestore/livestore';
|
|
4
|
-
import { queryDb, signal } from '@livestore/livestore';
|
|
4
|
+
import { queryDb, StoreInternalsSymbol, signal } from '@livestore/livestore';
|
|
5
5
|
import { RG } from '@livestore/livestore/internal/testing-utils';
|
|
6
6
|
import { Effect, Schema } from '@livestore/utils/effect';
|
|
7
7
|
import { Vitest } from '@livestore/utils-dev/node-vitest';
|
|
@@ -10,8 +10,8 @@ import React from 'react';
|
|
|
10
10
|
// @ts-expect-error no types
|
|
11
11
|
import * as ReactWindow from 'react-window';
|
|
12
12
|
import { expect } from 'vitest';
|
|
13
|
-
import { events, makeTodoMvcReact, tables } from
|
|
14
|
-
import { __resetUseRcResourceCache } from
|
|
13
|
+
import { events, makeTodoMvcReact, tables } from "./__tests__/fixture.js";
|
|
14
|
+
import { __resetUseRcResourceCache } from "./useRcResource.js";
|
|
15
15
|
Vitest.describe.each([{ strictMode: true }, { strictMode: false }])('useQuery (strictMode=%s)', ({ strictMode }) => {
|
|
16
16
|
Vitest.afterEach(() => {
|
|
17
17
|
RG.__resetIds();
|
|
@@ -26,12 +26,12 @@ Vitest.describe.each([{ strictMode: true }, { strictMode: false }])('useQuery (s
|
|
|
26
26
|
}, { wrapper });
|
|
27
27
|
expect(result.current.length).toBe(0);
|
|
28
28
|
expect(renderCount.val).toBe(1);
|
|
29
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
29
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
30
30
|
ReactTesting.act(() => store.commit(events.todoCreated({ id: 't1', text: 'buy milk', completed: false })));
|
|
31
31
|
expect(result.current.length).toBe(1);
|
|
32
32
|
expect(result.current[0].text).toBe('buy milk');
|
|
33
33
|
expect(renderCount.val).toBe(2);
|
|
34
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
34
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
35
35
|
}));
|
|
36
36
|
Vitest.scopedLive('same `useQuery` hook invoked with different queries', () => Effect.gen(function* () {
|
|
37
37
|
const { wrapper, store, renderCount } = yield* makeTodoMvcReact({ strictMode });
|
|
@@ -45,15 +45,15 @@ Vitest.describe.each([{ strictMode: true }, { strictMode: false }])('useQuery (s
|
|
|
45
45
|
}, { wrapper, initialProps: 't1' });
|
|
46
46
|
expect(result.current).toBe('buy milk');
|
|
47
47
|
expect(renderCount.val).toBe(1);
|
|
48
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot('1: after first render');
|
|
48
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot('1: after first render');
|
|
49
49
|
ReactTesting.act(() => store.commit(events.todoUpdated({ id: 't1', text: 'buy soy milk' })));
|
|
50
50
|
expect(result.current).toBe('buy soy milk');
|
|
51
51
|
expect(renderCount.val).toBe(2);
|
|
52
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot('2: after first commit');
|
|
52
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot('2: after first commit');
|
|
53
53
|
rerender('t2');
|
|
54
54
|
expect(result.current).toBe('buy eggs');
|
|
55
55
|
expect(renderCount.val).toBe(3);
|
|
56
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot('3: after forced rerender');
|
|
56
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot('3: after forced rerender');
|
|
57
57
|
}));
|
|
58
58
|
Vitest.scopedLive('filtered dependency query', () => Effect.gen(function* () {
|
|
59
59
|
const { wrapper, store, renderCount } = yield* makeTodoMvcReact({ strictMode });
|
|
@@ -66,15 +66,15 @@ Vitest.describe.each([{ strictMode: true }, { strictMode: false }])('useQuery (s
|
|
|
66
66
|
}, { wrapper });
|
|
67
67
|
expect(result.current).toBe('buy milk');
|
|
68
68
|
expect(renderCount.val).toBe(1);
|
|
69
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
69
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
70
70
|
ReactTesting.act(() => store.commit(events.todoUpdated({ id: 't1', text: 'buy soy milk' })));
|
|
71
71
|
expect(result.current).toBe('buy soy milk');
|
|
72
72
|
expect(renderCount.val).toBe(2);
|
|
73
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
73
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
74
74
|
ReactTesting.act(() => store.setSignal(filter$, 't2'));
|
|
75
75
|
expect(result.current).toBe('buy eggs');
|
|
76
76
|
expect(renderCount.val).toBe(3);
|
|
77
|
-
expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
77
|
+
expect(store[StoreInternalsSymbol].reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
|
|
78
78
|
}));
|
|
79
79
|
// NOTE this test covers some special react lifecyle paths which I couldn't easily reproduce without react-window
|
|
80
80
|
// it basically causes a "query swap" in the `useMemo` and both a `useEffect` cleanup call.
|
|
@@ -102,5 +102,29 @@ Vitest.describe.each([{ strictMode: true }, { strictMode: false }])('useQuery (s
|
|
|
102
102
|
ReactTesting.act(() => store.setSignal(num$, 1));
|
|
103
103
|
expect(result.current).toBe(1);
|
|
104
104
|
}));
|
|
105
|
+
Vitest.scopedLive('supports query builders directly', () => Effect.gen(function* () {
|
|
106
|
+
const { wrapper, store } = yield* makeTodoMvcReact({ strictMode });
|
|
107
|
+
store.commit(events.todoCreated({ id: 't1', text: 'buy milk', completed: false }), events.todoCreated({ id: 't2', text: 'buy eggs', completed: true }));
|
|
108
|
+
const todosWhereIncomplete = tables.todos.where({ completed: false });
|
|
109
|
+
const { result } = ReactTesting.renderHook(() => store.useQuery(todosWhereIncomplete).map((todo) => todo.id), {
|
|
110
|
+
wrapper,
|
|
111
|
+
});
|
|
112
|
+
expect(result.current).toEqual(['t1']);
|
|
113
|
+
}));
|
|
114
|
+
Vitest.scopedLive('union of different result types with useQuery', () => Effect.gen(function* () {
|
|
115
|
+
const { wrapper, store, renderCount } = yield* makeTodoMvcReact({ strictMode });
|
|
116
|
+
const str$ = signal('hello', { label: 'str' });
|
|
117
|
+
const num$ = signal(123, { label: 'num' });
|
|
118
|
+
const { result, rerender } = ReactTesting.renderHook((useNum) => {
|
|
119
|
+
renderCount.inc();
|
|
120
|
+
const query$ = React.useMemo(() => (useNum ? num$ : str$), [useNum]);
|
|
121
|
+
return store.useQuery(query$);
|
|
122
|
+
}, { wrapper, initialProps: false });
|
|
123
|
+
expect(result.current).toBe('hello');
|
|
124
|
+
expect(renderCount.val).toBe(1);
|
|
125
|
+
rerender(true);
|
|
126
|
+
expect(result.current).toBe(123);
|
|
127
|
+
expect(renderCount.val).toBe(2);
|
|
128
|
+
}));
|
|
105
129
|
});
|
|
106
130
|
//# sourceMappingURL=useQuery.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useQuery.test.js","sourceRoot":"","sources":["../src/useQuery.test.tsx"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"useQuery.test.js","sourceRoot":"","sources":["../src/useQuery.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as ReactTesting from '@testing-library/react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
-
import { __resetUseRcResourceCache, useRcResource } from
|
|
4
|
+
import { __resetUseRcResourceCache, useRcResource } from "./useRcResource.js";
|
|
5
5
|
describe.each([{ strictMode: true }, { strictMode: false }])('useRcResource (strictMode=%s)', ({ strictMode }) => {
|
|
6
6
|
beforeEach(() => {
|
|
7
7
|
__resetUseRcResourceCache();
|
package/dist/useStore.d.ts
CHANGED
|
@@ -1,6 +1,58 @@
|
|
|
1
|
+
import type { LiveStoreSchema } from '@livestore/common/schema';
|
|
1
2
|
import type { Store } from '@livestore/livestore';
|
|
2
3
|
import type { ReactApi } from './LiveStoreContext.ts';
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Augments a Store instance with React-specific methods (`useQuery`, `useClientDocument`).
|
|
6
|
+
*
|
|
7
|
+
* This is called automatically by `useStore()` and `LiveStoreProvider`. You typically
|
|
8
|
+
* don't need to call it directly unless you're building custom integrations.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* // Usually not needed—useStore() does this automatically
|
|
13
|
+
* const store = withReactApi(myStore)
|
|
14
|
+
* const todos = store.useQuery(tables.todos.all())
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const withReactApi: <TSchema extends LiveStoreSchema>(store: Store<TSchema>) => Store<TSchema> & ReactApi;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the current Store instance from React context, augmented with React-specific methods.
|
|
20
|
+
*
|
|
21
|
+
* Use this hook when you need direct access to the Store for operations like
|
|
22
|
+
* `store.commit()`, `store.subscribe()`, or accessing `store.sessionId`.
|
|
23
|
+
*
|
|
24
|
+
* For reactive queries, prefer `useQuery()` or `useClientDocument()` which handle
|
|
25
|
+
* subscriptions and re-renders automatically.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const MyComponent = () => {
|
|
30
|
+
* const { store } = useStore()
|
|
31
|
+
*
|
|
32
|
+
* const handleClick = () => {
|
|
33
|
+
* store.commit(events.todoCreated({ id: nanoid(), text: 'New todo' }))
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* return <button onClick={handleClick}>Add Todo</button>
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* // Access store metadata
|
|
43
|
+
* const { store } = useStore()
|
|
44
|
+
* console.log('Session ID:', store.sessionId)
|
|
45
|
+
* console.log('Client ID:', store.clientId)
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* // Use with an explicit store instance (bypasses context)
|
|
51
|
+
* const { store } = useStore({ store: myExternalStore })
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @throws Error if called outside of `<LiveStoreProvider>` or before the store is running
|
|
55
|
+
*/
|
|
4
56
|
export declare const useStore: (options?: {
|
|
5
57
|
store?: Store;
|
|
6
58
|
}) => {
|
package/dist/useStore.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStore.d.ts","sourceRoot":"","sources":["../src/useStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAGjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAKrD,eAAO,MAAM,YAAY,GAAI,OAAO,KAAK,KAAG,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"useStore.d.ts","sourceRoot":"","sources":["../src/useStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAGjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAKrD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,SAAS,eAAe,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAG,KAAK,CAAC,OAAO,CAAC,GAAG,QAQtG,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAU;IAAE,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,KAAG;IAAE,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAA;CAiB/E,CAAA"}
|
package/dist/useStore.js
CHANGED
|
@@ -2,13 +2,64 @@ import React from 'react';
|
|
|
2
2
|
import { LiveStoreContext } from "./LiveStoreContext.js";
|
|
3
3
|
import { useClientDocument } from "./useClientDocument.js";
|
|
4
4
|
import { useQuery } from "./useQuery.js";
|
|
5
|
+
/**
|
|
6
|
+
* Augments a Store instance with React-specific methods (`useQuery`, `useClientDocument`).
|
|
7
|
+
*
|
|
8
|
+
* This is called automatically by `useStore()` and `LiveStoreProvider`. You typically
|
|
9
|
+
* don't need to call it directly unless you're building custom integrations.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* // Usually not needed—useStore() does this automatically
|
|
14
|
+
* const store = withReactApi(myStore)
|
|
15
|
+
* const todos = store.useQuery(tables.todos.all())
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
5
18
|
export const withReactApi = (store) => {
|
|
6
19
|
// @ts-expect-error TODO properly implement this
|
|
7
|
-
store.useQuery = (
|
|
20
|
+
store.useQuery = (queryable) => useQuery(queryable, { store });
|
|
8
21
|
// @ts-expect-error TODO properly implement this
|
|
9
22
|
store.useClientDocument = (table, idOrOptions, options) => useClientDocument(table, idOrOptions, options, { store });
|
|
10
23
|
return store;
|
|
11
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* Returns the current Store instance from React context, augmented with React-specific methods.
|
|
27
|
+
*
|
|
28
|
+
* Use this hook when you need direct access to the Store for operations like
|
|
29
|
+
* `store.commit()`, `store.subscribe()`, or accessing `store.sessionId`.
|
|
30
|
+
*
|
|
31
|
+
* For reactive queries, prefer `useQuery()` or `useClientDocument()` which handle
|
|
32
|
+
* subscriptions and re-renders automatically.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const MyComponent = () => {
|
|
37
|
+
* const { store } = useStore()
|
|
38
|
+
*
|
|
39
|
+
* const handleClick = () => {
|
|
40
|
+
* store.commit(events.todoCreated({ id: nanoid(), text: 'New todo' }))
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* return <button onClick={handleClick}>Add Todo</button>
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* // Access store metadata
|
|
50
|
+
* const { store } = useStore()
|
|
51
|
+
* console.log('Session ID:', store.sessionId)
|
|
52
|
+
* console.log('Client ID:', store.clientId)
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* // Use with an explicit store instance (bypasses context)
|
|
58
|
+
* const { store } = useStore({ store: myExternalStore })
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @throws Error if called outside of `<LiveStoreProvider>` or before the store is running
|
|
62
|
+
*/
|
|
12
63
|
export const useStore = (options) => {
|
|
13
64
|
if (options?.store !== undefined) {
|
|
14
65
|
return { store: withReactApi(options.store) };
|
package/dist/useStore.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStore.js","sourceRoot":"","sources":["../src/useStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useStore.js","sourceRoot":"","sources":["../src/useStore.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAkC,KAAqB,EAA6B,EAAE;IAChH,gDAAgD;IAEhD,KAAK,CAAC,QAAQ,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAC9D,gDAAgD;IAEhD,KAAK,CAAC,iBAAiB,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IACpH,OAAO,KAAkC,CAAA;AAC3C,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAA2B,EAA+B,EAAE;IACnF,IAAI,OAAO,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAA;IAC/C,CAAC;IAED,mEAAmE;IACnE,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAA;IAEvD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAC3E,CAAC;IAED,IAAI,YAAY,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;IACzE,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAA;AACpD,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/react",
|
|
3
|
-
"version": "0.4.0-dev.
|
|
3
|
+
"version": "0.4.0-dev.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -9,25 +9,25 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@opentelemetry/api": "1.9.0",
|
|
12
|
-
"@livestore/common": "0.4.0-dev.
|
|
13
|
-
"@livestore/utils": "0.4.0-dev.
|
|
14
|
-
"@livestore/livestore": "0.4.0-dev.
|
|
12
|
+
"@livestore/common": "0.4.0-dev.21",
|
|
13
|
+
"@livestore/utils": "0.4.0-dev.21",
|
|
14
|
+
"@livestore/livestore": "0.4.0-dev.21"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@opentelemetry/sdk-trace-base": "
|
|
17
|
+
"@opentelemetry/sdk-trace-base": "2.0.1",
|
|
18
18
|
"@testing-library/dom": "^10.4.1",
|
|
19
19
|
"@testing-library/react": "^16.3.0",
|
|
20
|
-
"@types/react": "
|
|
21
|
-
"@types/react-dom": "
|
|
20
|
+
"@types/react": "19.1.13",
|
|
21
|
+
"@types/react-dom": "19.1.9",
|
|
22
22
|
"jsdom": "^26.1.0",
|
|
23
|
-
"react": "
|
|
24
|
-
"react-dom": "
|
|
23
|
+
"react": "19.1.0",
|
|
24
|
+
"react-dom": "19.1.0",
|
|
25
25
|
"react-window": "^1.8.11",
|
|
26
|
-
"typescript": "
|
|
27
|
-
"vite": "
|
|
26
|
+
"typescript": "5.9.2",
|
|
27
|
+
"vite": "7.2.4",
|
|
28
28
|
"vitest": "3.2.4",
|
|
29
|
-
"@livestore/
|
|
30
|
-
"@livestore/
|
|
29
|
+
"@livestore/adapter-web": "0.4.0-dev.21",
|
|
30
|
+
"@livestore/utils-dev": "0.4.0-dev.21"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"package.json",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
],
|
|
37
37
|
"license": "Apache-2.0",
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"react": "^19.
|
|
39
|
+
"react": "^19.1.0"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
package/src/LiveStoreContext.ts
CHANGED
|
@@ -4,11 +4,38 @@ import React from 'react'
|
|
|
4
4
|
import type { useClientDocument } from './useClientDocument.ts'
|
|
5
5
|
import type { useQuery } from './useQuery.ts'
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* React-specific methods added to the Store when used via React hooks.
|
|
9
|
+
*
|
|
10
|
+
* These methods are attached by `withReactApi()` and `useStore()`, allowing you
|
|
11
|
+
* to call `store.useQuery()` and `store.useClientDocument()` directly on the
|
|
12
|
+
* Store instance.
|
|
13
|
+
*/
|
|
7
14
|
export type ReactApi = {
|
|
15
|
+
/** Hook version of query subscription—re-renders component when query result changes */
|
|
8
16
|
useQuery: typeof useQuery
|
|
17
|
+
/** Hook for reading and writing client-document tables with React state semantics */
|
|
9
18
|
useClientDocument: typeof useClientDocument
|
|
10
19
|
}
|
|
11
20
|
|
|
21
|
+
/**
|
|
22
|
+
* React context for accessing the LiveStore instance.
|
|
23
|
+
*
|
|
24
|
+
* This context is provided by `<LiveStoreProvider>` and consumed by hooks like
|
|
25
|
+
* `useStore()`, `useQuery()`, and `useClientDocument()`.
|
|
26
|
+
*
|
|
27
|
+
* The context value is `undefined` until the Store has finished booting,
|
|
28
|
+
* then transitions to `{ stage: 'running', store: ... }`.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* // Typically you don't use this directly—use useStore() instead
|
|
33
|
+
* const context = React.useContext(LiveStoreContext)
|
|
34
|
+
* if (context?.stage === 'running') {
|
|
35
|
+
* console.log('Store ready:', context.store.storeId)
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
12
39
|
export const LiveStoreContext = React.createContext<
|
|
13
40
|
{ stage: 'running'; store: LiveStoreContextRunning['store'] & ReactApi } | undefined
|
|
14
41
|
>(undefined)
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
/** biome-ignore-all lint/a11y: test */
|
|
1
|
+
/** biome-ignore-all lint/a11y: test files need a11y disabled */
|
|
2
2
|
import { makeInMemoryAdapter } from '@livestore/adapter-web'
|
|
3
|
-
import { queryDb, type Store } from '@livestore/livestore'
|
|
3
|
+
import { queryDb, type Store, StoreInternalsSymbol } from '@livestore/livestore'
|
|
4
4
|
import { Schema } from '@livestore/utils/effect'
|
|
5
5
|
import * as ReactTesting from '@testing-library/react'
|
|
6
6
|
import React from 'react'
|
|
7
7
|
import { unstable_batchedUpdates as batchUpdates } from 'react-dom'
|
|
8
8
|
import { describe, expect, it } from 'vitest'
|
|
9
9
|
|
|
10
|
-
import { events, schema, tables } from './__tests__/fixture.
|
|
11
|
-
import { LiveStoreProvider } from './LiveStoreProvider.
|
|
12
|
-
import * as LiveStoreReact from './mod.
|
|
10
|
+
import { events, schema, tables } from './__tests__/fixture.tsx'
|
|
11
|
+
import { LiveStoreProvider } from './LiveStoreProvider.tsx'
|
|
12
|
+
import * as LiveStoreReact from './mod.ts'
|
|
13
13
|
|
|
14
14
|
describe.each([true, false])('LiveStoreProvider (strictMode: %s)', (strictMode) => {
|
|
15
15
|
const WithStrictMode = strictMode ? React.StrictMode : React.Fragment
|
|
@@ -115,7 +115,7 @@ describe.each([true, false])('LiveStoreProvider (strictMode: %s)', (strictMode)
|
|
|
115
115
|
|
|
116
116
|
expect(appRenderCount).toBe(0)
|
|
117
117
|
|
|
118
|
-
await ReactTesting.waitFor(() => ReactTesting.screen.getByText((_) => _.startsWith('LiveStore.
|
|
118
|
+
await ReactTesting.waitFor(() => ReactTesting.screen.getByText((_) => _.startsWith('LiveStore.UnknownError')))
|
|
119
119
|
})
|
|
120
120
|
|
|
121
121
|
it('unmounts when store is shutdown', async () => {
|
|
@@ -184,7 +184,7 @@ it('should work two stores with the same storeId', async () => {
|
|
|
184
184
|
|
|
185
185
|
const App = () => {
|
|
186
186
|
const { store } = LiveStoreReact.useStore()
|
|
187
|
-
const instanceId = store.clientSession.debugInstanceId as 'store1' | 'store2'
|
|
187
|
+
const instanceId = store[StoreInternalsSymbol].clientSession.debugInstanceId as 'store1' | 'store2'
|
|
188
188
|
appRenderCount[instanceId]!++
|
|
189
189
|
|
|
190
190
|
const todos = store.useQuery(allTodos$)
|