@tanstack/react-db 0.5.11 → 1.0.0-rc.1
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/cjs/live-query-internals.cjs.map +1 -1
- package/dist/cjs/live-query-internals.d.cts +3 -1
- package/dist/cjs/source-id-bindings.cjs +9 -42
- package/dist/cjs/source-id-bindings.cjs.map +1 -1
- package/dist/cjs/source-id-bindings.d.cts +6 -17
- package/dist/cjs/useLiveInfiniteQuery.cjs +93 -173
- package/dist/cjs/useLiveInfiniteQuery.cjs.map +1 -1
- package/dist/cjs/useLiveInfiniteQuery.d.cts +3 -14
- package/dist/cjs/useLiveQuery.cjs +187 -224
- package/dist/cjs/useLiveQuery.cjs.map +1 -1
- package/dist/cjs/useLiveQuery.d.cts +37 -136
- package/dist/cjs/useLiveSuspenseQuery.cjs +71 -64
- package/dist/cjs/useLiveSuspenseQuery.cjs.map +1 -1
- package/dist/cjs/useLiveSuspenseQuery.d.cts +10 -9
- package/dist/cjs/usePacedMutations.cjs.map +1 -1
- package/dist/cjs/usePacedMutations.d.cts +1 -1
- package/dist/esm/live-query-internals.d.ts +3 -1
- package/dist/esm/live-query-internals.js.map +1 -1
- package/dist/esm/source-id-bindings.d.ts +6 -17
- package/dist/esm/source-id-bindings.js +9 -40
- package/dist/esm/source-id-bindings.js.map +1 -1
- package/dist/esm/useLiveInfiniteQuery.d.ts +3 -14
- package/dist/esm/useLiveInfiniteQuery.js +95 -175
- package/dist/esm/useLiveInfiniteQuery.js.map +1 -1
- package/dist/esm/useLiveQuery.d.ts +37 -136
- package/dist/esm/useLiveQuery.js +189 -226
- package/dist/esm/useLiveQuery.js.map +1 -1
- package/dist/esm/useLiveSuspenseQuery.d.ts +10 -9
- package/dist/esm/useLiveSuspenseQuery.js +71 -64
- package/dist/esm/useLiveSuspenseQuery.js.map +1 -1
- package/dist/esm/usePacedMutations.d.ts +1 -1
- package/dist/esm/usePacedMutations.js.map +1 -1
- package/package.json +3 -3
- package/skills/react-db/SKILL.md +24 -15
- package/src/live-query-internals.ts +3 -0
- package/src/source-id-bindings.ts +16 -62
- package/src/useLiveInfiniteQuery.ts +138 -296
- package/src/useLiveQuery.ts +329 -495
- package/src/useLiveSuspenseQuery.ts +122 -132
- package/src/usePacedMutations.ts +1 -1
package/dist/esm/useLiveQuery.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useRef, useSyncExternalStore } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { identifyLiveQuery, prepareLiveQueryValue, isCollection, getLiveQueryKey, getStableValueHash, UnhashableQueryIRError, deepEquals, resolveLiveQueryValue, releaseDeferredOnReclaim, createLiveQueryObserver, rejectLiveQueryInput, createLiveQuerySourceIdClaims, getSourceObjectToken, resumeDeferredLiveQueryCollections } from "@tanstack/db";
|
|
4
4
|
import { useOptionalDbClient } from "./DbProvider.js";
|
|
5
5
|
import { setLiveQueryResultInfo } from "./live-query-internals.js";
|
|
6
6
|
import { shouldWarnInDevelopment } from "./development.js";
|
|
7
|
-
import {
|
|
7
|
+
import { getPreparedSources, getUnboundDescriptorReporter } from "./source-id-bindings.js";
|
|
8
8
|
const DEFAULT_GC_TIME_MS = 1;
|
|
9
9
|
const DEFAULT_SUSPENSE_GC_TIME_MS = 5e3;
|
|
10
10
|
const DERIVED_IDENTITY_SINGLE_RENDER_WARN_MS = 16;
|
|
11
11
|
const DERIVED_IDENTITY_RENDER_COUNT_WARN_THRESHOLD = 10;
|
|
12
12
|
const DERIVED_IDENTITY_TOTAL_WARN_MS = 50;
|
|
13
|
-
const warnedDepsCallsites = /* @__PURE__ */ new Set();
|
|
14
13
|
const warnedDerivedIdentityCallsites = /* @__PURE__ */ new Set();
|
|
15
|
-
const warnedUnhashableIdentityCallsites = /* @__PURE__ */ new Set();
|
|
16
14
|
const unpreparedQueryValue = /* @__PURE__ */ Symbol(`unpreparedQueryValue`);
|
|
17
15
|
const unscopedSuspenseCollections = /* @__PURE__ */ new Map();
|
|
18
16
|
const suspenseCollectionsByClient = /* @__PURE__ */ new WeakMap();
|
|
@@ -40,20 +38,6 @@ function releaseSuspenseCollection(collections, queryHash, collection) {
|
|
|
40
38
|
collections.delete(queryHash);
|
|
41
39
|
entry.removeStatusListeners();
|
|
42
40
|
}
|
|
43
|
-
function warnDeprecatedDepsArray(hookName = `useLiveQuery`) {
|
|
44
|
-
if (!shouldWarnInDevelopment(`TANSTACK_DB_DISABLE_DEPRECATION_WARNINGS`)) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
const callsite = getWarningCallsite(4);
|
|
48
|
-
if (warnedDepsCallsites.has(callsite)) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
warnedDepsCallsites.add(callsite);
|
|
52
|
-
const replacement = hookName === `useLiveQuery` ? `useLiveQuery({ query })` : `useLiveInfiniteQuery(query, { queryKey })`;
|
|
53
|
-
console.warn(
|
|
54
|
-
`[${hookName}] The dependency-array form is deprecated and will be removed in 1.0. Use ${replacement} instead. Provide queryKey only for functional/opaque queries or to avoid deriving identity from structured query IR on render.`
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
41
|
function getCurrentTime() {
|
|
58
42
|
return typeof performance !== `undefined` && typeof performance.now === `function` ? performance.now() : Date.now();
|
|
59
43
|
}
|
|
@@ -67,7 +51,7 @@ function getWarningCallsite(stackIndex) {
|
|
|
67
51
|
return userFrame?.trim() ?? lines[stackIndex]?.trim() ?? stack;
|
|
68
52
|
}
|
|
69
53
|
function warnDerivedIdentityHotPath(profiler, durationMs) {
|
|
70
|
-
if (profiler.warned || !shouldWarnInDevelopment(`TANSTACK_DB_DISABLE_QUERY_IDENTITY_WARNINGS`)) {
|
|
54
|
+
if (profiler.warned || !(shouldWarnInDevelopment(`TANSTACK_DB_DISABLE_QUERY_IDENTITY_WARNINGS`) && process.env.NODE_ENV !== `production`)) {
|
|
71
55
|
return;
|
|
72
56
|
}
|
|
73
57
|
const isSlowSingleRender = durationMs >= DERIVED_IDENTITY_SINGLE_RENDER_WARN_MS;
|
|
@@ -87,33 +71,33 @@ function warnDerivedIdentityHotPath(profiler, durationMs) {
|
|
|
87
71
|
`[useLiveQuery] Deriving live query identity from structured query IR is running on a hot render path (${reason}, max ${profiler.maxMs.toFixed(1)}ms). Provide an explicit queryKey to skip rebuilding and hashing the IR on every render: useLiveQuery({ queryKey: [...], query }).`
|
|
88
72
|
);
|
|
89
73
|
}
|
|
90
|
-
function getExplicitQueryKey(value) {
|
|
91
|
-
return value && typeof value === `object` && Array.isArray(value.queryKey) ? value.queryKey : void 0;
|
|
92
|
-
}
|
|
93
74
|
function getExplicitDbClient(value) {
|
|
94
75
|
return value && typeof value === `object` && `client` in value && value.client !== void 0 ? value.client : void 0;
|
|
95
76
|
}
|
|
96
77
|
function prepareQueryValue(value, dbClient, deferredCollections) {
|
|
97
78
|
return prepareLiveQueryValue(value, dbClient, deferredCollections);
|
|
98
79
|
}
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
80
|
+
function getIdentityScope(claims, dbClient, hookName) {
|
|
81
|
+
return {
|
|
82
|
+
claims,
|
|
83
|
+
client: dbClient,
|
|
84
|
+
bindingName: hookName,
|
|
85
|
+
onUnboundDescriptor: getUnboundDescriptorReporter(dbClient, hookName)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function prepareDerivedQuery(value, profiler, scope, deferredCollections) {
|
|
89
|
+
const shouldProfile = shouldWarnInDevelopment(`TANSTACK_DB_DISABLE_QUERY_IDENTITY_WARNINGS`) && process.env.NODE_ENV !== `production`;
|
|
103
90
|
const start = shouldProfile ? getCurrentTime() : 0;
|
|
104
|
-
const preparedValue = prepareQueryValue(
|
|
91
|
+
const preparedValue = prepareQueryValue(
|
|
92
|
+
value,
|
|
93
|
+
scope.client,
|
|
94
|
+
deferredCollections
|
|
95
|
+
);
|
|
105
96
|
try {
|
|
106
|
-
const identity = getPreparedLiveQueryIdentity(preparedValue);
|
|
107
97
|
return {
|
|
108
|
-
status: `hashable`,
|
|
109
98
|
value: preparedValue,
|
|
110
|
-
identityDeps: [`derived`,
|
|
99
|
+
identityDeps: [`derived`, identifyLiveQuery(preparedValue, scope)]
|
|
111
100
|
};
|
|
112
|
-
} catch (error) {
|
|
113
|
-
if (error instanceof UnhashableQueryIRError) {
|
|
114
|
-
return { status: `unhashable`, value: preparedValue, error };
|
|
115
|
-
}
|
|
116
|
-
throw error;
|
|
117
101
|
} finally {
|
|
118
102
|
if (shouldProfile) {
|
|
119
103
|
const durationMs = getCurrentTime() - start;
|
|
@@ -124,32 +108,18 @@ function prepareDerivedQuery(value, dbClient, profiler, deferredCollections) {
|
|
|
124
108
|
}
|
|
125
109
|
}
|
|
126
110
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const callsite = getWarningCallsite(4);
|
|
132
|
-
if (warnedUnhashableIdentityCallsites.has(callsite)) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
warnedUnhashableIdentityCallsites.add(callsite);
|
|
136
|
-
console.warn(
|
|
137
|
-
`[useLiveQuery] This query cannot derive a stable identity because ${error.reason} at ${error.path}. It will keep the legacy mount-stable behavior for now. Add queryKey: [...] to make captured values reactive. Unhashable queries without queryKey will throw in 1.0.`
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
function useLiveQuery(configOrQueryOrCollection, deps) {
|
|
141
|
-
return useLiveQueryImpl(configOrQueryOrCollection, deps);
|
|
111
|
+
function useLiveQuery(configOrQueryOrCollection) {
|
|
112
|
+
return useLiveQueryImpl(configOrQueryOrCollection);
|
|
142
113
|
}
|
|
143
|
-
function useLiveQueryForSuspense(configOrQueryOrCollection
|
|
144
|
-
return useLiveQueryImpl(configOrQueryOrCollection,
|
|
114
|
+
function useLiveQueryForSuspense(configOrQueryOrCollection) {
|
|
115
|
+
return useLiveQueryImpl(configOrQueryOrCollection, true);
|
|
145
116
|
}
|
|
146
117
|
function createHookInstance(dbClient) {
|
|
147
118
|
return {
|
|
148
119
|
collection: null,
|
|
149
|
-
|
|
120
|
+
identityDeps: null,
|
|
150
121
|
config: null,
|
|
151
122
|
client: dbClient,
|
|
152
|
-
legacyUnhashableIdentity: [`legacy-unhashable`],
|
|
153
123
|
derivedIdentityProfiler: {
|
|
154
124
|
renderCount: 0,
|
|
155
125
|
totalMs: 0,
|
|
@@ -157,7 +127,8 @@ function createHookInstance(dbClient) {
|
|
|
157
127
|
warned: false
|
|
158
128
|
},
|
|
159
129
|
deferredCollections: /* @__PURE__ */ new Set(),
|
|
160
|
-
sourceIds:
|
|
130
|
+
sourceIds: createLiveQuerySourceIdClaims(),
|
|
131
|
+
cancelReclaimRelease: void 0,
|
|
161
132
|
observer: null,
|
|
162
133
|
queryHash: void 0,
|
|
163
134
|
suspenseKey: void 0,
|
|
@@ -165,119 +136,89 @@ function createHookInstance(dbClient) {
|
|
|
165
136
|
subscribe: null
|
|
166
137
|
};
|
|
167
138
|
}
|
|
168
|
-
function useLiveQueryImpl(configOrQueryOrCollection,
|
|
139
|
+
function useLiveQueryImpl(configOrQueryOrCollection, forSuspense = false) {
|
|
169
140
|
const contextDbClient = useOptionalDbClient();
|
|
170
141
|
const inputIsCollection = isCollection(configOrQueryOrCollection);
|
|
171
142
|
const dbClient = inputIsCollection ? contextDbClient : getExplicitDbClient(configOrQueryOrCollection) ?? contextDbClient;
|
|
172
|
-
const resolvedDeps = deps ?? [];
|
|
173
143
|
const instanceRef = useRef(null);
|
|
174
144
|
const instance = instanceRef.current ??= createHookInstance(dbClient);
|
|
175
|
-
const resumeDeferredCollections = () =>
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
warnUnhashableDerivedIdentity(error);
|
|
201
|
-
identityError = error;
|
|
202
|
-
}
|
|
203
|
-
} else if (inputIsCollection) {
|
|
204
|
-
identityDeps = [];
|
|
205
|
-
streamIdentity = [`collection`, configOrQueryOrCollection.id];
|
|
206
|
-
} else {
|
|
207
|
-
const preparation = prepareDerivedQuery(
|
|
208
|
-
configOrQueryOrCollection,
|
|
209
|
-
dbClient,
|
|
210
|
-
instance.derivedIdentityProfiler,
|
|
211
|
-
instance.deferredCollections
|
|
212
|
-
);
|
|
213
|
-
preparedQueryValue = preparation.value;
|
|
214
|
-
if (preparation.status === `hashable`) {
|
|
145
|
+
const resumeDeferredCollections = () => {
|
|
146
|
+
instance.cancelReclaimRelease?.();
|
|
147
|
+
instance.cancelReclaimRelease = void 0;
|
|
148
|
+
resumeDeferredLiveQueryCollections(instance.deferredCollections);
|
|
149
|
+
};
|
|
150
|
+
try {
|
|
151
|
+
const queryKey = !inputIsCollection ? getLiveQueryKey(configOrQueryOrCollection) : void 0;
|
|
152
|
+
let preparedQueryValue = unpreparedQueryValue;
|
|
153
|
+
let identityDeps;
|
|
154
|
+
let streamIdentity = void 0;
|
|
155
|
+
let identityError;
|
|
156
|
+
if (queryKey) {
|
|
157
|
+
identityDeps = queryKey;
|
|
158
|
+
streamIdentity = [`queryKey`, queryKey];
|
|
159
|
+
} else if (inputIsCollection) {
|
|
160
|
+
identityDeps = [];
|
|
161
|
+
streamIdentity = [`collection`, configOrQueryOrCollection.id];
|
|
162
|
+
} else {
|
|
163
|
+
const preparation = prepareDerivedQuery(
|
|
164
|
+
configOrQueryOrCollection,
|
|
165
|
+
instance.derivedIdentityProfiler,
|
|
166
|
+
getIdentityScope(instance.sourceIds, dbClient, `useLiveQuery`),
|
|
167
|
+
instance.deferredCollections
|
|
168
|
+
);
|
|
169
|
+
preparedQueryValue = preparation.value;
|
|
215
170
|
identityDeps = preparation.identityDeps;
|
|
216
171
|
streamIdentity = preparation.identityDeps;
|
|
217
|
-
} else {
|
|
218
|
-
warnUnhashableDerivedIdentity(preparation.error);
|
|
219
|
-
identityDeps = instance.legacyUnhashableIdentity;
|
|
220
|
-
identityError = preparation.error;
|
|
221
172
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
173
|
+
let queryHash;
|
|
174
|
+
if (streamIdentity !== void 0) {
|
|
175
|
+
try {
|
|
176
|
+
queryHash = getStableValueHash(streamIdentity, `queryKey`);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (error instanceof UnhashableQueryIRError) {
|
|
179
|
+
if (queryKey !== void 0) throw error;
|
|
180
|
+
identityError = error;
|
|
181
|
+
} else {
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
233
184
|
}
|
|
234
185
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
186
|
+
const canReuseSuspenseKey = forSuspense && !inputIsCollection && queryHash !== void 0 && instance.collection !== null && instance.client === dbClient && instance.queryHash === queryHash && instance.suspenseKey !== void 0;
|
|
187
|
+
if (forSuspense && !inputIsCollection && queryHash && !canReuseSuspenseKey && preparedQueryValue === unpreparedQueryValue) {
|
|
188
|
+
preparedQueryValue = prepareQueryValue(
|
|
189
|
+
configOrQueryOrCollection,
|
|
190
|
+
dbClient,
|
|
191
|
+
instance.deferredCollections
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
const suspenseKey = queryHash && forSuspense && !inputIsCollection ? canReuseSuspenseKey ? instance.suspenseKey : getSourceQualifiedSuspenseKey(
|
|
242
195
|
preparedQueryValue,
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const suspenseCollection = suspenseEntry?.collection;
|
|
260
|
-
const identityChanged = instance.deps === null || (deps !== void 0 ? instance.deps.length !== identityDeps.length || instance.deps.some((dep, index) => dep !== identityDeps[index]) : !deepEquals(instance.deps, identityDeps));
|
|
261
|
-
const needsNewCollection = !instance.collection || inputIsCollection && instance.config !== configOrQueryOrCollection || !inputIsCollection && (instance.client !== dbClient || identityChanged);
|
|
262
|
-
if (needsNewCollection) {
|
|
263
|
-
if (inputIsCollection) {
|
|
264
|
-
const syncMode = configOrQueryOrCollection.config?.syncMode;
|
|
265
|
-
if (syncMode === `on-demand` && shouldWarnInDevelopment(`TANSTACK_DB_DISABLE_QUERY_IDENTITY_WARNINGS`)) {
|
|
266
|
-
console.warn(
|
|
267
|
-
`[useLiveQuery] Warning: Passing a collection with syncMode "on-demand" directly to useLiveQuery will not load any data. In on-demand mode, data is only loaded when queries with predicates request it.
|
|
196
|
+
queryHash,
|
|
197
|
+
dbClient
|
|
198
|
+
) : queryHash;
|
|
199
|
+
const suspenseCollections = forSuspense && !inputIsCollection && suspenseKey ? getSuspenseCollections(dbClient) : void 0;
|
|
200
|
+
const suspenseEntry = suspenseKey ? suspenseCollections?.get(suspenseKey) : void 0;
|
|
201
|
+
const suspenseCollection = suspenseEntry?.collection;
|
|
202
|
+
const identityChanged = instance.identityDeps === null || !deepEquals(instance.identityDeps, identityDeps);
|
|
203
|
+
const needsNewCollection = !instance.collection || inputIsCollection && instance.config !== configOrQueryOrCollection || !inputIsCollection && (instance.client !== dbClient || identityChanged);
|
|
204
|
+
if (needsNewCollection) {
|
|
205
|
+
if (inputIsCollection) {
|
|
206
|
+
const syncMode = configOrQueryOrCollection.config?.syncMode;
|
|
207
|
+
if (syncMode === `on-demand` && shouldWarnInDevelopment(
|
|
208
|
+
`TANSTACK_DB_DISABLE_QUERY_IDENTITY_WARNINGS`
|
|
209
|
+
) && process.env.NODE_ENV !== `production`) {
|
|
210
|
+
console.warn(
|
|
211
|
+
`[useLiveQuery] Warning: Passing a collection with syncMode "on-demand" directly to useLiveQuery will not load any data. In on-demand mode, data is only loaded when queries with predicates request it.
|
|
268
212
|
|
|
269
213
|
Instead, use a query builder function:
|
|
270
214
|
const { data } = useLiveQuery({ query: (q) => q.from({ c: myCollection }).select(({ c }) => c) })
|
|
271
215
|
|
|
272
216
|
Or switch to syncMode "eager" if you want all data to sync automatically.`
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
} else {
|
|
279
|
-
if (suspenseCollection) {
|
|
280
|
-
instance.collection = suspenseCollection;
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
configOrQueryOrCollection.startSyncImmediate();
|
|
220
|
+
instance.collection = configOrQueryOrCollection;
|
|
221
|
+
instance.config = configOrQueryOrCollection;
|
|
281
222
|
} else {
|
|
282
223
|
if (preparedQueryValue === unpreparedQueryValue) {
|
|
283
224
|
preparedQueryValue = prepareQueryValue(
|
|
@@ -286,28 +227,38 @@ Or switch to syncMode "eager" if you want all data to sync automatically.`
|
|
|
286
227
|
instance.deferredCollections
|
|
287
228
|
);
|
|
288
229
|
}
|
|
289
|
-
if (
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
collection
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
230
|
+
if (suspenseCollection) {
|
|
231
|
+
instance.collection = suspenseCollection;
|
|
232
|
+
} else {
|
|
233
|
+
if (!dbClient && queryKey !== void 0) {
|
|
234
|
+
getPreparedSources(preparedQueryValue, dbClient, `useLiveQuery`);
|
|
235
|
+
}
|
|
236
|
+
instance.collection = resolveLiveQueryValue(preparedQueryValue, {
|
|
237
|
+
gcTime: forSuspense ? DEFAULT_SUSPENSE_GC_TIME_MS : DEFAULT_GC_TIME_MS,
|
|
238
|
+
// Hydration and Suspense key the live-query Collection by identity,
|
|
239
|
+
// so they never pool, even when the config passes a pool.
|
|
240
|
+
pool: forSuspense || dbClient ? false : void 0,
|
|
241
|
+
// Without a DbClient, Suspense starts it through a preload below.
|
|
242
|
+
startSync: !forSuspense || dbClient !== void 0
|
|
243
|
+
});
|
|
244
|
+
if (instance.collection && !isCollection(preparedQueryValue)) {
|
|
245
|
+
instance.cancelReclaimRelease?.();
|
|
246
|
+
instance.cancelReclaimRelease = releaseDeferredOnReclaim(
|
|
247
|
+
instance.collection,
|
|
248
|
+
instance.deferredCollections
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
if (suspenseCollections && suspenseKey && instance.collection) {
|
|
252
|
+
const collection = instance.collection;
|
|
253
|
+
const removeCleanupListener = collection.on(
|
|
254
|
+
`status:cleaned-up`,
|
|
255
|
+
() => releaseSuspenseCollection(
|
|
256
|
+
suspenseCollections,
|
|
257
|
+
suspenseKey,
|
|
258
|
+
collection
|
|
259
|
+
)
|
|
260
|
+
);
|
|
261
|
+
const retireAfterRetry = () => setTimeout(
|
|
311
262
|
() => releaseSuspenseCollection(
|
|
312
263
|
suspenseCollections,
|
|
313
264
|
suspenseKey,
|
|
@@ -315,66 +266,78 @@ Or switch to syncMode "eager" if you want all data to sync automatically.`
|
|
|
315
266
|
),
|
|
316
267
|
0
|
|
317
268
|
);
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
269
|
+
const removeErrorListener = collection.on(
|
|
270
|
+
`status:error`,
|
|
271
|
+
retireAfterRetry
|
|
272
|
+
);
|
|
273
|
+
const removeCrashListener = collection.on(
|
|
274
|
+
`status:crashed`,
|
|
275
|
+
retireAfterRetry
|
|
276
|
+
);
|
|
277
|
+
const entry = {
|
|
278
|
+
collection,
|
|
279
|
+
removeStatusListeners: () => {
|
|
280
|
+
removeCleanupListener();
|
|
281
|
+
removeErrorListener();
|
|
282
|
+
removeCrashListener();
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
suspenseCollections.set(suspenseKey, entry);
|
|
286
|
+
}
|
|
327
287
|
}
|
|
288
|
+
instance.config = configOrQueryOrCollection;
|
|
289
|
+
instance.identityDeps = [...identityDeps];
|
|
328
290
|
}
|
|
329
|
-
instance.
|
|
330
|
-
instance.
|
|
291
|
+
instance.client = dbClient;
|
|
292
|
+
instance.queryHash = queryHash;
|
|
293
|
+
instance.suspenseKey = suspenseKey;
|
|
294
|
+
instance.identityError = identityError;
|
|
331
295
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
296
|
+
if (needsNewCollection) {
|
|
297
|
+
instance.observer = createLiveQueryObserver(instance.collection, {
|
|
298
|
+
mode: `wholesale`,
|
|
299
|
+
client: dbClient,
|
|
300
|
+
queryHash: instance.queryHash,
|
|
301
|
+
onPreload: resumeDeferredCollections,
|
|
302
|
+
suspendUntilReady: forSuspense
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
const observer = instance.observer;
|
|
306
|
+
if (forSuspense && !dbClient && (instance.collection?.status === `idle` || instance.collection?.status === `cleaned-up`)) {
|
|
307
|
+
observer.preload().catch(() => {
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
if (!instance.subscribe || needsNewCollection) {
|
|
311
|
+
instance.subscribe = (onStoreChange) => {
|
|
312
|
+
const unsubscribe = observer.subscribe(onStoreChange);
|
|
313
|
+
resumeDeferredCollections();
|
|
314
|
+
return unsubscribe;
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
const returned = useSyncExternalStore(
|
|
318
|
+
instance.subscribe,
|
|
319
|
+
() => observer.getSnapshot(),
|
|
320
|
+
() => observer.getServerSnapshot(forSuspense)
|
|
321
|
+
);
|
|
322
|
+
if (forSuspense) {
|
|
323
|
+
setLiveQueryResultInfo(returned, {
|
|
324
|
+
client: dbClient,
|
|
325
|
+
queryHash: instance.queryHash,
|
|
326
|
+
identityError: instance.identityError,
|
|
327
|
+
observer,
|
|
328
|
+
deferredCollections: instance.deferredCollections
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
return returned;
|
|
332
|
+
} catch (error) {
|
|
333
|
+
return rejectLiveQueryInput(instance.deferredCollections, error);
|
|
369
334
|
}
|
|
370
|
-
return returned;
|
|
371
335
|
}
|
|
372
336
|
export {
|
|
337
|
+
getIdentityScope,
|
|
373
338
|
prepareDerivedQuery,
|
|
374
339
|
prepareQueryValue,
|
|
375
340
|
useLiveQuery,
|
|
376
|
-
useLiveQueryForSuspense
|
|
377
|
-
warnDeprecatedDepsArray,
|
|
378
|
-
warnUnhashableDerivedIdentity
|
|
341
|
+
useLiveQueryForSuspense
|
|
379
342
|
};
|
|
380
343
|
//# sourceMappingURL=useLiveQuery.js.map
|