@tanstack/solid-query 5.91.1 → 6.0.0-alpha.0

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/build/dev.d.cts CHANGED
@@ -60,7 +60,7 @@ export { createMutationState } from './_tsup-dts-rollup.cjs';
60
60
  export { useQueries } from './_tsup-dts-rollup.cjs';
61
61
  export { createQueries } from './_tsup-dts-rollup.cjs';
62
62
  export { useIsRestoring } from './_tsup-dts-rollup.cjs';
63
- export { IsRestoringProvider } from './_tsup-dts-rollup.cjs';
63
+ export { IsRestoringContext } from './_tsup-dts-rollup.cjs';
64
64
  export { focusManager } from './_tsup-dts-rollup.cjs';
65
65
  export { environmentManager } from './_tsup-dts-rollup.cjs';
66
66
  export { defaultShouldDehydrateMutation } from './_tsup-dts-rollup.cjs';
package/build/dev.d.ts CHANGED
@@ -60,7 +60,7 @@ export { createMutationState } from './_tsup-dts-rollup.js';
60
60
  export { useQueries } from './_tsup-dts-rollup.js';
61
61
  export { createQueries } from './_tsup-dts-rollup.js';
62
62
  export { useIsRestoring } from './_tsup-dts-rollup.js';
63
- export { IsRestoringProvider } from './_tsup-dts-rollup.js';
63
+ export { IsRestoringContext } from './_tsup-dts-rollup.js';
64
64
  export { focusManager } from './_tsup-dts-rollup.js';
65
65
  export { environmentManager } from './_tsup-dts-rollup.js';
66
66
  export { defaultShouldDehydrateMutation } from './_tsup-dts-rollup.js';
package/build/dev.js CHANGED
@@ -1,11 +1,10 @@
1
- import { MutationObserver, shouldThrowError, QueriesObserver, noop, QueryClient as QueryClient$1, replaceEqualDeep, hydrate, notifyManager, QueryObserver, InfiniteQueryObserver } from '@tanstack/query-core';
1
+ import { MutationObserver, shouldThrowError, QueriesObserver, QueryClient as QueryClient$1, replaceEqualDeep, noop, notifyManager, QueryObserver, InfiniteQueryObserver } from '@tanstack/query-core';
2
2
  export * from '@tanstack/query-core';
3
- import { createContext, useContext, createRenderEffect, onCleanup, createMemo, createComputed, on, mergeProps, createResource, batch, onMount, createSignal, createEffect } from 'solid-js';
4
- import { createComponent, isServer } from 'solid-js/web';
5
- import { createStore, unwrap, reconcile } from 'solid-js/store';
3
+ import { createContext, useContext, onCleanup, createMemo, createStore, createRenderEffect, merge, createEffect, reconcile, createSignal, isPending, refresh, snapshot } from 'solid-js';
4
+ import { createComponent } from '@solidjs/web';
6
5
 
7
6
  // src/useQuery.ts
