@tanstack/solid-query 6.0.0-beta.7 → 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/dev.js CHANGED
@@ -1,9 +1,161 @@
1
- import { MutationObserver, shouldThrowError, QueriesObserver, QueryClient as QueryClient$1, replaceEqualDeep, noop, notifyManager, QueryObserver, InfiniteQueryObserver } from '@tanstack/query-core';
1
+ import { MutationObserver, shouldThrowError, QueriesObserver, QueryClient as QueryClient$1, replaceEqualDeep, noop, hydrate, notifyManager, QueryObserver, InfiniteQueryObserver } from '@tanstack/query-core';
2
2
  export * from '@tanstack/query-core';
3
- import { createContext, useContext, onCleanup, createMemo, untrack, createRenderEffect, createStore, runWithOwner, merge, createEffect, reconcile, createSignal, isPending, refresh, snapshot } from 'solid-js';
3
+ import { createContext, useContext, onCleanup, createSignal, createRenderEffect, createMemo, untrack, createStore, runWithOwner, merge, createEffect, reconcile, isPending, refresh, snapshot } from 'solid-js';
4
4
  import { createComponent } from '@solidjs/web';
5
5
 
6
6
  // src/useQuery.ts
7
+ function createServerDehydrationChannel(client) {
8
+ const cache = client.getQueryCache();
9
+ const entryCache = /* @__PURE__ */ new Map();
10
+ const snapshot2 = () => {
11
+ const entries = [];
12
+ for (const query of cache.getAll()) {
13
+ if (query.state.status !== "success") continue;
14
+ let cached = entryCache.get(query.queryHash);
15
+ if (!cached || cached.state !== query.state) {
16
+ cached = {
17
+ state: query.state,
18
+ entry: {
19
+ dehydratedAt: Date.now(),
20
+ state: query.state,
21
+ queryKey: query.queryKey,
22
+ queryHash: query.queryHash,
23
+ ...query.meta && { meta: query.meta },
24
+ ...query.queryType && { queryType: query.queryType }
25
+ }
26
+ };
27
+ entryCache.set(query.queryHash, cached);
28
+ }
29
+ entries.push(cached.entry);
30
+ }
31
+ return entries;
32
+ };
33
+ let closed = false;
34
+ let pull = null;
35
+ const buffered = [];
36
+ const emit = (value) => {
37
+ if (closed) return;
38
+ if (value.done) closed = true;
39
+ if (pull) {
40
+ const resolve = pull;
41
+ pull = null;
42
+ resolve({ done: false, value });
43
+ } else {
44
+ buffered.push(value);
45
+ }
46
+ };
47
+ let closeTimer = null;
48
+ const scheduleCloseCheck = () => {
49
+ if (closed || closeTimer !== null) return;
50
+ closeTimer = setTimeout(() => {
51
+ closeTimer = null;
52
+ if (closed) return;
53
+ if (client.isFetching() === 0) {
54
+ unsubscribe();
55
+ emit({ entries: snapshot2(), done: true });
56
+ }
57
+ }, 0);
58
+ };
59
+ const unsubscribe = cache.subscribe((event) => {
60
+ if (closed) return;
61
+ if (event.type === "updated" && event.action.type === "success") {
62
+ emit({ entries: snapshot2(), done: false });
63
+ }
64
+ scheduleCloseCheck();
65
+ });
66
+ scheduleCloseCheck();
67
+ return {
68
+ [Symbol.asyncIterator]() {
69
+ return {
70
+ next() {
71
+ if (buffered.length > 0) {
72
+ return Promise.resolve({ done: false, value: buffered.shift() });
73
+ }
74
+ if (closed) {
75
+ return Promise.resolve({
76
+ done: true,
77
+ value: void 0
78
+ });
79
+ }
80
+ return new Promise(
81
+ (resolve) => {
82
+ pull = resolve;
83
+ }
84
+ );
85
+ },
86
+ return(value) {
87
+ if (!closed) {
88
+ closed = true;
89
+ unsubscribe();
90
+ if (closeTimer !== null) {
91
+ clearTimeout(closeTimer);
92
+ closeTimer = null;
93
+ }
94
+ const resolve = pull;
95
+ pull = null;
96
+ resolve?.({ done: true, value: void 0 });
97
+ }
98
+ return Promise.resolve({
99
+ done: true,
100
+ value
101
+ });
102
+ }
103
+ };
104
+ }
105
+ };
106
+ }
107
+ function createHydrationCoordinator(client) {
108
+ const applied = /* @__PURE__ */ new Map();
109
+ const waiters = /* @__PURE__ */ new Map();
110
+ let channelDone = false;
111
+ const fireWaiters = (queryHash) => {
112
+ const callbacks = waiters.get(queryHash);
113
+ if (!callbacks) return;
114
+ waiters.delete(queryHash);
115
+ for (const callback of callbacks) queueMicrotask(callback);
116
+ };
117
+ return {
118
+ applyYield(value) {
119
+ const fresh = value.entries.filter(
120
+ (entry) => applied.get(entry.queryHash) !== entry.state.dataUpdatedAt
121
+ );
122
+ if (fresh.length > 0) {
123
+ runWithOwner(
124
+ null,
125
+ () => hydrate(client(), { queries: fresh, mutations: [] })
126
+ );
127
+ for (const entry of fresh) {
128
+ applied.set(entry.queryHash, entry.state.dataUpdatedAt);
129
+ fireWaiters(entry.queryHash);
130
+ }
131
+ }
132
+ if (value.done && !channelDone) {
133
+ channelDone = true;
134
+ const remaining = [...waiters.values()];
135
+ waiters.clear();
136
+ for (const callbacks of remaining) {
137
+ for (const callback of callbacks) queueMicrotask(callback);
138
+ }
139
+ }
140
+ },
141
+ whenQueryPrimed(queryHash, callback) {
142
+ if (channelDone || applied.has(queryHash)) {
143
+ queueMicrotask(callback);
144
+ return;
145
+ }
146
+ let list = waiters.get(queryHash);
147
+ if (!list) {
148
+ list = [];
149
+ waiters.set(queryHash, list);
150
+ }
151
+ list.push(callback);
152
+ }
153
+ };
154
+ }
155
+ var HydrationCoordinatorContext = createContext(null);
156
+
157
+ // src/QueryClientProvider.tsx
158
+ var isServer = typeof window === "undefined";
7
159
  var QueryClientContext = createContext(null);
