@tanstack/solid-query 6.0.0-beta.6 → 6.0.0-beta.8
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/_tsup-dts-rollup.d.cts +85 -0
- package/build/_tsup-dts-rollup.d.ts +85 -0
- package/build/dev.cjs +196 -18
- package/build/dev.js +198 -20
- package/build/index.cjs +196 -18
- package/build/index.js +198 -20
- package/package.json +6 -6
- package/src/QueryClientProvider.tsx +60 -2
- package/src/hydrationChannel.ts +260 -0
- package/src/useBaseQuery.ts +63 -13
|
@@ -147,6 +147,15 @@ export { CancelledError }
|
|
|
147
147
|
|
|
148
148
|
export { CancelOptions }
|
|
149
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Client side of the channel. Created by `QueryClientProvider` on the
|
|
152
|
+
* client and handed to `useBaseQuery` via context so hydrated components
|
|
153
|
+
* can attach their observers as soon as their query's entry has been
|
|
154
|
+
* primed — per query, not at global hydration end, which keeps
|
|
155
|
+
* early-hydrated components live while other boundaries still stream.
|
|
156
|
+
*/
|
|
157
|
+
export declare function createHydrationCoordinator(client: () => QueryClient): HydrationCoordinator;
|
|
158
|
+
|
|
150
159
|
export declare const createInfiniteQuery: typeof useInfiniteQuery;
|
|
151
160
|
|
|
152
161
|
export declare const createMutation: typeof useMutation;
|
|
@@ -155,6 +164,34 @@ export declare const createQueries: typeof useQueries;
|
|
|
155
164
|
|
|
156
165
|
export declare const createQuery: typeof useQuery;
|
|
157
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Server side of the library-owned serialization channel.
|
|
169
|
+
*
|
|
170
|
+
* Returns an AsyncIterable that yields a cumulative snapshot of the
|
|
171
|
+
* dehydrated query cache (success entries, per query-core `dehydrate()`
|
|
172
|
+
* shapes) every time a query settles during SSR. `QueryClientProvider`
|
|
173
|
+
* holds it as a signal value, so Solid serializes it through the normal
|
|
174
|
+
* per-computation path: the server runtime tees the iterator into the
|
|
175
|
+
* hydration serializer (`ctx.serialize(id, tapped)` in solid-js'
|
|
176
|
+
* `processResult`) and seroval streams each yield to the client as a
|
|
177
|
+
* script chunk riding the SSR stream.
|
|
178
|
+
*
|
|
179
|
+
* The iterable must terminate for the SSR stream to complete: the
|
|
180
|
+
* hydration serializer's `flush()` only fires its `onDone` once all
|
|
181
|
+
* pending streams have closed, and the render root is disposed *after*
|
|
182
|
+
* that, so neither `onCleanup` nor the serializer itself can close the
|
|
183
|
+
* channel. Instead the channel closes itself on cache quiescence: after
|
|
184
|
+
* every cache event (and once at creation) it schedules a timer-task
|
|
185
|
+
* check; if no query is fetching by then, no further settle can occur —
|
|
186
|
+
* suspense retry passes that start waterfall fetches are scheduled on
|
|
187
|
+
* microtasks, so they have begun before the check runs — and the channel
|
|
188
|
+
* emits its final cumulative snapshot with `done: true` and completes.
|
|
189
|
+
*
|
|
190
|
+
* Single-consumer by design: solid-js creates exactly one iterator from
|
|
191
|
+
* the value and shares it between the memo and the serializer tap.
|
|
192
|
+
*/
|
|
193
|
+
export declare function createServerDehydrationChannel(client: QueryClient): AsyncIterable<DehydrationChannelYield>;
|
|
194
|
+
|
|
158
195
|
export { DataTag }
|
|
159
196
|
|
|
160
197
|
export { dataTagErrorSymbol }
|
|
@@ -212,10 +249,40 @@ export { DefinedUseQueryResult as DefinedUseQueryResult_alias_1 }
|
|
|
212
249
|
|
|
213
250
|
export { dehydrate }
|
|
214
251
|
|
|
252
|
+
declare type DehydratedQueryEntry = DehydratedState['queries'][number];
|
|
253
|
+
|
|
215
254
|
export { DehydratedState }
|
|
216
255
|
|
|
217
256
|
export { DehydrateOptions }
|
|
218
257
|
|
|
258
|
+
/**
|
|
259
|
+
* A single message on the dehydration channel. `entries` is *cumulative* —
|
|
260
|
+
* every yield carries all entries settled so far. Two reasons:
|
|
261
|
+
*
|
|
262
|
+
* - It is what makes Solid's signal-path hydration replay lossless.
|
|
263
|
+
* Yields still buffered when hydration begins are conflated to the
|
|
264
|
+
* LATEST one (`normalizeIterator` drains synchronously available
|
|
265
|
+
* results, keeps the last data yield, and delivers the stream's done
|
|
266
|
+
* result on a subsequent pull), so each yield must be self-contained:
|
|
267
|
+
* the latest cumulative snapshot alone carries everything the dropped
|
|
268
|
+
* intermediates did. Requires the solid-js build with that conflation
|
|
269
|
+
* behavior (> 2.0.0-beta.32); earlier betas pinned the replay at the
|
|
270
|
+
* FIRST buffered yield, dropping every later entry and the `done`
|
|
271
|
+
* marker.
|
|
272
|
+
* - Entry objects keep their identity across yields, so seroval's
|
|
273
|
+
* cross-reference serialization emits each entry once and later yields
|
|
274
|
+
* only reference it — the cumulative shape costs bytes proportional to
|
|
275
|
+
* the number of entries, not its square.
|
|
276
|
+
*
|
|
277
|
+
* `done: true` marks the final yield. The client uses it to release
|
|
278
|
+
* subscribers still waiting for entries that will never arrive (e.g.
|
|
279
|
+
* queries that errored during SSR and were not dehydrated).
|
|
280
|
+
*/
|
|
281
|
+
export declare interface DehydrationChannelYield {
|
|
282
|
+
entries: Array<DehydratedQueryEntry>;
|
|
283
|
+
done: boolean;
|
|
284
|
+
}
|
|
285
|
+
|
|
219
286
|
export { DistributiveOmit }
|
|
220
287
|
|
|
221
288
|
export { EnsureInfiniteQueryDataOptions }
|
|
@@ -280,6 +347,24 @@ export { hydrate }
|
|
|
280
347
|
|
|
281
348
|
export { HydrateOptions }
|
|
282
349
|
|
|
350
|
+
declare interface HydrationCoordinator {
|
|
351
|
+
/**
|
|
352
|
+
* Prime the QueryClient from a channel yield. Entries already applied
|
|
353
|
+
* (same queryHash and dataUpdatedAt) are skipped; the rest go through
|
|
354
|
+
* query-core `hydrate()`, which keeps whichever data is newer.
|
|
355
|
+
*/
|
|
356
|
+
applyYield: (value: DehydrationChannelYield) => void;
|
|
357
|
+
/**
|
|
358
|
+
* Invoke `callback` (on a microtask) once the entry for `queryHash` has
|
|
359
|
+
* been applied — or immediately-on-a-microtask if it already was, or
|
|
360
|
+
* when the channel completes without one (SSR-errored queries are not
|
|
361
|
+
* dehydrated, so their components must not wait forever).
|
|
362
|
+
*/
|
|
363
|
+
whenQueryPrimed: (queryHash: string, callback: () => void) => void;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export declare const HydrationCoordinatorContext: Context<HydrationCoordinator | null>;
|
|
367
|
+
|
|
283
368
|
export { InferDataFromTag }
|
|
284
369
|
|
|
285
370
|
export { InferErrorFromTag }
|
|
@@ -147,6 +147,15 @@ export { CancelledError }
|
|
|
147
147
|
|
|
148
148
|
export { CancelOptions }
|
|
149
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Client side of the channel. Created by `QueryClientProvider` on the
|
|
152
|
+
* client and handed to `useBaseQuery` via context so hydrated components
|
|
153
|
+
* can attach their observers as soon as their query's entry has been
|
|
154
|
+
* primed — per query, not at global hydration end, which keeps
|
|
155
|
+
* early-hydrated components live while other boundaries still stream.
|
|
156
|
+
*/
|
|
157
|
+
export declare function createHydrationCoordinator(client: () => QueryClient): HydrationCoordinator;
|
|
158
|
+
|
|
150
159
|
export declare const createInfiniteQuery: typeof useInfiniteQuery;
|
|
151
160
|
|
|
152
161
|
export declare const createMutation: typeof useMutation;
|
|
@@ -155,6 +164,34 @@ export declare const createQueries: typeof useQueries;
|
|
|
155
164
|
|
|
156
165
|
export declare const createQuery: typeof useQuery;
|
|
157
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Server side of the library-owned serialization channel.
|
|
169
|
+
*
|
|
170
|
+
* Returns an AsyncIterable that yields a cumulative snapshot of the
|
|
171
|
+
* dehydrated query cache (success entries, per query-core `dehydrate()`
|
|
172
|
+
* shapes) every time a query settles during SSR. `QueryClientProvider`
|
|
173
|
+
* holds it as a signal value, so Solid serializes it through the normal
|
|
174
|
+
* per-computation path: the server runtime tees the iterator into the
|
|
175
|
+
* hydration serializer (`ctx.serialize(id, tapped)` in solid-js'
|
|
176
|
+
* `processResult`) and seroval streams each yield to the client as a
|
|
177
|
+
* script chunk riding the SSR stream.
|
|
178
|
+
*
|
|
179
|
+
* The iterable must terminate for the SSR stream to complete: the
|
|
180
|
+
* hydration serializer's `flush()` only fires its `onDone` once all
|
|
181
|
+
* pending streams have closed, and the render root is disposed *after*
|
|
182
|
+
* that, so neither `onCleanup` nor the serializer itself can close the
|
|
183
|
+
* channel. Instead the channel closes itself on cache quiescence: after
|
|
184
|
+
* every cache event (and once at creation) it schedules a timer-task
|
|
185
|
+
* check; if no query is fetching by then, no further settle can occur —
|
|
186
|
+
* suspense retry passes that start waterfall fetches are scheduled on
|
|
187
|
+
* microtasks, so they have begun before the check runs — and the channel
|
|
188
|
+
* emits its final cumulative snapshot with `done: true` and completes.
|
|
189
|
+
*
|
|
190
|
+
* Single-consumer by design: solid-js creates exactly one iterator from
|
|
191
|
+
* the value and shares it between the memo and the serializer tap.
|
|
192
|
+
*/
|
|
193
|
+
export declare function createServerDehydrationChannel(client: QueryClient): AsyncIterable<DehydrationChannelYield>;
|
|
194
|
+
|
|
158
195
|
export { DataTag }
|
|
159
196
|
|
|
160
197
|
export { dataTagErrorSymbol }
|
|
@@ -212,10 +249,40 @@ export { DefinedUseQueryResult as DefinedUseQueryResult_alias_1 }
|
|
|
212
249
|
|
|
213
250
|
export { dehydrate }
|
|
214
251
|
|
|
252
|
+
declare type DehydratedQueryEntry = DehydratedState['queries'][number];
|
|
253
|
+
|
|
215
254
|
export { DehydratedState }
|
|
216
255
|
|
|
217
256
|
export { DehydrateOptions }
|
|
218
257
|
|
|
258
|
+
/**
|
|
259
|
+
* A single message on the dehydration channel. `entries` is *cumulative* —
|
|
260
|
+
* every yield carries all entries settled so far. Two reasons:
|
|
261
|
+
*
|
|
262
|
+
* - It is what makes Solid's signal-path hydration replay lossless.
|
|
263
|
+
* Yields still buffered when hydration begins are conflated to the
|
|
264
|
+
* LATEST one (`normalizeIterator` drains synchronously available
|
|
265
|
+
* results, keeps the last data yield, and delivers the stream's done
|
|
266
|
+
* result on a subsequent pull), so each yield must be self-contained:
|
|
267
|
+
* the latest cumulative snapshot alone carries everything the dropped
|
|
268
|
+
* intermediates did. Requires the solid-js build with that conflation
|
|
269
|
+
* behavior (> 2.0.0-beta.32); earlier betas pinned the replay at the
|
|
270
|
+
* FIRST buffered yield, dropping every later entry and the `done`
|
|
271
|
+
* marker.
|
|
272
|
+
* - Entry objects keep their identity across yields, so seroval's
|
|
273
|
+
* cross-reference serialization emits each entry once and later yields
|
|
274
|
+
* only reference it — the cumulative shape costs bytes proportional to
|
|
275
|
+
* the number of entries, not its square.
|
|
276
|
+
*
|
|
277
|
+
* `done: true` marks the final yield. The client uses it to release
|
|
278
|
+
* subscribers still waiting for entries that will never arrive (e.g.
|
|
279
|
+
* queries that errored during SSR and were not dehydrated).
|
|
280
|
+
*/
|
|
281
|
+
export declare interface DehydrationChannelYield {
|
|
282
|
+
entries: Array<DehydratedQueryEntry>;
|
|
283
|
+
done: boolean;
|
|
284
|
+
}
|
|
285
|
+
|
|
219
286
|
export { DistributiveOmit }
|
|
220
287
|
|
|
221
288
|
export { EnsureInfiniteQueryDataOptions }
|
|
@@ -280,6 +347,24 @@ export { hydrate }
|
|
|
280
347
|
|
|
281
348
|
export { HydrateOptions }
|
|
282
349
|
|
|
350
|
+
declare interface HydrationCoordinator {
|
|
351
|
+
/**
|
|
352
|
+
* Prime the QueryClient from a channel yield. Entries already applied
|
|
353
|
+
* (same queryHash and dataUpdatedAt) are skipped; the rest go through
|
|
354
|
+
* query-core `hydrate()`, which keeps whichever data is newer.
|
|
355
|
+
*/
|
|
356
|
+
applyYield: (value: DehydrationChannelYield) => void;
|
|
357
|
+
/**
|
|
358
|
+
* Invoke `callback` (on a microtask) once the entry for `queryHash` has
|
|
359
|
+
* been applied — or immediately-on-a-microtask if it already was, or
|
|
360
|
+
* when the channel completes without one (SSR-errored queries are not
|
|
361
|
+
* dehydrated, so their components must not wait forever).
|
|
362
|
+
*/
|
|
363
|
+
whenQueryPrimed: (queryHash: string, callback: () => void) => void;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export declare const HydrationCoordinatorContext: Context<HydrationCoordinator | null>;
|
|
367
|
+
|
|
283
368
|
export { InferDataFromTag }
|
|
284
369
|
|
|
285
370
|
export { InferErrorFromTag }
|
package/build/dev.cjs
CHANGED
|
@@ -5,6 +5,158 @@ var solidJs = require('solid-js');
|
|
|
5
5
|
var web = require('@solidjs/web');
|
|
6
6
|
|
|
7
7
|
// src/useQuery.ts
|
|
8
|
+
function createServerDehydrationChannel(client) {
|
|
9
|
+
const cache = client.getQueryCache();
|
|
10
|
+
const entryCache = /* @__PURE__ */ new Map();
|
|
11
|
+
const snapshot2 = () => {
|
|
12
|
+
const entries = [];
|
|
13
|
+
for (const query of cache.getAll()) {
|
|
14
|
+
if (query.state.status !== "success") continue;
|
|
15
|
+
let cached = entryCache.get(query.queryHash);
|
|
16
|
+
if (!cached || cached.state !== query.state) {
|
|
17
|
+
cached = {
|
|
18
|
+
state: query.state,
|
|
19
|
+
entry: {
|
|
20
|
+
dehydratedAt: Date.now(),
|
|
21
|
+
state: query.state,
|
|
22
|
+
queryKey: query.queryKey,
|
|
23
|
+
queryHash: query.queryHash,
|
|
24
|
+
...query.meta && { meta: query.meta },
|
|
25
|
+
...query.queryType && { queryType: query.queryType }
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
entryCache.set(query.queryHash, cached);
|
|
29
|
+
}
|
|
30
|
+
entries.push(cached.entry);
|
|
31
|
+
}
|
|
32
|
+
return entries;
|
|
33
|
+
};
|
|
34
|
+
let closed = false;
|
|
35
|
+
let pull = null;
|
|
36
|
+
const buffered = [];
|
|
37
|
+
const emit = (value) => {
|
|
38
|
+
if (closed) return;
|
|
39
|
+
if (value.done) closed = true;
|
|
40
|
+
if (pull) {
|
|
41
|
+
const resolve = pull;
|
|
42
|
+
pull = null;
|
|
43
|
+
resolve({ done: false, value });
|
|
44
|
+
} else {
|
|
45
|
+
buffered.push(value);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
let closeTimer = null;
|
|
49
|
+
const scheduleCloseCheck = () => {
|
|
50
|
+
if (closed || closeTimer !== null) return;
|
|
51
|
+
closeTimer = setTimeout(() => {
|
|
52
|
+
closeTimer = null;
|
|
53
|
+
if (closed) return;
|
|
54
|
+
if (client.isFetching() === 0) {
|
|
55
|
+
unsubscribe();
|
|
56
|
+
emit({ entries: snapshot2(), done: true });
|
|
57
|
+
}
|
|
58
|
+
}, 0);
|
|
59
|
+
};
|
|
60
|
+
const unsubscribe = cache.subscribe((event) => {
|
|
61
|
+
if (closed) return;
|
|
62
|
+
if (event.type === "updated" && event.action.type === "success") {
|
|
63
|
+
emit({ entries: snapshot2(), done: false });
|
|
64
|
+
}
|
|
65
|
+
scheduleCloseCheck();
|
|
66
|
+
});
|
|
67
|
+
scheduleCloseCheck();
|
|
68
|
+
return {
|
|
69
|
+
[Symbol.asyncIterator]() {
|
|
70
|
+
return {
|
|
71
|
+
next() {
|
|
72
|
+
if (buffered.length > 0) {
|
|
73
|
+
return Promise.resolve({ done: false, value: buffered.shift() });
|
|
74
|
+
}
|
|
75
|
+
if (closed) {
|
|
76
|
+
return Promise.resolve({
|
|
77
|
+
done: true,
|
|
78
|
+
value: void 0
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return new Promise(
|
|
82
|
+
(resolve) => {
|
|
83
|
+
pull = resolve;
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
},
|
|
87
|
+
return(value) {
|
|
88
|
+
if (!closed) {
|
|
89
|
+
closed = true;
|
|
90
|
+
unsubscribe();
|
|
91
|
+
if (closeTimer !== null) {
|
|
92
|
+
clearTimeout(closeTimer);
|
|
93
|
+
closeTimer = null;
|
|
94
|
+
}
|
|
95
|
+
const resolve = pull;
|
|
96
|
+
pull = null;
|
|
97
|
+
resolve?.({ done: true, value: void 0 });
|
|
98
|
+
}
|
|
99
|
+
return Promise.resolve({
|
|
100
|
+
done: true,
|
|
101
|
+
value
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function createHydrationCoordinator(client) {
|
|
109
|
+
const applied = /* @__PURE__ */ new Map();
|
|
110
|
+
const waiters = /* @__PURE__ */ new Map();
|
|
111
|
+
let channelDone = false;
|
|
112
|
+
const fireWaiters = (queryHash) => {
|
|
113
|
+
const callbacks = waiters.get(queryHash);
|
|
114
|
+
if (!callbacks) return;
|
|
115
|
+
waiters.delete(queryHash);
|
|
116
|
+
for (const callback of callbacks) queueMicrotask(callback);
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
applyYield(value) {
|
|
120
|
+
const fresh = value.entries.filter(
|
|
121
|
+
(entry) => applied.get(entry.queryHash) !== entry.state.dataUpdatedAt
|
|
122
|
+
);
|
|
123
|
+
if (fresh.length > 0) {
|
|
124
|
+
solidJs.runWithOwner(
|
|
125
|
+
null,
|
|
126
|
+
() => queryCore.hydrate(client(), { queries: fresh, mutations: [] })
|
|
127
|
+
);
|
|
128
|
+
for (const entry of fresh) {
|
|
129
|
+
applied.set(entry.queryHash, entry.state.dataUpdatedAt);
|
|
130
|
+
fireWaiters(entry.queryHash);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (value.done && !channelDone) {
|
|
134
|
+
channelDone = true;
|
|
135
|
+
const remaining = [...waiters.values()];
|
|
136
|
+
waiters.clear();
|
|
137
|
+
for (const callbacks of remaining) {
|
|
138
|
+
for (const callback of callbacks) queueMicrotask(callback);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
whenQueryPrimed(queryHash, callback) {
|
|
143
|
+
if (channelDone || applied.has(queryHash)) {
|
|
144
|
+
queueMicrotask(callback);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
let list = waiters.get(queryHash);
|
|
148
|
+
if (!list) {
|
|
149
|
+
list = [];
|
|
150
|
+
waiters.set(queryHash, list);
|
|
151
|
+
}
|
|
152
|
+
list.push(callback);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
var HydrationCoordinatorContext = solidJs.createContext(null);
|
|
157
|
+
|
|
158
|
+
// src/QueryClientProvider.tsx
|
|
159
|
+
var isServer = typeof window === "undefined";
|
|
8
160
|
exports.QueryClientContext = solidJs.createContext(null);
|
|
9
161
|
exports.useQueryClient = (queryClient) => {
|
|
10
162
|
if (queryClient) {
|
|
@@ -19,10 +171,22 @@ exports.useQueryClient = (queryClient) => {
|
|
|
19
171
|
exports.QueryClientProvider = (props) => {
|
|
20
172
|
props.client.mount();
|
|
21
173
|
solidJs.onCleanup(() => props.client.unmount());
|
|
174
|
+
const [channelValue] = solidJs.createSignal(() => isServer ? createServerDehydrationChannel(props.client) : void 0);
|
|
175
|
+
const coordinator = isServer ? null : createHydrationCoordinator(() => props.client);
|
|
176
|
+
solidJs.createRenderEffect(() => isServer ? void 0 : channelValue(), (value) => {
|
|
177
|
+
if (value && coordinator) {
|
|
178
|
+
coordinator.applyYield(value);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
22
181
|
return web.createComponent(exports.QueryClientContext, {
|
|
23
182
|
value: () => props.client,
|
|
24
183
|
get children() {
|
|
25
|
-
return
|
|
184
|
+
return web.createComponent(HydrationCoordinatorContext, {
|
|
185
|
+
value: coordinator,
|
|
186
|
+
get children() {
|
|
187
|
+
return props.children;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
26
190
|
}
|
|
27
191
|
});
|
|
28
192
|
};
|
|
@@ -30,9 +194,9 @@ exports.IsRestoringContext = solidJs.createContext(() => false);
|
|
|
30
194
|
exports.useIsRestoring = () => solidJs.useContext(exports.IsRestoringContext);
|
|
31
195
|
|
|
32
196
|
// src/useBaseQuery.ts
|
|
33
|
-
var
|
|
197
|
+
var isServer2 = typeof window === "undefined";
|
|
34
198
|
function _stripFnsForSSR(obj) {
|
|
35
|
-
if (!
|
|
199
|
+
if (!isServer2) return obj;
|
|
36
200
|
const out = {};
|
|
37
201
|
for (const k of Object.keys(obj)) {
|
|
38
202
|
if (k === "refetch" || k === "fetchNextPage" || k === "fetchPreviousPage") {
|
|
@@ -72,8 +236,8 @@ function reconcileFn(store, result, reconcileOption, queryHash) {
|
|
|
72
236
|
}
|
|
73
237
|
return { ...result, data };
|
|
74
238
|
}
|
|
75
|
-
var hydratableObserverResult = (
|
|
76
|
-
if (!
|
|
239
|
+
var hydratableObserverResult = (_query, result) => {
|
|
240
|
+
if (!isServer2) return result;
|
|
77
241
|
const obj = {
|
|
78
242
|
...solidJs.snapshot(result),
|
|
79
243
|
// During SSR, functions cannot be serialized, so we need to remove them
|
|
@@ -84,12 +248,6 @@ var hydratableObserverResult = (query, result) => {
|
|
|
84
248
|
obj.fetchNextPage = void 0;
|
|
85
249
|
obj.fetchPreviousPage = void 0;
|
|
86
250
|
}
|
|
87
|
-
obj.hydrationData = {
|
|
88
|
-
state: query.state,
|
|
89
|
-
queryKey: query.queryKey,
|
|
90
|
-
queryHash: query.queryHash,
|
|
91
|
-
...query.meta && { meta: query.meta }
|
|
92
|
-
};
|
|
93
251
|
return obj;
|
|
94
252
|
};
|
|
95
253
|
function useBaseQuery(options, Observer, queryClient) {
|
|
@@ -100,7 +258,7 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
100
258
|
const defaultOptions = client().defaultQueryOptions(options());
|
|
101
259
|
defaultOptions._optimisticResults = isRestoring() ? "isRestoring" : "optimistic";
|
|
102
260
|
defaultOptions.structuralSharing = false;
|
|
103
|
-
if (
|
|
261
|
+
if (isServer2) {
|
|
104
262
|
defaultOptions.retry = false;
|
|
105
263
|
defaultOptions.throwOnError = true;
|
|
106
264
|
defaultOptions.experimental_prefetchInRender = true;
|
|
@@ -172,11 +330,25 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
172
330
|
}
|
|
173
331
|
let unsubscribe = null;
|
|
174
332
|
let disposed = false;
|
|
333
|
+
const coordinator = solidJs.useContext(HydrationCoordinatorContext);
|
|
334
|
+
const attachHydratedSubscriber = () => {
|
|
335
|
+
if (!unsubscribe && !disposed && !isRestoring()) {
|
|
336
|
+
unsubscribe = createClientSubscriber();
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
const scheduleHydratedAttach = () => {
|
|
340
|
+
const queryHash = solidJs.untrack(() => observer.getCurrentQuery().queryHash);
|
|
341
|
+
if (coordinator) {
|
|
342
|
+
coordinator.whenQueryPrimed(queryHash, attachHydratedSubscriber);
|
|
343
|
+
} else {
|
|
344
|
+
queueMicrotask(attachHydratedSubscriber);
|
|
345
|
+
}
|
|
346
|
+
};
|
|
175
347
|
let resolver = null;
|
|
176
348
|
const [queryResource] = solidJs.createSignal(() => {
|
|
177
349
|
const opts = trackedDefaultedOptions();
|
|
178
350
|
const restoring = isRestoring();
|
|
179
|
-
if (
|
|
351
|
+
if (isServer2) {
|
|
180
352
|
const cached = observer.getOptimisticResult(opts);
|
|
181
353
|
if (!cached.isLoading) {
|
|
182
354
|
observerResult = cached;
|
|
@@ -189,9 +361,11 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
189
361
|
);
|
|
190
362
|
}
|
|
191
363
|
}
|
|
192
|
-
|
|
364
|
+
const replayProbe = { executorRan: false };
|
|
365
|
+
const resource = new Promise((resolve, reject) => {
|
|
366
|
+
replayProbe.executorRan = true;
|
|
193
367
|
resolver = resolve;
|
|
194
|
-
if (
|
|
368
|
+
if (isServer2) {
|
|
195
369
|
unsubscribe = createServerSubscriber((data) => {
|
|
196
370
|
resolve(data);
|
|
197
371
|
}, reject);
|
|
@@ -224,10 +398,14 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
224
398
|
);
|
|
225
399
|
}
|
|
226
400
|
});
|
|
401
|
+
if (!isServer2 && !replayProbe.executorRan) {
|
|
402
|
+
scheduleHydratedAttach();
|
|
403
|
+
}
|
|
404
|
+
return resource;
|
|
227
405
|
});
|
|
228
406
|
solidJs.onCleanup(() => {
|
|
229
407
|
disposed = true;
|
|
230
|
-
if (
|
|
408
|
+
if (isServer2 && solidJs.isPending(queryResource)) {
|
|
231
409
|
unsubscribeQueued = true;
|
|
232
410
|
return;
|
|
233
411
|
}
|
|
@@ -235,7 +413,7 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
235
413
|
unsubscribe();
|
|
236
414
|
unsubscribe = null;
|
|
237
415
|
}
|
|
238
|
-
if (resolver && !
|
|
416
|
+
if (resolver && !isServer2) {
|
|
239
417
|
resolver(observerResult);
|
|
240
418
|
resolver = null;
|
|
241
419
|
}
|
|
@@ -253,7 +431,7 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
253
431
|
if (typeof prop === "symbol") {
|
|
254
432
|
return Reflect.get(target, prop, receiver);
|
|
255
433
|
}
|
|
256
|
-
if (
|
|
434
|
+
if (isServer2) {
|
|
257
435
|
const resolved = queryResource();
|
|
258
436
|
if (prop in resolved) {
|
|
259
437
|
return Reflect.get(resolved, prop);
|