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