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