@braine/quantum-query 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -6
- package/dist/index.cjs +1312 -137
- package/dist/index.d.cts +298 -9
- package/dist/index.d.ts +298 -9
- package/dist/index.js +1301 -136
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
23
|
+
QuantumDevTools: () => QuantumDevTools,
|
|
24
|
+
QueryCache: () => QueryCache,
|
|
25
|
+
QueryClientProvider: () => QueryClientProvider,
|
|
24
26
|
computed: () => computed,
|
|
25
27
|
createHttpClient: () => createHttpClient,
|
|
26
28
|
createState: () => createState,
|
|
@@ -29,9 +31,17 @@ __export(index_exports, {
|
|
|
29
31
|
getPromiseState: () => getPromiseState,
|
|
30
32
|
handlePromise: () => handlePromise,
|
|
31
33
|
isPromise: () => isPromise,
|
|
34
|
+
optimisticHelpers: () => optimisticHelpers,
|
|
35
|
+
queryCache: () => queryCache,
|
|
32
36
|
scheduleUpdate: () => scheduleUpdate,
|
|
33
37
|
subscribe: () => subscribe,
|
|
34
38
|
unwrapPromise: () => unwrapPromise,
|
|
39
|
+
useInfiniteQuery: () => useInfiniteQuery,
|
|
40
|
+
useMutation: () => useMutation,
|
|
41
|
+
usePaginatedQuery: () => usePaginatedQuery,
|
|
42
|
+
useQuery: () => useQuery,
|
|
43
|
+
useQueryCache: () => useQueryCache,
|
|
44
|
+
useQueryClient: () => useQueryClient,
|
|
35
45
|
useStore: () => useStore
|
|
36
46
|
});
|
|
37
47
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -96,6 +106,7 @@ function getPromiseState(promise) {
|
|
|
96
106
|
// src/core/proxy.ts
|
|
97
107
|
var LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
98
108
|
var PROXIES = /* @__PURE__ */ new WeakMap();
|
|
109
|
+
var PROXY_TO_TARGET = /* @__PURE__ */ new WeakMap();
|
|
99
110
|
var activeListener = null;
|
|
100
111
|
function setActiveListener(listener) {
|
|
101
112
|
activeListener = listener;
|
|
@@ -105,10 +116,11 @@ function getActiveListener() {
|
|
|
105
116
|
}
|
|
106
117
|
var GLOBAL_LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
107
118
|
function subscribe(store, callback) {
|
|
108
|
-
|
|
119
|
+
const target = PROXY_TO_TARGET.get(store) || store;
|
|
120
|
+
let listeners = GLOBAL_LISTENERS.get(target);
|
|
109
121
|
if (!listeners) {
|
|
110
122
|
listeners = /* @__PURE__ */ new Set();
|
|
111
|
-
GLOBAL_LISTENERS.set(
|
|
123
|
+
GLOBAL_LISTENERS.set(target, listeners);
|
|
112
124
|
}
|
|
113
125
|
listeners.add(callback);
|
|
114
126
|
return () => listeners?.delete(callback);
|
|
@@ -125,8 +137,6 @@ var handler = {
|
|
|
125
137
|
}
|
|
126
138
|
const value = Reflect.get(target, prop, receiver);
|
|
127
139
|
if (isPromise(value)) {
|
|
128
|
-
if (prop === "$state") {
|
|
129
|
-
}
|
|
130
140
|
return unwrapPromise(value);
|
|
131
141
|
}
|
|
132
142
|
if (typeof value === "object" && value !== null) {
|
|
@@ -170,10 +180,18 @@ function createState(initialState) {
|
|
|
170
180
|
}
|
|
171
181
|
const proxy = new Proxy(initialState, handler);
|
|
172
182
|
PROXIES.set(initialState, proxy);
|
|
183
|
+
PROXY_TO_TARGET.set(proxy, initialState);
|
|
173
184
|
return proxy;
|
|
174
185
|
}
|
|
175
186
|
|
|
176
187
|
// src/core/model.ts
|
|
188
|
+
function debounce(fn, ms) {
|
|
189
|
+
let timeout;
|
|
190
|
+
return (...args) => {
|
|
191
|
+
clearTimeout(timeout);
|
|
192
|
+
timeout = setTimeout(() => fn(...args), ms);
|
|
193
|
+
};
|
|
194
|
+
}
|
|
177
195
|
function defineModel(def) {
|
|
178
196
|
const target = def.state;
|
|
179
197
|
if (def.actions) {
|
|
@@ -194,7 +212,69 @@ function defineModel(def) {
|
|
|
194
212
|
}
|
|
195
213
|
}
|
|
196
214
|
}
|
|
197
|
-
|
|
215
|
+
const proxy = createState(target);
|
|
216
|
+
if (def.persist) {
|
|
217
|
+
const { key, storage = "local", paths, debug } = def.persist;
|
|
218
|
+
let engine = null;
|
|
219
|
+
if (typeof storage === "string") {
|
|
220
|
+
if (typeof window !== "undefined") {
|
|
221
|
+
engine = storage === "local" ? window.localStorage : window.sessionStorage;
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
engine = storage;
|
|
225
|
+
}
|
|
226
|
+
if (engine) {
|
|
227
|
+
const hydrate = () => {
|
|
228
|
+
const process = (stored) => {
|
|
229
|
+
try {
|
|
230
|
+
if (stored) {
|
|
231
|
+
const parsed = JSON.parse(stored);
|
|
232
|
+
Object.assign(proxy, parsed);
|
|
233
|
+
if (debug) console.log(`[Quantum] Hydrated '${key}'`, parsed);
|
|
234
|
+
}
|
|
235
|
+
} catch (err) {
|
|
236
|
+
if (debug) console.error(`[Quantum] Hydration Failed for '${key}'`, err);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
try {
|
|
240
|
+
const result = engine.getItem(key);
|
|
241
|
+
if (result instanceof Promise) {
|
|
242
|
+
result.then(process);
|
|
243
|
+
} else {
|
|
244
|
+
process(result);
|
|
245
|
+
}
|
|
246
|
+
} catch (err) {
|
|
247
|
+
if (debug) console.error(`[Quantum] Storage Access Failed`, err);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
hydrate();
|
|
251
|
+
const save = debounce(async () => {
|
|
252
|
+
try {
|
|
253
|
+
let stateToSave;
|
|
254
|
+
if (paths) {
|
|
255
|
+
stateToSave = {};
|
|
256
|
+
for (const p of paths) {
|
|
257
|
+
stateToSave[p] = proxy[p];
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
stateToSave = {};
|
|
261
|
+
const keys = Object.keys(def.state);
|
|
262
|
+
for (const k of keys) {
|
|
263
|
+
stateToSave[k] = proxy[k];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const serialized = JSON.stringify(stateToSave);
|
|
267
|
+
await engine.setItem(key, serialized);
|
|
268
|
+
if (debug) console.log(`[Quantum] Saved '${key}'`);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
}
|
|
271
|
+
}, 100);
|
|
272
|
+
subscribe(proxy, () => {
|
|
273
|
+
save();
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return proxy;
|
|
198
278
|
}
|
|
199
279
|
|
|
200
280
|
// src/react/autoHook.ts
|
|
@@ -255,8 +335,7 @@ function computed(fn) {
|
|
|
255
335
|
};
|
|
256
336
|
}
|
|
257
337
|
|
|
258
|
-
// src/addon/
|
|
259
|
-
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
338
|
+
// src/addon/clientTypes.ts
|
|
260
339
|
var HttpError = class extends Error {
|
|
261
340
|
constructor(status, message) {
|
|
262
341
|
super(message);
|
|
@@ -264,156 +343,259 @@ var HttpError = class extends Error {
|
|
|
264
343
|
this.name = "HttpError";
|
|
265
344
|
}
|
|
266
345
|
};
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
346
|
+
|
|
347
|
+
// src/addon/middleware/types.ts
|
|
348
|
+
function compose(middleware) {
|
|
349
|
+
return (ctx, next) => {
|
|
350
|
+
let index = -1;
|
|
351
|
+
async function dispatch(i) {
|
|
352
|
+
index = i;
|
|
353
|
+
let fn = middleware[i];
|
|
354
|
+
if (i === middleware.length) fn = next;
|
|
355
|
+
if (!fn) return Promise.resolve(new Response(null, { status: 404 }));
|
|
356
|
+
try {
|
|
357
|
+
return fn(ctx, dispatch.bind(null, i + 1));
|
|
358
|
+
} catch (err) {
|
|
359
|
+
return Promise.reject(err);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return dispatch(0);
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/addon/middleware/dedupe.ts
|
|
367
|
+
var DedupeMiddleware = async (ctx, next) => {
|
|
368
|
+
if (ctx.req.method !== "GET") {
|
|
369
|
+
return next(ctx);
|
|
370
|
+
}
|
|
371
|
+
const key = `${ctx.req.method}:${ctx.req.url}`;
|
|
372
|
+
if (ctx.inflight.has(key)) {
|
|
373
|
+
const promise = ctx.inflight.get(key);
|
|
374
|
+
const response = await promise;
|
|
375
|
+
return response.clone();
|
|
376
|
+
}
|
|
377
|
+
const sharedPromise = next(ctx).then((res) => {
|
|
378
|
+
return res;
|
|
379
|
+
}).catch((err) => {
|
|
380
|
+
ctx.inflight.delete(key);
|
|
381
|
+
throw err;
|
|
382
|
+
});
|
|
383
|
+
ctx.inflight.set(key, sharedPromise);
|
|
384
|
+
try {
|
|
385
|
+
const response = await sharedPromise;
|
|
386
|
+
return response.clone();
|
|
387
|
+
} finally {
|
|
388
|
+
ctx.inflight.delete(key);
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
// src/addon/middleware/cache.ts
|
|
393
|
+
var CacheMiddleware = async (ctx, next) => {
|
|
394
|
+
const { method, url } = ctx.req;
|
|
395
|
+
const { cache: cacheConfig } = ctx.config;
|
|
396
|
+
if (method !== "GET" || !cacheConfig?.ttl || cacheConfig.force) {
|
|
397
|
+
return next(ctx);
|
|
398
|
+
}
|
|
399
|
+
const key = `${method}:${url}`;
|
|
400
|
+
const cache = ctx.cache;
|
|
401
|
+
if (cache.has(key)) {
|
|
402
|
+
const entry = cache.get(key);
|
|
403
|
+
if (entry.expiresAt > Date.now()) {
|
|
404
|
+
const blob = JSON.stringify(entry.data);
|
|
405
|
+
return new Response(blob, { status: 200, statusText: "OK (Cached)" });
|
|
406
|
+
} else {
|
|
407
|
+
cache.delete(key);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const response = await next(ctx);
|
|
411
|
+
if (response.ok) {
|
|
412
|
+
const clone = response.clone();
|
|
413
|
+
const text = await clone.text();
|
|
414
|
+
try {
|
|
415
|
+
const data = JSON.parse(text);
|
|
416
|
+
cache.set(key, {
|
|
417
|
+
data,
|
|
418
|
+
// Storing raw data object
|
|
419
|
+
timestamp: Date.now(),
|
|
420
|
+
expiresAt: Date.now() + cacheConfig.ttl
|
|
421
|
+
});
|
|
422
|
+
} catch {
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return response;
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
// src/addon/middleware/auth.ts
|
|
429
|
+
var AuthMiddleware = async (ctx, next) => {
|
|
430
|
+
const { auth } = ctx.client.config;
|
|
431
|
+
if (auth && auth.getToken && !ctx.req.headers.get("Authorization")) {
|
|
432
|
+
const token = await auth.getToken();
|
|
433
|
+
if (token) {
|
|
434
|
+
const newHeaders = new Headers(ctx.req.headers);
|
|
435
|
+
newHeaders.set("Authorization", `Bearer ${token}`);
|
|
436
|
+
const newReq = new Request(ctx.req, {
|
|
437
|
+
headers: newHeaders
|
|
438
|
+
});
|
|
439
|
+
ctx.req = newReq;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const response = await next(ctx);
|
|
443
|
+
if (response.status === 401 && auth && auth.onTokenExpired) {
|
|
444
|
+
try {
|
|
445
|
+
const newToken = await auth.onTokenExpired(ctx.client);
|
|
446
|
+
if (newToken) {
|
|
447
|
+
const newHeaders = new Headers(ctx.req.headers);
|
|
448
|
+
newHeaders.set("Authorization", `Bearer ${newToken}`);
|
|
449
|
+
const newReq = new Request(ctx.req.url, {
|
|
450
|
+
method: ctx.req.method,
|
|
451
|
+
headers: newHeaders,
|
|
452
|
+
body: ctx.req.body,
|
|
453
|
+
mode: ctx.req.mode,
|
|
454
|
+
credentials: ctx.req.credentials,
|
|
455
|
+
cache: ctx.req.cache,
|
|
456
|
+
redirect: ctx.req.redirect,
|
|
457
|
+
referrer: ctx.req.referrer,
|
|
458
|
+
integrity: ctx.req.integrity
|
|
459
|
+
});
|
|
460
|
+
ctx.req = newReq;
|
|
461
|
+
return next(ctx);
|
|
462
|
+
} else {
|
|
463
|
+
auth.onAuthFailed?.();
|
|
464
|
+
throw new HttpError(401, "Authentication Failed");
|
|
465
|
+
}
|
|
466
|
+
} catch (err) {
|
|
467
|
+
throw err;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return response;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
// src/addon/middleware/fetch.ts
|
|
474
|
+
var FetchMiddleware = async (ctx) => {
|
|
475
|
+
return fetch(ctx.req);
|
|
476
|
+
};
|
|
477
|
+
var delay = (ms) => new Promise((res) => setTimeout(res, ms));
|
|
478
|
+
var RetryMiddleware = async (ctx, next) => {
|
|
479
|
+
const retryConfig = ctx.config.retry;
|
|
480
|
+
if (!retryConfig) return next(ctx);
|
|
481
|
+
const { retries = 0, baseDelay = 1e3, maxDelay = 3e3 } = typeof retryConfig === "number" ? { retries: retryConfig } : retryConfig;
|
|
482
|
+
const attempt = async (count) => {
|
|
483
|
+
try {
|
|
484
|
+
const response = await next(ctx);
|
|
485
|
+
if (!response.ok && response.status !== 401) {
|
|
486
|
+
if (response.status < 500 && response.status !== 429) {
|
|
487
|
+
return response;
|
|
488
|
+
}
|
|
489
|
+
throw new HttpError(response.status, response.statusText);
|
|
490
|
+
}
|
|
491
|
+
return response;
|
|
492
|
+
} catch (err) {
|
|
493
|
+
if (count < retries) {
|
|
494
|
+
if (err.name === "AbortError") throw err;
|
|
495
|
+
const d = Math.min(baseDelay * 2 ** count, maxDelay);
|
|
496
|
+
await delay(d);
|
|
497
|
+
return attempt(count + 1);
|
|
498
|
+
}
|
|
499
|
+
throw err;
|
|
500
|
+
}
|
|
278
501
|
};
|
|
502
|
+
return attempt(0);
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// src/addon/httpClient.ts
|
|
506
|
+
function createHttpClient(config) {
|
|
507
|
+
const cache = /* @__PURE__ */ new Map();
|
|
508
|
+
const inflight = /* @__PURE__ */ new Map();
|
|
509
|
+
const pipeline = compose([
|
|
510
|
+
DedupeMiddleware,
|
|
511
|
+
CacheMiddleware,
|
|
512
|
+
AuthMiddleware,
|
|
513
|
+
RetryMiddleware,
|
|
514
|
+
FetchMiddleware
|
|
515
|
+
]);
|
|
279
516
|
const client = {
|
|
517
|
+
config,
|
|
518
|
+
// Expose for middleware access
|
|
280
519
|
async request(endpoint, options = {}) {
|
|
281
520
|
let url = config.baseURL ? `${config.baseURL}${endpoint}` : endpoint;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
const retryConfig = getRetryConfig(options);
|
|
521
|
+
let headers = new Headers({
|
|
522
|
+
"Content-Type": "application/json",
|
|
523
|
+
...config.headers,
|
|
524
|
+
...options.headers
|
|
525
|
+
});
|
|
289
526
|
const timeoutMs = options.timeout ?? config.timeout ?? 1e4;
|
|
290
527
|
const controller = new AbortController();
|
|
291
528
|
const id = setTimeout(() => controller.abort(), timeoutMs);
|
|
292
529
|
const userSignal = options.signal;
|
|
293
|
-
let finalSignal = controller.signal;
|
|
294
530
|
if (userSignal) {
|
|
295
531
|
if (userSignal.aborted) {
|
|
296
532
|
clearTimeout(id);
|
|
297
533
|
throw new Error("Aborted");
|
|
298
534
|
}
|
|
535
|
+
userSignal.addEventListener("abort", () => {
|
|
536
|
+
clearTimeout(id);
|
|
537
|
+
controller.abort();
|
|
538
|
+
});
|
|
299
539
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
540
|
+
let req = new Request(url, {
|
|
541
|
+
...options,
|
|
542
|
+
headers,
|
|
543
|
+
signal: controller.signal
|
|
544
|
+
});
|
|
545
|
+
if (config.interceptors?.request) {
|
|
546
|
+
const newConfig = await config.interceptors.request({ ...options, headers: Object.fromEntries(headers) });
|
|
547
|
+
req = new Request(url, {
|
|
548
|
+
...newConfig,
|
|
549
|
+
signal: controller.signal
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
const ctx = {
|
|
553
|
+
req,
|
|
554
|
+
config: {
|
|
315
555
|
...options,
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
556
|
+
retry: options.retry !== void 0 ? options.retry : config.retry
|
|
557
|
+
},
|
|
558
|
+
// Merge retry
|
|
559
|
+
cache,
|
|
560
|
+
inflight,
|
|
561
|
+
client: this
|
|
562
|
+
// Pass client for Auth access hooks
|
|
563
|
+
};
|
|
564
|
+
try {
|
|
565
|
+
let response = await pipeline(ctx, async () => new Response("Internal Error", { status: 500 }));
|
|
566
|
+
clearTimeout(id);
|
|
567
|
+
if (config.interceptors?.response) {
|
|
568
|
+
response = await config.interceptors.response(response);
|
|
321
569
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
let response = await fetch(url, requestConfig);
|
|
325
|
-
if (config.interceptors?.response) {
|
|
326
|
-
response = await config.interceptors.response(response);
|
|
327
|
-
}
|
|
328
|
-
return response;
|
|
329
|
-
} catch (error) {
|
|
330
|
-
throw error;
|
|
570
|
+
if (!response.ok) {
|
|
571
|
+
throw new HttpError(response.status, `HTTP Error ${response.status}`);
|
|
331
572
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
refreshPromise = null;
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
const newToken = await refreshPromise;
|
|
345
|
-
if (newToken) {
|
|
346
|
-
return executeBaseRequest(newToken);
|
|
347
|
-
} else {
|
|
348
|
-
config.auth.onAuthFailed?.();
|
|
349
|
-
throw new HttpError(401, "Authentication Failed");
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
if (!response.ok) {
|
|
353
|
-
throw new HttpError(response.status, `HTTP Error ${response.status}`);
|
|
573
|
+
let data;
|
|
574
|
+
if (response.status === 204) {
|
|
575
|
+
data = {};
|
|
576
|
+
} else {
|
|
577
|
+
const text = await response.text();
|
|
578
|
+
try {
|
|
579
|
+
data = JSON.parse(text);
|
|
580
|
+
} catch {
|
|
581
|
+
data = text;
|
|
354
582
|
}
|
|
355
|
-
return response;
|
|
356
|
-
} catch (error) {
|
|
357
|
-
if (retryConfig && attempt < retryConfig.retries) {
|
|
358
|
-
const isAbort = error.name === "AbortError";
|
|
359
|
-
if (isAbort) throw error;
|
|
360
|
-
if (error instanceof HttpError) {
|
|
361
|
-
if (error.status < 500 && error.status !== 429) {
|
|
362
|
-
throw error;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
const d = Math.min(
|
|
366
|
-
retryConfig.baseDelay * 2 ** attempt,
|
|
367
|
-
retryConfig.maxDelay
|
|
368
|
-
);
|
|
369
|
-
await delay(d);
|
|
370
|
-
return attemptRequest(attempt + 1);
|
|
371
|
-
}
|
|
372
|
-
throw error;
|
|
373
583
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
data = {};
|
|
382
|
-
} else {
|
|
383
|
-
const text = await response.text();
|
|
384
|
-
try {
|
|
385
|
-
data = JSON.parse(text);
|
|
386
|
-
} catch {
|
|
387
|
-
data = text;
|
|
584
|
+
if (options.schema) {
|
|
585
|
+
try {
|
|
586
|
+
if (options.schema.parse) return options.schema.parse(data);
|
|
587
|
+
if (options.schema.validateSync) return options.schema.validateSync(data);
|
|
588
|
+
} catch (error) {
|
|
589
|
+
if (error.errors || error.name === "ZodError" || error.name === "ValidationError") {
|
|
590
|
+
throw new Error(`Validation Error: ${JSON.stringify(error.errors || error.message)}`);
|
|
388
591
|
}
|
|
592
|
+
throw error;
|
|
389
593
|
}
|
|
390
|
-
if (options.schema) {
|
|
391
|
-
try {
|
|
392
|
-
if (options.schema.parse) {
|
|
393
|
-
return options.schema.parse(data);
|
|
394
|
-
} else if (options.schema.validateSync) {
|
|
395
|
-
return options.schema.validateSync(data);
|
|
396
|
-
}
|
|
397
|
-
} catch (error) {
|
|
398
|
-
throw new Error(`Validation Error: ${error}`);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
return data;
|
|
402
|
-
} catch (err) {
|
|
403
|
-
clearTimeout(id);
|
|
404
|
-
throw err;
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
const promise = execute();
|
|
408
|
-
if (dedupeKey) {
|
|
409
|
-
inflightRequests.set(dedupeKey, promise);
|
|
410
|
-
}
|
|
411
|
-
try {
|
|
412
|
-
return await promise;
|
|
413
|
-
} finally {
|
|
414
|
-
if (dedupeKey) {
|
|
415
|
-
inflightRequests.delete(dedupeKey);
|
|
416
594
|
}
|
|
595
|
+
return data;
|
|
596
|
+
} catch (err) {
|
|
597
|
+
clearTimeout(id);
|
|
598
|
+
throw err;
|
|
417
599
|
}
|
|
418
600
|
},
|
|
419
601
|
get(url, config2) {
|
|
@@ -434,9 +616,994 @@ function createHttpClient(config) {
|
|
|
434
616
|
};
|
|
435
617
|
return client;
|
|
436
618
|
}
|
|
619
|
+
|
|
620
|
+
// src/addon/query/utils.ts
|
|
621
|
+
function stableHash(value) {
|
|
622
|
+
if (value === null || typeof value !== "object") {
|
|
623
|
+
return String(value);
|
|
624
|
+
}
|
|
625
|
+
if (Array.isArray(value)) {
|
|
626
|
+
return "[" + value.map(stableHash).join(",") + "]";
|
|
627
|
+
}
|
|
628
|
+
const keys = Object.keys(value).sort();
|
|
629
|
+
return "{" + keys.map((key) => `${key}:${stableHash(value[key])}`).join(",") + "}";
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/addon/signals.ts
|
|
633
|
+
var pendingSignals = /* @__PURE__ */ new Set();
|
|
634
|
+
var isFlushScheduled = false;
|
|
635
|
+
function flushPendingSignals() {
|
|
636
|
+
const toFlush = Array.from(pendingSignals);
|
|
637
|
+
pendingSignals.clear();
|
|
638
|
+
isFlushScheduled = false;
|
|
639
|
+
toFlush.forEach((signal) => signal.flush());
|
|
640
|
+
}
|
|
641
|
+
var SignalImpl = class {
|
|
642
|
+
value;
|
|
643
|
+
subscribers = /* @__PURE__ */ new Set();
|
|
644
|
+
constructor(initialValue) {
|
|
645
|
+
this.value = initialValue;
|
|
646
|
+
}
|
|
647
|
+
get = () => this.value;
|
|
648
|
+
set = (newValue) => {
|
|
649
|
+
if (this.value === newValue) return;
|
|
650
|
+
this.value = newValue;
|
|
651
|
+
pendingSignals.add(this);
|
|
652
|
+
if (!isFlushScheduled) {
|
|
653
|
+
isFlushScheduled = true;
|
|
654
|
+
queueMicrotask(flushPendingSignals);
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
flush() {
|
|
658
|
+
const currentValue = this.value;
|
|
659
|
+
this.subscribers.forEach((fn) => fn(currentValue));
|
|
660
|
+
}
|
|
661
|
+
subscribe = (fn) => {
|
|
662
|
+
this.subscribers.add(fn);
|
|
663
|
+
return () => {
|
|
664
|
+
this.subscribers.delete(fn);
|
|
665
|
+
};
|
|
666
|
+
};
|
|
667
|
+
};
|
|
668
|
+
function createSignal(initialValue) {
|
|
669
|
+
return new SignalImpl(initialValue);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/addon/query/queryCache.ts
|
|
673
|
+
var QueryCache = class {
|
|
674
|
+
// Store signals instead of raw values
|
|
675
|
+
signals = /* @__PURE__ */ new Map();
|
|
676
|
+
gcInterval = null;
|
|
677
|
+
defaultStaleTime = 0;
|
|
678
|
+
// Immediately stale
|
|
679
|
+
defaultCacheTime = 5 * 60 * 1e3;
|
|
680
|
+
// 5 minutes
|
|
681
|
+
constructor(config) {
|
|
682
|
+
if (config?.enableGC !== false) {
|
|
683
|
+
this.startGarbageCollection();
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Generate cache key from query key array
|
|
688
|
+
*/
|
|
689
|
+
generateKey(queryKey) {
|
|
690
|
+
if (Array.isArray(queryKey)) {
|
|
691
|
+
return stableHash(queryKey);
|
|
692
|
+
}
|
|
693
|
+
return stableHash([queryKey.key, queryKey.params]);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Get data (wrapper around signal.get)
|
|
697
|
+
*/
|
|
698
|
+
get(queryKey) {
|
|
699
|
+
const key = this.generateKey(queryKey);
|
|
700
|
+
const signal = this.signals.get(key);
|
|
701
|
+
if (!signal) return void 0;
|
|
702
|
+
const entry = signal.get();
|
|
703
|
+
if (!entry) return void 0;
|
|
704
|
+
const now = Date.now();
|
|
705
|
+
const age = now - entry.timestamp;
|
|
706
|
+
if (age > entry.cacheTime) {
|
|
707
|
+
this.signals.delete(key);
|
|
708
|
+
return void 0;
|
|
709
|
+
}
|
|
710
|
+
return entry.data;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Get Signal for a key (Low level API for hooks)
|
|
714
|
+
* Automatically creates a signal if one doesn't exist
|
|
715
|
+
*/
|
|
716
|
+
getSignal(queryKey) {
|
|
717
|
+
const key = this.generateKey(queryKey);
|
|
718
|
+
let signal = this.signals.get(key);
|
|
719
|
+
if (!signal) {
|
|
720
|
+
signal = createSignal(void 0);
|
|
721
|
+
this.signals.set(key, signal);
|
|
722
|
+
}
|
|
723
|
+
return signal;
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Check if data is stale
|
|
727
|
+
*/
|
|
728
|
+
isStale(queryKey) {
|
|
729
|
+
const key = this.generateKey(queryKey);
|
|
730
|
+
const signal = this.signals.get(key);
|
|
731
|
+
if (!signal) return true;
|
|
732
|
+
const entry = signal.get();
|
|
733
|
+
if (!entry) return true;
|
|
734
|
+
const now = Date.now();
|
|
735
|
+
const age = now - entry.timestamp;
|
|
736
|
+
return age > entry.staleTime;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Set cached data (updates signal)
|
|
740
|
+
*/
|
|
741
|
+
set(queryKey, data, options) {
|
|
742
|
+
const key = this.generateKey(queryKey);
|
|
743
|
+
const entry = {
|
|
744
|
+
data,
|
|
745
|
+
timestamp: Date.now(),
|
|
746
|
+
staleTime: options?.staleTime !== void 0 ? options.staleTime : this.defaultStaleTime,
|
|
747
|
+
cacheTime: options?.cacheTime !== void 0 ? options.cacheTime : this.defaultCacheTime,
|
|
748
|
+
key: Array.isArray(queryKey) ? queryKey : [queryKey]
|
|
749
|
+
};
|
|
750
|
+
const existingSignal = this.signals.get(key);
|
|
751
|
+
if (existingSignal) {
|
|
752
|
+
existingSignal.set(entry);
|
|
753
|
+
} else {
|
|
754
|
+
this.signals.set(key, createSignal(entry));
|
|
755
|
+
}
|
|
756
|
+
const normalizedKey = Array.isArray(queryKey) ? queryKey : [queryKey.key, queryKey.params];
|
|
757
|
+
this.plugins.forEach((p) => p.onQueryUpdated?.(normalizedKey, data));
|
|
758
|
+
}
|
|
759
|
+
// --- DEDUPLICATION ---
|
|
760
|
+
deduplicationCache = /* @__PURE__ */ new Map();
|
|
761
|
+
// --- MIDDLEWARE / PLUGINS ---
|
|
762
|
+
plugins = [];
|
|
763
|
+
/**
|
|
764
|
+
* Register a middleware plugin
|
|
765
|
+
*/
|
|
766
|
+
use(plugin) {
|
|
767
|
+
this.plugins.push(plugin);
|
|
768
|
+
return this;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Fetch data with deduplication.
|
|
772
|
+
* If a request for the same key is already in flight, returns the existing promise.
|
|
773
|
+
*/
|
|
774
|
+
async fetch(queryKey, fn) {
|
|
775
|
+
const key = this.generateKey(queryKey);
|
|
776
|
+
const normalizedKey = Array.isArray(queryKey) ? queryKey : [queryKey.key, queryKey.params];
|
|
777
|
+
if (this.deduplicationCache.has(key)) {
|
|
778
|
+
return this.deduplicationCache.get(key);
|
|
779
|
+
}
|
|
780
|
+
this.plugins.forEach((p) => p.onFetchStart?.(normalizedKey));
|
|
781
|
+
const promise = fn().then(
|
|
782
|
+
(data) => {
|
|
783
|
+
this.deduplicationCache.delete(key);
|
|
784
|
+
this.plugins.forEach((p) => p.onFetchSuccess?.(normalizedKey, data));
|
|
785
|
+
return data;
|
|
786
|
+
},
|
|
787
|
+
(error) => {
|
|
788
|
+
this.deduplicationCache.delete(key);
|
|
789
|
+
this.plugins.forEach((p) => p.onFetchError?.(normalizedKey, error));
|
|
790
|
+
throw error;
|
|
791
|
+
}
|
|
792
|
+
);
|
|
793
|
+
this.deduplicationCache.set(key, promise);
|
|
794
|
+
return promise;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Invalidate queries matching the key prefix
|
|
798
|
+
* Marks them as undefined to trigger refetches without breaking subscriptions
|
|
799
|
+
*/
|
|
800
|
+
invalidate(queryKey) {
|
|
801
|
+
const prefix = this.generateKey(queryKey);
|
|
802
|
+
const normalizedKey = Array.isArray(queryKey) ? queryKey : [queryKey.key, queryKey.params];
|
|
803
|
+
this.plugins.forEach((p) => p.onInvalidate?.(normalizedKey));
|
|
804
|
+
const invalidateKey = (key) => {
|
|
805
|
+
const signal = this.signals.get(key);
|
|
806
|
+
if (signal) {
|
|
807
|
+
signal.set(void 0);
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
invalidateKey(prefix);
|
|
811
|
+
for (const key of this.signals.keys()) {
|
|
812
|
+
if (key.startsWith(prefix.slice(0, -1))) {
|
|
813
|
+
invalidateKey(key);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Remove all cache entries
|
|
819
|
+
*/
|
|
820
|
+
clear() {
|
|
821
|
+
this.signals.clear();
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Prefetch data (same as set but explicit intent)
|
|
825
|
+
*/
|
|
826
|
+
prefetch(queryKey, data, options) {
|
|
827
|
+
this.set(queryKey, data, options);
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Garbage collection - remove expired entries
|
|
831
|
+
*/
|
|
832
|
+
startGarbageCollection() {
|
|
833
|
+
this.gcInterval = setInterval(() => {
|
|
834
|
+
const now = Date.now();
|
|
835
|
+
for (const [key, signal] of this.signals.entries()) {
|
|
836
|
+
const entry = signal.get();
|
|
837
|
+
if (!entry) continue;
|
|
838
|
+
const age = now - entry.timestamp;
|
|
839
|
+
if (age > entry.cacheTime) {
|
|
840
|
+
this.signals.delete(key);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}, 60 * 1e3);
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Stop garbage collection
|
|
847
|
+
*/
|
|
848
|
+
destroy() {
|
|
849
|
+
if (this.gcInterval) {
|
|
850
|
+
clearInterval(this.gcInterval);
|
|
851
|
+
this.gcInterval = null;
|
|
852
|
+
}
|
|
853
|
+
this.clear();
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* Get cache stats (for debugging)
|
|
857
|
+
*/
|
|
858
|
+
getStats() {
|
|
859
|
+
return {
|
|
860
|
+
size: this.signals.size,
|
|
861
|
+
keys: Array.from(this.signals.keys())
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Get all entries (wrapper for DevTools)
|
|
866
|
+
*/
|
|
867
|
+
getAll() {
|
|
868
|
+
const map = /* @__PURE__ */ new Map();
|
|
869
|
+
for (const [key, signal] of this.signals.entries()) {
|
|
870
|
+
const val = signal.get();
|
|
871
|
+
if (val) map.set(key, val);
|
|
872
|
+
}
|
|
873
|
+
return map;
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
var queryCache = new QueryCache();
|
|
877
|
+
|
|
878
|
+
// src/addon/query/pagination.ts
|
|
879
|
+
var import_react2 = require("react");
|
|
880
|
+
function usePaginatedQuery({
|
|
881
|
+
queryKey,
|
|
882
|
+
queryFn,
|
|
883
|
+
pageSize = 20,
|
|
884
|
+
staleTime,
|
|
885
|
+
cacheTime,
|
|
886
|
+
enabled = true
|
|
887
|
+
}) {
|
|
888
|
+
const [page, setPage] = (0, import_react2.useState)(0);
|
|
889
|
+
const [data, setData] = (0, import_react2.useState)();
|
|
890
|
+
const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
|
|
891
|
+
const [isError, setIsError] = (0, import_react2.useState)(false);
|
|
892
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
893
|
+
const [hasNext, setHasNext] = (0, import_react2.useState)(true);
|
|
894
|
+
const queryFnRef = (0, import_react2.useRef)(queryFn);
|
|
895
|
+
(0, import_react2.useEffect)(() => {
|
|
896
|
+
queryFnRef.current = queryFn;
|
|
897
|
+
});
|
|
898
|
+
const queryKeyHash = JSON.stringify(queryKey);
|
|
899
|
+
const fetchPage = (0, import_react2.useCallback)(async (pageNum) => {
|
|
900
|
+
if (!enabled) return;
|
|
901
|
+
const pageQueryKey = [...queryKey, "page", pageNum];
|
|
902
|
+
const cached = queryCache.get(pageQueryKey);
|
|
903
|
+
if (cached && !queryCache.isStale(pageQueryKey)) {
|
|
904
|
+
setData(cached);
|
|
905
|
+
setIsLoading(false);
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
try {
|
|
909
|
+
setIsLoading(true);
|
|
910
|
+
setIsError(false);
|
|
911
|
+
setError(null);
|
|
912
|
+
const result = await queryFnRef.current(pageNum);
|
|
913
|
+
queryCache.set(pageQueryKey, result, { staleTime, cacheTime });
|
|
914
|
+
setData(result);
|
|
915
|
+
if (Array.isArray(result)) {
|
|
916
|
+
setHasNext(result.length === pageSize);
|
|
917
|
+
} else if (result && typeof result === "object" && "hasMore" in result) {
|
|
918
|
+
setHasNext(result.hasMore);
|
|
919
|
+
}
|
|
920
|
+
setIsLoading(false);
|
|
921
|
+
} catch (err) {
|
|
922
|
+
setIsError(true);
|
|
923
|
+
setError(err);
|
|
924
|
+
setIsLoading(false);
|
|
925
|
+
}
|
|
926
|
+
}, [queryKeyHash, enabled, pageSize, staleTime, cacheTime]);
|
|
927
|
+
(0, import_react2.useEffect)(() => {
|
|
928
|
+
fetchPage(page);
|
|
929
|
+
}, [page, fetchPage]);
|
|
930
|
+
const nextPage = (0, import_react2.useCallback)(() => {
|
|
931
|
+
if (hasNext) {
|
|
932
|
+
setPage((p) => p + 1);
|
|
933
|
+
}
|
|
934
|
+
}, [hasNext]);
|
|
935
|
+
const previousPage = (0, import_react2.useCallback)(() => {
|
|
936
|
+
if (page > 0) {
|
|
937
|
+
setPage((p) => p - 1);
|
|
938
|
+
}
|
|
939
|
+
}, [page]);
|
|
940
|
+
const refetch = (0, import_react2.useCallback)(async () => {
|
|
941
|
+
queryCache.invalidate([...queryKey, "page", String(page)]);
|
|
942
|
+
await fetchPage(page);
|
|
943
|
+
}, [queryKeyHash, page, fetchPage]);
|
|
944
|
+
return {
|
|
945
|
+
data,
|
|
946
|
+
isLoading,
|
|
947
|
+
isError,
|
|
948
|
+
error,
|
|
949
|
+
page,
|
|
950
|
+
setPage,
|
|
951
|
+
nextPage,
|
|
952
|
+
previousPage,
|
|
953
|
+
hasNext,
|
|
954
|
+
hasPrevious: page > 0,
|
|
955
|
+
refetch
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// src/addon/query/useQuery.ts
|
|
960
|
+
var import_react4 = require("react");
|
|
961
|
+
|
|
962
|
+
// src/addon/query/context.tsx
|
|
963
|
+
var import_react3 = require("react");
|
|
964
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
965
|
+
var QueryClientContext = (0, import_react3.createContext)(void 0);
|
|
966
|
+
var QueryClientProvider = ({
|
|
967
|
+
client,
|
|
968
|
+
children
|
|
969
|
+
}) => {
|
|
970
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(QueryClientContext.Provider, { value: client, children });
|
|
971
|
+
};
|
|
972
|
+
var useQueryClient = () => {
|
|
973
|
+
const client = (0, import_react3.useContext)(QueryClientContext);
|
|
974
|
+
return client || queryCache;
|
|
975
|
+
};
|
|
976
|
+
|
|
977
|
+
// src/addon/query/useQuery.ts
|
|
978
|
+
function useQuery({
|
|
979
|
+
queryKey,
|
|
980
|
+
queryFn,
|
|
981
|
+
schema,
|
|
982
|
+
staleTime = 0,
|
|
983
|
+
cacheTime = 5 * 60 * 1e3,
|
|
984
|
+
enabled = true,
|
|
985
|
+
refetchOnWindowFocus = false,
|
|
986
|
+
refetchOnReconnect = false,
|
|
987
|
+
refetchInterval
|
|
988
|
+
}) {
|
|
989
|
+
const client = useQueryClient();
|
|
990
|
+
const queryKeyHash = stableHash(queryKey);
|
|
991
|
+
const subscribe2 = (0, import_react4.useCallback)((onStoreChange) => {
|
|
992
|
+
const signal = client.getSignal(queryKey);
|
|
993
|
+
return signal.subscribe(() => {
|
|
994
|
+
onStoreChange();
|
|
995
|
+
});
|
|
996
|
+
}, [client, queryKeyHash]);
|
|
997
|
+
const getSnapshot = (0, import_react4.useCallback)(() => {
|
|
998
|
+
const signal = client.getSignal(queryKey);
|
|
999
|
+
return signal.get();
|
|
1000
|
+
}, [client, queryKeyHash]);
|
|
1001
|
+
const cacheEntry = (0, import_react4.useSyncExternalStore)(subscribe2, getSnapshot);
|
|
1002
|
+
const data = cacheEntry?.data;
|
|
1003
|
+
const dataTimestamp = cacheEntry?.timestamp;
|
|
1004
|
+
const [statusState, dispatch] = (0, import_react4.useReducer)(statusReducer, {
|
|
1005
|
+
isFetching: false,
|
|
1006
|
+
error: null
|
|
1007
|
+
});
|
|
1008
|
+
const abortControllerRef = (0, import_react4.useRef)(null);
|
|
1009
|
+
const intervalRef = (0, import_react4.useRef)(null);
|
|
1010
|
+
const isStale = dataTimestamp ? Date.now() - dataTimestamp > staleTime : true;
|
|
1011
|
+
const isLoading = data === void 0 && statusState.isFetching;
|
|
1012
|
+
const derivedIsLoading = data === void 0;
|
|
1013
|
+
const queryFnRef = (0, import_react4.useRef)(queryFn);
|
|
1014
|
+
const schemaRef = (0, import_react4.useRef)(schema);
|
|
1015
|
+
const queryKeyRef = (0, import_react4.useRef)(queryKey);
|
|
1016
|
+
(0, import_react4.useEffect)(() => {
|
|
1017
|
+
queryFnRef.current = queryFn;
|
|
1018
|
+
schemaRef.current = schema;
|
|
1019
|
+
queryKeyRef.current = queryKey;
|
|
1020
|
+
});
|
|
1021
|
+
const fetchData = (0, import_react4.useCallback)(async (background = false) => {
|
|
1022
|
+
if (!enabled) return;
|
|
1023
|
+
if (abortControllerRef.current) abortControllerRef.current.abort();
|
|
1024
|
+
abortControllerRef.current = new AbortController();
|
|
1025
|
+
if (!background) {
|
|
1026
|
+
const currentEntry = getSnapshot();
|
|
1027
|
+
if (currentEntry && Date.now() - currentEntry.timestamp <= staleTime) {
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
try {
|
|
1032
|
+
dispatch({ type: "FETCH_START", background });
|
|
1033
|
+
const fn = queryFnRef.current;
|
|
1034
|
+
const sc = schemaRef.current;
|
|
1035
|
+
const key = queryKeyRef.current;
|
|
1036
|
+
let result = await client.fetch(key, async () => {
|
|
1037
|
+
let res = await fn();
|
|
1038
|
+
if (sc) {
|
|
1039
|
+
res = sc.parse(res);
|
|
1040
|
+
}
|
|
1041
|
+
return res;
|
|
1042
|
+
});
|
|
1043
|
+
client.set(key, result, { staleTime, cacheTime });
|
|
1044
|
+
dispatch({ type: "FETCH_SUCCESS" });
|
|
1045
|
+
} catch (err) {
|
|
1046
|
+
if (err.name === "AbortError") return;
|
|
1047
|
+
dispatch({ type: "FETCH_ERROR", error: err });
|
|
1048
|
+
}
|
|
1049
|
+
}, [queryKeyHash, enabled, staleTime, cacheTime, client, getSnapshot]);
|
|
1050
|
+
(0, import_react4.useEffect)(() => {
|
|
1051
|
+
if (data === void 0 && !statusState.error) {
|
|
1052
|
+
fetchData();
|
|
1053
|
+
}
|
|
1054
|
+
}, [fetchData, data, statusState.error]);
|
|
1055
|
+
(0, import_react4.useEffect)(() => {
|
|
1056
|
+
if (!enabled || !refetchInterval) return;
|
|
1057
|
+
intervalRef.current = setInterval(() => fetchData(true), refetchInterval);
|
|
1058
|
+
return () => {
|
|
1059
|
+
if (intervalRef.current) clearInterval(intervalRef.current);
|
|
1060
|
+
};
|
|
1061
|
+
}, [enabled, refetchInterval, fetchData]);
|
|
1062
|
+
(0, import_react4.useEffect)(() => {
|
|
1063
|
+
if (!enabled || !refetchOnWindowFocus) return;
|
|
1064
|
+
const handleFocus = () => {
|
|
1065
|
+
const entry = getSnapshot();
|
|
1066
|
+
const isStaleNow = !entry || Date.now() - entry.timestamp > staleTime;
|
|
1067
|
+
if (isStaleNow) fetchData(true);
|
|
1068
|
+
};
|
|
1069
|
+
window.addEventListener("focus", handleFocus);
|
|
1070
|
+
return () => window.removeEventListener("focus", handleFocus);
|
|
1071
|
+
}, [enabled, refetchOnWindowFocus, fetchData, getSnapshot, staleTime]);
|
|
1072
|
+
(0, import_react4.useEffect)(() => {
|
|
1073
|
+
if (!enabled || !refetchOnReconnect) return;
|
|
1074
|
+
const handleOnline = () => {
|
|
1075
|
+
const entry = getSnapshot();
|
|
1076
|
+
const isStaleNow = !entry || Date.now() - entry.timestamp > staleTime;
|
|
1077
|
+
if (isStaleNow) fetchData(true);
|
|
1078
|
+
};
|
|
1079
|
+
window.addEventListener("online", handleOnline);
|
|
1080
|
+
return () => window.removeEventListener("online", handleOnline);
|
|
1081
|
+
}, [enabled, refetchOnReconnect, fetchData, getSnapshot, staleTime]);
|
|
1082
|
+
const refetch = (0, import_react4.useCallback)(async () => {
|
|
1083
|
+
client.invalidate(queryKey);
|
|
1084
|
+
await fetchData();
|
|
1085
|
+
}, [queryKeyHash, fetchData, client]);
|
|
1086
|
+
return {
|
|
1087
|
+
data,
|
|
1088
|
+
isLoading: derivedIsLoading,
|
|
1089
|
+
isError: !!statusState.error,
|
|
1090
|
+
isFetching: statusState.isFetching,
|
|
1091
|
+
isStale,
|
|
1092
|
+
error: statusState.error,
|
|
1093
|
+
refetch
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
function statusReducer(state, action) {
|
|
1097
|
+
switch (action.type) {
|
|
1098
|
+
case "FETCH_START":
|
|
1099
|
+
return {
|
|
1100
|
+
...state,
|
|
1101
|
+
isFetching: true,
|
|
1102
|
+
error: null
|
|
1103
|
+
};
|
|
1104
|
+
case "FETCH_SUCCESS":
|
|
1105
|
+
return {
|
|
1106
|
+
...state,
|
|
1107
|
+
isFetching: false,
|
|
1108
|
+
error: null
|
|
1109
|
+
};
|
|
1110
|
+
case "FETCH_ERROR":
|
|
1111
|
+
return {
|
|
1112
|
+
...state,
|
|
1113
|
+
isFetching: false,
|
|
1114
|
+
error: action.error
|
|
1115
|
+
};
|
|
1116
|
+
default:
|
|
1117
|
+
return state;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// src/addon/query/useMutation.ts
|
|
1122
|
+
var import_react5 = require("react");
|
|
1123
|
+
function useMutation({
|
|
1124
|
+
mutationFn,
|
|
1125
|
+
onMutate,
|
|
1126
|
+
onSuccess,
|
|
1127
|
+
onError,
|
|
1128
|
+
onSettled
|
|
1129
|
+
}) {
|
|
1130
|
+
const [data, setData] = (0, import_react5.useState)();
|
|
1131
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
1132
|
+
const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
|
|
1133
|
+
const [isError, setIsError] = (0, import_react5.useState)(false);
|
|
1134
|
+
const [isSuccess, setIsSuccess] = (0, import_react5.useState)(false);
|
|
1135
|
+
const mutateAsync = (0, import_react5.useCallback)(async (variables) => {
|
|
1136
|
+
let context;
|
|
1137
|
+
try {
|
|
1138
|
+
setIsLoading(true);
|
|
1139
|
+
setIsError(false);
|
|
1140
|
+
setError(null);
|
|
1141
|
+
setIsSuccess(false);
|
|
1142
|
+
if (onMutate) {
|
|
1143
|
+
context = await onMutate(variables);
|
|
1144
|
+
}
|
|
1145
|
+
const result = await mutationFn(variables);
|
|
1146
|
+
setData(result);
|
|
1147
|
+
setIsSuccess(true);
|
|
1148
|
+
setIsLoading(false);
|
|
1149
|
+
if (onSuccess) {
|
|
1150
|
+
onSuccess(result, variables, context);
|
|
1151
|
+
}
|
|
1152
|
+
if (onSettled) {
|
|
1153
|
+
onSettled(result, null, variables, context);
|
|
1154
|
+
}
|
|
1155
|
+
return result;
|
|
1156
|
+
} catch (err) {
|
|
1157
|
+
setIsError(true);
|
|
1158
|
+
setError(err);
|
|
1159
|
+
setIsLoading(false);
|
|
1160
|
+
if (onError) {
|
|
1161
|
+
onError(err, variables, context);
|
|
1162
|
+
}
|
|
1163
|
+
if (onSettled) {
|
|
1164
|
+
onSettled(void 0, err, variables, context);
|
|
1165
|
+
}
|
|
1166
|
+
throw err;
|
|
1167
|
+
}
|
|
1168
|
+
}, [mutationFn, onMutate, onSuccess, onError, onSettled]);
|
|
1169
|
+
const mutate = (0, import_react5.useCallback)(async (variables) => {
|
|
1170
|
+
try {
|
|
1171
|
+
await mutateAsync(variables);
|
|
1172
|
+
} catch {
|
|
1173
|
+
}
|
|
1174
|
+
}, [mutateAsync]);
|
|
1175
|
+
const reset = (0, import_react5.useCallback)(() => {
|
|
1176
|
+
setData(void 0);
|
|
1177
|
+
setError(null);
|
|
1178
|
+
setIsLoading(false);
|
|
1179
|
+
setIsError(false);
|
|
1180
|
+
setIsSuccess(false);
|
|
1181
|
+
}, []);
|
|
1182
|
+
return {
|
|
1183
|
+
mutate,
|
|
1184
|
+
mutateAsync,
|
|
1185
|
+
data,
|
|
1186
|
+
error,
|
|
1187
|
+
isLoading,
|
|
1188
|
+
isError,
|
|
1189
|
+
isSuccess,
|
|
1190
|
+
reset
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
var optimisticHelpers = {
|
|
1194
|
+
/**
|
|
1195
|
+
* Cancel ongoing queries for a key
|
|
1196
|
+
*/
|
|
1197
|
+
async cancelQueries(queryKey) {
|
|
1198
|
+
},
|
|
1199
|
+
/**
|
|
1200
|
+
* Get current query data
|
|
1201
|
+
*/
|
|
1202
|
+
getQueryData(queryKey) {
|
|
1203
|
+
return queryCache.get(queryKey);
|
|
1204
|
+
},
|
|
1205
|
+
/**
|
|
1206
|
+
* Set query data (for optimistic updates)
|
|
1207
|
+
*/
|
|
1208
|
+
setQueryData(queryKey, updater) {
|
|
1209
|
+
const current = queryCache.get(queryKey);
|
|
1210
|
+
const newData = typeof updater === "function" ? updater(current) : updater;
|
|
1211
|
+
queryCache.set(queryKey, newData);
|
|
1212
|
+
return current;
|
|
1213
|
+
},
|
|
1214
|
+
/**
|
|
1215
|
+
* Invalidate queries (trigger refetch)
|
|
1216
|
+
*/
|
|
1217
|
+
invalidateQueries(queryKey) {
|
|
1218
|
+
queryCache.invalidate(queryKey);
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
|
|
1222
|
+
// src/addon/query/infiniteQuery.ts
|
|
1223
|
+
var import_react6 = require("react");
|
|
1224
|
+
function statusReducer2(state, action) {
|
|
1225
|
+
switch (action.type) {
|
|
1226
|
+
case "FETCH_START":
|
|
1227
|
+
return {
|
|
1228
|
+
...state,
|
|
1229
|
+
isFetching: true,
|
|
1230
|
+
isFetchingNextPage: action.direction === "next",
|
|
1231
|
+
isFetchingPreviousPage: action.direction === "previous",
|
|
1232
|
+
error: null
|
|
1233
|
+
};
|
|
1234
|
+
case "FETCH_SUCCESS":
|
|
1235
|
+
return {
|
|
1236
|
+
...state,
|
|
1237
|
+
isFetching: false,
|
|
1238
|
+
isFetchingNextPage: false,
|
|
1239
|
+
isFetchingPreviousPage: false,
|
|
1240
|
+
hasNextPage: action.hasNextPage !== void 0 ? action.hasNextPage : state.hasNextPage,
|
|
1241
|
+
hasPreviousPage: action.hasPreviousPage !== void 0 ? action.hasPreviousPage : state.hasPreviousPage
|
|
1242
|
+
};
|
|
1243
|
+
case "FETCH_ERROR":
|
|
1244
|
+
return {
|
|
1245
|
+
...state,
|
|
1246
|
+
isFetching: false,
|
|
1247
|
+
isFetchingNextPage: false,
|
|
1248
|
+
isFetchingPreviousPage: false,
|
|
1249
|
+
error: action.error
|
|
1250
|
+
};
|
|
1251
|
+
case "SET_PAGINATION":
|
|
1252
|
+
return {
|
|
1253
|
+
...state,
|
|
1254
|
+
hasNextPage: action.hasNextPage !== void 0 ? action.hasNextPage : state.hasNextPage,
|
|
1255
|
+
hasPreviousPage: action.hasPreviousPage !== void 0 ? action.hasPreviousPage : state.hasPreviousPage
|
|
1256
|
+
};
|
|
1257
|
+
default:
|
|
1258
|
+
return state;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
function useInfiniteQuery({
|
|
1262
|
+
queryKey,
|
|
1263
|
+
queryFn,
|
|
1264
|
+
getNextPageParam,
|
|
1265
|
+
getPreviousPageParam,
|
|
1266
|
+
initialPageParam,
|
|
1267
|
+
staleTime = 0,
|
|
1268
|
+
cacheTime = 5 * 60 * 1e3,
|
|
1269
|
+
enabled = true
|
|
1270
|
+
}) {
|
|
1271
|
+
const client = useQueryClient();
|
|
1272
|
+
const queryKeyHash = stableHash(queryKey);
|
|
1273
|
+
const infiniteQueryKey = [...queryKey, "__infinite__"];
|
|
1274
|
+
const subscribe2 = (0, import_react6.useCallback)((onStoreChange) => {
|
|
1275
|
+
const signal = client.getSignal(infiniteQueryKey);
|
|
1276
|
+
return signal.subscribe(() => onStoreChange());
|
|
1277
|
+
}, [client, queryKeyHash]);
|
|
1278
|
+
const getSnapshot = (0, import_react6.useCallback)(() => {
|
|
1279
|
+
const signal = client.getSignal(infiniteQueryKey);
|
|
1280
|
+
return signal.get();
|
|
1281
|
+
}, [client, queryKeyHash]);
|
|
1282
|
+
const cacheEntry = (0, import_react6.useSyncExternalStore)(subscribe2, getSnapshot);
|
|
1283
|
+
const data = cacheEntry?.data;
|
|
1284
|
+
const [statusState, dispatch] = (0, import_react6.useReducer)(statusReducer2, {
|
|
1285
|
+
isFetching: false,
|
|
1286
|
+
isFetchingNextPage: false,
|
|
1287
|
+
isFetchingPreviousPage: false,
|
|
1288
|
+
error: null,
|
|
1289
|
+
hasNextPage: false,
|
|
1290
|
+
// Will be set after first fetch
|
|
1291
|
+
hasPreviousPage: false
|
|
1292
|
+
});
|
|
1293
|
+
const queryFnRef = (0, import_react6.useRef)(queryFn);
|
|
1294
|
+
const getNextPageParamRef = (0, import_react6.useRef)(getNextPageParam);
|
|
1295
|
+
const getPreviousPageParamRef = (0, import_react6.useRef)(getPreviousPageParam);
|
|
1296
|
+
const initialFetchDoneRef = (0, import_react6.useRef)(false);
|
|
1297
|
+
const clientRef = (0, import_react6.useRef)(client);
|
|
1298
|
+
const infiniteQueryKeyRef = (0, import_react6.useRef)(infiniteQueryKey);
|
|
1299
|
+
const initialPageParamRef = (0, import_react6.useRef)(initialPageParam);
|
|
1300
|
+
const staleTimeRef = (0, import_react6.useRef)(staleTime);
|
|
1301
|
+
const cacheTimeRef = (0, import_react6.useRef)(cacheTime);
|
|
1302
|
+
(0, import_react6.useEffect)(() => {
|
|
1303
|
+
queryFnRef.current = queryFn;
|
|
1304
|
+
getNextPageParamRef.current = getNextPageParam;
|
|
1305
|
+
getPreviousPageParamRef.current = getPreviousPageParam;
|
|
1306
|
+
clientRef.current = client;
|
|
1307
|
+
infiniteQueryKeyRef.current = infiniteQueryKey;
|
|
1308
|
+
initialPageParamRef.current = initialPageParam;
|
|
1309
|
+
staleTimeRef.current = staleTime;
|
|
1310
|
+
cacheTimeRef.current = cacheTime;
|
|
1311
|
+
});
|
|
1312
|
+
const prevDataRef = (0, import_react6.useRef)(data);
|
|
1313
|
+
(0, import_react6.useEffect)(() => {
|
|
1314
|
+
if (prevDataRef.current && !data) {
|
|
1315
|
+
initialFetchDoneRef.current = false;
|
|
1316
|
+
}
|
|
1317
|
+
prevDataRef.current = data;
|
|
1318
|
+
}, [data]);
|
|
1319
|
+
(0, import_react6.useEffect)(() => {
|
|
1320
|
+
if (!enabled) return;
|
|
1321
|
+
if (data) return;
|
|
1322
|
+
const doFetch = async () => {
|
|
1323
|
+
const initialParam = initialPageParamRef.current;
|
|
1324
|
+
const firstParam = initialParam !== void 0 ? initialParam : 0;
|
|
1325
|
+
if (!initialFetchDoneRef.current) {
|
|
1326
|
+
initialFetchDoneRef.current = true;
|
|
1327
|
+
}
|
|
1328
|
+
dispatch({ type: "FETCH_START", direction: "initial" });
|
|
1329
|
+
const pageKey = [...infiniteQueryKey, "initial", String(firstParam)];
|
|
1330
|
+
let firstPage;
|
|
1331
|
+
try {
|
|
1332
|
+
firstPage = await clientRef.current.fetch(
|
|
1333
|
+
pageKey,
|
|
1334
|
+
() => queryFnRef.current({ pageParam: firstParam })
|
|
1335
|
+
);
|
|
1336
|
+
} catch (error) {
|
|
1337
|
+
dispatch({ type: "FETCH_ERROR", error });
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1340
|
+
if (firstPage) {
|
|
1341
|
+
const initialData = {
|
|
1342
|
+
pages: [firstPage],
|
|
1343
|
+
pageParams: [firstParam]
|
|
1344
|
+
};
|
|
1345
|
+
let hasNext = false;
|
|
1346
|
+
if (getNextPageParamRef.current) {
|
|
1347
|
+
const nextParam = getNextPageParamRef.current(firstPage, [firstPage]);
|
|
1348
|
+
hasNext = nextParam !== void 0;
|
|
1349
|
+
}
|
|
1350
|
+
clientRef.current.set(infiniteQueryKeyRef.current, initialData, {
|
|
1351
|
+
staleTime: staleTimeRef.current,
|
|
1352
|
+
cacheTime: cacheTimeRef.current
|
|
1353
|
+
});
|
|
1354
|
+
dispatch({ type: "FETCH_SUCCESS", hasNextPage: hasNext });
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
doFetch();
|
|
1358
|
+
}, [enabled, data]);
|
|
1359
|
+
const fetchPageHelper = (0, import_react6.useCallback)(async (pageParam) => {
|
|
1360
|
+
try {
|
|
1361
|
+
const pageKey = [...infiniteQueryKey, String(pageParam)];
|
|
1362
|
+
return await clientRef.current.fetch(
|
|
1363
|
+
pageKey,
|
|
1364
|
+
() => queryFnRef.current({ pageParam })
|
|
1365
|
+
);
|
|
1366
|
+
} catch (error) {
|
|
1367
|
+
dispatch({ type: "FETCH_ERROR", error });
|
|
1368
|
+
return void 0;
|
|
1369
|
+
}
|
|
1370
|
+
}, [client, infiniteQueryKey]);
|
|
1371
|
+
const fetchNextPage = (0, import_react6.useCallback)(async () => {
|
|
1372
|
+
if (!statusState.hasNextPage || statusState.isFetchingNextPage || !data) return;
|
|
1373
|
+
const lastPage = data.pages[data.pages.length - 1];
|
|
1374
|
+
if (!lastPage || !getNextPageParamRef.current) return;
|
|
1375
|
+
const nextPageParam = getNextPageParamRef.current(lastPage, data.pages);
|
|
1376
|
+
if (nextPageParam === void 0) return;
|
|
1377
|
+
dispatch({ type: "FETCH_START", direction: "next" });
|
|
1378
|
+
const newPage = await fetchPageHelper(nextPageParam);
|
|
1379
|
+
if (newPage) {
|
|
1380
|
+
const updatedData = {
|
|
1381
|
+
pages: [...data.pages, newPage],
|
|
1382
|
+
pageParams: [...data.pageParams, nextPageParam]
|
|
1383
|
+
};
|
|
1384
|
+
let hasNext = false;
|
|
1385
|
+
if (getNextPageParamRef.current) {
|
|
1386
|
+
const nextParam = getNextPageParamRef.current(newPage, updatedData.pages);
|
|
1387
|
+
hasNext = nextParam !== void 0;
|
|
1388
|
+
}
|
|
1389
|
+
clientRef.current.set(infiniteQueryKeyRef.current, updatedData, {
|
|
1390
|
+
staleTime: staleTimeRef.current,
|
|
1391
|
+
cacheTime: cacheTimeRef.current
|
|
1392
|
+
});
|
|
1393
|
+
dispatch({ type: "FETCH_SUCCESS", hasNextPage: hasNext });
|
|
1394
|
+
}
|
|
1395
|
+
}, [statusState.hasNextPage, statusState.isFetchingNextPage, data, fetchPageHelper]);
|
|
1396
|
+
const fetchPreviousPage = (0, import_react6.useCallback)(async () => {
|
|
1397
|
+
if (!statusState.hasPreviousPage || statusState.isFetchingPreviousPage || !data) return;
|
|
1398
|
+
const firstPage = data.pages[0];
|
|
1399
|
+
if (!firstPage || !getPreviousPageParamRef.current) return;
|
|
1400
|
+
const previousPageParam = getPreviousPageParamRef.current(firstPage, data.pages);
|
|
1401
|
+
if (previousPageParam === void 0) return;
|
|
1402
|
+
dispatch({ type: "FETCH_START", direction: "previous" });
|
|
1403
|
+
const newPage = await fetchPageHelper(previousPageParam);
|
|
1404
|
+
if (newPage) {
|
|
1405
|
+
const updatedData = {
|
|
1406
|
+
pages: [newPage, ...data.pages],
|
|
1407
|
+
pageParams: [previousPageParam, ...data.pageParams]
|
|
1408
|
+
};
|
|
1409
|
+
let hasPrev = false;
|
|
1410
|
+
if (getPreviousPageParamRef.current) {
|
|
1411
|
+
const prevParam = getPreviousPageParamRef.current(newPage, updatedData.pages);
|
|
1412
|
+
hasPrev = prevParam !== void 0;
|
|
1413
|
+
}
|
|
1414
|
+
clientRef.current.set(infiniteQueryKeyRef.current, updatedData, {
|
|
1415
|
+
staleTime: staleTimeRef.current,
|
|
1416
|
+
cacheTime: cacheTimeRef.current
|
|
1417
|
+
});
|
|
1418
|
+
dispatch({ type: "FETCH_SUCCESS", hasPreviousPage: hasPrev });
|
|
1419
|
+
}
|
|
1420
|
+
}, [statusState.hasPreviousPage, statusState.isFetchingPreviousPage, data, fetchPageHelper]);
|
|
1421
|
+
const refetch = (0, import_react6.useCallback)(async () => {
|
|
1422
|
+
initialFetchDoneRef.current = false;
|
|
1423
|
+
clientRef.current.invalidate(infiniteQueryKeyRef.current);
|
|
1424
|
+
}, []);
|
|
1425
|
+
return {
|
|
1426
|
+
data,
|
|
1427
|
+
fetchNextPage,
|
|
1428
|
+
fetchPreviousPage,
|
|
1429
|
+
hasNextPage: statusState.hasNextPage,
|
|
1430
|
+
hasPreviousPage: statusState.hasPreviousPage,
|
|
1431
|
+
isFetching: statusState.isFetching,
|
|
1432
|
+
isFetchingNextPage: statusState.isFetchingNextPage,
|
|
1433
|
+
isFetchingPreviousPage: statusState.isFetchingPreviousPage,
|
|
1434
|
+
isLoading: data === void 0 && statusState.isFetching,
|
|
1435
|
+
isError: !!statusState.error,
|
|
1436
|
+
error: statusState.error,
|
|
1437
|
+
refetch
|
|
1438
|
+
};
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
// src/addon/query/devtools.tsx
|
|
1442
|
+
var import_react8 = require("react");
|
|
1443
|
+
|
|
1444
|
+
// src/addon/query/useQueryCache.ts
|
|
1445
|
+
var import_react7 = require("react");
|
|
1446
|
+
function useQueryCache() {
|
|
1447
|
+
const client = useQueryClient();
|
|
1448
|
+
const [cache, setCache] = (0, import_react7.useState)(client.getAll());
|
|
1449
|
+
(0, import_react7.useEffect)(() => {
|
|
1450
|
+
const interval = setInterval(() => {
|
|
1451
|
+
setCache({ ...client.getAll() });
|
|
1452
|
+
}, 500);
|
|
1453
|
+
return () => clearInterval(interval);
|
|
1454
|
+
}, [client]);
|
|
1455
|
+
return cache;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
// src/addon/query/devtools.tsx
|
|
1459
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1460
|
+
function QuantumDevTools() {
|
|
1461
|
+
const [isOpen, setIsOpen] = (0, import_react8.useState)(false);
|
|
1462
|
+
const cache = useQueryCache();
|
|
1463
|
+
const client = useQueryClient();
|
|
1464
|
+
if (!isOpen) {
|
|
1465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1466
|
+
"button",
|
|
1467
|
+
{
|
|
1468
|
+
onClick: () => setIsOpen(true),
|
|
1469
|
+
style: {
|
|
1470
|
+
position: "fixed",
|
|
1471
|
+
bottom: "10px",
|
|
1472
|
+
right: "10px",
|
|
1473
|
+
background: "#000",
|
|
1474
|
+
color: "#fff",
|
|
1475
|
+
border: "none",
|
|
1476
|
+
borderRadius: "50%",
|
|
1477
|
+
width: "40px",
|
|
1478
|
+
height: "40px",
|
|
1479
|
+
cursor: "pointer",
|
|
1480
|
+
zIndex: 9999,
|
|
1481
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.1)",
|
|
1482
|
+
fontSize: "20px",
|
|
1483
|
+
display: "flex",
|
|
1484
|
+
alignItems: "center",
|
|
1485
|
+
justifyContent: "center"
|
|
1486
|
+
},
|
|
1487
|
+
children: "\u26A1\uFE0F"
|
|
1488
|
+
}
|
|
1489
|
+
);
|
|
1490
|
+
}
|
|
1491
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: {
|
|
1492
|
+
position: "fixed",
|
|
1493
|
+
bottom: 0,
|
|
1494
|
+
right: 0,
|
|
1495
|
+
width: "100%",
|
|
1496
|
+
maxWidth: "600px",
|
|
1497
|
+
height: "400px",
|
|
1498
|
+
background: "#1a1a1a",
|
|
1499
|
+
color: "#fff",
|
|
1500
|
+
borderTopLeftRadius: "10px",
|
|
1501
|
+
boxShadow: "0 -4px 20px rgba(0,0,0,0.3)",
|
|
1502
|
+
zIndex: 9999,
|
|
1503
|
+
display: "flex",
|
|
1504
|
+
flexDirection: "column",
|
|
1505
|
+
fontFamily: "monospace"
|
|
1506
|
+
}, children: [
|
|
1507
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: {
|
|
1508
|
+
padding: "10px",
|
|
1509
|
+
borderBottom: "1px solid #333",
|
|
1510
|
+
display: "flex",
|
|
1511
|
+
justifyContent: "space-between",
|
|
1512
|
+
alignItems: "center",
|
|
1513
|
+
background: "#222",
|
|
1514
|
+
borderTopLeftRadius: "10px"
|
|
1515
|
+
}, children: [
|
|
1516
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontWeight: "bold" }, children: "\u26A1\uFE0F Quantum DevTools" }),
|
|
1517
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1518
|
+
"button",
|
|
1519
|
+
{
|
|
1520
|
+
onClick: () => setIsOpen(false),
|
|
1521
|
+
style: {
|
|
1522
|
+
background: "transparent",
|
|
1523
|
+
border: "none",
|
|
1524
|
+
color: "#999",
|
|
1525
|
+
cursor: "pointer",
|
|
1526
|
+
fontSize: "16px"
|
|
1527
|
+
},
|
|
1528
|
+
children: "\u2715"
|
|
1529
|
+
}
|
|
1530
|
+
)
|
|
1531
|
+
] }),
|
|
1532
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
|
|
1533
|
+
flex: 1,
|
|
1534
|
+
overflowY: "auto",
|
|
1535
|
+
padding: "10px",
|
|
1536
|
+
display: "flex",
|
|
1537
|
+
flexDirection: "column",
|
|
1538
|
+
gap: "8px"
|
|
1539
|
+
}, children: Array.from(cache.entries()).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: "20px", textAlign: "center", color: "#666" }, children: "No active queries" }) : Array.from(cache.entries()).map(([keyHash, entry]) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: {
|
|
1540
|
+
background: "#2a2a2a",
|
|
1541
|
+
borderRadius: "4px",
|
|
1542
|
+
padding: "8px",
|
|
1543
|
+
border: "1px solid #333"
|
|
1544
|
+
}, children: [
|
|
1545
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: "8px" }, children: [
|
|
1546
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#aaa", fontSize: "12px" }, children: entry.key.map((k) => String(k)).join(" / ") }),
|
|
1547
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: "5px" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: {
|
|
1548
|
+
fontSize: "10px",
|
|
1549
|
+
padding: "2px 4px",
|
|
1550
|
+
borderRadius: "2px",
|
|
1551
|
+
background: client.isStale(entry.key) ? "#dda0dd" : "#90ee90",
|
|
1552
|
+
color: "#000"
|
|
1553
|
+
}, children: client.isStale(entry.key) ? "STALE" : "FRESH" }) })
|
|
1554
|
+
] }),
|
|
1555
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
|
|
1556
|
+
fontSize: "11px",
|
|
1557
|
+
color: "#ddd",
|
|
1558
|
+
whiteSpace: "pre-wrap",
|
|
1559
|
+
maxHeight: "100px",
|
|
1560
|
+
overflow: "hidden",
|
|
1561
|
+
opacity: 0.8
|
|
1562
|
+
}, children: JSON.stringify(entry.data, null, 2) }),
|
|
1563
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginTop: "8px", display: "flex", gap: "8px" }, children: [
|
|
1564
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1565
|
+
"button",
|
|
1566
|
+
{
|
|
1567
|
+
onClick: () => client.invalidate(entry.key),
|
|
1568
|
+
style: {
|
|
1569
|
+
background: "#444",
|
|
1570
|
+
border: "none",
|
|
1571
|
+
color: "#fff",
|
|
1572
|
+
padding: "4px 8px",
|
|
1573
|
+
borderRadius: "3px",
|
|
1574
|
+
cursor: "pointer",
|
|
1575
|
+
fontSize: "10px"
|
|
1576
|
+
},
|
|
1577
|
+
children: "Invalidate"
|
|
1578
|
+
}
|
|
1579
|
+
),
|
|
1580
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1581
|
+
"button",
|
|
1582
|
+
{
|
|
1583
|
+
onClick: () => {
|
|
1584
|
+
client.invalidate(entry.key);
|
|
1585
|
+
},
|
|
1586
|
+
style: {
|
|
1587
|
+
background: "#444",
|
|
1588
|
+
border: "none",
|
|
1589
|
+
color: "#fff",
|
|
1590
|
+
padding: "4px 8px",
|
|
1591
|
+
borderRadius: "3px",
|
|
1592
|
+
cursor: "pointer",
|
|
1593
|
+
fontSize: "10px"
|
|
1594
|
+
},
|
|
1595
|
+
children: "Refetch"
|
|
1596
|
+
}
|
|
1597
|
+
)
|
|
1598
|
+
] })
|
|
1599
|
+
] }, keyHash)) })
|
|
1600
|
+
] });
|
|
1601
|
+
}
|
|
437
1602
|
// Annotate the CommonJS export names for ESM import in node:
|
|
438
1603
|
0 && (module.exports = {
|
|
439
|
-
|
|
1604
|
+
QuantumDevTools,
|
|
1605
|
+
QueryCache,
|
|
1606
|
+
QueryClientProvider,
|
|
440
1607
|
computed,
|
|
441
1608
|
createHttpClient,
|
|
442
1609
|
createState,
|
|
@@ -445,8 +1612,16 @@ function createHttpClient(config) {
|
|
|
445
1612
|
getPromiseState,
|
|
446
1613
|
handlePromise,
|
|
447
1614
|
isPromise,
|
|
1615
|
+
optimisticHelpers,
|
|
1616
|
+
queryCache,
|
|
448
1617
|
scheduleUpdate,
|
|
449
1618
|
subscribe,
|
|
450
1619
|
unwrapPromise,
|
|
1620
|
+
useInfiniteQuery,
|
|
1621
|
+
useMutation,
|
|
1622
|
+
usePaginatedQuery,
|
|
1623
|
+
useQuery,
|
|
1624
|
+
useQueryCache,
|
|
1625
|
+
useQueryClient,
|
|
451
1626
|
useStore
|
|
452
1627
|
});
|