@braine/quantum-query 1.2.6 → 1.2.7
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/README.md +56 -297
- package/dist/index.cjs +866 -827
- package/dist/index.d.cts +138 -128
- package/dist/index.d.ts +138 -128
- package/dist/index.js +887 -839
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -21,302 +21,34 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
HydrationBoundary: () => HydrationBoundary,
|
|
24
|
-
|
|
24
|
+
QueryClient: () => QueryClient,
|
|
25
25
|
QueryClientProvider: () => QueryClientProvider,
|
|
26
|
-
|
|
26
|
+
SignalValue: () => SignalValue,
|
|
27
|
+
atom: () => atom,
|
|
27
28
|
createHttpClient: () => createHttpClient,
|
|
28
|
-
createState: () => createState,
|
|
29
|
-
defineModel: () => defineModel,
|
|
30
29
|
dehydrate: () => dehydrate,
|
|
31
30
|
enableDevTools: () => enableDevTools,
|
|
32
|
-
fromSignal: () => fromSignal,
|
|
33
31
|
getPromiseState: () => getPromiseState,
|
|
34
32
|
handlePromise: () => handlePromise,
|
|
35
33
|
hydrate: () => hydrate,
|
|
36
34
|
isPromise: () => isPromise,
|
|
37
35
|
scheduleUpdate: () => scheduleUpdate,
|
|
38
|
-
subscribe: () => subscribe,
|
|
39
|
-
toSignal: () => toSignal,
|
|
40
36
|
unwrapPromise: () => unwrapPromise,
|
|
41
37
|
useInfiniteQuery: () => useInfiniteQuery,
|
|
42
38
|
useMutation: () => useMutation,
|
|
43
39
|
usePaginatedQuery: () => usePaginatedQuery,
|
|
44
40
|
useQuery: () => useQuery,
|
|
41
|
+
useQuery$: () => useQuery$,
|
|
45
42
|
useQueryClient: () => useQueryClient,
|
|
46
|
-
|
|
43
|
+
useQueryStore: () => useQueryStore,
|
|
47
44
|
useSuspenseQuery: () => useSuspenseQuery
|
|
48
45
|
});
|
|
49
46
|
module.exports = __toCommonJS(index_exports);
|
|
50
47
|
|
|
51
|
-
// src/
|
|
52
|
-
var pending = /* @__PURE__ */ new Set();
|
|
53
|
-
var timer = null;
|
|
54
|
-
function flush() {
|
|
55
|
-
timer = null;
|
|
56
|
-
const tasks = [...pending];
|
|
57
|
-
pending.clear();
|
|
58
|
-
tasks.forEach((task) => task());
|
|
59
|
-
}
|
|
60
|
-
function scheduleUpdate(callback) {
|
|
61
|
-
pending.add(callback);
|
|
62
|
-
if (!timer) {
|
|
63
|
-
timer = Promise.resolve().then(flush);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// src/core/asyncUtils.ts
|
|
68
|
-
var PROMISE_CACHE = /* @__PURE__ */ new WeakMap();
|
|
69
|
-
var PROMISE_STATUS = /* @__PURE__ */ new WeakMap();
|
|
70
|
-
var PROMISE_ERROR = /* @__PURE__ */ new WeakMap();
|
|
71
|
-
function isPromise(value) {
|
|
72
|
-
return !!value && typeof value.then === "function";
|
|
73
|
-
}
|
|
74
|
-
function handlePromise(promise, triggerUpdate) {
|
|
75
|
-
if (PROMISE_STATUS.has(promise)) return;
|
|
76
|
-
PROMISE_STATUS.set(promise, "pending");
|
|
77
|
-
promise.then(
|
|
78
|
-
(value) => {
|
|
79
|
-
PROMISE_STATUS.set(promise, "fulfilled");
|
|
80
|
-
PROMISE_CACHE.set(promise, value);
|
|
81
|
-
triggerUpdate();
|
|
82
|
-
},
|
|
83
|
-
(error) => {
|
|
84
|
-
PROMISE_STATUS.set(promise, "rejected");
|
|
85
|
-
PROMISE_ERROR.set(promise, error);
|
|
86
|
-
triggerUpdate();
|
|
87
|
-
}
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
function unwrapPromise(promise) {
|
|
91
|
-
const status = PROMISE_STATUS.get(promise);
|
|
92
|
-
if (status === "fulfilled") {
|
|
93
|
-
return PROMISE_CACHE.get(promise);
|
|
94
|
-
} else if (status === "rejected") {
|
|
95
|
-
throw PROMISE_ERROR.get(promise);
|
|
96
|
-
} else {
|
|
97
|
-
throw promise;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
function getPromiseState(promise) {
|
|
101
|
-
return {
|
|
102
|
-
status: PROMISE_STATUS.get(promise) || "pending",
|
|
103
|
-
value: PROMISE_CACHE.get(promise),
|
|
104
|
-
error: PROMISE_ERROR.get(promise)
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// src/core/proxy.ts
|
|
109
|
-
var LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
110
|
-
var PROXIES = /* @__PURE__ */ new WeakMap();
|
|
111
|
-
var PROXY_TO_TARGET = /* @__PURE__ */ new WeakMap();
|
|
112
|
-
var activeListener = null;
|
|
113
|
-
function setActiveListener(listener) {
|
|
114
|
-
activeListener = listener;
|
|
115
|
-
}
|
|
116
|
-
function getActiveListener() {
|
|
117
|
-
return activeListener;
|
|
118
|
-
}
|
|
119
|
-
var GLOBAL_LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
120
|
-
function subscribe(store, callback) {
|
|
121
|
-
const target = PROXY_TO_TARGET.get(store) || store;
|
|
122
|
-
let listeners = GLOBAL_LISTENERS.get(target);
|
|
123
|
-
if (!listeners) {
|
|
124
|
-
listeners = /* @__PURE__ */ new Set();
|
|
125
|
-
GLOBAL_LISTENERS.set(target, listeners);
|
|
126
|
-
}
|
|
127
|
-
listeners.add(callback);
|
|
128
|
-
return () => listeners?.delete(callback);
|
|
129
|
-
}
|
|
130
|
-
var handler = {
|
|
131
|
-
get(target, prop, receiver) {
|
|
132
|
-
if (activeListener) {
|
|
133
|
-
let listeners = LISTENERS.get(target);
|
|
134
|
-
if (!listeners) {
|
|
135
|
-
listeners = /* @__PURE__ */ new Set();
|
|
136
|
-
LISTENERS.set(target, listeners);
|
|
137
|
-
}
|
|
138
|
-
listeners.add(activeListener);
|
|
139
|
-
}
|
|
140
|
-
const value = Reflect.get(target, prop, receiver);
|
|
141
|
-
if (isPromise(value)) {
|
|
142
|
-
return unwrapPromise(value);
|
|
143
|
-
}
|
|
144
|
-
if (typeof value === "object" && value !== null) {
|
|
145
|
-
return createState(value);
|
|
146
|
-
}
|
|
147
|
-
return value;
|
|
148
|
-
},
|
|
149
|
-
set(target, prop, value, receiver) {
|
|
150
|
-
const oldValue = Reflect.get(target, prop, receiver);
|
|
151
|
-
if (Object.is(oldValue, value)) return true;
|
|
152
|
-
if (isPromise(value)) {
|
|
153
|
-
const trigger = () => {
|
|
154
|
-
const listeners2 = LISTENERS.get(target);
|
|
155
|
-
if (listeners2) listeners2.forEach((l) => l());
|
|
156
|
-
};
|
|
157
|
-
handlePromise(value, trigger);
|
|
158
|
-
}
|
|
159
|
-
const result = Reflect.set(target, prop, value, receiver);
|
|
160
|
-
const listeners = LISTENERS.get(target);
|
|
161
|
-
if (listeners) {
|
|
162
|
-
listeners.forEach((l) => l());
|
|
163
|
-
}
|
|
164
|
-
const globals = GLOBAL_LISTENERS.get(target);
|
|
165
|
-
if (globals) {
|
|
166
|
-
globals.forEach((cb) => cb(target, prop, value));
|
|
167
|
-
}
|
|
168
|
-
return result;
|
|
169
|
-
},
|
|
170
|
-
deleteProperty(target, prop) {
|
|
171
|
-
const result = Reflect.deleteProperty(target, prop);
|
|
172
|
-
const listeners = LISTENERS.get(target);
|
|
173
|
-
if (listeners) {
|
|
174
|
-
listeners.forEach((l) => l());
|
|
175
|
-
}
|
|
176
|
-
return result;
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
function createState(initialState) {
|
|
180
|
-
if (PROXIES.has(initialState)) {
|
|
181
|
-
return PROXIES.get(initialState);
|
|
182
|
-
}
|
|
183
|
-
const proxy = new Proxy(initialState, handler);
|
|
184
|
-
PROXIES.set(initialState, proxy);
|
|
185
|
-
PROXY_TO_TARGET.set(proxy, initialState);
|
|
186
|
-
return proxy;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// src/core/model.ts
|
|
190
|
-
function debounce(fn, ms) {
|
|
191
|
-
let timeout;
|
|
192
|
-
return (...args) => {
|
|
193
|
-
clearTimeout(timeout);
|
|
194
|
-
timeout = setTimeout(() => fn(...args), ms);
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
function defineModel(def) {
|
|
198
|
-
const target = def.state;
|
|
199
|
-
if (def.actions) {
|
|
200
|
-
for (const [key, fn] of Object.entries(def.actions)) {
|
|
201
|
-
target[key] = fn;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (def.computed) {
|
|
205
|
-
for (const [key, getter] of Object.entries(def.computed)) {
|
|
206
|
-
if (typeof getter === "function") {
|
|
207
|
-
Object.defineProperty(target, key, {
|
|
208
|
-
get: function() {
|
|
209
|
-
return getter.call(this);
|
|
210
|
-
},
|
|
211
|
-
enumerable: true,
|
|
212
|
-
configurable: true
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const proxy = createState(target);
|
|
218
|
-
if (def.persist) {
|
|
219
|
-
const { key, storage = "local", paths, debug } = def.persist;
|
|
220
|
-
let engine = null;
|
|
221
|
-
if (typeof storage === "string") {
|
|
222
|
-
if (typeof window !== "undefined") {
|
|
223
|
-
engine = storage === "local" ? window.localStorage : window.sessionStorage;
|
|
224
|
-
}
|
|
225
|
-
} else {
|
|
226
|
-
engine = storage;
|
|
227
|
-
}
|
|
228
|
-
if (engine) {
|
|
229
|
-
const hydrate2 = () => {
|
|
230
|
-
const process = (stored) => {
|
|
231
|
-
try {
|
|
232
|
-
if (stored) {
|
|
233
|
-
const parsed = JSON.parse(stored);
|
|
234
|
-
Object.assign(proxy, parsed);
|
|
235
|
-
if (debug) console.log(`[Quantum] Hydrated '${key}'`, parsed);
|
|
236
|
-
}
|
|
237
|
-
} catch (err) {
|
|
238
|
-
if (debug) console.error(`[Quantum] Hydration Failed for '${key}'`, err);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
try {
|
|
242
|
-
const result = engine.getItem(key);
|
|
243
|
-
if (result instanceof Promise) {
|
|
244
|
-
result.then(process);
|
|
245
|
-
} else {
|
|
246
|
-
process(result);
|
|
247
|
-
}
|
|
248
|
-
} catch (err) {
|
|
249
|
-
if (debug) console.error(`[Quantum] Storage Access Failed`, err);
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
hydrate2();
|
|
253
|
-
const save = debounce(async () => {
|
|
254
|
-
try {
|
|
255
|
-
let stateToSave;
|
|
256
|
-
if (paths) {
|
|
257
|
-
stateToSave = {};
|
|
258
|
-
for (const p of paths) {
|
|
259
|
-
stateToSave[p] = proxy[p];
|
|
260
|
-
}
|
|
261
|
-
} else {
|
|
262
|
-
stateToSave = {};
|
|
263
|
-
const keys = Object.keys(def.state);
|
|
264
|
-
for (const k of keys) {
|
|
265
|
-
stateToSave[k] = proxy[k];
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
const serialized = JSON.stringify(stateToSave);
|
|
269
|
-
await engine.setItem(key, serialized);
|
|
270
|
-
if (debug) console.log(`[Quantum] Saved '${key}'`);
|
|
271
|
-
} catch (err) {
|
|
272
|
-
}
|
|
273
|
-
}, 100);
|
|
274
|
-
subscribe(proxy, () => {
|
|
275
|
-
save();
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
return proxy;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// src/react/autoHook.ts
|
|
283
|
-
var import_react = require("react");
|
|
284
|
-
function useStore(store) {
|
|
285
|
-
const versionRef = (0, import_react.useRef)(0);
|
|
286
|
-
const notifyRef = (0, import_react.useRef)(void 0);
|
|
287
|
-
const listener = (0, import_react.useCallback)(() => {
|
|
288
|
-
versionRef.current++;
|
|
289
|
-
if (notifyRef.current) {
|
|
290
|
-
notifyRef.current();
|
|
291
|
-
}
|
|
292
|
-
}, []);
|
|
293
|
-
const subscribe2 = (0, import_react.useCallback)((onStoreChange) => {
|
|
294
|
-
notifyRef.current = onStoreChange;
|
|
295
|
-
return () => {
|
|
296
|
-
notifyRef.current = void 0;
|
|
297
|
-
};
|
|
298
|
-
}, []);
|
|
299
|
-
const getSnapshot = (0, import_react.useCallback)(() => versionRef.current, []);
|
|
300
|
-
(0, import_react.useSyncExternalStore)(subscribe2, getSnapshot, getSnapshot);
|
|
301
|
-
const proxy = new Proxy(store, {
|
|
302
|
-
get(target, prop, receiver) {
|
|
303
|
-
const prev = getActiveListener();
|
|
304
|
-
setActiveListener(listener);
|
|
305
|
-
try {
|
|
306
|
-
return Reflect.get(target, prop, receiver);
|
|
307
|
-
} finally {
|
|
308
|
-
setActiveListener(prev);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
return proxy;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// src/addon/signals.ts
|
|
48
|
+
// src/signals.ts
|
|
316
49
|
var import_signals_core = require("@preact/signals-core");
|
|
317
50
|
function createSignal(initialValue, options) {
|
|
318
51
|
const s = (0, import_signals_core.signal)(initialValue);
|
|
319
|
-
let unsubscribeActive;
|
|
320
52
|
let subscriberCount = 0;
|
|
321
53
|
return {
|
|
322
54
|
get: () => s.value,
|
|
@@ -338,9 +70,122 @@ function createSignal(initialValue, options) {
|
|
|
338
70
|
options?.onInactive?.();
|
|
339
71
|
}
|
|
340
72
|
};
|
|
341
|
-
}
|
|
73
|
+
},
|
|
74
|
+
isWatched: () => subscriberCount > 0
|
|
342
75
|
};
|
|
343
76
|
}
|
|
77
|
+
function computed(fn) {
|
|
78
|
+
const c = (0, import_signals_core.computed)(fn);
|
|
79
|
+
let subscriberCount = 0;
|
|
80
|
+
return {
|
|
81
|
+
get: () => c.value,
|
|
82
|
+
set: () => {
|
|
83
|
+
throw new Error("[Quantum] Cannot set a computed signal directly.");
|
|
84
|
+
},
|
|
85
|
+
subscribe: (fn2) => {
|
|
86
|
+
subscriberCount++;
|
|
87
|
+
const dispose = (0, import_signals_core.effect)(() => {
|
|
88
|
+
fn2(c.value);
|
|
89
|
+
});
|
|
90
|
+
return () => {
|
|
91
|
+
dispose();
|
|
92
|
+
subscriberCount--;
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
isWatched: () => subscriberCount > 0
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function effect(fn) {
|
|
99
|
+
return (0, import_signals_core.effect)(fn);
|
|
100
|
+
}
|
|
101
|
+
function untracked(fn) {
|
|
102
|
+
return (0, import_signals_core.untracked)(fn);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/store/model.ts
|
|
106
|
+
function atom(initialValue, options) {
|
|
107
|
+
const s = createSignal(initialValue);
|
|
108
|
+
if (options?.key) {
|
|
109
|
+
setupPersistence(s, options);
|
|
110
|
+
}
|
|
111
|
+
return s;
|
|
112
|
+
}
|
|
113
|
+
function setupPersistence(s, options) {
|
|
114
|
+
const { key, storage = "local", debug } = options;
|
|
115
|
+
if (!key) return;
|
|
116
|
+
let engine = null;
|
|
117
|
+
if (typeof storage === "string") {
|
|
118
|
+
if (typeof window !== "undefined") {
|
|
119
|
+
engine = storage === "local" ? window.localStorage : window.sessionStorage;
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
engine = storage;
|
|
123
|
+
}
|
|
124
|
+
if (!engine) return;
|
|
125
|
+
try {
|
|
126
|
+
const stored = engine.getItem(key);
|
|
127
|
+
const applyValue = (val) => {
|
|
128
|
+
try {
|
|
129
|
+
const parsed = JSON.parse(val);
|
|
130
|
+
const validated = options.validate ? options.validate(parsed) : parsed;
|
|
131
|
+
s.set(validated);
|
|
132
|
+
if (debug) console.log(`[Quantum] Hydrated atom '${key}'`);
|
|
133
|
+
} catch (e) {
|
|
134
|
+
if (debug) console.error(`[Quantum] Hydration validation failed for '${key}'`, e);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
if (stored instanceof Promise) {
|
|
138
|
+
stored.then((val) => {
|
|
139
|
+
if (val) applyValue(val);
|
|
140
|
+
});
|
|
141
|
+
} else if (stored) {
|
|
142
|
+
applyValue(stored);
|
|
143
|
+
}
|
|
144
|
+
} catch (err) {
|
|
145
|
+
if (debug) console.error(`[Quantum] Hydration error`, err);
|
|
146
|
+
}
|
|
147
|
+
s.subscribe((value) => {
|
|
148
|
+
try {
|
|
149
|
+
const serialized = JSON.stringify(value);
|
|
150
|
+
engine.setItem(key, serialized);
|
|
151
|
+
if (debug) console.log(`[Quantum] Saved atom '${key}'`);
|
|
152
|
+
} catch (err) {
|
|
153
|
+
if (debug) console.error(`[Quantum] Save error`, err);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/react/SignalValue.tsx
|
|
159
|
+
var import_react = require("react");
|
|
160
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
161
|
+
function SignalValue({ signal: signal2, render, children }) {
|
|
162
|
+
const [value, setValue] = (0, import_react.useState)(() => signal2.get());
|
|
163
|
+
(0, import_react.useEffect)(() => {
|
|
164
|
+
const unsubscribe = signal2.subscribe((newValue) => {
|
|
165
|
+
setValue(newValue);
|
|
166
|
+
});
|
|
167
|
+
return () => unsubscribe();
|
|
168
|
+
}, [signal2]);
|
|
169
|
+
const renderer = render || children;
|
|
170
|
+
if (!renderer) return null;
|
|
171
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderer(value) });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/store/scheduler.ts
|
|
175
|
+
var pending = /* @__PURE__ */ new Set();
|
|
176
|
+
var timer = null;
|
|
177
|
+
function flush() {
|
|
178
|
+
timer = null;
|
|
179
|
+
const tasks = [...pending];
|
|
180
|
+
pending.clear();
|
|
181
|
+
tasks.forEach((task) => task());
|
|
182
|
+
}
|
|
183
|
+
function scheduleUpdate(callback) {
|
|
184
|
+
pending.add(callback);
|
|
185
|
+
if (!timer) {
|
|
186
|
+
timer = Promise.resolve().then(flush);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
344
189
|
|
|
345
190
|
// src/devtools/registry.ts
|
|
346
191
|
var stores = createSignal([]);
|
|
@@ -354,30 +199,10 @@ function registerStore(store, name = "Store") {
|
|
|
354
199
|
// src/middleware/devtools.ts
|
|
355
200
|
function enableDevTools(store, name = "Store") {
|
|
356
201
|
registerStore(store, name);
|
|
357
|
-
|
|
358
|
-
const devTools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ name });
|
|
359
|
-
devTools.init(store);
|
|
360
|
-
subscribe(store, (target, prop, value) => {
|
|
361
|
-
devTools.send({ type: `SET_${String(prop)}`, payload: value }, store);
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// src/core/computed.ts
|
|
366
|
-
function computed(fn) {
|
|
367
|
-
let value;
|
|
368
|
-
let dirty = true;
|
|
369
|
-
return {
|
|
370
|
-
get value() {
|
|
371
|
-
if (dirty) {
|
|
372
|
-
value = fn();
|
|
373
|
-
dirty = false;
|
|
374
|
-
}
|
|
375
|
-
return value;
|
|
376
|
-
}
|
|
377
|
-
};
|
|
202
|
+
console.warn("DevTools for Signals are WIP");
|
|
378
203
|
}
|
|
379
204
|
|
|
380
|
-
// src/
|
|
205
|
+
// src/clientTypes.ts
|
|
381
206
|
var HttpError = class extends Error {
|
|
382
207
|
constructor(status, message) {
|
|
383
208
|
super(message);
|
|
@@ -386,7 +211,7 @@ var HttpError = class extends Error {
|
|
|
386
211
|
}
|
|
387
212
|
};
|
|
388
213
|
|
|
389
|
-
// src/
|
|
214
|
+
// src/middleware/types.ts
|
|
390
215
|
function compose(middleware) {
|
|
391
216
|
return (ctx, next) => {
|
|
392
217
|
let index = -1;
|
|
@@ -405,7 +230,7 @@ function compose(middleware) {
|
|
|
405
230
|
};
|
|
406
231
|
}
|
|
407
232
|
|
|
408
|
-
// src/
|
|
233
|
+
// src/middleware/dedupe.ts
|
|
409
234
|
var DedupeMiddleware = async (ctx, next) => {
|
|
410
235
|
if (ctx.req.method !== "GET") {
|
|
411
236
|
return next(ctx);
|
|
@@ -431,10 +256,10 @@ var DedupeMiddleware = async (ctx, next) => {
|
|
|
431
256
|
}
|
|
432
257
|
};
|
|
433
258
|
|
|
434
|
-
// src/
|
|
259
|
+
// src/middleware/cache.ts
|
|
435
260
|
var CacheMiddleware = async (ctx, next) => {
|
|
436
261
|
const { method, url } = ctx.req;
|
|
437
|
-
const
|
|
262
|
+
const cacheConfig = typeof ctx.config.cache === "object" ? ctx.config.cache : void 0;
|
|
438
263
|
if (method !== "GET" || !cacheConfig?.ttl || cacheConfig.force) {
|
|
439
264
|
return next(ctx);
|
|
440
265
|
}
|
|
@@ -467,7 +292,7 @@ var CacheMiddleware = async (ctx, next) => {
|
|
|
467
292
|
return response;
|
|
468
293
|
};
|
|
469
294
|
|
|
470
|
-
// src/
|
|
295
|
+
// src/middleware/auth.ts
|
|
471
296
|
var AuthMiddleware = async (ctx, next) => {
|
|
472
297
|
const { auth } = ctx.client.config;
|
|
473
298
|
if (auth && auth.getToken && !ctx.req.headers.get("Authorization")) {
|
|
@@ -512,7 +337,7 @@ var AuthMiddleware = async (ctx, next) => {
|
|
|
512
337
|
return response;
|
|
513
338
|
};
|
|
514
339
|
|
|
515
|
-
// src/
|
|
340
|
+
// src/middleware/fetch.ts
|
|
516
341
|
var FetchMiddleware = async (ctx) => {
|
|
517
342
|
return fetch(ctx.req);
|
|
518
343
|
};
|
|
@@ -550,7 +375,7 @@ var RetryMiddleware = async (ctx, next) => {
|
|
|
550
375
|
return attempt(0);
|
|
551
376
|
};
|
|
552
377
|
|
|
553
|
-
// src/
|
|
378
|
+
// src/httpClient.ts
|
|
554
379
|
function createHttpClient(config) {
|
|
555
380
|
const cache = /* @__PURE__ */ new Map();
|
|
556
381
|
const inflight = /* @__PURE__ */ new Map();
|
|
@@ -585,15 +410,17 @@ function createHttpClient(config) {
|
|
|
585
410
|
controller.abort();
|
|
586
411
|
});
|
|
587
412
|
}
|
|
413
|
+
const { cache: _c, schema: _s, timeout: _t, retry: _r, ...fetchOptions } = options;
|
|
588
414
|
let req = new Request(url, {
|
|
589
|
-
...
|
|
415
|
+
...fetchOptions,
|
|
590
416
|
headers,
|
|
591
417
|
signal: controller.signal
|
|
592
418
|
});
|
|
593
419
|
if (config.interceptors?.request) {
|
|
594
420
|
const newConfig = await config.interceptors.request({ ...options, headers: Object.fromEntries(headers) });
|
|
421
|
+
const { cache: _nc, schema: _ns, timeout: _nt, retry: _nr, ...newFetchOptions } = newConfig;
|
|
595
422
|
req = new Request(url, {
|
|
596
|
-
...
|
|
423
|
+
...newFetchOptions,
|
|
597
424
|
signal: controller.signal
|
|
598
425
|
});
|
|
599
426
|
}
|
|
@@ -634,8 +461,9 @@ function createHttpClient(config) {
|
|
|
634
461
|
if (options.schema.parse) return options.schema.parse(data);
|
|
635
462
|
if (options.schema.validateSync) return options.schema.validateSync(data);
|
|
636
463
|
} catch (error) {
|
|
637
|
-
|
|
638
|
-
|
|
464
|
+
const err = error;
|
|
465
|
+
if (err.errors || err.name === "ZodError" || err.name === "ValidationError") {
|
|
466
|
+
throw new Error(`Validation Error: ${JSON.stringify(err.errors || err.message)}`);
|
|
639
467
|
}
|
|
640
468
|
throw error;
|
|
641
469
|
}
|
|
@@ -665,56 +493,168 @@ function createHttpClient(config) {
|
|
|
665
493
|
return client;
|
|
666
494
|
}
|
|
667
495
|
|
|
668
|
-
// src/
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
496
|
+
// src/store/asyncUtils.ts
|
|
497
|
+
var PROMISE_CACHE = /* @__PURE__ */ new WeakMap();
|
|
498
|
+
var PROMISE_STATUS = /* @__PURE__ */ new WeakMap();
|
|
499
|
+
var PROMISE_ERROR = /* @__PURE__ */ new WeakMap();
|
|
500
|
+
function isPromise(value) {
|
|
501
|
+
return !!value && typeof value.then === "function";
|
|
502
|
+
}
|
|
503
|
+
function handlePromise(promise, triggerUpdate) {
|
|
504
|
+
if (PROMISE_STATUS.has(promise)) return;
|
|
505
|
+
PROMISE_STATUS.set(promise, "pending");
|
|
506
|
+
promise.then(
|
|
507
|
+
(value) => {
|
|
508
|
+
PROMISE_STATUS.set(promise, "fulfilled");
|
|
509
|
+
PROMISE_CACHE.set(promise, value);
|
|
510
|
+
triggerUpdate();
|
|
511
|
+
},
|
|
512
|
+
(error) => {
|
|
513
|
+
PROMISE_STATUS.set(promise, "rejected");
|
|
514
|
+
PROMISE_ERROR.set(promise, error);
|
|
515
|
+
triggerUpdate();
|
|
516
|
+
}
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
function unwrapPromise(promise) {
|
|
520
|
+
const status = PROMISE_STATUS.get(promise);
|
|
521
|
+
if (status === "fulfilled") {
|
|
522
|
+
return PROMISE_CACHE.get(promise);
|
|
523
|
+
} else if (status === "rejected") {
|
|
524
|
+
throw PROMISE_ERROR.get(promise);
|
|
525
|
+
} else {
|
|
526
|
+
throw promise;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
function getPromiseState(promise) {
|
|
530
|
+
return {
|
|
531
|
+
status: PROMISE_STATUS.get(promise) || "pending",
|
|
532
|
+
value: PROMISE_CACHE.get(promise),
|
|
533
|
+
error: PROMISE_ERROR.get(promise)
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// src/query/utils.ts
|
|
538
|
+
function stableHash(value, depth = 0) {
|
|
539
|
+
if (depth > 15) {
|
|
540
|
+
throw new Error("[Quantum] Query key is too deeply nested. Max depth is 15.");
|
|
541
|
+
}
|
|
542
|
+
if (value === null) return "null";
|
|
543
|
+
if (value === void 0) return "undefined";
|
|
544
|
+
if (typeof value !== "object") {
|
|
545
|
+
const strValue = String(value);
|
|
546
|
+
if (strValue.length > 1e3) {
|
|
547
|
+
return `${typeof value}:[large-string:${strValue.slice(0, 10)}...]`;
|
|
548
|
+
}
|
|
549
|
+
return `${typeof value}:${strValue}`;
|
|
672
550
|
}
|
|
673
551
|
if (Array.isArray(value)) {
|
|
674
|
-
return
|
|
552
|
+
return `array:[${value.map((v) => stableHash(v, depth + 1)).join(",")}]`;
|
|
675
553
|
}
|
|
676
554
|
const keys = Object.keys(value).sort();
|
|
677
|
-
return
|
|
555
|
+
return `object:{${keys.map((key) => `${key}:${stableHash(value[key], depth + 1)}`).join(",")}}`;
|
|
556
|
+
}
|
|
557
|
+
function isDeepEqual(a, b) {
|
|
558
|
+
if (a === b) return true;
|
|
559
|
+
if (a && b && typeof a === "object" && typeof b === "object") {
|
|
560
|
+
const objA = a;
|
|
561
|
+
const objB = b;
|
|
562
|
+
if (objA.constructor !== objB.constructor) return false;
|
|
563
|
+
let length, i, keys;
|
|
564
|
+
if (Array.isArray(a)) {
|
|
565
|
+
const arrA = a;
|
|
566
|
+
const arrB = b;
|
|
567
|
+
length = arrA.length;
|
|
568
|
+
if (length !== arrB.length) return false;
|
|
569
|
+
for (i = length; i-- !== 0; ) {
|
|
570
|
+
if (!isDeepEqual(arrA[i], arrB[i])) return false;
|
|
571
|
+
}
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
if (objA.valueOf !== Object.prototype.valueOf) return objA.valueOf() === objB.valueOf();
|
|
575
|
+
if (objA.toString !== Object.prototype.toString) return objA.toString() === objB.toString();
|
|
576
|
+
keys = Object.keys(objA);
|
|
577
|
+
length = keys.length;
|
|
578
|
+
if (length !== Object.keys(objB).length) return false;
|
|
579
|
+
for (const key of keys) {
|
|
580
|
+
if (!Object.prototype.hasOwnProperty.call(objB, key)) return false;
|
|
581
|
+
}
|
|
582
|
+
for (const key of keys) {
|
|
583
|
+
if (!isDeepEqual(objA[key], objB[key])) return false;
|
|
584
|
+
}
|
|
585
|
+
return true;
|
|
586
|
+
}
|
|
587
|
+
return a !== a && b !== b;
|
|
678
588
|
}
|
|
679
589
|
|
|
680
|
-
// src/
|
|
590
|
+
// src/query/queryStorage.ts
|
|
681
591
|
var QueryStorage = class {
|
|
592
|
+
// Tracks access order (least to most recent)
|
|
682
593
|
// Default configuration
|
|
683
|
-
constructor(defaultStaleTime = 0, defaultCacheTime = 5 * 60 * 1e3) {
|
|
594
|
+
constructor(defaultStaleTime = 0, defaultCacheTime = 5 * 60 * 1e3, maxSize = 100) {
|
|
684
595
|
this.defaultStaleTime = defaultStaleTime;
|
|
685
596
|
this.defaultCacheTime = defaultCacheTime;
|
|
597
|
+
this.maxSize = maxSize;
|
|
686
598
|
}
|
|
687
599
|
signals = /* @__PURE__ */ new Map();
|
|
688
600
|
gcTimers = /* @__PURE__ */ new Map();
|
|
601
|
+
lruOrder = /* @__PURE__ */ new Set();
|
|
689
602
|
generateKey(queryKey) {
|
|
690
603
|
const key = Array.isArray(queryKey) ? stableHash(queryKey) : stableHash([queryKey.key, queryKey.params]);
|
|
691
604
|
return key;
|
|
692
605
|
}
|
|
693
606
|
get(key, autoCreate = true) {
|
|
694
607
|
let signal2 = this.signals.get(key);
|
|
608
|
+
if (signal2) {
|
|
609
|
+
this.touch(key);
|
|
610
|
+
}
|
|
695
611
|
if (!signal2 && autoCreate) {
|
|
696
612
|
const newSignal = createSignal(void 0, {
|
|
697
613
|
onActive: () => {
|
|
698
614
|
this.cancelGC(key);
|
|
699
615
|
},
|
|
700
616
|
onInactive: () => {
|
|
701
|
-
const
|
|
702
|
-
const cacheTime =
|
|
617
|
+
const currentEntry = this.signals.get(key)?.get();
|
|
618
|
+
const cacheTime = currentEntry?.cacheTime ?? this.defaultCacheTime;
|
|
703
619
|
this.scheduleGC(key, cacheTime);
|
|
704
620
|
}
|
|
705
621
|
});
|
|
706
622
|
this.signals.set(key, newSignal);
|
|
623
|
+
this.touch(key);
|
|
624
|
+
if (!newSignal.isWatched()) {
|
|
625
|
+
this.scheduleGC(key, this.defaultCacheTime);
|
|
626
|
+
}
|
|
627
|
+
this.enforceMaxSize();
|
|
707
628
|
signal2 = newSignal;
|
|
708
629
|
}
|
|
709
|
-
if (!signal2) return void 0;
|
|
710
630
|
return signal2;
|
|
711
631
|
}
|
|
632
|
+
tagIndex = /* @__PURE__ */ new Map();
|
|
712
633
|
set(key, entry) {
|
|
713
|
-
|
|
634
|
+
this.touch(key);
|
|
635
|
+
const oldEntry = this.signals.get(key)?.get();
|
|
636
|
+
if (oldEntry?.tags) {
|
|
637
|
+
for (const tag of oldEntry.tags) {
|
|
638
|
+
const set = this.tagIndex.get(tag);
|
|
639
|
+
if (set) {
|
|
640
|
+
set.delete(key);
|
|
641
|
+
if (set.size === 0) this.tagIndex.delete(tag);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
if (entry.tags) {
|
|
646
|
+
for (const tag of entry.tags) {
|
|
647
|
+
if (!this.tagIndex.has(tag)) {
|
|
648
|
+
this.tagIndex.set(tag, /* @__PURE__ */ new Set());
|
|
649
|
+
}
|
|
650
|
+
this.tagIndex.get(tag).add(key);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
let signal2 = this.signals.get(key);
|
|
714
654
|
if (signal2) {
|
|
715
655
|
signal2.set(entry);
|
|
716
656
|
} else {
|
|
717
|
-
|
|
657
|
+
const newSignal = createSignal(entry, {
|
|
718
658
|
onActive: () => {
|
|
719
659
|
this.cancelGC(key);
|
|
720
660
|
},
|
|
@@ -723,15 +663,50 @@ var QueryStorage = class {
|
|
|
723
663
|
const cacheTime = entry2?.cacheTime ?? this.defaultCacheTime;
|
|
724
664
|
this.scheduleGC(key, cacheTime);
|
|
725
665
|
}
|
|
726
|
-
})
|
|
666
|
+
});
|
|
667
|
+
this.signals.set(key, newSignal);
|
|
668
|
+
if (!newSignal.isWatched()) {
|
|
669
|
+
this.scheduleGC(key, entry.cacheTime ?? this.defaultCacheTime);
|
|
670
|
+
}
|
|
671
|
+
this.enforceMaxSize();
|
|
727
672
|
}
|
|
728
673
|
}
|
|
729
674
|
delete(key) {
|
|
675
|
+
const entry = this.signals.get(key)?.get();
|
|
676
|
+
if (entry?.tags) {
|
|
677
|
+
for (const tag of entry.tags) {
|
|
678
|
+
const set = this.tagIndex.get(tag);
|
|
679
|
+
if (set) {
|
|
680
|
+
set.delete(key);
|
|
681
|
+
if (set.size === 0) this.tagIndex.delete(tag);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
730
685
|
this.signals.delete(key);
|
|
686
|
+
this.lruOrder.delete(key);
|
|
731
687
|
this.cancelGC(key);
|
|
732
688
|
}
|
|
689
|
+
touch(key) {
|
|
690
|
+
this.lruOrder.delete(key);
|
|
691
|
+
this.lruOrder.add(key);
|
|
692
|
+
}
|
|
693
|
+
enforceMaxSize() {
|
|
694
|
+
if (this.signals.size <= this.maxSize) return;
|
|
695
|
+
for (const key of this.lruOrder) {
|
|
696
|
+
const signal2 = this.signals.get(key);
|
|
697
|
+
if (signal2 && !signal2.isWatched()) {
|
|
698
|
+
this.delete(key);
|
|
699
|
+
if (this.signals.size <= this.maxSize) break;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
getKeysByTag(tag) {
|
|
704
|
+
return this.tagIndex.get(tag);
|
|
705
|
+
}
|
|
733
706
|
clear() {
|
|
734
707
|
this.signals.clear();
|
|
708
|
+
this.tagIndex.clear();
|
|
709
|
+
this.lruOrder.clear();
|
|
735
710
|
this.gcTimers.forEach((timer2) => clearTimeout(timer2));
|
|
736
711
|
this.gcTimers.clear();
|
|
737
712
|
}
|
|
@@ -746,11 +721,19 @@ var QueryStorage = class {
|
|
|
746
721
|
getStats() {
|
|
747
722
|
return {
|
|
748
723
|
size: this.signals.size,
|
|
749
|
-
keys: Array.from(this.signals.keys())
|
|
724
|
+
keys: Array.from(this.signals.keys()),
|
|
725
|
+
tags: this.tagIndex.size
|
|
750
726
|
};
|
|
751
727
|
}
|
|
752
728
|
getSnapshot() {
|
|
753
|
-
|
|
729
|
+
const snapshot = /* @__PURE__ */ new Map();
|
|
730
|
+
for (const [key, signal2] of this.signals.entries()) {
|
|
731
|
+
const value = signal2.get();
|
|
732
|
+
if (value) {
|
|
733
|
+
snapshot.set(key, value);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return snapshot;
|
|
754
737
|
}
|
|
755
738
|
// --- GC Logic ---
|
|
756
739
|
scheduleGC(key, delay2) {
|
|
@@ -770,7 +753,7 @@ var QueryStorage = class {
|
|
|
770
753
|
}
|
|
771
754
|
};
|
|
772
755
|
|
|
773
|
-
// src/
|
|
756
|
+
// src/query/remotes.ts
|
|
774
757
|
var QueryRemotes = class {
|
|
775
758
|
deduplicationCache = /* @__PURE__ */ new Map();
|
|
776
759
|
async fetch(key, fn, options) {
|
|
@@ -833,7 +816,7 @@ var QueryRemotes = class {
|
|
|
833
816
|
}
|
|
834
817
|
};
|
|
835
818
|
|
|
836
|
-
// src/
|
|
819
|
+
// src/query/mutationCache.ts
|
|
837
820
|
var MutationCache = class {
|
|
838
821
|
// Map<ID, Signal> - Stores state for every unique mutation execution
|
|
839
822
|
mutations = /* @__PURE__ */ new Map();
|
|
@@ -912,9 +895,13 @@ var MutationCache = class {
|
|
|
912
895
|
};
|
|
913
896
|
};
|
|
914
897
|
|
|
915
|
-
// src/
|
|
898
|
+
// src/query/pluginManager.ts
|
|
916
899
|
var PluginManager = class {
|
|
917
900
|
plugins = [];
|
|
901
|
+
client;
|
|
902
|
+
setClient(client) {
|
|
903
|
+
this.client = client;
|
|
904
|
+
}
|
|
918
905
|
add(plugin) {
|
|
919
906
|
this.plugins.push(plugin);
|
|
920
907
|
}
|
|
@@ -935,8 +922,16 @@ var PluginManager = class {
|
|
|
935
922
|
}
|
|
936
923
|
};
|
|
937
924
|
|
|
938
|
-
// src/
|
|
939
|
-
|
|
925
|
+
// src/query/plugins/validation.ts
|
|
926
|
+
function validateWithSchema(data, schema) {
|
|
927
|
+
if (!schema) {
|
|
928
|
+
return data;
|
|
929
|
+
}
|
|
930
|
+
return schema.parse(data);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// src/query/queryClient.ts
|
|
934
|
+
var QueryClient = class {
|
|
940
935
|
// Components
|
|
941
936
|
storage;
|
|
942
937
|
remotes;
|
|
@@ -947,11 +942,18 @@ var QueryCache = class {
|
|
|
947
942
|
// Config defaults
|
|
948
943
|
defaultStaleTime;
|
|
949
944
|
defaultCacheTime;
|
|
945
|
+
defaultSchema;
|
|
950
946
|
constructor(config) {
|
|
951
947
|
this.defaultStaleTime = config?.defaultStaleTime ?? 0;
|
|
952
948
|
this.defaultCacheTime = config?.defaultCacheTime ?? 5 * 60 * 1e3;
|
|
953
|
-
this.
|
|
949
|
+
this.defaultSchema = config?.defaultSchema;
|
|
950
|
+
this.storage = new QueryStorage(
|
|
951
|
+
this.defaultStaleTime,
|
|
952
|
+
this.defaultCacheTime,
|
|
953
|
+
config?.maxCacheSize
|
|
954
|
+
);
|
|
954
955
|
this.remotes = new QueryRemotes();
|
|
956
|
+
this.pluginManager.setClient(this);
|
|
955
957
|
}
|
|
956
958
|
// --- FACADE API ---
|
|
957
959
|
/**
|
|
@@ -962,7 +964,7 @@ var QueryCache = class {
|
|
|
962
964
|
const signal2 = this.storage.get(key, false);
|
|
963
965
|
if (!signal2) return void 0;
|
|
964
966
|
const entry = signal2.get();
|
|
965
|
-
if (!entry) return void 0;
|
|
967
|
+
if (!this.isCacheEntry(entry)) return void 0;
|
|
966
968
|
const now = Date.now();
|
|
967
969
|
const age = now - entry.timestamp;
|
|
968
970
|
if (age > entry.cacheTime) {
|
|
@@ -1017,18 +1019,18 @@ var QueryCache = class {
|
|
|
1017
1019
|
const direction = options?.fetchDirection || "initial";
|
|
1018
1020
|
const signal2 = this.storage.get(key, true);
|
|
1019
1021
|
const currentEntry = signal2.get();
|
|
1022
|
+
const mergedTags = options?.tags ?? currentEntry?.tags;
|
|
1020
1023
|
this.storage.set(key, {
|
|
1021
1024
|
data: currentEntry?.data,
|
|
1022
1025
|
status: currentEntry?.status || "pending",
|
|
1023
1026
|
error: null,
|
|
1024
1027
|
isFetching: true,
|
|
1025
|
-
// Mark fetching
|
|
1026
1028
|
fetchDirection: direction,
|
|
1027
1029
|
timestamp: currentEntry?.timestamp || Date.now(),
|
|
1028
1030
|
staleTime: currentEntry?.staleTime ?? this.defaultStaleTime,
|
|
1029
1031
|
cacheTime: currentEntry?.cacheTime ?? this.defaultCacheTime,
|
|
1030
1032
|
key: queryKey,
|
|
1031
|
-
tags:
|
|
1033
|
+
tags: mergedTags
|
|
1032
1034
|
});
|
|
1033
1035
|
this.pluginManager.onFetchStart(normalizedKey);
|
|
1034
1036
|
try {
|
|
@@ -1037,21 +1039,40 @@ var QueryCache = class {
|
|
|
1037
1039
|
retry: options?.retry,
|
|
1038
1040
|
retryDelay: options?.retryDelay
|
|
1039
1041
|
});
|
|
1040
|
-
this.
|
|
1041
|
-
|
|
1042
|
+
this.storage.set(key, {
|
|
1043
|
+
data,
|
|
1044
|
+
status: "success",
|
|
1045
|
+
error: null,
|
|
1046
|
+
isFetching: false,
|
|
1047
|
+
isInvalidated: void 0,
|
|
1048
|
+
// Clear invalidation on success
|
|
1049
|
+
fetchDirection: "idle",
|
|
1050
|
+
timestamp: Date.now(),
|
|
1051
|
+
staleTime: currentEntry?.staleTime ?? this.defaultStaleTime,
|
|
1052
|
+
cacheTime: currentEntry?.cacheTime ?? this.defaultCacheTime,
|
|
1053
|
+
key: queryKey,
|
|
1054
|
+
tags: mergedTags
|
|
1055
|
+
});
|
|
1056
|
+
const schema = options?.schema || this.defaultSchema;
|
|
1057
|
+
const validatedData = validateWithSchema(data, schema);
|
|
1058
|
+
this.pluginManager.onFetchSuccess(normalizedKey, validatedData);
|
|
1059
|
+
return validatedData;
|
|
1042
1060
|
} catch (error) {
|
|
1043
|
-
const
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1061
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1062
|
+
this.storage.set(key, {
|
|
1063
|
+
data: currentEntry?.data,
|
|
1064
|
+
status: "error",
|
|
1065
|
+
error: err,
|
|
1066
|
+
isFetching: false,
|
|
1067
|
+
fetchDirection: "idle",
|
|
1068
|
+
timestamp: currentEntry?.timestamp || Date.now(),
|
|
1069
|
+
staleTime: currentEntry?.staleTime ?? this.defaultStaleTime,
|
|
1070
|
+
cacheTime: currentEntry?.cacheTime ?? this.defaultCacheTime,
|
|
1071
|
+
key: queryKey,
|
|
1072
|
+
tags: mergedTags
|
|
1073
|
+
});
|
|
1074
|
+
this.pluginManager.onFetchError(normalizedKey, err);
|
|
1075
|
+
throw err;
|
|
1055
1076
|
}
|
|
1056
1077
|
};
|
|
1057
1078
|
/**
|
|
@@ -1076,12 +1097,17 @@ var QueryCache = class {
|
|
|
1076
1097
|
};
|
|
1077
1098
|
invalidateTags = (tags) => {
|
|
1078
1099
|
const tagsToInvalidate = new Set(tags);
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
signal2
|
|
1100
|
+
for (const tag of tagsToInvalidate) {
|
|
1101
|
+
const keys = this.storage.getKeysByTag(tag);
|
|
1102
|
+
if (keys) {
|
|
1103
|
+
for (const key of keys) {
|
|
1104
|
+
const signal2 = this.storage.get(key, false);
|
|
1105
|
+
if (signal2) {
|
|
1106
|
+
const current = signal2.get();
|
|
1107
|
+
if (current) {
|
|
1108
|
+
signal2.set({ ...current, isInvalidated: true });
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1085
1111
|
}
|
|
1086
1112
|
}
|
|
1087
1113
|
}
|
|
@@ -1114,8 +1140,9 @@ var QueryCache = class {
|
|
|
1114
1140
|
// For Hydration
|
|
1115
1141
|
getSnapshot = () => this.storage.getSnapshot();
|
|
1116
1142
|
invalidateAll = () => {
|
|
1117
|
-
|
|
1118
|
-
|
|
1143
|
+
const snapshot = this.storage.getSnapshot();
|
|
1144
|
+
for (const key of snapshot.keys()) {
|
|
1145
|
+
const signal2 = this.storage.get(key, false);
|
|
1119
1146
|
const entry = signal2?.get();
|
|
1120
1147
|
if (entry) {
|
|
1121
1148
|
signal2?.set({ ...entry, isInvalidated: true });
|
|
@@ -1125,20 +1152,30 @@ var QueryCache = class {
|
|
|
1125
1152
|
normalizeKey(queryKey) {
|
|
1126
1153
|
return Array.isArray(queryKey) ? queryKey : [queryKey.key, queryKey.params];
|
|
1127
1154
|
}
|
|
1155
|
+
isCacheEntry(entry) {
|
|
1156
|
+
return entry !== null && typeof entry === "object" && "status" in entry && "timestamp" in entry;
|
|
1157
|
+
}
|
|
1158
|
+
// --- DEBUGGER API (For DevTools) ---
|
|
1159
|
+
debugSet = (key, data) => {
|
|
1160
|
+
this.set(key, data);
|
|
1161
|
+
};
|
|
1162
|
+
debugInvalidate = (key) => {
|
|
1163
|
+
this.invalidate(key);
|
|
1164
|
+
};
|
|
1128
1165
|
};
|
|
1129
1166
|
|
|
1130
|
-
// src/
|
|
1167
|
+
// src/query/pagination.ts
|
|
1131
1168
|
var import_react3 = require("react");
|
|
1132
1169
|
|
|
1133
|
-
// src/
|
|
1170
|
+
// src/query/context.tsx
|
|
1134
1171
|
var import_react2 = require("react");
|
|
1135
|
-
var
|
|
1172
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1136
1173
|
var QueryClientContext = (0, import_react2.createContext)(void 0);
|
|
1137
1174
|
var QueryClientProvider = ({
|
|
1138
1175
|
client,
|
|
1139
1176
|
children
|
|
1140
1177
|
}) => {
|
|
1141
|
-
return /* @__PURE__ */ (0,
|
|
1178
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(QueryClientContext.Provider, { value: client, children: children || null });
|
|
1142
1179
|
};
|
|
1143
1180
|
var useQueryClient = () => {
|
|
1144
1181
|
const client = (0, import_react2.useContext)(QueryClientContext);
|
|
@@ -1148,7 +1185,7 @@ var useQueryClient = () => {
|
|
|
1148
1185
|
return client;
|
|
1149
1186
|
};
|
|
1150
1187
|
|
|
1151
|
-
// src/
|
|
1188
|
+
// src/query/pagination.ts
|
|
1152
1189
|
function usePaginatedQuery({
|
|
1153
1190
|
queryKey,
|
|
1154
1191
|
queryFn,
|
|
@@ -1162,7 +1199,7 @@ function usePaginatedQuery({
|
|
|
1162
1199
|
const [page, setPage] = (0, import_react3.useState)(0);
|
|
1163
1200
|
const pageQueryKey = [...queryKey, "page", page];
|
|
1164
1201
|
const pageQueryKeyHash = JSON.stringify(pageQueryKey);
|
|
1165
|
-
const
|
|
1202
|
+
const subscribe = (0, import_react3.useCallback)((onStoreChange) => {
|
|
1166
1203
|
const signal2 = client.getSignal(pageQueryKey);
|
|
1167
1204
|
return signal2.subscribe(() => onStoreChange());
|
|
1168
1205
|
}, [client, pageQueryKeyHash]);
|
|
@@ -1170,7 +1207,7 @@ function usePaginatedQuery({
|
|
|
1170
1207
|
const signal2 = client.getSignal(pageQueryKey);
|
|
1171
1208
|
return signal2.get();
|
|
1172
1209
|
}, [client, pageQueryKeyHash]);
|
|
1173
|
-
const cacheEntry = (0, import_react3.useSyncExternalStore)(
|
|
1210
|
+
const cacheEntry = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot);
|
|
1174
1211
|
const data = cacheEntry?.data;
|
|
1175
1212
|
const status = cacheEntry?.status || "pending";
|
|
1176
1213
|
const error = cacheEntry?.error || null;
|
|
@@ -1183,7 +1220,7 @@ function usePaginatedQuery({
|
|
|
1183
1220
|
if (Array.isArray(data)) {
|
|
1184
1221
|
hasNext = data.length === pageSize;
|
|
1185
1222
|
} else if (typeof data === "object" && "hasMore" in data) {
|
|
1186
|
-
hasNext = data.hasMore;
|
|
1223
|
+
hasNext = !!data.hasMore;
|
|
1187
1224
|
}
|
|
1188
1225
|
}
|
|
1189
1226
|
const hasPrevious = page > 0;
|
|
@@ -1248,289 +1285,263 @@ function usePaginatedQuery({
|
|
|
1248
1285
|
};
|
|
1249
1286
|
}
|
|
1250
1287
|
|
|
1251
|
-
// src/
|
|
1288
|
+
// src/query/useQuery.ts
|
|
1252
1289
|
var import_react4 = require("react");
|
|
1253
1290
|
|
|
1254
|
-
// src/
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1291
|
+
// src/query/focusManager.ts
|
|
1292
|
+
var FocusManager = class {
|
|
1293
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1294
|
+
focused = true;
|
|
1295
|
+
unsubscribe = null;
|
|
1296
|
+
constructor() {
|
|
1297
|
+
if (typeof window !== "undefined" && window.addEventListener) {
|
|
1298
|
+
const handleFocus = () => {
|
|
1299
|
+
this.focused = true;
|
|
1300
|
+
this.onFocus();
|
|
1301
|
+
};
|
|
1302
|
+
const handleBlur = () => {
|
|
1303
|
+
this.focused = false;
|
|
1304
|
+
};
|
|
1305
|
+
window.addEventListener("focus", handleFocus, false);
|
|
1306
|
+
window.addEventListener("visibilitychange", handleFocus, false);
|
|
1307
|
+
window.addEventListener("blur", handleBlur, false);
|
|
1308
|
+
this.unsubscribe = () => {
|
|
1309
|
+
window.removeEventListener("focus", handleFocus);
|
|
1310
|
+
window.removeEventListener("visibilitychange", handleFocus);
|
|
1311
|
+
window.removeEventListener("blur", handleBlur);
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1258
1314
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1315
|
+
onFocus() {
|
|
1316
|
+
this.listeners.forEach((listener) => listener());
|
|
1317
|
+
}
|
|
1318
|
+
subscribe(listener) {
|
|
1319
|
+
this.listeners.add(listener);
|
|
1320
|
+
return () => this.listeners.delete(listener);
|
|
1321
|
+
}
|
|
1322
|
+
isFocused() {
|
|
1323
|
+
return this.focused;
|
|
1324
|
+
}
|
|
1325
|
+
setFocused(focused) {
|
|
1326
|
+
this.focused = focused;
|
|
1327
|
+
if (focused) this.onFocus();
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
var focusManager = new FocusManager();
|
|
1331
|
+
|
|
1332
|
+
// src/query/onlineManager.ts
|
|
1333
|
+
var OnlineManager = class {
|
|
1334
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1335
|
+
online = true;
|
|
1336
|
+
constructor() {
|
|
1337
|
+
if (typeof window !== "undefined" && window.addEventListener) {
|
|
1338
|
+
window.addEventListener("online", () => this.setOnline(true), false);
|
|
1339
|
+
window.addEventListener("offline", () => this.setOnline(false), false);
|
|
1340
|
+
this.online = navigator.onLine;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
setOnline(online) {
|
|
1344
|
+
this.online = online;
|
|
1345
|
+
this.listeners.forEach((listener) => listener(online));
|
|
1346
|
+
}
|
|
1347
|
+
subscribe(listener) {
|
|
1348
|
+
this.listeners.add(listener);
|
|
1349
|
+
return () => this.listeners.delete(listener);
|
|
1350
|
+
}
|
|
1351
|
+
isOnline() {
|
|
1352
|
+
return this.online;
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
var onlineManager = new OnlineManager();
|
|
1261
1356
|
|
|
1262
|
-
// src/
|
|
1357
|
+
// src/query/queryObserver.ts
|
|
1263
1358
|
var QueryObserver = class {
|
|
1264
1359
|
client;
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
// Internal
|
|
1360
|
+
// Reactive Inputs
|
|
1361
|
+
options$;
|
|
1362
|
+
// Reactive Outputs
|
|
1363
|
+
result$;
|
|
1364
|
+
// Internal
|
|
1365
|
+
unsubscribe = null;
|
|
1366
|
+
gcUnsubscribe = null;
|
|
1270
1367
|
abortController = null;
|
|
1271
1368
|
intervalParams = { id: null };
|
|
1272
|
-
unsubscribeSignal = null;
|
|
1273
|
-
// Derived state cache to ensure referential stability where possible
|
|
1274
|
-
currentResult;
|
|
1275
1369
|
constructor(client, options) {
|
|
1276
1370
|
this.client = client;
|
|
1277
|
-
this.options = options;
|
|
1278
|
-
|
|
1279
|
-
this.
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1371
|
+
this.options$ = createSignal(options);
|
|
1372
|
+
let lastResult = null;
|
|
1373
|
+
this.result$ = computed(() => {
|
|
1374
|
+
const opts = this.options$.get();
|
|
1375
|
+
const queryKey = opts.queryKey;
|
|
1376
|
+
const cacheSignal = this.client.getSignal(queryKey);
|
|
1377
|
+
const entry = cacheSignal.get();
|
|
1378
|
+
const data = entry?.data;
|
|
1379
|
+
const status = entry?.status || "pending";
|
|
1380
|
+
const error = entry?.error || null;
|
|
1381
|
+
const isFetching = entry?.isFetching || false;
|
|
1382
|
+
const staleTime = opts.staleTime ?? 0;
|
|
1383
|
+
const now = Date.now();
|
|
1384
|
+
const dataTimestamp = entry?.timestamp;
|
|
1385
|
+
const diff = dataTimestamp ? now - dataTimestamp : -1;
|
|
1386
|
+
const isTimeStale = dataTimestamp ? diff > staleTime : true;
|
|
1387
|
+
const isStale = entry?.isInvalidated || isTimeStale;
|
|
1388
|
+
const isError = status === "error";
|
|
1389
|
+
const isSuccess = status === "success";
|
|
1390
|
+
const isPending = status === "pending";
|
|
1391
|
+
const isLoading = data === void 0 && isFetching;
|
|
1392
|
+
let finalData;
|
|
1393
|
+
if (data !== void 0) {
|
|
1394
|
+
try {
|
|
1395
|
+
finalData = opts.select ? opts.select(data) : data;
|
|
1396
|
+
} catch (e) {
|
|
1397
|
+
return {
|
|
1398
|
+
...lastResult ?? {},
|
|
1399
|
+
status: "error",
|
|
1400
|
+
error: e,
|
|
1401
|
+
isError: true
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1292
1404
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1405
|
+
const nextResult = {
|
|
1406
|
+
data: finalData,
|
|
1407
|
+
isLoading,
|
|
1408
|
+
isError,
|
|
1409
|
+
isSuccess,
|
|
1410
|
+
isPending,
|
|
1411
|
+
isFetching,
|
|
1412
|
+
isStale,
|
|
1413
|
+
error,
|
|
1414
|
+
status,
|
|
1415
|
+
refetch: this.refetch
|
|
1416
|
+
};
|
|
1417
|
+
const isDataEqual = lastResult?.data === nextResult.data || isDeepEqual(lastResult?.data, nextResult.data);
|
|
1418
|
+
if (lastResult && isDataEqual && lastResult.status === nextResult.status && lastResult.isFetching === nextResult.isFetching && lastResult.isStale === nextResult.isStale && lastResult.error === nextResult.error) {
|
|
1419
|
+
return lastResult;
|
|
1307
1420
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
this.
|
|
1312
|
-
this.setupGlobalListeners();
|
|
1313
|
-
this.setupInterval();
|
|
1314
|
-
this.checkAndFetch();
|
|
1421
|
+
lastResult = nextResult;
|
|
1422
|
+
return nextResult;
|
|
1423
|
+
});
|
|
1424
|
+
this.initSideEffects();
|
|
1315
1425
|
}
|
|
1316
|
-
|
|
1317
|
-
this.
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
if (this.abortController) {
|
|
1324
|
-
this.abortController.abort();
|
|
1426
|
+
setOptions(options) {
|
|
1427
|
+
const current = this.options$.get();
|
|
1428
|
+
if (current === options) return;
|
|
1429
|
+
const isKeyEqual = stableHash(current.queryKey) === stableHash(options.queryKey);
|
|
1430
|
+
const isConfigEqual = current.enabled === options.enabled && current.staleTime === options.staleTime && current.cacheTime === options.cacheTime && current.refetchInterval === options.refetchInterval && current.retry === options.retry;
|
|
1431
|
+
if (!isKeyEqual || !isConfigEqual || current.select !== options.select) {
|
|
1432
|
+
this.options$.set(options);
|
|
1325
1433
|
}
|
|
1326
1434
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
this.unsubscribeSignal = this.signal.subscribe(() => {
|
|
1331
|
-
this.notify();
|
|
1435
|
+
subscribe(listener) {
|
|
1436
|
+
const unsub = this.result$.subscribe(() => {
|
|
1437
|
+
listener();
|
|
1332
1438
|
});
|
|
1333
|
-
|
|
1334
|
-
computeResult() {
|
|
1335
|
-
const entry = this.signal.get();
|
|
1336
|
-
const data = entry?.data;
|
|
1337
|
-
const status = entry?.status || "pending";
|
|
1338
|
-
const error = entry?.error || null;
|
|
1339
|
-
const isFetching = entry?.isFetching || false;
|
|
1340
|
-
const dataTimestamp = entry?.timestamp;
|
|
1341
|
-
const staleTime = this.options.staleTime ?? 0;
|
|
1342
|
-
const isStale = entry?.isInvalidated || (dataTimestamp ? Date.now() - dataTimestamp > staleTime : true);
|
|
1343
|
-
const isError = status === "error";
|
|
1344
|
-
const isLoading = data === void 0;
|
|
1345
|
-
const nextResult = {
|
|
1346
|
-
data,
|
|
1347
|
-
isLoading,
|
|
1348
|
-
isError,
|
|
1349
|
-
isFetching,
|
|
1350
|
-
isStale,
|
|
1351
|
-
error,
|
|
1352
|
-
status,
|
|
1353
|
-
refetch: this.refetch
|
|
1354
|
-
};
|
|
1355
|
-
if (this.currentResult && this.shallowEqual(this.currentResult, nextResult)) {
|
|
1356
|
-
return this.currentResult;
|
|
1357
|
-
}
|
|
1358
|
-
this.currentResult = nextResult;
|
|
1359
|
-
return nextResult;
|
|
1439
|
+
return unsub;
|
|
1360
1440
|
}
|
|
1361
1441
|
getSnapshot = () => {
|
|
1362
|
-
|
|
1363
|
-
return this.computeResult();
|
|
1364
|
-
}
|
|
1365
|
-
return this.currentResult;
|
|
1442
|
+
return this.result$.get();
|
|
1366
1443
|
};
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
return false;
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
return true;
|
|
1381
|
-
}
|
|
1382
|
-
notify() {
|
|
1383
|
-
this.computeResult();
|
|
1384
|
-
this.listeners.forEach((l) => l());
|
|
1385
|
-
this.checkAndFetch();
|
|
1386
|
-
}
|
|
1387
|
-
// --- Fetch Logic ---
|
|
1388
|
-
fetch = async (background = false) => {
|
|
1389
|
-
if (this.options.enabled === false) return;
|
|
1390
|
-
if (this.abortController) this.abortController.abort();
|
|
1391
|
-
this.abortController = new AbortController();
|
|
1392
|
-
const signal2 = this.abortController.signal;
|
|
1393
|
-
try {
|
|
1394
|
-
let result = await this.client.fetch(
|
|
1395
|
-
this.options.queryKey,
|
|
1396
|
-
(ctx) => this.options.queryFn(ctx),
|
|
1397
|
-
{ signal: signal2, retry: this.options.retry, retryDelay: this.options.retryDelay }
|
|
1398
|
-
);
|
|
1399
|
-
try {
|
|
1400
|
-
result = validateWithSchema(result, this.options.schema);
|
|
1401
|
-
} catch (validationErr) {
|
|
1402
|
-
const current = this.signal.get();
|
|
1403
|
-
this.signal.set({
|
|
1404
|
-
...current,
|
|
1405
|
-
status: "error",
|
|
1406
|
-
error: validationErr,
|
|
1407
|
-
isFetching: false,
|
|
1408
|
-
data: void 0
|
|
1409
|
-
});
|
|
1410
|
-
return;
|
|
1444
|
+
initSideEffects() {
|
|
1445
|
+
const disposeEffect = effect(() => {
|
|
1446
|
+
const opts = this.options$.get();
|
|
1447
|
+
const res = this.result$.get();
|
|
1448
|
+
if (opts.enabled !== false) {
|
|
1449
|
+
if (res.isLoading && !res.isFetching && !res.isError) {
|
|
1450
|
+
untracked(() => this.fetch());
|
|
1451
|
+
} else if (res.isStale && !res.isFetching && !res.isError) {
|
|
1452
|
+
untracked(() => this.fetch());
|
|
1453
|
+
}
|
|
1411
1454
|
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1455
|
+
});
|
|
1456
|
+
const disposeGC = effect(() => {
|
|
1457
|
+
const opts = this.options$.get();
|
|
1458
|
+
const signal2 = this.client.getSignal(opts.queryKey);
|
|
1459
|
+
const unsub = signal2.subscribe(() => {
|
|
1416
1460
|
});
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1461
|
+
return () => unsub();
|
|
1462
|
+
});
|
|
1463
|
+
const disposeFocus = focusManager.subscribe(() => {
|
|
1464
|
+
const opts = this.options$.get();
|
|
1465
|
+
if (opts.enabled !== false && opts.refetchOnWindowFocus !== false) {
|
|
1466
|
+
this.fetch();
|
|
1420
1467
|
}
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1468
|
+
});
|
|
1469
|
+
const disposeOnline = onlineManager.subscribe((isOnline) => {
|
|
1470
|
+
const opts = this.options$.get();
|
|
1471
|
+
if (isOnline && opts.enabled !== false && opts.refetchOnReconnect !== false) {
|
|
1472
|
+
this.fetch();
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
this.unsubscribe = () => {
|
|
1476
|
+
disposeEffect();
|
|
1477
|
+
disposeGC();
|
|
1478
|
+
disposeFocus();
|
|
1479
|
+
disposeOnline();
|
|
1480
|
+
};
|
|
1431
1481
|
}
|
|
1432
1482
|
refetch = async () => {
|
|
1433
|
-
this.
|
|
1483
|
+
const opts = this.options$.get();
|
|
1484
|
+
this.client.invalidate(opts.queryKey);
|
|
1434
1485
|
await this.fetch();
|
|
1435
1486
|
};
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
if (this.
|
|
1440
|
-
this.
|
|
1441
|
-
this.fetch(true);
|
|
1442
|
-
}, this.options.refetchInterval);
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
cleanupInterval() {
|
|
1446
|
-
if (this.intervalParams.id) {
|
|
1447
|
-
clearInterval(this.intervalParams.id);
|
|
1448
|
-
this.intervalParams.id = null;
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
onFocus = () => {
|
|
1452
|
-
if (this.options.refetchOnWindowFocus) {
|
|
1453
|
-
const snapshot = this.getSnapshot();
|
|
1454
|
-
if (snapshot.isStale && !snapshot.isFetching) {
|
|
1455
|
-
this.fetch(true);
|
|
1456
|
-
}
|
|
1487
|
+
fetch = async (background = false) => {
|
|
1488
|
+
const opts = this.options$.get();
|
|
1489
|
+
if (opts.enabled === false) return;
|
|
1490
|
+
if (this.abortController) {
|
|
1491
|
+
this.abortController.abort();
|
|
1457
1492
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1493
|
+
this.abortController = new AbortController();
|
|
1494
|
+
const signal2 = this.abortController.signal;
|
|
1495
|
+
try {
|
|
1496
|
+
await this.client.fetch(
|
|
1497
|
+
opts.queryKey,
|
|
1498
|
+
async (ctx) => {
|
|
1499
|
+
const data = await opts.queryFn(ctx);
|
|
1500
|
+
if (opts.schema) {
|
|
1501
|
+
return validateWithSchema(data, opts.schema);
|
|
1502
|
+
}
|
|
1503
|
+
return data;
|
|
1504
|
+
},
|
|
1505
|
+
{ signal: signal2, retry: opts.retry, retryDelay: opts.retryDelay, tags: opts.tags }
|
|
1506
|
+
);
|
|
1507
|
+
} catch (e) {
|
|
1465
1508
|
}
|
|
1466
1509
|
};
|
|
1467
|
-
|
|
1468
|
-
if (
|
|
1469
|
-
|
|
1470
|
-
window.addEventListener("online", this.onOnline);
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
cleanupGlobalListeners() {
|
|
1474
|
-
if (typeof window !== "undefined") {
|
|
1475
|
-
window.removeEventListener("focus", this.onFocus);
|
|
1476
|
-
window.removeEventListener("online", this.onOnline);
|
|
1477
|
-
}
|
|
1510
|
+
destroy() {
|
|
1511
|
+
if (this.unsubscribe) this.unsubscribe();
|
|
1512
|
+
if (this.abortController) this.abortController.abort();
|
|
1478
1513
|
}
|
|
1479
1514
|
};
|
|
1480
1515
|
|
|
1481
|
-
// src/
|
|
1516
|
+
// src/query/useQuery.ts
|
|
1482
1517
|
function useQuery(options) {
|
|
1483
1518
|
const client = useQueryClient();
|
|
1484
1519
|
const [observer] = (0, import_react4.useState)(() => new QueryObserver(client, options));
|
|
1485
1520
|
(0, import_react4.useEffect)(() => {
|
|
1486
1521
|
observer.setOptions(options);
|
|
1487
1522
|
}, [observer, options]);
|
|
1488
|
-
|
|
1523
|
+
(0, import_react4.useEffect)(() => {
|
|
1524
|
+
return () => {
|
|
1525
|
+
observer.destroy();
|
|
1526
|
+
};
|
|
1527
|
+
}, [observer]);
|
|
1528
|
+
const subscribe = (0, import_react4.useCallback)((onStoreChange) => {
|
|
1489
1529
|
return observer.subscribe(onStoreChange);
|
|
1490
1530
|
}, [observer]);
|
|
1491
|
-
const
|
|
1492
|
-
|
|
1493
|
-
selectRef.current = select;
|
|
1494
|
-
const memoRef = (0, import_react4.useRef)({ entry: void 0, selected: void 0 });
|
|
1495
|
-
const getSnapshotWithSelector = (0, import_react4.useCallback)(() => {
|
|
1496
|
-
const entry = observer.getSnapshot();
|
|
1497
|
-
if (entry === memoRef.current.entry) {
|
|
1498
|
-
return memoRef.current.selected;
|
|
1499
|
-
}
|
|
1500
|
-
let processedResult;
|
|
1501
|
-
if (!entry) {
|
|
1502
|
-
processedResult = void 0;
|
|
1503
|
-
} else {
|
|
1504
|
-
if (selectRef.current && entry.data !== void 0) {
|
|
1505
|
-
processedResult = { ...entry, data: selectRef.current(entry.data) };
|
|
1506
|
-
} else {
|
|
1507
|
-
processedResult = entry;
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
memoRef.current = { entry, selected: processedResult };
|
|
1511
|
-
return processedResult;
|
|
1531
|
+
const getSnapshot = (0, import_react4.useCallback)(() => {
|
|
1532
|
+
return observer.getSnapshot();
|
|
1512
1533
|
}, [observer]);
|
|
1513
|
-
const result = (0, import_react4.useSyncExternalStore)(
|
|
1514
|
-
const status = result?.status || "pending";
|
|
1515
|
-
const computedResult = {
|
|
1516
|
-
...result,
|
|
1517
|
-
isPending: status === "pending",
|
|
1518
|
-
isSuccess: status === "success",
|
|
1519
|
-
isError: status === "error"
|
|
1520
|
-
};
|
|
1521
|
-
const typedResult = computedResult;
|
|
1522
|
-
const signal2 = client.getSignal(options.queryKey);
|
|
1534
|
+
const result = (0, import_react4.useSyncExternalStore)(subscribe, getSnapshot);
|
|
1523
1535
|
return {
|
|
1524
|
-
...
|
|
1525
|
-
signal:
|
|
1526
|
-
// Keep signal as T (source)
|
|
1536
|
+
...result,
|
|
1537
|
+
signal: observer.result$
|
|
1527
1538
|
};
|
|
1528
1539
|
}
|
|
1529
1540
|
|
|
1530
|
-
// src/
|
|
1541
|
+
// src/query/useMutation.ts
|
|
1531
1542
|
var import_react5 = require("react");
|
|
1532
1543
|
|
|
1533
|
-
// src/
|
|
1544
|
+
// src/query/mutationObserver.ts
|
|
1534
1545
|
var generateId = () => {
|
|
1535
1546
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
1536
1547
|
return crypto.randomUUID();
|
|
@@ -1618,8 +1629,7 @@ var MutationObserver = class {
|
|
|
1618
1629
|
return result;
|
|
1619
1630
|
} catch (error) {
|
|
1620
1631
|
if (optimistic && optimisticSnapshot !== void 0) {
|
|
1621
|
-
|
|
1622
|
-
queryCache.set(optimistic.queryKey, optimisticSnapshot);
|
|
1632
|
+
this.client.set(optimistic.queryKey, optimisticSnapshot);
|
|
1623
1633
|
}
|
|
1624
1634
|
notify({ status: "error", error });
|
|
1625
1635
|
if (onError) onError(error, variables, context);
|
|
@@ -1633,13 +1643,14 @@ var MutationObserver = class {
|
|
|
1633
1643
|
data: void 0,
|
|
1634
1644
|
error: null,
|
|
1635
1645
|
variables: void 0,
|
|
1646
|
+
context: void 0,
|
|
1636
1647
|
submittedAt: 0
|
|
1637
1648
|
});
|
|
1638
1649
|
this.currentMutationId = null;
|
|
1639
1650
|
};
|
|
1640
1651
|
};
|
|
1641
1652
|
|
|
1642
|
-
// src/
|
|
1653
|
+
// src/query/useMutation.ts
|
|
1643
1654
|
function useMutation(options) {
|
|
1644
1655
|
const client = useQueryClient();
|
|
1645
1656
|
const [observer] = (0, import_react5.useState)(() => new MutationObserver(client, options));
|
|
@@ -1671,10 +1682,10 @@ function useMutation(options) {
|
|
|
1671
1682
|
};
|
|
1672
1683
|
}
|
|
1673
1684
|
|
|
1674
|
-
// src/
|
|
1685
|
+
// src/query/infiniteQuery.ts
|
|
1675
1686
|
var import_react6 = require("react");
|
|
1676
1687
|
|
|
1677
|
-
// src/
|
|
1688
|
+
// src/query/plugins/logger.ts
|
|
1678
1689
|
var consoleLogger = {
|
|
1679
1690
|
log: console.log,
|
|
1680
1691
|
warn: console.warn,
|
|
@@ -1683,133 +1694,166 @@ var consoleLogger = {
|
|
|
1683
1694
|
var currentLogger = consoleLogger;
|
|
1684
1695
|
var getLogger = () => currentLogger;
|
|
1685
1696
|
|
|
1686
|
-
// src/
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
const
|
|
1726
|
-
|
|
1727
|
-
|
|
1697
|
+
// src/query/infiniteQueryObserver.ts
|
|
1698
|
+
var InfiniteQueryObserver = class {
|
|
1699
|
+
client;
|
|
1700
|
+
options$;
|
|
1701
|
+
result$;
|
|
1702
|
+
unsubscribe = null;
|
|
1703
|
+
lastFetchTime = 0;
|
|
1704
|
+
constructor(client, options) {
|
|
1705
|
+
this.client = client;
|
|
1706
|
+
this.options$ = createSignal(options);
|
|
1707
|
+
const infiniteQueryKey = computed(() => {
|
|
1708
|
+
const opts = this.options$.get();
|
|
1709
|
+
return [...opts.queryKey, "__infinite__"];
|
|
1710
|
+
});
|
|
1711
|
+
let lastResult = null;
|
|
1712
|
+
this.result$ = computed(() => {
|
|
1713
|
+
const opts = this.options$.get();
|
|
1714
|
+
const key = infiniteQueryKey.get();
|
|
1715
|
+
const cacheSignal = this.client.getSignal(key);
|
|
1716
|
+
const entry = cacheSignal.get();
|
|
1717
|
+
const data = entry?.data;
|
|
1718
|
+
const isFetching = entry?.isFetching || false;
|
|
1719
|
+
const fetchDirection = entry?.fetchDirection || "idle";
|
|
1720
|
+
const status = entry?.status || "pending";
|
|
1721
|
+
const error = entry?.error || null;
|
|
1722
|
+
let hasNextPage = false;
|
|
1723
|
+
let hasPreviousPage = false;
|
|
1724
|
+
if (data && data.pages.length > 0) {
|
|
1725
|
+
if (opts.getNextPageParam) {
|
|
1726
|
+
const lastPage = data.pages[data.pages.length - 1];
|
|
1727
|
+
hasNextPage = opts.getNextPageParam(lastPage, data.pages) !== void 0;
|
|
1728
|
+
}
|
|
1729
|
+
if (opts.getPreviousPageParam) {
|
|
1730
|
+
const firstPage = data.pages[0];
|
|
1731
|
+
hasPreviousPage = opts.getPreviousPageParam(firstPage, data.pages) !== void 0;
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
const isFetchingNextPage = isFetching && fetchDirection === "next";
|
|
1735
|
+
const isFetchingPreviousPage = isFetching && fetchDirection === "previous";
|
|
1736
|
+
const isLoading = data === void 0 && isFetching;
|
|
1737
|
+
const nextResult = {
|
|
1738
|
+
data,
|
|
1739
|
+
isFetching,
|
|
1740
|
+
isFetchingNextPage,
|
|
1741
|
+
isFetchingPreviousPage,
|
|
1742
|
+
isLoading,
|
|
1743
|
+
isError: status === "error",
|
|
1744
|
+
hasNextPage,
|
|
1745
|
+
hasPreviousPage,
|
|
1746
|
+
error,
|
|
1747
|
+
status,
|
|
1748
|
+
fetchNextPage: this.fetchNextPage,
|
|
1749
|
+
fetchPreviousPage: this.fetchPreviousPage,
|
|
1750
|
+
refetch: this.refetch
|
|
1751
|
+
};
|
|
1752
|
+
const isDataEqual = lastResult?.data === nextResult.data || isDeepEqual(lastResult?.data, nextResult.data);
|
|
1753
|
+
if (lastResult && isDataEqual && lastResult.isFetching === nextResult.isFetching && lastResult.status === nextResult.status && lastResult.hasNextPage === nextResult.hasNextPage && lastResult.hasPreviousPage === nextResult.hasPreviousPage) {
|
|
1754
|
+
return lastResult;
|
|
1755
|
+
}
|
|
1756
|
+
lastResult = nextResult;
|
|
1757
|
+
return nextResult;
|
|
1758
|
+
});
|
|
1759
|
+
this.initSideEffects();
|
|
1728
1760
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
const doInitialFetch = async () => {
|
|
1752
|
-
try {
|
|
1753
|
-
if (data && data.pageParams.length > 0) {
|
|
1754
|
-
const updatedPages = [];
|
|
1755
|
-
const updatedParams = [];
|
|
1756
|
-
let param = data.pageParams[0];
|
|
1757
|
-
updatedParams.push(param);
|
|
1758
|
-
const limit = data.pages.length;
|
|
1759
|
-
const fetchedData = await client.fetch(infiniteQueryKey, async () => {
|
|
1760
|
-
for (let i = 0; i < limit; i++) {
|
|
1761
|
-
const page = await queryFnRef.current({ pageParam: param });
|
|
1762
|
-
updatedPages.push(page);
|
|
1763
|
-
if (i < limit - 1) {
|
|
1764
|
-
const next = getNextPageParamRef.current?.(page, updatedPages);
|
|
1765
|
-
if (next === void 0) break;
|
|
1766
|
-
param = next;
|
|
1767
|
-
updatedParams.push(param);
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
return {
|
|
1771
|
-
pages: updatedPages,
|
|
1772
|
-
pageParams: updatedParams
|
|
1773
|
-
};
|
|
1774
|
-
}, { fetchDirection: "initial", retry });
|
|
1775
|
-
client.set(infiniteQueryKey, fetchedData, {
|
|
1776
|
-
staleTime: staleTimeRef.current,
|
|
1777
|
-
cacheTime: cacheTimeRef.current
|
|
1778
|
-
});
|
|
1779
|
-
return;
|
|
1761
|
+
setOptions(options) {
|
|
1762
|
+
const current = this.options$.get();
|
|
1763
|
+
if (current === options) return;
|
|
1764
|
+
const isKeyEqual = stableHash(current.queryKey) === stableHash(options.queryKey);
|
|
1765
|
+
const isConfigEqual = current.enabled === options.enabled && current.staleTime === options.staleTime;
|
|
1766
|
+
if (!isKeyEqual || !isConfigEqual || current.getNextPageParam !== options.getNextPageParam || current.getPreviousPageParam !== options.getPreviousPageParam) {
|
|
1767
|
+
this.options$.set(options);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
initSideEffects() {
|
|
1771
|
+
const dispose = effect(() => {
|
|
1772
|
+
const opts = this.options$.get();
|
|
1773
|
+
const res = this.result$.get();
|
|
1774
|
+
if (opts.enabled !== false) {
|
|
1775
|
+
const infiniteKey = [...opts.queryKey, "__infinite__"];
|
|
1776
|
+
const entry = this.client.getSignal(infiniteKey).get();
|
|
1777
|
+
const staleTime = opts.staleTime ?? 0;
|
|
1778
|
+
const now = Date.now();
|
|
1779
|
+
const timestamp = entry?.timestamp || 0;
|
|
1780
|
+
const isStale = entry?.isInvalidated || entry?.data && now - timestamp > staleTime;
|
|
1781
|
+
if ((!entry?.data || isStale) && !res.isFetching && !res.isError) {
|
|
1782
|
+
untracked(() => this.fetchInitial());
|
|
1780
1783
|
}
|
|
1781
|
-
const initialParam = initialPageParamRef.current;
|
|
1782
|
-
const firstParam = initialParam !== void 0 ? initialParam : 0;
|
|
1783
|
-
const initialData = await client.fetch(infiniteQueryKey, async () => {
|
|
1784
|
-
const firstPage = await queryFnRef.current({ pageParam: firstParam });
|
|
1785
|
-
return {
|
|
1786
|
-
pages: [firstPage],
|
|
1787
|
-
pageParams: [firstParam]
|
|
1788
|
-
};
|
|
1789
|
-
}, { fetchDirection: "initial", retry });
|
|
1790
|
-
client.set(infiniteQueryKey, initialData, {
|
|
1791
|
-
staleTime: staleTimeRef.current,
|
|
1792
|
-
cacheTime: cacheTimeRef.current
|
|
1793
|
-
});
|
|
1794
|
-
} catch (err) {
|
|
1795
|
-
getLogger().error("Initial fetch failed", err);
|
|
1796
1784
|
}
|
|
1785
|
+
});
|
|
1786
|
+
const disposeFocus = focusManager.subscribe(() => {
|
|
1787
|
+
const opts = this.options$.get();
|
|
1788
|
+
if (opts.enabled !== false && opts.refetchOnWindowFocus !== false) {
|
|
1789
|
+
this.fetchInitial();
|
|
1790
|
+
}
|
|
1791
|
+
});
|
|
1792
|
+
const disposeOnline = onlineManager.subscribe((isOnline) => {
|
|
1793
|
+
const opts = this.options$.get();
|
|
1794
|
+
if (isOnline && opts.enabled !== false && opts.refetchOnReconnect !== false) {
|
|
1795
|
+
this.fetchInitial();
|
|
1796
|
+
}
|
|
1797
|
+
});
|
|
1798
|
+
this.unsubscribe = () => {
|
|
1799
|
+
dispose();
|
|
1800
|
+
disposeFocus();
|
|
1801
|
+
disposeOnline();
|
|
1797
1802
|
};
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1803
|
+
}
|
|
1804
|
+
fetchInitial = async (options) => {
|
|
1805
|
+
const opts = this.options$.get();
|
|
1806
|
+
const infiniteKey = [...opts.queryKey, "__infinite__"];
|
|
1807
|
+
try {
|
|
1808
|
+
const entrySignal = this.client.getSignal(infiniteKey);
|
|
1809
|
+
const data = entrySignal.get()?.data;
|
|
1810
|
+
if (data && data.pageParams.length > 0 && !options?.force) {
|
|
1811
|
+
const firstParam2 = data.pageParams[0];
|
|
1812
|
+
const firstPage = await opts.queryFn({ pageParam: firstParam2 });
|
|
1813
|
+
const latest = entrySignal.get()?.data;
|
|
1814
|
+
if (!latest) return;
|
|
1815
|
+
const updatedData = {
|
|
1816
|
+
...latest,
|
|
1817
|
+
pages: [firstPage, ...latest.pages.slice(1)]
|
|
1818
|
+
};
|
|
1819
|
+
this.client.set(infiniteKey, updatedData, {
|
|
1820
|
+
staleTime: opts.staleTime,
|
|
1821
|
+
cacheTime: opts.cacheTime
|
|
1822
|
+
});
|
|
1823
|
+
return;
|
|
1824
|
+
}
|
|
1825
|
+
const initialParam = opts.initialPageParam;
|
|
1826
|
+
const firstParam = initialParam !== void 0 ? initialParam : 0;
|
|
1827
|
+
const initialData = await this.client.fetch(infiniteKey, async () => {
|
|
1828
|
+
const firstPage = await opts.queryFn({ pageParam: firstParam });
|
|
1829
|
+
return {
|
|
1830
|
+
pages: [firstPage],
|
|
1831
|
+
pageParams: [firstParam]
|
|
1832
|
+
};
|
|
1833
|
+
}, { fetchDirection: "initial", retry: opts.retry });
|
|
1834
|
+
this.client.set(infiniteKey, initialData, {
|
|
1835
|
+
staleTime: opts.staleTime,
|
|
1836
|
+
cacheTime: opts.cacheTime
|
|
1837
|
+
});
|
|
1838
|
+
} catch (err) {
|
|
1839
|
+
getLogger().error("Initial fetch failed", err);
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
fetchNextPage = async () => {
|
|
1843
|
+
const res = this.result$.get();
|
|
1844
|
+
const opts = this.options$.get();
|
|
1845
|
+
if (!res.hasNextPage || res.isFetching || !res.data) return;
|
|
1846
|
+
const infiniteKey = [...opts.queryKey, "__infinite__"];
|
|
1847
|
+
const lastPage = res.data.pages[res.data.pages.length - 1];
|
|
1848
|
+
const nextPageParam = opts.getNextPageParam?.(lastPage, res.data.pages);
|
|
1804
1849
|
if (nextPageParam === void 0) return;
|
|
1805
1850
|
try {
|
|
1806
|
-
const updatedData = await client.fetch(
|
|
1807
|
-
const newPage = await
|
|
1808
|
-
const
|
|
1809
|
-
|
|
1810
|
-
if (!currentData) throw new Error("Infinite query data missing during fetchNextPage");
|
|
1811
|
-
const nextCursor = getNextPageParamRef.current?.(newPage, [...currentData.pages, newPage]);
|
|
1851
|
+
const updatedData = await this.client.fetch(infiniteKey, async () => {
|
|
1852
|
+
const newPage = await opts.queryFn({ pageParam: nextPageParam });
|
|
1853
|
+
const currentData = this.client.getSignal(infiniteKey).get()?.data;
|
|
1854
|
+
if (!currentData) throw new Error("Infinite query data missing");
|
|
1812
1855
|
const updatedParams = [...currentData.pageParams, nextPageParam];
|
|
1856
|
+
const nextCursor = opts.getNextPageParam?.(newPage, [...currentData.pages, newPage]);
|
|
1813
1857
|
if (nextCursor !== void 0) {
|
|
1814
1858
|
updatedParams.push(nextCursor);
|
|
1815
1859
|
}
|
|
@@ -1817,77 +1861,86 @@ function useInfiniteQuery({
|
|
|
1817
1861
|
pages: [...currentData.pages, newPage],
|
|
1818
1862
|
pageParams: updatedParams
|
|
1819
1863
|
};
|
|
1820
|
-
}, {
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
client.set(infiniteQueryKey, updatedData, {
|
|
1825
|
-
staleTime: staleTimeRef.current,
|
|
1826
|
-
cacheTime: cacheTimeRef.current
|
|
1864
|
+
}, { fetchDirection: "next", retry: opts.retry });
|
|
1865
|
+
this.client.set(infiniteKey, updatedData, {
|
|
1866
|
+
staleTime: opts.staleTime,
|
|
1867
|
+
cacheTime: opts.cacheTime
|
|
1827
1868
|
});
|
|
1828
1869
|
} catch (err) {
|
|
1829
1870
|
getLogger().error("Fetch next page failed", err);
|
|
1830
1871
|
}
|
|
1831
|
-
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
const
|
|
1835
|
-
|
|
1872
|
+
};
|
|
1873
|
+
fetchPreviousPage = async () => {
|
|
1874
|
+
const res = this.result$.get();
|
|
1875
|
+
const opts = this.options$.get();
|
|
1876
|
+
if (!res.hasPreviousPage || res.isFetching || !res.data) return;
|
|
1877
|
+
const infiniteKey = [...opts.queryKey, "__infinite__"];
|
|
1878
|
+
const firstPage = res.data.pages[0];
|
|
1879
|
+
const previousPageParam = opts.getPreviousPageParam?.(firstPage, res.data.pages);
|
|
1836
1880
|
if (previousPageParam === void 0) return;
|
|
1837
1881
|
try {
|
|
1838
|
-
const updatedData = await client.fetch(
|
|
1839
|
-
const newPage = await
|
|
1840
|
-
const
|
|
1841
|
-
|
|
1842
|
-
if (!currentData) throw new Error("Infinite query data missing during fetchPreviousPage");
|
|
1882
|
+
const updatedData = await this.client.fetch(infiniteKey, async () => {
|
|
1883
|
+
const newPage = await opts.queryFn({ pageParam: previousPageParam });
|
|
1884
|
+
const currentData = this.client.getSignal(infiniteKey).get()?.data;
|
|
1885
|
+
if (!currentData) throw new Error("Infinite query data missing");
|
|
1843
1886
|
return {
|
|
1844
1887
|
pages: [newPage, ...currentData.pages],
|
|
1845
1888
|
pageParams: [previousPageParam, ...currentData.pageParams]
|
|
1846
1889
|
};
|
|
1847
|
-
}, { fetchDirection: "previous", retry });
|
|
1848
|
-
client.set(
|
|
1849
|
-
staleTime:
|
|
1850
|
-
cacheTime:
|
|
1890
|
+
}, { fetchDirection: "previous", retry: opts.retry });
|
|
1891
|
+
this.client.set(infiniteKey, updatedData, {
|
|
1892
|
+
staleTime: opts.staleTime,
|
|
1893
|
+
cacheTime: opts.cacheTime
|
|
1851
1894
|
});
|
|
1852
1895
|
} catch (err) {
|
|
1853
1896
|
getLogger().error("Fetch previous page failed", err);
|
|
1854
1897
|
}
|
|
1855
|
-
}, [hasPreviousPage, isFetching, data, client, JSON.stringify(infiniteQueryKey)]);
|
|
1856
|
-
const refetch = (0, import_react6.useCallback)(async () => {
|
|
1857
|
-
client.invalidate(infiniteQueryKey);
|
|
1858
|
-
}, [client, JSON.stringify(infiniteQueryKey)]);
|
|
1859
|
-
return {
|
|
1860
|
-
data,
|
|
1861
|
-
fetchNextPage,
|
|
1862
|
-
fetchPreviousPage,
|
|
1863
|
-
hasNextPage,
|
|
1864
|
-
hasPreviousPage,
|
|
1865
|
-
isFetching,
|
|
1866
|
-
isFetchingNextPage,
|
|
1867
|
-
isFetchingPreviousPage,
|
|
1868
|
-
isLoading,
|
|
1869
|
-
isError,
|
|
1870
|
-
error,
|
|
1871
|
-
refetch
|
|
1872
1898
|
};
|
|
1899
|
+
refetch = async () => {
|
|
1900
|
+
const opts = this.options$.get();
|
|
1901
|
+
const infiniteKey = [...opts.queryKey, "__infinite__"];
|
|
1902
|
+
this.client.invalidate(infiniteKey);
|
|
1903
|
+
await this.fetchInitial({ force: true });
|
|
1904
|
+
};
|
|
1905
|
+
destroy() {
|
|
1906
|
+
if (this.unsubscribe) this.unsubscribe();
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1909
|
+
|
|
1910
|
+
// src/query/infiniteQuery.ts
|
|
1911
|
+
function useInfiniteQuery(options) {
|
|
1912
|
+
const client = useQueryClient();
|
|
1913
|
+
const [observer] = (0, import_react6.useState)(() => new InfiniteQueryObserver(client, options));
|
|
1914
|
+
(0, import_react6.useEffect)(() => {
|
|
1915
|
+
observer.setOptions(options);
|
|
1916
|
+
}, [observer, options]);
|
|
1917
|
+
(0, import_react6.useEffect)(() => {
|
|
1918
|
+
return () => {
|
|
1919
|
+
observer.destroy();
|
|
1920
|
+
};
|
|
1921
|
+
}, [observer]);
|
|
1922
|
+
const subscribe = (0, import_react6.useCallback)((onStoreChange) => {
|
|
1923
|
+
return observer.result$.subscribe(() => onStoreChange());
|
|
1924
|
+
}, [observer]);
|
|
1925
|
+
const getSnapshot = (0, import_react6.useCallback)(() => {
|
|
1926
|
+
return observer.result$.get();
|
|
1927
|
+
}, [observer]);
|
|
1928
|
+
return (0, import_react6.useSyncExternalStore)(subscribe, getSnapshot);
|
|
1873
1929
|
}
|
|
1874
1930
|
|
|
1875
|
-
// src/
|
|
1931
|
+
// src/query/HydrationBoundary.tsx
|
|
1876
1932
|
var import_react7 = require("react");
|
|
1877
1933
|
|
|
1878
|
-
// src/
|
|
1934
|
+
// src/query/hydration.ts
|
|
1879
1935
|
function dehydrate(client) {
|
|
1880
1936
|
const queries = [];
|
|
1881
1937
|
const snapshot = client.getSnapshot();
|
|
1882
|
-
snapshot.forEach((
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
state
|
|
1889
|
-
});
|
|
1890
|
-
}
|
|
1938
|
+
snapshot.forEach((state, hash) => {
|
|
1939
|
+
queries.push({
|
|
1940
|
+
queryKey: state.key,
|
|
1941
|
+
queryHash: hash,
|
|
1942
|
+
state
|
|
1943
|
+
});
|
|
1891
1944
|
});
|
|
1892
1945
|
return { queries };
|
|
1893
1946
|
}
|
|
@@ -1899,8 +1952,8 @@ function hydrate(client, state) {
|
|
|
1899
1952
|
});
|
|
1900
1953
|
}
|
|
1901
1954
|
|
|
1902
|
-
// src/
|
|
1903
|
-
var
|
|
1955
|
+
// src/query/HydrationBoundary.tsx
|
|
1956
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1904
1957
|
function HydrationBoundary({ state, children }) {
|
|
1905
1958
|
const client = useQueryClient();
|
|
1906
1959
|
const hydratedRef = (0, import_react7.useRef)(false);
|
|
@@ -1908,10 +1961,10 @@ function HydrationBoundary({ state, children }) {
|
|
|
1908
1961
|
hydrate(client, state);
|
|
1909
1962
|
hydratedRef.current = true;
|
|
1910
1963
|
}
|
|
1911
|
-
return /* @__PURE__ */ (0,
|
|
1964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
|
|
1912
1965
|
}
|
|
1913
1966
|
|
|
1914
|
-
// src/
|
|
1967
|
+
// src/query/useSuspenseQuery.ts
|
|
1915
1968
|
function useSuspenseQuery(options) {
|
|
1916
1969
|
const client = useQueryClient();
|
|
1917
1970
|
const signal2 = client.getSignal(options.queryKey);
|
|
@@ -1920,8 +1973,7 @@ function useSuspenseQuery(options) {
|
|
|
1920
1973
|
if (shouldSuspend) {
|
|
1921
1974
|
const fetchPromise = client.fetch(
|
|
1922
1975
|
options.queryKey,
|
|
1923
|
-
|
|
1924
|
-
(ctx) => options.queryFn(ctx),
|
|
1976
|
+
(ctx) => options.queryFn({ ...ctx, signal: void 0 }),
|
|
1925
1977
|
{ signal: void 0 }
|
|
1926
1978
|
).then((data) => {
|
|
1927
1979
|
client.set(options.queryKey, data);
|
|
@@ -1939,73 +1991,60 @@ function useSuspenseQuery(options) {
|
|
|
1939
1991
|
};
|
|
1940
1992
|
}
|
|
1941
1993
|
|
|
1942
|
-
// src/
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
const
|
|
1946
|
-
const
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
});
|
|
1955
|
-
return proxy;
|
|
1994
|
+
// src/query/useQueryStore.ts
|
|
1995
|
+
var import_react8 = require("react");
|
|
1996
|
+
function useQueryStore() {
|
|
1997
|
+
const client = useQueryClient();
|
|
1998
|
+
const [cache, setCache] = (0, import_react8.useState)(client.getAll());
|
|
1999
|
+
(0, import_react8.useEffect)(() => {
|
|
2000
|
+
const interval = setInterval(() => {
|
|
2001
|
+
setCache(new Map(client.getAll()));
|
|
2002
|
+
}, 500);
|
|
2003
|
+
return () => clearInterval(interval);
|
|
2004
|
+
}, [client]);
|
|
2005
|
+
return cache;
|
|
1956
2006
|
}
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
run();
|
|
1976
|
-
return {
|
|
1977
|
-
get: s.get,
|
|
1978
|
-
set: () => {
|
|
1979
|
-
throw new Error("Cannot set a read-only bridge signal");
|
|
1980
|
-
},
|
|
1981
|
-
subscribe: s.subscribe
|
|
1982
|
-
};
|
|
2007
|
+
|
|
2008
|
+
// src/query/useQuerySignal.ts
|
|
2009
|
+
var import_react9 = require("react");
|
|
2010
|
+
function useQuery$(options) {
|
|
2011
|
+
const client = useQueryClient();
|
|
2012
|
+
const [observer] = (0, import_react9.useState)(() => new QueryObserver(client, options));
|
|
2013
|
+
(0, import_react9.useEffect)(() => {
|
|
2014
|
+
observer.setOptions(options);
|
|
2015
|
+
}, [observer, options.enabled, options.staleTime, options.cacheTime, options.queryKey, options.refetchInterval]);
|
|
2016
|
+
(0, import_react9.useEffect)(() => {
|
|
2017
|
+
const unsubscribe = observer.subscribe(() => {
|
|
2018
|
+
});
|
|
2019
|
+
return () => {
|
|
2020
|
+
unsubscribe();
|
|
2021
|
+
observer.destroy();
|
|
2022
|
+
};
|
|
2023
|
+
}, [observer]);
|
|
2024
|
+
return observer.result$;
|
|
1983
2025
|
}
|
|
1984
2026
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1985
2027
|
0 && (module.exports = {
|
|
1986
2028
|
HydrationBoundary,
|
|
1987
|
-
|
|
2029
|
+
QueryClient,
|
|
1988
2030
|
QueryClientProvider,
|
|
1989
|
-
|
|
2031
|
+
SignalValue,
|
|
2032
|
+
atom,
|
|
1990
2033
|
createHttpClient,
|
|
1991
|
-
createState,
|
|
1992
|
-
defineModel,
|
|
1993
2034
|
dehydrate,
|
|
1994
2035
|
enableDevTools,
|
|
1995
|
-
fromSignal,
|
|
1996
2036
|
getPromiseState,
|
|
1997
2037
|
handlePromise,
|
|
1998
2038
|
hydrate,
|
|
1999
2039
|
isPromise,
|
|
2000
2040
|
scheduleUpdate,
|
|
2001
|
-
subscribe,
|
|
2002
|
-
toSignal,
|
|
2003
2041
|
unwrapPromise,
|
|
2004
2042
|
useInfiniteQuery,
|
|
2005
2043
|
useMutation,
|
|
2006
2044
|
usePaginatedQuery,
|
|
2007
2045
|
useQuery,
|
|
2046
|
+
useQuery$,
|
|
2008
2047
|
useQueryClient,
|
|
2009
|
-
|
|
2048
|
+
useQueryStore,
|
|
2010
2049
|
useSuspenseQuery
|
|
2011
2050
|
});
|