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