8
- var QueryClientContext = createContext(void 0);
7
+ var QueryClientContext = createContext(null);
9
8
  var useQueryClient = (queryClient) => {
10
9
  if (queryClient) {
11
10
  return queryClient;
@@ -17,13 +16,9 @@ var useQueryClient = (queryClient) => {
17
16
  return client();
18
17
  };
19
18
  var QueryClientProvider = (props) => {
20
- createRenderEffect((unmount) => {
21
- unmount?.();
22
- props.client.mount();
23
- return props.client.unmount.bind(props.client);
24
- });
19
+ props.client.mount();
25
20
  onCleanup(() => props.client.unmount());
26
- return createComponent(QueryClientContext.Provider, {
21
+ return createComponent(QueryClientContext, {
27
22
  value: () => props.client,
28
23
  get children() {
29
24
  return props.children;
@@ -32,15 +27,28 @@ var QueryClientProvider = (props) => {
32
27
  };
33
28
  var IsRestoringContext = createContext(() => false);
34
29
  var useIsRestoring = () => useContext(IsRestoringContext);
35
- var IsRestoringProvider = IsRestoringContext.Provider;
36
30
 
37
31
  // src/useBaseQuery.ts
32
+ var isServer = typeof window === "undefined";
33
+ function _stripFnsForSSR(obj) {
34
+ if (!isServer) return obj;
35
+ const out = {};
36
+ for (const k of Object.keys(obj)) {
37
+ if (k === "refetch" || k === "fetchNextPage" || k === "fetchPreviousPage") {
38
+ out[k] = void 0;
39
+ } else {
40
+ out[k] = obj[k];
41
+ }
42
+ }
43
+ return out;
44
+ }
38
45
  function reconcileFn(store, result, reconcileOption, queryHash) {
39
- if (reconcileOption === false) return result;
40
46
  if (typeof reconcileOption === "function") {
41
- const newData2 = reconcileOption(store.data, result.data);
42
- return { ...result, data: newData2 };
47
+ const newData = reconcileOption(store.data, result.data);
48
+ return { ...result, data: newData };
43
49
  }
50
+ if (reconcileOption === false) return result;
51
+ const key = reconcileOption;
44
52
  let data = result.data;
45
53
  if (store.data === void 0) {
46
54
  try {
@@ -57,13 +65,16 @@ function reconcileFn(store, result, reconcileOption, queryHash) {
57
65
  }
58
66
  }
59
67
  }
60
- const newData = reconcile(data, { key: reconcileOption })(store.data);
61
- return { ...result, data: newData };
68
+ if (store.data !== void 0 && data !== void 0) {
69
+ reconcile(data, key)(store.data);
70
+ return { ...result, data: store.data };
71
+ }
72
+ return { ...result, data };
62
73
  }
63
74
  var hydratableObserverResult = (query, result) => {
64
75
  if (!isServer) return result;
65
76
  const obj = {
66
- ...unwrap(result),
77
+ ...snapshot(result),
67
78
  // During SSR, functions cannot be serialized, so we need to remove them
68
79
  // This is safe because we will add these functions back when the query is hydrated
69
80
  refetch: void 0
@@ -95,16 +106,22 @@ function useBaseQuery(options, Observer, queryClient) {
95
106
  }
96
107
  return defaultOptions;
97
108
  });
98
- const initialOptions = defaultedOptions();
99
- const [observer, setObserver] = createSignal(
100
- new Observer(client(), defaultedOptions())
109
+ const observer = new Observer(client(), defaultedOptions());
110
+ const trackedDefaultedOptions = createMemo(() => defaultedOptions());
111
+ createRenderEffect(
112
+ () => trackedDefaultedOptions(),
113
+ (opts) => {
114
+ observer.setOptions(opts);
115
+ }
116
+ );
117
+ let observerResult = observer.getOptimisticResult(defaultedOptions());
118
+ const [state, setState] = createStore(
119
+ _stripFnsForSSR(observerResult)
101
120
  );
102
- let observerResult = observer().getOptimisticResult(defaultedOptions());
103
- const [state, setState] = createStore(observerResult);
104
121
  const createServerSubscriber = (resolve, reject) => {
105
- return observer().subscribe((result) => {
122
+ return observer.subscribe((result) => {
106
123
  notifyManager.batchCalls(() => {
107
- const query = observer().getCurrentQuery();
124
+ const query = observer.getCurrentQuery();
108
125
  const unwrappedResult = hydratableObserverResult(query, result);
109
126
  if (result.data !== void 0 && unwrappedResult.isError) {
110
127
  reject(unwrappedResult.error);
@@ -123,133 +140,74 @@ function useBaseQuery(options, Observer, queryClient) {
123
140
  }
124
141
  };
125
142
  const createClientSubscriber = () => {
126
- const obs = observer();
127
- return obs.subscribe((result) => {
143
+ return observer.subscribe((result) => {
144
+ const previousResult = observerResult;
128
145
  observerResult = result;
146
+ setStateWithReconciliation(result);
129
147
  queueMicrotask(() => {
130
- if (unsubscribe) {
131
- refetch();
148
+ if (unsubscribe && !disposed && (previousResult.isLoading !== result.isLoading || previousResult.isError !== result.isError)) {
149
+ try {
150
+ refresh(queryResource);
151
+ } catch {
152
+ }
132
153
  }
133
154
  });
134
155
  });
135
156
  };
136
157
  function setStateWithReconciliation(res) {
137
- const opts = observer().options;
158
+ const opts = observer.options;
138
159
  const reconcileOptions = opts.reconcile;
160
+ const sanitized = _stripFnsForSSR(res);
139
161
  setState((store) => {
140
162
  return reconcileFn(
141
163
  store,
142
- res,
164
+ sanitized,
143
165
  reconcileOptions === void 0 ? false : reconcileOptions,
144
166
  opts.queryHash
145
167
  );
146
168
  });
147
169
  }
148
- function createDeepSignal() {
149
- return [
150
- () => state,
151
- (v) => {
152
- const unwrapped = unwrap(state);
153
- if (typeof v === "function") {
154
- v = v(unwrapped);
155
- }
156
- if (v?.hydrationData) {
157
- const { hydrationData, ...rest } = v;
158
- v = rest;
159
- }
160
- setStateWithReconciliation(v);
161
- }
162
- ];
163
- }
164
170
  let unsubscribe = null;
171
+ let disposed = false;
165
172
  let resolver = null;
166
- const [queryResource, { refetch }] = createResource(
173
+ const queryResource = createMemo(
167
174
  () => {
168
- const obs = observer();
175
+ const opts = trackedDefaultedOptions();
176
+ const restoring = isRestoring();
169
177
  return new Promise((resolve, reject) => {
170
178
  resolver = resolve;
171
179
  if (isServer) {
172
- unsubscribe = createServerSubscriber(resolve, reject);
173
- } else if (!unsubscribe && !isRestoring()) {
180
+ unsubscribe = createServerSubscriber((data) => {
181
+ resolve(data);
182
+ }, reject);
183
+ } else if (!unsubscribe && !restoring) {
174
184
  unsubscribe = createClientSubscriber();
175
185
  }
176
- obs.updateResult();
177
- if (observerResult.isError && !observerResult.isFetching && !isRestoring() && shouldThrowError(obs.options.throwOnError, [
178
- observerResult.error,
179
- obs.getCurrentQuery()
186
+ const currentResult = observer.getOptimisticResult(opts);
187
+ observerResult = currentResult;
188
+ if (currentResult.isError && !currentResult.isFetching && !restoring && shouldThrowError(opts.throwOnError, [
189
+ currentResult.error,
190
+ observer.getCurrentQuery()
180
191
  ])) {
181
- setStateWithReconciliation(observerResult);
182
- return reject(observerResult.error);
192
+ setStateWithReconciliation(currentResult);
193
+ return reject(currentResult.error);
183
194
  }
184
- if (!observerResult.isLoading) {
195
+ if (!currentResult.isLoading) {
185
196
  resolver = null;
197
+ setStateWithReconciliation(currentResult);
186
198
  return resolve(
187
- hydratableObserverResult(obs.getCurrentQuery(), observerResult)
199
+ hydratableObserverResult(observer.getCurrentQuery(), currentResult)
188
200
  );
189
201
  }
190
- setStateWithReconciliation(observerResult);
202
+ queueMicrotask(() => setStateWithReconciliation(currentResult));
191
203
  });
192
204
  },
193
- {
194
- storage: createDeepSignal,
195
- get deferStream() {
196
- return options().deferStream;
197
- },
198
- /**
199
- * If this resource was populated on the server (either sync render, or streamed in over time), onHydrated
200
- * will be called. This is the point at which we can hydrate the query cache state, and setup the query subscriber.
201
- *
202
- * Leveraging onHydrated allows us to plug into the async and streaming support that solidjs resources already support.
203
- *
204
- * Note that this is only invoked on the client, for queries that were originally run on the server.
205
- */
206
- onHydrated(_k, info) {
207
- if (info.value && "hydrationData" in info.value) {
208
- hydrate(client(), {
209
- // @ts-expect-error - hydrationData is not correctly typed internally
210
- queries: [{ ...info.value.hydrationData }]
211
- });
212
- }
213
- if (unsubscribe) return;
214
- const newOptions = { ...initialOptions };
215
- if ((initialOptions.staleTime || !initialOptions.initialData) && info.value) {
216
- newOptions.refetchOnMount = false;
217
- }
218
- observer().setOptions(newOptions);
219
- setStateWithReconciliation(observer().getOptimisticResult(newOptions));
220
- unsubscribe = createClientSubscriber();
221
- }
222
- }
223
- );
224
- createComputed(
225
- on(
226
- client,
227
- (c) => {
228
- if (unsubscribe) {
229
- unsubscribe();
230
- }
231
- const newObserver = new Observer(c, defaultedOptions());
232
- unsubscribe = createClientSubscriber();
233
- setObserver(newObserver);
234
- },
235
- {
236
- defer: true
237
- }
238
- )
239
- );
240
- createComputed(
241
- on(
242
- isRestoring,
243
- (restoring) => {
244
- if (!restoring && !isServer) {
245
- refetch();
246
- }
247
- },
248
- { defer: true }
249
- )
205
+ observerResult,
206
+ { ssrSource: "client" }
250
207
  );
251
208
  onCleanup(() => {
252
- if (isServer && queryResource.loading) {
209
+ disposed = true;
210
+ if (isServer && isPending(queryResource)) {
253
211
  unsubscribeQueued = true;
254
212
  return;
255
213
  }
@@ -262,29 +220,31 @@ function useBaseQuery(options, Observer, queryClient) {
262
220
  resolver = null;
263
221
  }
264
222
  });
265
- createComputed(
266
- on(
267
- [observer, defaultedOptions],
268
- ([obs, opts]) => {
269
- obs.setOptions(opts);
270
- setStateWithReconciliation(obs.getOptimisticResult(opts));
271
- refetch();
272
- },
273
- { defer: true }
274
- )
275
- );
276
- const handler = {
277
- get(target, prop) {
278
- if (prop === "data") {
279
- if (state.data !== void 0) {
280
- return queryResource.latest?.data;
281
- }
282
- return queryResource()?.data;
223
+ const errorPassthroughProps = /* @__PURE__ */ new Set([
224
+ "error",
225
+ "isError",
226
+ "failureCount",
227
+ "failureReason",
228
+ "errorUpdateCount",
229
+ "errorUpdatedAt"
230
+ ]);
231
+ return new Proxy(state, {
232
+ get(target, prop, receiver) {
233
+ if (typeof prop === "symbol") {
234
+ return Reflect.get(target, prop, receiver);
235
+ }
236
+ if (errorPassthroughProps.has(prop)) {
237
+ return Reflect.get(target, prop, receiver);
283
238
  }
284
- return Reflect.get(target, prop);
239
+ if (state.isError && !state.isFetching && shouldThrowError(observer.options.throwOnError, [
240
+ state.error,
241
+ observer.getCurrentQuery()
242
+ ])) {
243
+ throw state.error;
244
+ }
245
+ return Reflect.get(target, prop, receiver);
285
246
  }
286
- };
287
- return new Proxy(state, handler);
247
+ });
288
248
  }
289
249
 
290
250
  // src/useQuery.ts
@@ -305,6 +265,9 @@ function useInfiniteQuery(options, queryClient) {
305
265
  function useMutation(options, queryClient) {
306
266
  const client = createMemo(() => useQueryClient(queryClient?.()));
307
267
  const observer = new MutationObserver(client(), options());
268
+ createMemo(() => {
269
+ observer.setOptions(options());
270
+ });
308
271
  const mutate = (variables, mutateOptions) => {
309
272
  observer.mutate(variables, mutateOptions).catch(noop);
310
273
  };
@@ -313,27 +276,25 @@ function useMutation(options, queryClient) {
313
276
  mutate,
314
277
  mutateAsync: observer.getCurrentResult().mutate
315
278
  });
316
- createComputed(() => {
317
- observer.setOptions(options());
318
- });
319
- createComputed(
320
- on(
321
- () => state.status,
322
- () => {
323
- if (state.isError && shouldThrowError(observer.options.throwOnError, [state.error])) {
324
- throw state.error;
325
- }
326
- }
327
- )
328
- );
329
279
  const unsubscribe = observer.subscribe((result) => {
330
- setState({
280
+ setState(() => ({
331
281
  ...result,
332
282
  mutate,
333
283
  mutateAsync: result.mutate
334
- });
284
+ }));
335
285
  });
336
286
  onCleanup(unsubscribe);
287
+ createRenderEffect(
288
+ () => {
289
+ const isError = state.isError;
290
+ const error = state.error;
291
+ if (isError && shouldThrowError(observer.options.throwOnError, [error])) {
292
+ throw error;
293
+ }
294
+ },
295
+ () => {
296
+ }
297
+ );
337
298
  return state;
338
299
  }
339
300
  function useQueries(queriesOptions, queryClient) {
@@ -341,14 +302,11 @@ function useQueries(queriesOptions, queryClient) {
341
302
  const isRestoring = useIsRestoring();
342
303
  const defaultedQueries = createMemo(
343
304
  () => queriesOptions().queries.map(
344
- (options) => mergeProps(
345
- client().defaultQueryOptions(options),
346
- {
347
- get _optimisticResults() {
348
- return isRestoring() ? "isRestoring" : "optimistic";
349
- }
305
+ (options) => merge(client().defaultQueryOptions(options), {
306
+ get _optimisticResults() {
307
+ return isRestoring() ? "isRestoring" : "optimistic";
350
308
  }
351
- )
309
+ })
352
310
  )
353
311
  );
354
312
  const observer = new QueriesObserver(
@@ -358,100 +316,47 @@ function useQueries(queriesOptions, queryClient) {
358
316
  combine: queriesOptions().combine
359
317
  } : void 0
360
318
  );
361
- const [state, setState] = createStore(
362
- observer.getOptimisticResult(
363
- defaultedQueries(),
364
- queriesOptions().combine
365
- )[1]()
319
+ const [, getCombinedResult] = observer.getOptimisticResult(
320
+ defaultedQueries(),
321
+ queriesOptions().combine
366
322
  );
367
- createRenderEffect(
368
- on(
369
- () => queriesOptions().queries.length,
370
- () => setState(
371
- observer.getOptimisticResult(
372
- defaultedQueries(),
373
- queriesOptions().combine
374
- )[1]()
375
- )
376
- )
323
+ const initialResult = getCombinedResult();
324
+ const [state, setState] = createStore(
325
+ Array.isArray(initialResult) ? initialResult : [initialResult]
377
326
  );
378
- const dataResources = createMemo(
379
- on(
380
- () => state.length,
381
- () => state.map((queryRes) => {
382
- const dataPromise = () => new Promise((resolve) => {
383
- if (queryRes.isFetching && queryRes.isLoading) return;
384
- resolve(unwrap(queryRes.data));
327
+ let unsubscribe = noop;
328
+ createEffect(
329
+ () => {
330
+ if (!isRestoring()) {
331
+ unsubscribe = observer.subscribe((result) => {
332
+ setState(
333
+ reconcile(
334
+ [...result],
335
+ // Use a key function that returns undefined so reconcile
336
+ // uses positional matching and recursively updates nested properties
337
+ () => void 0
338
+ )
339
+ );
385
340
  });
386
- return createResource(dataPromise);
387
- })
388
- )
389
- );
390
- batch(() => {
391
- const dataResources_ = dataResources();
392
- for (let index = 0; index < dataResources_.length; index++) {
393
- const dataResource = dataResources_[index];
394
- dataResource[1].mutate(() => unwrap(state[index].data));
395
- dataResource[1].refetch();
341
+ }
342
+ },
343
+ () => {
396
344
  }
345
+ );
346
+ onCleanup(() => {
347
+ unsubscribe();
397
348
  });
398
- let taskQueue = [];
399
- const subscribeToObserver = () => observer.subscribe((result) => {
400
- taskQueue.push(() => {
401
- batch(() => {
402
- const dataResources_ = dataResources();
403
- for (let index = 0; index < dataResources_.length; index++) {
404
- const dataResource = dataResources_[index];
405
- const unwrappedResult = { ...unwrap(result[index]) };
406
- setState(index, unwrap(unwrappedResult));
407
- dataResource[1].mutate(() => unwrap(state[index].data));
408
- dataResource[1].refetch();
409
- }
410
- });
411
- });
412
- queueMicrotask(() => {
413
- const taskToRun = taskQueue.pop();
414
- if (taskToRun) taskToRun();
415
- taskQueue = [];
416
- });
417
- });
418
- let unsubscribe = noop;
419
- createComputed((cleanup) => {
420
- cleanup?.();
421
- unsubscribe = isRestoring() ? noop : subscribeToObserver();
422
- return () => queueMicrotask(unsubscribe);
423
- });
424
- onCleanup(unsubscribe);
425
- onMount(() => {
426
- observer.setQueries(
427
- defaultedQueries(),
428
- queriesOptions().combine ? {
429
- combine: queriesOptions().combine
430
- } : void 0
431
- );
432
- });
433
- createComputed(() => {
349
+ createMemo(() => {
350
+ const queries = defaultedQueries();
434
351
  observer.setQueries(
435
- defaultedQueries(),
352
+ queries,
436
353
  queriesOptions().combine ? {
437
354
  combine: queriesOptions().combine
438
355
  } : void 0
439
356
  );
357
+ return queries;
440
358
  });
441
- const handler = (index) => ({
442
- get(target, prop) {
443
- if (prop === "data") {
444
- return dataResources()[index][0]();
445
- }
446
- return Reflect.get(target, prop);
447
- }
448
- });
449
- const getProxies = () => state.map((s, index) => {
450
- return new Proxy(s, handler(index));
451
- });
452
- const [proxyState, setProxyState] = createStore(getProxies());
453
- createRenderEffect(() => setProxyState(getProxies()));
454
- return proxyState;
359
+ return state;
455
360
  }
456
361
  var QueryClient = class extends QueryClient$1 {
457
362
  constructor(config = {}) {
@@ -506,18 +411,16 @@ function useMutationState(options = () => ({}), queryClient) {
506
411
  const [result, setResult] = createSignal(
507
412
  getResult(mutationCache(), options())
508
413
  );
509
- createEffect(() => {
510
- const unsubscribe = mutationCache().subscribe(() => {
414
+ const unsubscribe = mutationCache().subscribe(() => {
415
+ setResult((prev) => {
511
416
  const nextResult = replaceEqualDeep(
512
- result(),
417
+ prev,
513
418
  getResult(mutationCache(), options())
514
419
  );
515
- if (result() !== nextResult) {
516
- setResult(nextResult);
517
- }
420
+ return prev === nextResult ? prev : nextResult;
518
421
  });
519
- onCleanup(unsubscribe);
520
422
  });
423
+ onCleanup(unsubscribe);
521
424
  return result;
522
425
  }
523
426
 
@@ -527,4 +430,4 @@ var createInfiniteQuery = useInfiniteQuery;
527
430
  var createMutation = useMutation;
528
431
  var createQueries = useQueries;
529
432
 
530
- export { IsRestoringProvider, QueryClient, QueryClientContext, QueryClientProvider, createInfiniteQuery, useIsFetching as createIsFetching, useIsMutating as createIsMutating, createMutation, useMutationState as createMutationState, createQueries, createQuery, infiniteQueryOptions, mutationOptions, queryOptions, useInfiniteQuery, useIsFetching, useIsMutating, useIsRestoring, useMutation, useMutationState, useQueries, useQuery, useQueryClient };
433
+ export { IsRestoringContext, QueryClient, QueryClientContext, QueryClientProvider, createInfiniteQuery, useIsFetching as createIsFetching, useIsMutating as createIsMutating, createMutation, useMutationState as createMutationState, createQueries, createQuery, infiniteQueryOptions, mutationOptions, queryOptions, useInfiniteQuery, useIsFetching, useIsMutating, useIsRestoring, useMutation, useMutationState, useQueries, useQuery, useQueryClient };