@tanstack/solid-query 5.0.0-beta.9 → 5.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/build/dev.cjs CHANGED
@@ -21,17 +21,17 @@ exports.useQueryClient = (queryClient) => {
21
21
  if (!client) {
22
22
  throw new Error("No QueryClient set, use QueryClientProvider to set one");
23
23
  }
24
- return client;
24
+ return client();
25
25
  };
26
26
  exports.QueryClientProvider = (props) => {
27
- solidJs.onMount(() => {
27
+ solidJs.createRenderEffect((unmount) => {
28
+ unmount?.();
28
29
  props.client.mount();
30
+ return props.client.unmount.bind(props.client);
29
31
  });
30
32
  solidJs.onCleanup(() => props.client.unmount());
31
33
  return web.createComponent(exports.QueryClientContext.Provider, {
32
- get value() {
33
- return props.client;
34
- },
34
+ value: () => props.client,
35
35
  get children() {
36
36
  return props.children;
37
37
  }
@@ -45,6 +45,9 @@ function shouldThrowError(throwError, params) {
45
45
  }
46
46
  return !!throwError;
47
47
  }
48
+ var IsRestoringContext = solidJs.createContext(() => false);
49
+ exports.useIsRestoring = () => solidJs.useContext(IsRestoringContext);
50
+ exports.IsRestoringProvider = IsRestoringContext.Provider;
48
51
 
49
52
  // src/createBaseQuery.ts
50
53
  function reconcileFn(store$1, result, reconcileOption) {
@@ -78,21 +81,31 @@ var hydrateableObserverResult = (query, result) => {
78
81
  };
79
82
  function createBaseQuery(options, Observer, queryClient) {
80
83
  const client = solidJs.createMemo(() => exports.useQueryClient(queryClient?.()));
81
- const defaultedOptions = client().defaultQueryOptions(options());
82
- defaultedOptions._optimisticResults = "optimistic";
83
- defaultedOptions.structuralSharing = false;
84
- if (web.isServer) {
85
- defaultedOptions.retry = false;
86
- defaultedOptions.throwOnError = true;
87
- }
88
- const observer = new Observer(client(), defaultedOptions);
84
+ const isRestoring = exports.useIsRestoring();
85
+ const defaultedOptions = solidJs.createMemo(
86
+ () => solidJs.mergeProps(client().defaultQueryOptions(options()), {
87
+ get _optimisticResults() {
88
+ return isRestoring() ? "isRestoring" : "optimistic";
89
+ },
90
+ structuralSharing: false,
91
+ ...web.isServer && { retry: false, throwOnError: true }
92
+ })
93
+ );
94
+ const [observer, setObserver] = solidJs.createSignal(
95
+ new Observer(client(), solidJs.untrack(defaultedOptions))
96
+ );
97
+ solidJs.createComputed(
98
+ solidJs.on(client, (c) => setObserver(new Observer(c, defaultedOptions())), {
99
+ defer: true
100
+ })
101
+ );
89
102
  const [state, setState] = store.createStore(
90
- observer.getOptimisticResult(defaultedOptions)
103
+ observer().getOptimisticResult(defaultedOptions())
91
104
  );
92
105
  const createServerSubscriber = (resolve, reject) => {
93
- return observer.subscribe((result) => {
106
+ return observer().subscribe((result) => {
94
107
  queryCore.notifyManager.batchCalls(() => {
95
- const query = observer.getCurrentQuery();
108
+ const query = observer().getCurrentQuery();
96
109
  const unwrappedResult = hydrateableObserverResult(query, result);
97
110
  if (unwrappedResult.isError) {
98
111
  reject(unwrappedResult.error);
@@ -103,44 +116,36 @@ function createBaseQuery(options, Observer, queryClient) {
103
116
  });
104
117
  };
105
118
  const createClientSubscriber = () => {
106
- return observer.subscribe((result) => {
119
+ const obs = observer();
120
+ return obs.subscribe((result) => {
107
121
  queryCore.notifyManager.batchCalls(() => {
108
- const reconcileOptions = observer.options.reconcile;
109
- if (queryResource()?.data && result.data && !queryResource.loading) {
110
- setState((store) => {
111
- return reconcileFn(
112
- store,
113
- result,
114
- reconcileOptions === void 0 ? "id" : reconcileOptions
115
- );
116
- });
122
+ const reconcileOptions = obs.options.reconcile;
123
+ setState((store) => {
124
+ return reconcileFn(
125
+ store,
126
+ result,
127
+ reconcileOptions === void 0 ? "id" : reconcileOptions
128
+ );
129
+ });
130
+ if (queryResource()?.data && result.data && !queryResource.loading && isRestoring())
117
131
  mutate(state);
118
- } else {
119
- setState((store) => {
120
- return reconcileFn(
121
- store,
122
- result,
123
- reconcileOptions === void 0 ? "id" : reconcileOptions
124
- );
125
- });
132
+ else
126
133
  refetch();
127
- }
128
134
  })();
129
135
  });
130
136
  };
131
137
  let unsubscribe = null;
132
138
  const [queryResource, { refetch, mutate }] = solidJs.createResource(
133
139
  () => {
140
+ const obs = observer();
134
141
  return new Promise((resolve, reject) => {
135
- if (web.isServer) {
142
+ if (web.isServer)
136
143
  unsubscribe = createServerSubscriber(resolve, reject);
137
- } else {
138
- if (!unsubscribe) {
139
- unsubscribe = createClientSubscriber();
140
- }
141
- }
142
- if (!state.isLoading) {
143
- const query = observer.getCurrentQuery();
144
+ else if (!unsubscribe && !isRestoring())
145
+ unsubscribe = createClientSubscriber();
146
+ obs.updateResult();
147
+ if (!state.isLoading && !isRestoring()) {
148
+ const query = obs.getCurrentQuery();
144
149
  resolve(hydrateableObserverResult(query, state));
145
150
  }
146
151
  });
@@ -148,7 +153,9 @@ function createBaseQuery(options, Observer, queryClient) {
148
153
  {
149
154
  initialValue: state,
150
155
  // If initialData is provided, we resolve the resource immediately
151
- ssrLoadFrom: options().initialData ? "initial" : "server",
156
+ get ssrLoadFrom() {
157
+ return options().initialData ? "initial" : "server";
158
+ },
152
159
  get deferStream() {
153
160
  return options().deferStream;
154
161
  },
@@ -161,29 +168,43 @@ function createBaseQuery(options, Observer, queryClient) {
161
168
  * Note that this is only invoked on the client, for queries that were originally run on the server.
162
169
  */
163
170
  onHydrated(_k, info) {
171
+ const defaultOptions = defaultedOptions();
164
172
  if (info.value) {
165
173
  queryCore.hydrate(client(), {
166
174
  queries: [
167
175
  {
168
- queryKey: defaultedOptions.queryKey,
169
- queryHash: defaultedOptions.queryHash,
176
+ queryKey: defaultOptions.queryKey,
177
+ queryHash: defaultOptions.queryHash,
170
178
  state: info.value
171
179
  }
172
180
  ]
173
181
  });
174
182
  }
175
- if (!unsubscribe) {
176
- const newOptions = { ...defaultedOptions };
177
- if (defaultedOptions.staleTime || !defaultedOptions.initialData) {
178
- newOptions.refetchOnMount = false;
179
- }
180
- observer.setOptions(newOptions);
181
- setState(observer.getOptimisticResult(newOptions));
182
- unsubscribe = createClientSubscriber();
183
+ if (unsubscribe)
184
+ return;
185
+ const newOptions = { ...defaultOptions };
186
+ if (defaultOptions.staleTime || !defaultOptions.initialData) {
187
+ newOptions.refetchOnMount = false;
183
188
  }
189
+ observer().setOptions(newOptions);
190
+ setState(observer().getOptimisticResult(newOptions));
191
+ unsubscribe = createClientSubscriber();
184
192
  }
185
193
  }
186
194
  );
195
+ solidJs.createComputed(
196
+ solidJs.on(
197
+ [isRestoring, observer],
198
+ ([restoring]) => {
199
+ const unsub = unsubscribe;
200
+ queueMicrotask(() => unsub?.());
201
+ unsubscribe = null;
202
+ if (!restoring)
203
+ refetch();
204
+ },
205
+ { defer: true }
206
+ )
207
+ );
187
208
  solidJs.onCleanup(() => {
188
209
  if (unsubscribe) {
189
210
  unsubscribe();
@@ -192,8 +213,11 @@ function createBaseQuery(options, Observer, queryClient) {
192
213
  });
193
214
  solidJs.createComputed(
194
215
  solidJs.on(
195
- () => client().defaultQueryOptions(options()),
196
- () => observer.setOptions(client().defaultQueryOptions(options())),
216
+ [observer, defaultedOptions],
217
+ ([obs, opts]) => {
218
+ obs.setOptions(opts);
219
+ setState(obs.getOptimisticResult(opts));
220
+ },
197
221
  {
198
222
  // Defer because we don't need to trigger on first render
199
223
  // This only cares about changes to options after the observer is created
@@ -205,9 +229,10 @@ function createBaseQuery(options, Observer, queryClient) {
205
229
  solidJs.on(
206
230
  () => state.status,
207
231
  () => {
208
- if (state.isError && !state.isFetching && shouldThrowError(observer.options.throwOnError, [
232
+ const obs = observer();
233
+ if (state.isError && !state.isFetching && !isRestoring() && shouldThrowError(obs.options.throwOnError, [
209
234
  state.error,
210
- observer.getCurrentQuery()
235
+ obs.getCurrentQuery()
211
236
  ])) {
212
237
  throw state.error;
213
238
  }
@@ -253,9 +278,9 @@ function createInfiniteQuery(options, queryClient) {
253
278
  );
254
279
  }
255
280
  function createMutation(options, queryClient) {
256
- const client = exports.useQueryClient(queryClient?.());
281
+ const client = solidJs.createMemo(() => exports.useQueryClient(queryClient?.()));
257
282
  const observer = new queryCore.MutationObserver(
258
- client,
283
+ client(),
259
284
  options()
260
285
  );
261
286
  const mutate = (variables, mutateOptions) => {
@@ -304,43 +329,114 @@ function useIsMutating(filters, queryClient) {
304
329
  return mutations;
305
330
  }
306
331
  function createQueries(queriesOptions, queryClient) {
307
- const client = exports.useQueryClient(queryClient?.());
308
- const defaultedQueries = queriesOptions().queries.map((options) => {
309
- const defaultedOptions = client.defaultQueryOptions(options);
310
- defaultedOptions._optimisticResults = "optimistic";
311
- return defaultedOptions;
312
- });
332
+ const client = solidJs.createMemo(() => exports.useQueryClient(queryClient?.()));
333
+ const isRestoring = exports.useIsRestoring();
334
+ const defaultedQueries = solidJs.createMemo(
335
+ () => queriesOptions().queries.map(
336
+ (options) => solidJs.mergeProps(client().defaultQueryOptions(options), {
337
+ get _optimisticResults() {
338
+ return isRestoring() ? "isRestoring" : "optimistic";
339
+ }
340
+ })
341
+ )
342
+ );
313
343
  const observer = new queryCore.QueriesObserver(
314
- client,
315
- defaultedQueries,
344
+ client(),
345
+ defaultedQueries(),
316
346
  queriesOptions().combine ? {
317
347
  combine: queriesOptions().combine
318
348
  } : void 0
319
349
  );
320
350
  const [state, setState] = store.createStore(
321
- observer.getOptimisticResult(defaultedQueries)[1]()
351
+ observer.getOptimisticResult(defaultedQueries())[1]()
322
352
  );
323
- const unsubscribe = observer.subscribe((result) => {
324
- queryCore.notifyManager.batchCalls(() => {
325
- setState(store.unwrap(result));
326
- })();
353
+ solidJs.createRenderEffect(
354
+ solidJs.on(
355
+ () => queriesOptions().queries.length,
356
+ () => setState(observer.getOptimisticResult(defaultedQueries())[1]())
357
+ )
358
+ );
359
+ const dataResources = solidJs.createMemo(
360
+ solidJs.on(
361
+ () => state.length,
362
+ () => state.map((queryRes) => {
363
+ const dataPromise = () => new Promise((resolve) => {
364
+ if (queryRes.isFetching && queryRes.isLoading)
365
+ return;
366
+ resolve(store.unwrap(queryRes.data));
367
+ });
368
+ return solidJs.createResource(dataPromise);
369
+ })
370
+ )
371
+ );
372
+ solidJs.batch(() => {
373
+ const dataResources_ = dataResources();
374
+ for (let index = 0; index < dataResources_.length; index++) {
375
+ const dataResource = dataResources_[index];
376
+ dataResource[1].mutate(() => store.unwrap(state[index].data));
377
+ dataResource[1].refetch();
378
+ }
379
+ });
380
+ let taskQueue = [];
381
+ const subscribeToObserver = () => observer.subscribe((result) => {
382
+ taskQueue.push(() => {
383
+ solidJs.batch(() => {
384
+ const dataResources_ = dataResources();
385
+ for (let index = 0; index < dataResources_.length; index++) {
386
+ const dataResource = dataResources_[index];
387
+ const unwrappedResult = { ...store.unwrap(result[index]) };
388
+ setState(index, store.unwrap(unwrappedResult));
389
+ dataResource[1].mutate(() => store.unwrap(state[index].data));
390
+ dataResource[1].refetch();
391
+ }
392
+ });
393
+ });
394
+ queueMicrotask(() => {
395
+ const taskToRun = taskQueue.pop();
396
+ if (taskToRun)
397
+ taskToRun();
398
+ taskQueue = [];
399
+ });
400
+ });
401
+ let unsubscribe = () => void 0;
402
+ solidJs.createComputed((cleanup) => {
403
+ cleanup?.();
404
+ unsubscribe = isRestoring() ? () => void 0 : subscribeToObserver();
405
+ return () => queueMicrotask(unsubscribe);
327
406
  });
328
407
  solidJs.onCleanup(unsubscribe);
408
+ solidJs.onMount(() => {
409
+ observer.setQueries(
410
+ defaultedQueries(),
411
+ queriesOptions().combine ? {
412
+ combine: queriesOptions().combine
413
+ } : void 0,
414
+ { listeners: false }
415
+ );
416
+ });
329
417
  solidJs.createComputed(() => {
330
- const updatedQueries = queriesOptions().queries.map((options) => {
331
- const defaultedOptions = client.defaultQueryOptions(options);
332
- defaultedOptions._optimisticResults = "optimistic";
333
- return defaultedOptions;
334
- });
335
418
  observer.setQueries(
336
- updatedQueries,
419
+ defaultedQueries(),
337
420
  queriesOptions().combine ? {
338
421
  combine: queriesOptions().combine
339
422
  } : void 0,
340
423
  { listeners: false }
341
424
  );
342
425
  });
343
- return state;
426
+ const handler = (index) => ({
427
+ get(target, prop) {
428
+ if (prop === "data") {
429
+ return dataResources()[index][0]();
430
+ }
431
+ return Reflect.get(target, prop);
432
+ }
433
+ });
434
+ const getProxies = () => state.map((s, index) => {
435
+ return new Proxy(s, handler(index));
436
+ });
437
+ const [proxifiedState, setProxifiedState] = store.createStore(getProxies());
438
+ solidJs.createRenderEffect(() => setProxifiedState(getProxies()));
439
+ return proxifiedState;
344
440
  }
345
441
 
346
442
  exports.createInfiniteQuery = createInfiniteQuery;