@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.
Files changed (40) hide show
  1. package/dist/cjs/live-query-internals.cjs.map +1 -1
  2. package/dist/cjs/live-query-internals.d.cts +3 -1
  3. package/dist/cjs/source-id-bindings.cjs +9 -42
  4. package/dist/cjs/source-id-bindings.cjs.map +1 -1
  5. package/dist/cjs/source-id-bindings.d.cts +6 -17
  6. package/dist/cjs/useLiveInfiniteQuery.cjs +93 -173
  7. package/dist/cjs/useLiveInfiniteQuery.cjs.map +1 -1
  8. package/dist/cjs/useLiveInfiniteQuery.d.cts +3 -14
  9. package/dist/cjs/useLiveQuery.cjs +187 -224
  10. package/dist/cjs/useLiveQuery.cjs.map +1 -1
  11. package/dist/cjs/useLiveQuery.d.cts +37 -136
  12. package/dist/cjs/useLiveSuspenseQuery.cjs +71 -64
  13. package/dist/cjs/useLiveSuspenseQuery.cjs.map +1 -1
  14. package/dist/cjs/useLiveSuspenseQuery.d.cts +10 -9
  15. package/dist/cjs/usePacedMutations.cjs.map +1 -1
  16. package/dist/cjs/usePacedMutations.d.cts +1 -1
  17. package/dist/esm/live-query-internals.d.ts +3 -1
  18. package/dist/esm/live-query-internals.js.map +1 -1
  19. package/dist/esm/source-id-bindings.d.ts +6 -17
  20. package/dist/esm/source-id-bindings.js +9 -40
  21. package/dist/esm/source-id-bindings.js.map +1 -1
  22. package/dist/esm/useLiveInfiniteQuery.d.ts +3 -14
  23. package/dist/esm/useLiveInfiniteQuery.js +95 -175
  24. package/dist/esm/useLiveInfiniteQuery.js.map +1 -1
  25. package/dist/esm/useLiveQuery.d.ts +37 -136
  26. package/dist/esm/useLiveQuery.js +189 -226
  27. package/dist/esm/useLiveQuery.js.map +1 -1
  28. package/dist/esm/useLiveSuspenseQuery.d.ts +10 -9
  29. package/dist/esm/useLiveSuspenseQuery.js +71 -64
  30. package/dist/esm/useLiveSuspenseQuery.js.map +1 -1
  31. package/dist/esm/usePacedMutations.d.ts +1 -1
  32. package/dist/esm/usePacedMutations.js.map +1 -1
  33. package/package.json +3 -3
  34. package/skills/react-db/SKILL.md +24 -15
  35. package/src/live-query-internals.ts +3 -0
  36. package/src/source-id-bindings.ts +16 -62
  37. package/src/useLiveInfiniteQuery.ts +138 -296
  38. package/src/useLiveQuery.ts +329 -495
  39. package/src/useLiveSuspenseQuery.ts +122 -132
  40. 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(sourceIdBindings.getSourceObjectToken);
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 prepareDerivedQuery(value, dbClient, profiler, deferredCollections) {
102
- const shouldProfile = development.shouldWarnInDevelopment(
103
- `TANSTACK_DB_DISABLE_QUERY_IDENTITY_WARNINGS`
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(value, dbClient, deferredCollections);
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`, identity]
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 warnUnhashableDerivedIdentity(error) {
130
- if (!development.shouldWarnInDevelopment(`TANSTACK_DB_DISABLE_QUERY_IDENTITY_WARNINGS`)) {
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, deps) {
146
- return useLiveQueryImpl(configOrQueryOrCollection, deps, true);
116
+ function useLiveQueryForSuspense(configOrQueryOrCollection) {
117
+ return useLiveQueryImpl(configOrQueryOrCollection, true);
147
118
  }
148
119
  function createHookInstance(dbClient) {
149
120
  return {
150
121
  collection: null,
151
- deps: null,
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: sourceIdBindings.createSourceIdBindings(),
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, deps, forSuspense = false) {
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 = () => db.resumeDeferredLiveQueryCollections(instance.deferredCollections);
178
- const queryKey = !inputIsCollection ? getExplicitQueryKey(configOrQueryOrCollection) : void 0;
179
- let preparedQueryValue = unpreparedQueryValue;
180
- let identityDeps;
181
- let streamIdentity = void 0;
182
- let identityError;
183
- if (queryKey) {
184
- identityDeps = queryKey;
185
- streamIdentity = [`queryKey`, queryKey];
186
- } else if (deps !== void 0) {
187
- identityDeps = resolvedDeps;
188
- if (dbClient || forSuspense || development.shouldWarnInDevelopment(`TANSTACK_DB_DISABLE_QUERY_IDENTITY_WARNINGS`))
189
- try {
190
- preparedQueryValue = prepareQueryValue(
191
- configOrQueryOrCollection,
192
- dbClient,
193
- instance.deferredCollections
194
- );
195
- streamIdentity = [
196
- `deps`,
197
- resolvedDeps,
198
- db.getPreparedLiveQueryIdentity(preparedQueryValue)
199
- ];
200
- } catch (error) {
201
- if (!(error instanceof db.UnhashableQueryIRError)) throw error;
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
- let queryHash;
226
- if (streamIdentity !== void 0) {
227
- try {
228
- queryHash = db.getStableValueHash(streamIdentity, `queryKey`);
229
- } catch (error) {
230
- if (error instanceof db.UnhashableQueryIRError) {
231
- if (queryKey !== void 0) throw error;
232
- identityError = error;
233
- } else {
234
- throw error;
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
- if (deps !== void 0) {
239
- warnDeprecatedDepsArray();
240
- }
241
- if (queryKey === void 0 && deps === void 0 && preparedQueryValue !== unpreparedQueryValue) {
242
- sourceIdBindings.claimSourceIds(
243
- instance.sourceIds,
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
- dbClient,
246
- `useLiveQuery`,
247
- resumeDeferredCollections
248
- );
249
- }
250
- const canReuseSuspenseKey = forSuspense && !inputIsCollection && queryHash !== void 0 && instance.collection !== null && instance.client === dbClient && instance.queryHash === queryHash && instance.suspenseKey !== void 0;
251
- if (forSuspense && !inputIsCollection && queryHash && !canReuseSuspenseKey && preparedQueryValue === unpreparedQueryValue) {
252
- preparedQueryValue = prepareQueryValue(
253
- configOrQueryOrCollection,
254
- dbClient,
255
- instance.deferredCollections
256
- );
257
- }
258
- const suspenseKey = queryHash && forSuspense && !inputIsCollection ? canReuseSuspenseKey ? instance.suspenseKey : getSourceQualifiedSuspenseKey(preparedQueryValue, queryHash, dbClient) : queryHash;
259
- const suspenseCollections = forSuspense && !inputIsCollection && suspenseKey ? getSuspenseCollections(dbClient) : void 0;
260
- const suspenseEntry = suspenseKey ? suspenseCollections?.get(suspenseKey) : void 0;
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
- configOrQueryOrCollection.startSyncImmediate();
278
- instance.collection = configOrQueryOrCollection;
279
- instance.config = configOrQueryOrCollection;
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 (!dbClient) {
292
- sourceIdBindings.getPreparedSources(preparedQueryValue, dbClient, `useLiveQuery`);
293
- }
294
- instance.collection = db.resolveLiveQueryValue(preparedQueryValue, {
295
- gcTime: forSuspense ? DEFAULT_SUSPENSE_GC_TIME_MS : DEFAULT_GC_TIME_MS,
296
- // Hydration and Suspense key the live-query Collection by identity.
297
- pool: !forSuspense && !dbClient,
298
- // Without a DbClient, Suspense starts it through a preload below.
299
- startSync: !forSuspense || dbClient !== void 0
300
- });
301
- if (suspenseCollections && suspenseKey && instance.collection) {
302
- const collection = instance.collection;
303
- const removeCleanupListener = collection.on(
304
- `status:cleaned-up`,
305
- () => releaseSuspenseCollection(
306
- suspenseCollections,
307
- suspenseKey,
308
- collection
309
- )
310
- );
311
- const removeErrorListener = collection.on(`status:error`, () => {
312
- setTimeout(
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
- const entry = {
322
- collection,
323
- removeStatusListeners: () => {
324
- removeCleanupListener();
325
- removeErrorListener();
326
- }
327
- };
328
- suspenseCollections.set(suspenseKey, entry);
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.config = configOrQueryOrCollection;
332
- instance.deps = [...identityDeps];
293
+ instance.client = dbClient;
294
+ instance.queryHash = queryHash;
295
+ instance.suspenseKey = suspenseKey;
296
+ instance.identityError = identityError;
333
297
  }
334
- instance.client = dbClient;
335
- instance.queryHash = queryHash;
336
- instance.suspenseKey = suspenseKey;
337
- instance.identityError = identityError;
338
- }
339
- if (needsNewCollection) {
340
- instance.observer = db.createLiveQueryObserver(instance.collection, {
341
- mode: `wholesale`,
342
- client: dbClient,
343
- queryHash: instance.queryHash,
344
- onPreload: resumeDeferredCollections
345
- });
346
- }
347
- const observer = instance.observer;
348
- if (forSuspense && !dbClient && (instance.collection?.status === `idle` || instance.collection?.status === `cleaned-up`)) {
349
- observer.preloadForInitialRender().catch(() => {
350
- });
351
- }
352
- if (!instance.subscribe || needsNewCollection) {
353
- instance.subscribe = (onStoreChange) => {
354
- const unsubscribe = observer.subscribe(onStoreChange);
355
- resumeDeferredCollections();
356
- return unsubscribe;
357
- };
358
- }
359
- const returned = react.useSyncExternalStore(
360
- instance.subscribe,
361
- () => observer.getSnapshot(),
362
- () => observer.getServerSnapshot()
363
- );
364
- if (forSuspense) {
365
- liveQueryInternals.setLiveQueryResultInfo(returned, {
366
- client: dbClient,
367
- queryHash: instance.queryHash,
368
- identityError: instance.identityError,
369
- observer
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