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