8
160
  var useQueryClient = (queryClient) => {
9
161
  if (queryClient) {
@@ -18,10 +170,22 @@ var useQueryClient = (queryClient) => {
18
170
  var QueryClientProvider = (props) => {
19
171
  props.client.mount();
20
172
  onCleanup(() => props.client.unmount());
173
+ const [channelValue] = createSignal(() => isServer ? createServerDehydrationChannel(props.client) : void 0);
174
+ const coordinator = isServer ? null : createHydrationCoordinator(() => props.client);
175
+ createRenderEffect(() => isServer ? void 0 : channelValue(), (value) => {
176
+ if (value && coordinator) {
177
+ coordinator.applyYield(value);
178
+ }
179
+ });
21
180
  return createComponent(QueryClientContext, {
22
181
  value: () => props.client,
23
182
  get children() {
24
- return props.children;
183
+ return createComponent(HydrationCoordinatorContext, {
184
+ value: coordinator,
185
+ get children() {
186
+ return props.children;
187
+ }
188
+ });
25
189
  }
26
190
  });
27
191
  };
@@ -29,9 +193,9 @@ var IsRestoringContext = createContext(() => false);
29
193
  var useIsRestoring = () => useContext(IsRestoringContext);
30
194
 
31
195
  // src/useBaseQuery.ts
32
- var isServer = typeof window === "undefined";
196
+ var isServer2 = typeof window === "undefined";
33
197
  function _stripFnsForSSR(obj) {
34
- if (!isServer) return obj;
198
+ if (!isServer2) return obj;
35
199
  const out = {};
36
200
  for (const k of Object.keys(obj)) {
37
201
  if (k === "refetch" || k === "fetchNextPage" || k === "fetchPreviousPage") {
@@ -71,8 +235,8 @@ function reconcileFn(store, result, reconcileOption, queryHash) {
71
235
  }
72
236
  return { ...result, data };
73
237
  }
74
- var hydratableObserverResult = (query, result) => {
75
- if (!isServer) return result;
238
+ var hydratableObserverResult = (_query, result) => {
239
+ if (!isServer2) return result;
76
240
  const obj = {
77
241
  ...snapshot(result),
78
242
  // During SSR, functions cannot be serialized, so we need to remove them
@@ -83,12 +247,6 @@ var hydratableObserverResult = (query, result) => {
83
247
  obj.fetchNextPage = void 0;
84
248
  obj.fetchPreviousPage = void 0;
85
249
  }
86
- obj.hydrationData = {
87
- state: query.state,
88
- queryKey: query.queryKey,
89
- queryHash: query.queryHash,
90
- ...query.meta && { meta: query.meta }
91
- };
92
250
  return obj;
93
251
  };
94
252
  function useBaseQuery(options, Observer, queryClient) {
@@ -99,7 +257,7 @@ function useBaseQuery(options, Observer, queryClient) {
99
257
  const defaultOptions = client().defaultQueryOptions(options());
100
258
  defaultOptions._optimisticResults = isRestoring() ? "isRestoring" : "optimistic";
101
259
  defaultOptions.structuralSharing = false;
102
- if (isServer) {
260
+ if (isServer2) {
103
261
  defaultOptions.retry = false;
104
262
  defaultOptions.throwOnError = true;
105
263
  defaultOptions.experimental_prefetchInRender = true;
@@ -171,11 +329,25 @@ function useBaseQuery(options, Observer, queryClient) {
171
329
  }
172
330
  let unsubscribe = null;
173
331
  let disposed = false;
332
+ const coordinator = useContext(HydrationCoordinatorContext);
333
+ const attachHydratedSubscriber = () => {
334
+ if (!unsubscribe && !disposed && !isRestoring()) {
335
+ unsubscribe = createClientSubscriber();
336
+ }
337
+ };
338
+ const scheduleHydratedAttach = () => {
339
+ const queryHash = untrack(() => observer.getCurrentQuery().queryHash);
340
+ if (coordinator) {
341
+ coordinator.whenQueryPrimed(queryHash, attachHydratedSubscriber);
342
+ } else {
343
+ queueMicrotask(attachHydratedSubscriber);
344
+ }
345
+ };
174
346
  let resolver = null;
175
347
  const [queryResource] = createSignal(() => {
176
348
  const opts = trackedDefaultedOptions();
177
349
  const restoring = isRestoring();
178
- if (isServer) {
350
+ if (isServer2) {
179
351
  const cached = observer.getOptimisticResult(opts);
180
352
  if (!cached.isLoading) {
181
353
  observerResult = cached;
@@ -188,9 +360,11 @@ function useBaseQuery(options, Observer, queryClient) {
188
360
  );
189
361
  }
190
362
  }
191
- return new Promise((resolve, reject) => {
363
+ const replayProbe = { executorRan: false };
364
+ const resource = new Promise((resolve, reject) => {
365
+ replayProbe.executorRan = true;
192
366
  resolver = resolve;
193
- if (isServer) {
367
+ if (isServer2) {
194
368
  unsubscribe = createServerSubscriber((data) => {
195
369
  resolve(data);
196
370
  }, reject);
@@ -223,10 +397,14 @@ function useBaseQuery(options, Observer, queryClient) {
223
397
  );
224
398
  }
225
399
  });
400
+ if (!isServer2 && !replayProbe.executorRan) {
401
+ scheduleHydratedAttach();
402
+ }
403
+ return resource;
226
404
  });
227
405
  onCleanup(() => {
228
406
  disposed = true;
229
- if (isServer && isPending(queryResource)) {
407
+ if (isServer2 && isPending(queryResource)) {
230
408
  unsubscribeQueued = true;
231
409
  return;
232
410
  }
@@ -234,7 +412,7 @@ function useBaseQuery(options, Observer, queryClient) {
234
412
  unsubscribe();
235
413
  unsubscribe = null;
236
414
  }
237
- if (resolver && !isServer) {
415
+ if (resolver && !isServer2) {
238
416
  resolver(observerResult);
239
417
  resolver = null;
240
418
  }
@@ -252,7 +430,7 @@ function useBaseQuery(options, Observer, queryClient) {
252
430
  if (typeof prop === "symbol") {
253
431
  return Reflect.get(target, prop, receiver);
254
432
  }
255
- if (isServer) {
433
+ if (isServer2) {
256
434
  const resolved = queryResource();
257
435
  if (prop in resolved) {
258
436
  return Reflect.get(resolved, prop);
package/build/index.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 props.children;
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 isServer = typeof window === "undefined";
197
+ var isServer2 = typeof window === "undefined";
34
198
  function _stripFnsForSSR(obj) {
35
- if (!isServer) return obj;
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") {
@@ -63,8 +227,8 @@ function reconcileFn(store, result, reconcileOption, queryHash) {
63
227
  }
64
228
  return { ...result, data };
65
229
  }
66
- var hydratableObserverResult = (query, result) => {
67
- if (!isServer) return result;
230
+ var hydratableObserverResult = (_query, result) => {
231
+ if (!isServer2) return result;
68
232
  const obj = {
69
233
  ...solidJs.snapshot(result),
70
234
  // During SSR, functions cannot be serialized, so we need to remove them
@@ -75,12 +239,6 @@ var hydratableObserverResult = (query, result) => {
75
239
  obj.fetchNextPage = void 0;
76
240
  obj.fetchPreviousPage = void 0;
77
241
  }
78
- obj.hydrationData = {
79
- state: query.state,
80
- queryKey: query.queryKey,
81
- queryHash: query.queryHash,
82
- ...query.meta && { meta: query.meta }
83
- };
84
242
  return obj;
85
243
  };
86
244
  function useBaseQuery(options, Observer, queryClient) {
@@ -91,7 +249,7 @@ function useBaseQuery(options, Observer, queryClient) {
91
249
  const defaultOptions = client().defaultQueryOptions(options());
92
250
  defaultOptions._optimisticResults = isRestoring() ? "isRestoring" : "optimistic";
93
251
  defaultOptions.structuralSharing = false;
94
- if (isServer) {
252
+ if (isServer2) {
95
253
  defaultOptions.retry = false;
96
254
  defaultOptions.throwOnError = true;
97
255
  defaultOptions.experimental_prefetchInRender = true;
@@ -163,11 +321,25 @@ function useBaseQuery(options, Observer, queryClient) {
163
321
  }
164
322
  let unsubscribe = null;
165
323
  let disposed = false;
324
+ const coordinator = solidJs.useContext(HydrationCoordinatorContext);
325
+ const attachHydratedSubscriber = () => {
326
+ if (!unsubscribe && !disposed && !isRestoring()) {
327
+ unsubscribe = createClientSubscriber();
328
+ }
329
+ };
330
+ const scheduleHydratedAttach = () => {
331
+ const queryHash = solidJs.untrack(() => observer.getCurrentQuery().queryHash);
332
+ if (coordinator) {
333
+ coordinator.whenQueryPrimed(queryHash, attachHydratedSubscriber);
334
+ } else {
335
+ queueMicrotask(attachHydratedSubscriber);
336
+ }
337
+ };
166
338
  let resolver = null;
167
339
  const [queryResource] = solidJs.createSignal(() => {
168
340
  const opts = trackedDefaultedOptions();
169
341
  const restoring = isRestoring();
170
- if (isServer) {
342
+ if (isServer2) {
171
343
  const cached = observer.getOptimisticResult(opts);
172
344
  if (!cached.isLoading) {
173
345
  observerResult = cached;
@@ -180,9 +352,11 @@ function useBaseQuery(options, Observer, queryClient) {
180
352
  );
181
353
  }
182
354
  }
183
- return new Promise((resolve, reject) => {
355
+ const replayProbe = { executorRan: false };
356
+ const resource = new Promise((resolve, reject) => {
357
+ replayProbe.executorRan = true;
184
358
  resolver = resolve;
185
- if (isServer) {
359
+ if (isServer2) {
186
360
  unsubscribe = createServerSubscriber((data) => {
187
361
  resolve(data);
188
362
  }, reject);
@@ -215,10 +389,14 @@ function useBaseQuery(options, Observer, queryClient) {
215
389
  );
216
390
  }
217
391
  });
392
+ if (!isServer2 && !replayProbe.executorRan) {
393
+ scheduleHydratedAttach();
394
+ }
395
+ return resource;
218
396
  });
219
397
  solidJs.onCleanup(() => {
220
398
  disposed = true;
221
- if (isServer && solidJs.isPending(queryResource)) {
399
+ if (isServer2 && solidJs.isPending(queryResource)) {
222
400
  unsubscribeQueued = true;
223
401
  return;
224
402
  }
@@ -226,7 +404,7 @@ function useBaseQuery(options, Observer, queryClient) {
226
404
  unsubscribe();
227
405
  unsubscribe = null;
228
406
  }
229
- if (resolver && !isServer) {
407
+ if (resolver && !isServer2) {
230
408
  resolver(observerResult);
231
409
  resolver = null;
232
410
  }
@@ -244,7 +422,7 @@ function useBaseQuery(options, Observer, queryClient) {
244
422
  if (typeof prop === "symbol") {
245
423
  return Reflect.get(target, prop, receiver);
246
424
  }
247
- if (isServer) {
425
+ if (isServer2) {
248
426
  const resolved = queryResource();
249
427
  if (prop in resolved) {
250
428
  return Reflect.get(resolved, prop);