@tanstack/solid-query 5.30.1 → 5.30.3

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
@@ -51,14 +51,30 @@ exports.useIsRestoring = () => solidJs.useContext(IsRestoringContext);
51
51
  exports.IsRestoringProvider = IsRestoringContext.Provider;
52
52
 
53
53
  // src/createBaseQuery.ts
54
- function reconcileFn(store$1, result, reconcileOption) {
54
+ function reconcileFn(store$1, result, reconcileOption, queryHash) {
55
55
  if (reconcileOption === false)
56
56
  return result;
57
57
  if (typeof reconcileOption === "function") {
58
58
  const newData2 = reconcileOption(store$1.data, result.data);
59
59
  return { ...result, data: newData2 };
60
60
  }
61
- const newData = store.reconcile(result.data, { key: reconcileOption })(store$1.data);
61
+ let data = result.data;
62
+ if (store$1.data === void 0) {
63
+ try {
64
+ data = structuredClone(data);
65
+ } catch (error) {
66
+ {
67
+ if (error instanceof Error) {
68
+ console.warn(
69
+ `Unable to correctly reconcile data for query key: ${queryHash}. Possibly because the query data contains data structures that aren't supported by the 'structuredClone' algorithm. Consider using a callback function instead to manage the reconciliation manually.
70
+
71
+ Error Received: ${error.name} - ${error.message}`
72
+ );
73
+ }
74
+ }
75
+ }
76
+ }
77
+ const newData = store.reconcile(data, { key: reconcileOption })(store$1.data);
62
78
  return { ...result, data: newData };
63
79
  }
64
80
  var hydratableObserverResult = (query, result) => {
@@ -133,12 +149,14 @@ function createBaseQuery(options, Observer, queryClient) {
133
149
  });
134
150
  };
135
151
  function setStateWithReconciliation(res) {
136
- const reconcileOptions = observer().options.reconcile;
152
+ const opts = observer().options;
153
+ const reconcileOptions = opts.reconcile;
137
154
  setState((store) => {
138
155
  return reconcileFn(
139
156
  store,
140
157
  res,
141
- reconcileOptions === void 0 ? false : reconcileOptions
158
+ reconcileOptions === void 0 ? false : reconcileOptions,
159
+ opts.queryHash
142
160
  );
143
161
  });
144
162
  }
@@ -155,10 +173,12 @@ function createBaseQuery(options, Observer, queryClient) {
155
173
  ];
156
174
  }
157
175
  let unsubscribe = null;
