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