176
+ let resolver = null;
158
177
  const [queryResource, { refetch }] = solidJs.createResource(
159
178
  () => {
160
179
  const obs = observer();
161
180
  return new Promise((resolve, reject) => {
181
+ resolver = resolve;
162
182
  if (web.isServer) {
163
183
  unsubscribe = createServerSubscriber(resolve, reject);
164
184
  } else if (!unsubscribe && !isRestoring()) {
@@ -174,6 +194,7 @@ function createBaseQuery(options, Observer, queryClient) {
174
194
  }
175
195
  if (!observerResult.isLoading) {
176
196
  const query = obs.getCurrentQuery();
197
+ resolver = null;
177
198
  return resolve(hydratableObserverResult(query, observerResult));
178
199
  }
179
200
  setStateWithReconciliation(observerResult);
@@ -211,7 +232,7 @@ function createBaseQuery(options, Observer, queryClient) {
211
232
  newOptions.refetchOnMount = false;
212
233
  }
213
234
  observer().setOptions(newOptions);
214
- setState(observer().getOptimisticResult(newOptions));
235
+ setStateWithReconciliation(observer().getOptimisticResult(newOptions));
215
236
  unsubscribe = createClientSubscriber();
216
237
  }
217
238
  }
@@ -252,6 +273,10 @@ function createBaseQuery(options, Observer, queryClient) {
252
273
  unsubscribe();
253
274
  unsubscribe = null;
254
275
  }
276
+ if (resolver && !web.isServer) {
277
+ resolver(observerResult);
278
+ resolver = null;
279
+ }
255
280
  });
256
281
  solidJs.createComputed(
257
282
  solidJs.on(
@@ -266,8 +291,7 @@ function createBaseQuery(options, Observer, queryClient) {
266
291
  const handler = {
267
292
  get(target, prop) {
268
293
  if (prop === "data") {
269
- const opts = observer().options;
270
- if (opts.placeholderData) {
294
+ if (state.data !== void 0) {
271
295
  return queryResource.latest?.data;
272
296
  }
273
297
  return queryResource()?.data;
package/build/dev.js CHANGED
@@ -50,14 +50,30 @@ var useIsRestoring = () => useContext(IsRestoringContext);
50
50
  var IsRestoringProvider = IsRestoringContext.Provider;
51
51
 
52
52
  // src/createBaseQuery.ts
53
- function reconcileFn(store, result, reconcileOption) {
53
+ function reconcileFn(store, result, reconcileOption, queryHash) {
54
54
  if (reconcileOption === false)
55
55
  return result;
56
56
  if (typeof reconcileOption === "function") {
57
57
  const newData2 = reconcileOption(store.data, result.data);
58
58
  return { ...result, data: newData2 };
59
59
  }
60
- const newData = reconcile(result.data, { key: reconcileOption })(store.data);
60
+ let data = result.data;
61
+ if (store.data === void 0) {
62
+ try {
63
+ data = structuredClone(data);
64
+ } catch (error) {
65
+ {
66
+ if (error instanceof Error) {
67
+ console.warn(
68
+ `Unable to correctly reconcile data for query key: ${queryHash}. Possibly because the query data contains data structures that aren't supported by the 'structuredClone' algorithm. Consider using a callback function instead to manage the reconciliation manually.
69
+
70
+ Error Received: ${error.name} - ${error.message}`
71
+ );
72
+ }
73
+ }
74
+ }
75
+ }
76
+ const newData = reconcile(data, { key: reconcileOption })(store.data);
61
77
  return { ...result, data: newData };
62
78
  }
63
79
  var hydratableObserverResult = (query, result) => {
@@ -132,12 +148,14 @@ function createBaseQuery(options, Observer, queryClient) {
132
148
  });
133
149
  };
134
150
  function setStateWithReconciliation(res) {
135
- const reconcileOptions = observer().options.reconcile;
151
+ const opts = observer().options;
152
+ const reconcileOptions = opts.reconcile;
136
153
  setState((store) => {
137
154
  return reconcileFn(
138
155
  store,
139
156
  res,
140
- reconcileOptions === void 0 ? false : reconcileOptions
157
+ reconcileOptions === void 0 ? false : reconcileOptions,
158
+ opts.queryHash
141
159
  );
142
160
  });
143
161
  }
@@ -154,10 +172,12 @@ function createBaseQuery(options, Observer, queryClient) {
154
172
  ];
155
173
  }
156
174
  let unsubscribe = null;
175
+ let resolver = null;
157
176
  const [queryResource, { refetch }] = createResource(
158
177
  () => {
159
178
  const obs = observer();
160
179
  return new Promise((resolve, reject) => {
180
+ resolver = resolve;
161
181
  if (isServer) {
162
182
  unsubscribe = createServerSubscriber(resolve, reject);
163
183
  } else if (!unsubscribe && !isRestoring()) {
@@ -173,6 +193,7 @@ function createBaseQuery(options, Observer, queryClient) {
173
193
  }
174
194
  if (!observerResult.isLoading) {
175
195
  const query = obs.getCurrentQuery();
196
+ resolver = null;
176
197
  return resolve(hydratableObserverResult(query, observerResult));
177
198
  }
178
199
  setStateWithReconciliation(observerResult);
@@ -210,7 +231,7 @@ function createBaseQuery(options, Observer, queryClient) {
210
231
  newOptions.refetchOnMount = false;
211
232
  }
212
233
  observer().setOptions(newOptions);
213
- setState(observer().getOptimisticResult(newOptions));
234
+ setStateWithReconciliation(observer().getOptimisticResult(newOptions));
214
235
  unsubscribe = createClientSubscriber();
215
236
  }
216
237
  }
@@ -251,6 +272,10 @@ function createBaseQuery(options, Observer, queryClient) {
251
272
  unsubscribe();
252
273
  unsubscribe = null;
253
274
  }
275
+ if (resolver && !isServer) {
276
+ resolver(observerResult);
277
+ resolver = null;
278
+ }
254
279
  });
255
280
  createComputed(
256
281
  on(
@@ -265,8 +290,7 @@ function createBaseQuery(options, Observer, queryClient) {
265
290
  const handler = {
266
291
  get(target, prop) {
267
292
  if (prop === "data") {
268
- const opts = observer().options;
269
- if (opts.placeholderData) {
293
+ if (state.data !== void 0) {
270
294
  return queryResource.latest?.data;
271
295
  }
272
296
  return queryResource()?.data;
package/build/index.cjs CHANGED
@@ -51,14 +51,21 @@ exports.useIsRestoring = () => solidJs.useContext(IsRestoringContext);
51
51
  exports.IsRestoringProvider = IsRestoringContext.Provider;
52
52
 
53
53
  // src/createBaseQuery.ts
54
- function reconcileFn(store$1, result, reconcileOption) {
54
+ function reconcileFn(store$1, result, reconcileOption, queryHash) {
55
55
  if (reconcileOption === false)
56
56
  return result;
57
57
  if (typeof reconcileOption === "function") {
58
58
  const newData2 = reconcileOption(store$1.data, result.data);
59
59
  return { ...result, data: newData2 };
60
60
  }
61
- const newData = store.reconcile(result.data, { key: reconcileOption })(store$1.data);
61
+ let data = result.data;
62
+ if (store$1.data === void 0) {
63
+ try {
64
+ data = structuredClone(data);
65
+ } catch (error) {
66
+ }
67
+ }
68
+ const newData = store.reconcile(data, { key: reconcileOption })(store$1.data);
62
69
  return { ...result, data: newData };
63
70
  }
64
71
  var hydratableObserverResult = (query, result) => {
@@ -133,12 +140,14 @@ function createBaseQuery(options, Observer, queryClient) {
133
140
  });
134
141
  };
135
142
  function setStateWithReconciliation(res) {
136
- const reconcileOptions = observer().options.reconcile;
143
+ const opts = observer().options;
144
+ const reconcileOptions = opts.reconcile;
137
145
  setState((store) => {
138
146
  return reconcileFn(
139
147
  store,
140
148
  res,
141
- reconcileOptions === void 0 ? false : reconcileOptions
149
+ reconcileOptions === void 0 ? false : reconcileOptions,
150
+ opts.queryHash
142
151
  );
143
152
  });
144
153
  }
@@ -155,10 +164,12 @@ function createBaseQuery(options, Observer, queryClient) {
155
164
  ];
156
165
  }
157
166
  let unsubscribe = null;
167
+ let resolver = null;
158
168
  const [queryResource, { refetch }] = solidJs.createResource(
159
169
  () => {
160
170
  const obs = observer();
161
171
  return new Promise((resolve, reject) => {
172
+ resolver = resolve;
162
173
  if (web.isServer) {
163
174
  unsubscribe = createServerSubscriber(resolve, reject);
164
175
  } else if (!unsubscribe && !isRestoring()) {
@@ -174,6 +185,7 @@ function createBaseQuery(options, Observer, queryClient) {
174
185
  }
175
186
  if (!observerResult.isLoading) {
176
187
  const query = obs.getCurrentQuery();
188
+ resolver = null;
177
189
  return resolve(hydratableObserverResult(query, observerResult));
178
190
  }
179
191
  setStateWithReconciliation(observerResult);
@@ -211,7 +223,7 @@ function createBaseQuery(options, Observer, queryClient) {
211
223
  newOptions.refetchOnMount = false;
212
224
  }
213
225
  observer().setOptions(newOptions);
214
- setState(observer().getOptimisticResult(newOptions));
226
+ setStateWithReconciliation(observer().getOptimisticResult(newOptions));
215
227
  unsubscribe = createClientSubscriber();
216
228
  }
217
229
  }
@@ -252,6 +264,10 @@ function createBaseQuery(options, Observer, queryClient) {
252
264
  unsubscribe();
253
265
  unsubscribe = null;
254
266
  }
267
+ if (resolver && !web.isServer) {
268
+ resolver(observerResult);
269
+ resolver = null;
270
+ }
255
271
  });
256
272
  solidJs.createComputed(
257
273
  solidJs.on(
@@ -266,8 +282,7 @@ function createBaseQuery(options, Observer, queryClient) {
266
282
  const handler = {
267
283
  get(target, prop) {
268
284
  if (prop === "data") {
269
- const opts = observer().options;
270
- if (opts.placeholderData) {
285
+ if (state.data !== void 0) {
271
286
  return queryResource.latest?.data;
272
287
  }
273
288
  return queryResource()?.data;
package/build/index.js CHANGED
@@ -50,14 +50,21 @@ var useIsRestoring = () => useContext(IsRestoringContext);
50
50
  var IsRestoringProvider = IsRestoringContext.Provider;
51
51
 
52
52
  // src/createBaseQuery.ts
53
- function reconcileFn(store, result, reconcileOption) {
53
+ function reconcileFn(store, result, reconcileOption, queryHash) {
54
54
  if (reconcileOption === false)
55
55
  return result;
56
56
  if (typeof reconcileOption === "function") {
57
57
  const newData2 = reconcileOption(store.data, result.data);
58
58
  return { ...result, data: newData2 };
59
59
  }
60
- const newData = reconcile(result.data, { key: reconcileOption })(store.data);
60
+ let data = result.data;
61
+ if (store.data === void 0) {
62
+ try {
63
+ data = structuredClone(data);
64
+ } catch (error) {
65
+ }
66
+ }
67
+ const newData = reconcile(data, { key: reconcileOption })(store.data);
61
68
  return { ...result, data: newData };
62
69
  }
63
70
  var hydratableObserverResult = (query, result) => {
@@ -132,12 +139,14 @@ function createBaseQuery(options, Observer, queryClient) {
132
139
  });
133
140
  };
134
141
  function setStateWithReconciliation(res) {
135
- const reconcileOptions = observer().options.reconcile;
142
+ const opts = observer().options;
143
+ const reconcileOptions = opts.reconcile;
136
144
  setState((store) => {
137
145
  return reconcileFn(
138
146
  store,
139
147
  res,
140
- reconcileOptions === void 0 ? false : reconcileOptions
148
+ reconcileOptions === void 0 ? false : reconcileOptions,
149
+ opts.queryHash
141
150
  );
142
151
  });
143
152
  }
@@ -154,10 +163,12 @@ function createBaseQuery(options, Observer, queryClient) {
154
163
  ];
155
164
  }
156
165
  let unsubscribe = null;
166
+ let resolver = null;
157
167
  const [queryResource, { refetch }] = createResource(
158
168
  () => {
159
169
  const obs = observer();
160
170
  return new Promise((resolve, reject) => {
171
+ resolver = resolve;
161
172
  if (isServer) {
162
173
  unsubscribe = createServerSubscriber(resolve, reject);
163
174
  } else if (!unsubscribe && !isRestoring()) {
@@ -173,6 +184,7 @@ function createBaseQuery(options, Observer, queryClient) {
173
184
  }
174
185
  if (!observerResult.isLoading) {
175
186
  const query = obs.getCurrentQuery();
187
+ resolver = null;
176
188
  return resolve(hydratableObserverResult(query, observerResult));
177
189
  }
178
190
  setStateWithReconciliation(observerResult);
@@ -210,7 +222,7 @@ function createBaseQuery(options, Observer, queryClient) {
210
222
  newOptions.refetchOnMount = false;
211
223
  }
212
224
  observer().setOptions(newOptions);
213
- setState(observer().getOptimisticResult(newOptions));
225
+ setStateWithReconciliation(observer().getOptimisticResult(newOptions));
214
226
  unsubscribe = createClientSubscriber();
215
227
  }
216
228
  }
@@ -251,6 +263,10 @@ function createBaseQuery(options, Observer, queryClient) {
251
263
  unsubscribe();
252
264
  unsubscribe = null;
253
265
  }
266
+ if (resolver && !isServer) {
267
+ resolver(observerResult);
268
+ resolver = null;
269
+ }
254
270
  });
255
271
  createComputed(
256
272
  on(
@@ -265,8 +281,7 @@ function createBaseQuery(options, Observer, queryClient) {
265
281
  const handler = {
266
282
  get(target, prop) {
267
283
  if (prop === "data") {
268
- const opts = observer().options;
269
- if (opts.placeholderData) {
284
+ if (state.data !== void 0) {
270
285
  return queryResource.latest?.data;
271
286
  }
272
287
  return queryResource()?.data;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/solid-query",
3
- "version": "5.30.1",
3
+ "version": "5.30.3",
4
4
  "description": "Primitives for managing, caching and syncing asynchronous and remote data in Solid",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -1051,7 +1051,9 @@ describe('createQuery', () => {
1051
1051
  count++
1052
1052
  return count === 1 ? result1 : result2
1053
1053
  },
1054
- reconcile: 'id',
1054
+ reconcile: (oldData, newData) => {
1055
+ return reconcile(newData)(oldData)
1056
+ },
1055
1057
  }))
1056
1058
 
1057
1059
  createRenderEffect(() => {
@@ -34,13 +34,31 @@ function reconcileFn<TData, TError>(
34
34
  | string
35
35
  | false
36
36
  | ((oldData: TData | undefined, newData: TData) => TData),
37
+ queryHash?: string,
37
38
  ): QueryObserverResult<TData, TError> {
38
39
  if (reconcileOption === false) return result
39
40
  if (typeof reconcileOption === 'function') {
40
41
  const newData = reconcileOption(store.data, result.data as TData)
41
42
  return { ...result, data: newData } as typeof result
42
43
  }
43
- const newData = reconcile(result.data, { key: reconcileOption })(store.data)
44
+ let data = result.data
45
+ if (store.data === undefined) {
46
+ try {
47
+ data = structuredClone(data)
48
+ } catch (error) {
49
+ if (process.env.NODE_ENV !== 'production') {
50
+ if (error instanceof Error) {
51
+ console.warn(
52
+ `Unable to correctly reconcile data for query key: ${queryHash}. ` +
53
+ `Possibly because the query data contains data structures that aren't supported ` +
54
+ `by the 'structuredClone' algorithm. Consider using a callback function instead ` +
55
+ `to manage the reconciliation manually.\n\n Error Received: ${error.name} - ${error.message}`,
56
+ )
57
+ }
58
+ }
59
+ }
60
+ }
61
+ const newData = reconcile(data, { key: reconcileOption })(store.data)
44
62
  return { ...result, data: newData } as typeof result
45
63
  }
46
64
 
@@ -186,14 +204,16 @@ export function createBaseQuery<
186
204
  }
187
205
 
188
206
  function setStateWithReconciliation(res: typeof observerResult) {
207
+ const opts = observer().options
189
208
  // @ts-expect-error - Reconcile option is not correctly typed internally
190
- const reconcileOptions = observer().options.reconcile
209
+ const reconcileOptions = opts.reconcile
191
210
 
192
211
  setState((store) => {
193
212
  return reconcileFn(
194
213
  store,
195
214
  res,
196
215
  reconcileOptions === undefined ? false : reconcileOptions,
216
+ opts.queryHash,
197
217
  )
198
218
  })
199
219
  }
@@ -216,10 +236,19 @@ export function createBaseQuery<
216
236
  */
217
237
  let unsubscribe: (() => void) | null = null
218
238
 
239
+ /*
240
+ Fixes #7275
241
+ In a few cases, the observer could unmount before the resource is loaded.
242
+ This leads to Suspense boundaries to be suspended indefinitely.
243
+ This resolver will be called when the observer is unmounting
244
+ but the resource is still in a loading state
245
+ */
246
+ let resolver: ((value: ResourceData) => void) | null = null
219
247
  const [queryResource, { refetch }] = createResource<ResourceData | undefined>(
220
248
  () => {
221
249
  const obs = observer()
222
250
  return new Promise((resolve, reject) => {
251
+ resolver = resolve
223
252
  if (isServer) {
224
253
  unsubscribe = createServerSubscriber(resolve, reject)
225
254
  } else if (!unsubscribe && !isRestoring()) {
@@ -241,6 +270,7 @@ export function createBaseQuery<
241
270
  }
242
271
  if (!observerResult.isLoading) {
243
272
  const query = obs.getCurrentQuery()
273
+ resolver = null
244
274
  return resolve(hydratableObserverResult(query, observerResult))
245
275
  }
246
276
 
@@ -290,7 +320,7 @@ export function createBaseQuery<
290
320
  // Setting the options as an immutable object to prevent
291
321
  // wonky behavior with observer subscriptions
292
322
  observer().setOptions(newOptions)
293
- setState(observer().getOptimisticResult(newOptions))
323
+ setStateWithReconciliation(observer().getOptimisticResult(newOptions))
294
324
  unsubscribe = createClientSubscriber()
295
325
  },
296
326
  },
@@ -334,6 +364,10 @@ export function createBaseQuery<
334
364
  unsubscribe()
335
365
  unsubscribe = null
336
366
  }
367
+ if (resolver && !isServer) {
368
+ resolver(observerResult)
369
+ resolver = null
370
+ }
337
371
  })
338
372
 
339
373
  createComputed(
@@ -353,8 +387,7 @@ export function createBaseQuery<
353
387
  prop: keyof QueryObserverResult<TData, TError>,
354
388
  ): any {
355
389
  if (prop === 'data') {
356
- const opts = observer().options
357
- if (opts.placeholderData) {
390
+ if (state.data !== undefined) {
358
391
  return queryResource.latest?.data
359
392
  }
360
393
  return queryResource()?.data