@choksheak/react-utils 0.2.2 → 0.2.4
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 +3 -1
- package/package.json +39 -33
- package/sharedQuery.d.mts +68 -8
- package/sharedQuery.d.ts +67 -7
- package/sharedQuery.js +240 -79
- package/sharedQuery.mjs +228 -77
- package/src/sharedQuery.ts +338 -103
- package/src/utils/useDeepMemo.ts +19 -0
- package/utils/useDeepMemo.d.mts +4 -0
- package/utils/useDeepMemo.d.ts +2 -0
- package/utils/useDeepMemo.js +51 -0
- package/utils/useDeepMemo.mjs +16 -0
- package/docs/.nojekyll +0 -1
- package/docs/assets/hierarchy.js +0 -1
- package/docs/assets/highlight.css +0 -22
- package/docs/assets/icons.js +0 -18
- package/docs/assets/icons.svg +0 -1
- package/docs/assets/main.js +0 -60
- package/docs/assets/navigation.js +0 -1
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1633
- package/docs/classes/sharedQuery.SharedQuery.html +0 -17
- package/docs/classes/sharedState.SharedState.html +0 -9
- package/docs/classes/utils_storage.InMemoryStorageAdapter.html +0 -9
- package/docs/classes/utils_storage.IndexedDbAdapter.html +0 -9
- package/docs/classes/utils_storage.LocalStorageAdapter.html +0 -9
- package/docs/functions/sharedQuery.sharedQuery.html +0 -5
- package/docs/functions/sharedQuery.useSharedQuery.html +0 -4
- package/docs/functions/sharedState.sharedState.html +0 -3
- package/docs/functions/sharedState.useSharedState.html +0 -3
- package/docs/functions/sharedState.useSharedStateSetter.html +0 -2
- package/docs/functions/sharedState.useSharedStateValue.html +0 -2
- package/docs/functions/utils_storage.getStorageAdapter.html +0 -1
- package/docs/functions/utils_stringify.stringifyDeterministicForKeys.html +0 -7
- package/docs/hierarchy.html +0 -1
- package/docs/index.html +0 -2
- package/docs/modules/fetcher.html +0 -1
- package/docs/modules/index.html +0 -1
- package/docs/modules/sharedQuery.html +0 -1
- package/docs/modules/sharedState.html +0 -1
- package/docs/modules/utils_storage.html +0 -1
- package/docs/modules/utils_stringify.html +0 -1
- package/docs/modules.html +0 -1
- package/docs/types/sharedQuery.FetchFn.html +0 -1
- package/docs/types/sharedQuery.PersistTo.html +0 -1
- package/docs/types/sharedQuery.QueryStateValue.html +0 -6
- package/docs/types/sharedQuery.SharedQueryOptions.html +0 -1
- package/docs/types/sharedQuery.SharedQueryState.html +0 -3
- package/docs/types/sharedQuery.UseQueryResult.html +0 -1
- package/docs/types/sharedState.SharedStateOptions.html +0 -1
- package/docs/types/utils_storage.StorageAdapter.html +0 -5
- package/docs/types/utils_storage.StorageOptions.html +0 -5
- package/docs/variables/fetcher.fetcher.html +0 -2
- package/docs/variables/fetcher.fetcherWithRetries.html +0 -2
- package/docs/variables/sharedQuery.SharedQueryDefaults.html +0 -2
- package/docs/variables/sharedState.SharedStateDefaults.html +0 -6
- package/src/utils/stringify.test.ts +0 -46
- package/utils/stringify.test.d.mts +0 -2
- package/utils/stringify.test.d.ts +0 -2
- package/utils/stringify.test.js +0 -69
- package/utils/stringify.test.mjs +0 -86
package/sharedQuery.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/sharedQuery.ts
|
|
@@ -27,7 +37,8 @@ __export(sharedQuery_exports, {
|
|
|
27
37
|
});
|
|
28
38
|
module.exports = __toCommonJS(sharedQuery_exports);
|
|
29
39
|
var import_timeConstants2 = require("@choksheak/ts-utils/timeConstants");
|
|
30
|
-
var
|
|
40
|
+
var import_object_sizeof = __toESM(require("object-sizeof"));
|
|
41
|
+
var import_react3 = require("react");
|
|
31
42
|
|
|
32
43
|
// src/sharedState.ts
|
|
33
44
|
var import_timeConstants = require("@choksheak/ts-utils/timeConstants");
|
|
@@ -292,34 +303,68 @@ function stringifyDeterministicForKeys(params) {
|
|
|
292
303
|
});
|
|
293
304
|
}
|
|
294
305
|
|
|
306
|
+
// src/utils/useDeepMemo.ts
|
|
307
|
+
var import_isEqual = __toESM(require("lodash/isEqual"));
|
|
308
|
+
var import_react2 = require("react");
|
|
309
|
+
function useDeepMemo(value) {
|
|
310
|
+
const [state, setState] = (0, import_react2.useState)(value);
|
|
311
|
+
return (0, import_react2.useMemo)(() => {
|
|
312
|
+
if (state === value || (0, import_isEqual.default)(state, value)) {
|
|
313
|
+
return state;
|
|
314
|
+
}
|
|
315
|
+
setState(value);
|
|
316
|
+
return value;
|
|
317
|
+
}, [state, value]);
|
|
318
|
+
}
|
|
319
|
+
|
|
295
320
|
// src/sharedQuery.ts
|
|
296
321
|
var SharedQueryDefaults = {
|
|
322
|
+
// Refetch on every page load.
|
|
297
323
|
staleMs: 0,
|
|
324
|
+
// Keep in cache for a long time.
|
|
298
325
|
expiryMs: 30 * import_timeConstants2.MS_PER_DAY,
|
|
299
|
-
|
|
326
|
+
// Always refetch automatically if the data is stale.
|
|
327
|
+
refetchOnStale: true,
|
|
328
|
+
// No default persistence configured.
|
|
329
|
+
persistTo: void 0,
|
|
330
|
+
// 100 is not too large, but please tweak accordingly.
|
|
331
|
+
maxSize: 100,
|
|
332
|
+
// 100kb limit before discarding old records.
|
|
333
|
+
maxBytes: 1e5,
|
|
334
|
+
// Default to log to console.
|
|
335
|
+
log: (...args) => console.log("[sharedQuery]", ...args)
|
|
300
336
|
};
|
|
301
337
|
var SharedQuery = class {
|
|
302
|
-
|
|
338
|
+
inflightQueries = /* @__PURE__ */ new Map();
|
|
303
339
|
queryState;
|
|
304
340
|
queryName;
|
|
305
341
|
queryFn;
|
|
306
342
|
expiryMs;
|
|
307
343
|
staleMs;
|
|
308
344
|
refetchOnStale;
|
|
345
|
+
maxSize;
|
|
346
|
+
maxBytes;
|
|
347
|
+
log;
|
|
309
348
|
constructor(options) {
|
|
310
349
|
this.queryName = options.queryName;
|
|
311
350
|
this.queryFn = options.queryFn;
|
|
312
|
-
this.
|
|
313
|
-
this.
|
|
314
|
-
this.refetchOnStale =
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
351
|
+
this.staleMs = options?.staleMs ?? SharedQueryDefaults.staleMs;
|
|
352
|
+
this.expiryMs = options?.expiryMs ?? SharedQueryDefaults.expiryMs;
|
|
353
|
+
this.refetchOnStale = options?.refetchOnStale ?? SharedQueryDefaults.refetchOnStale;
|
|
354
|
+
if (!options.localStorageKey && !options.indexedDbKey) {
|
|
355
|
+
const persistTo = options.persistTo ?? SharedQueryDefaults.persistTo;
|
|
356
|
+
if (persistTo === "localStorage") {
|
|
357
|
+
options.localStorageKey = options.queryName;
|
|
358
|
+
} else if (persistTo === "indexedDb") {
|
|
359
|
+
options.indexedDbKey = options.queryName;
|
|
360
|
+
}
|
|
320
361
|
}
|
|
362
|
+
this.maxSize = options?.maxSize ?? SharedQueryDefaults.maxSize;
|
|
363
|
+
this.maxBytes = options?.maxBytes ?? SharedQueryDefaults.maxBytes;
|
|
364
|
+
this.log = options?.log ?? SharedQueryDefaults.log;
|
|
321
365
|
this.queryState = sharedState(
|
|
322
366
|
{},
|
|
367
|
+
// defaultValue
|
|
323
368
|
{
|
|
324
369
|
...options,
|
|
325
370
|
// Fallback to use expiryMs for the storeExpiryMs.
|
|
@@ -327,9 +372,24 @@ var SharedQuery = class {
|
|
|
327
372
|
}
|
|
328
373
|
);
|
|
329
374
|
}
|
|
375
|
+
/** Returns a key to identify requests based on the given args. */
|
|
330
376
|
getQueryKey(args) {
|
|
331
377
|
return this.queryName + ":" + stringifyDeterministicForKeys(args);
|
|
332
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* Get the AbortController to abort the inflight query (if any).
|
|
381
|
+
*
|
|
382
|
+
* Note that once you get the controller, you can also get the signal easily
|
|
383
|
+
* using `controller.signal`. So if you need both the controller and the
|
|
384
|
+
* signal, just use this function.
|
|
385
|
+
*/
|
|
386
|
+
getAbortController(queryKey) {
|
|
387
|
+
return this.inflightQueries.get(queryKey)?.abortController ?? null;
|
|
388
|
+
}
|
|
389
|
+
/** Get the AbortSignal to check for query abortions. */
|
|
390
|
+
getAbortSignal(queryKey) {
|
|
391
|
+
return this.getAbortController(queryKey)?.signal ?? null;
|
|
392
|
+
}
|
|
333
393
|
isStale(dataUpdatedMs) {
|
|
334
394
|
if (this.staleMs === 0) return true;
|
|
335
395
|
const ageMs = Date.now() - dataUpdatedMs;
|
|
@@ -345,52 +405,53 @@ var SharedQuery = class {
|
|
|
345
405
|
const cached = this.queryState.getSnapshot()?.[queryKey];
|
|
346
406
|
if (cached?.data && !this.isExpired(cached.dataUpdatedMs ?? 0)) {
|
|
347
407
|
if (!this.isStale(cached.dataUpdatedMs ?? 0)) {
|
|
348
|
-
|
|
349
|
-
`Return fresh data ${queryKey} from cache without fetching`
|
|
350
|
-
);
|
|
408
|
+
this.log(`Return fresh data ${queryKey} from cache without fetching`);
|
|
351
409
|
return cached.data;
|
|
352
410
|
}
|
|
353
411
|
if (this.refetchOnStale) {
|
|
354
|
-
|
|
412
|
+
this.log(`refetchOnStale for ${queryKey}`);
|
|
355
413
|
void this.dedupedFetch(queryKey, ...args);
|
|
356
414
|
}
|
|
357
|
-
|
|
415
|
+
this.log(`Returning stale data for ${queryKey}`);
|
|
358
416
|
return cached.data;
|
|
359
417
|
}
|
|
360
418
|
return await this.dedupedFetch(queryKey, ...args);
|
|
361
419
|
}
|
|
362
420
|
dedupedFetch(queryKey, ...args) {
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
365
|
-
|
|
366
|
-
return
|
|
421
|
+
const inflightQuery = this.inflightQueries.get(queryKey);
|
|
422
|
+
if (inflightQuery) {
|
|
423
|
+
this.log(`Deduplicating inflight fetch for ${queryKey}`);
|
|
424
|
+
return inflightQuery.promise;
|
|
367
425
|
}
|
|
368
426
|
const promise = this.startFetching(queryKey, args);
|
|
369
|
-
|
|
427
|
+
const abortController = new AbortController();
|
|
428
|
+
this.inflightQueries.set(queryKey, { promise, abortController });
|
|
370
429
|
return promise;
|
|
371
430
|
}
|
|
372
431
|
async startFetching(queryKey, args) {
|
|
373
|
-
|
|
432
|
+
this.log(`Start fetching ${queryKey}`);
|
|
374
433
|
try {
|
|
375
434
|
const data = await this.queryFn(...args);
|
|
376
|
-
|
|
435
|
+
this.log(`Successfully fetched ${queryKey}`);
|
|
377
436
|
this.setData(queryKey, data, Date.now());
|
|
378
437
|
return data;
|
|
379
438
|
} catch (e) {
|
|
380
|
-
|
|
439
|
+
this.log(`Failed to fetch ${queryKey}: ${e}`);
|
|
381
440
|
throw e;
|
|
382
441
|
} finally {
|
|
383
|
-
this.
|
|
442
|
+
this.inflightQueries.delete(queryKey);
|
|
384
443
|
}
|
|
385
444
|
}
|
|
386
445
|
/** Set the data directly if the user obtained it from somewhere else. */
|
|
387
446
|
async setData(queryKey, data, dataUpdatedMs = Date.now()) {
|
|
388
447
|
const entry = {
|
|
448
|
+
lastUpdatedMs: Date.now(),
|
|
389
449
|
loading: false,
|
|
390
450
|
data,
|
|
391
451
|
dataUpdatedMs
|
|
392
452
|
};
|
|
393
453
|
this.queryState.setValue((prev) => ({ ...prev, [queryKey]: entry }));
|
|
454
|
+
this.enforceSizeLimit();
|
|
394
455
|
}
|
|
395
456
|
/** Do a new fetch even when the data is already cached. */
|
|
396
457
|
async updateFromSource(...args) {
|
|
@@ -398,18 +459,98 @@ var SharedQuery = class {
|
|
|
398
459
|
return await this.dedupedFetch(key, ...args);
|
|
399
460
|
}
|
|
400
461
|
/** Delete the cached data for one set of arguments. */
|
|
401
|
-
deleteData(
|
|
402
|
-
const queryKey = this.getQueryKey(args);
|
|
462
|
+
deleteData(queryKey) {
|
|
403
463
|
const record = this.queryState.getSnapshot();
|
|
404
464
|
const clone = { ...record };
|
|
405
465
|
delete clone[queryKey];
|
|
406
466
|
this.queryState.setValue(clone);
|
|
407
|
-
this.
|
|
467
|
+
const inflight = this.inflightQueries.get(queryKey);
|
|
468
|
+
if (inflight) {
|
|
469
|
+
this.inflightQueries.delete(queryKey);
|
|
470
|
+
inflight.abortController.abort("Deleted");
|
|
471
|
+
}
|
|
408
472
|
}
|
|
409
473
|
/** Delete all currently cached data & all inflight promises. */
|
|
410
474
|
clear() {
|
|
411
475
|
this.queryState.delete();
|
|
412
|
-
|
|
476
|
+
for (const { abortController } of Array.from(
|
|
477
|
+
this.inflightQueries.values()
|
|
478
|
+
)) {
|
|
479
|
+
abortController.abort("Cleared");
|
|
480
|
+
}
|
|
481
|
+
this.inflightQueries.clear();
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Discard the oldest entries if the size exceeds the limit. The last
|
|
485
|
+
* remaining record cannot be deleted no matter what the limit is.
|
|
486
|
+
*/
|
|
487
|
+
enforceSizeLimit() {
|
|
488
|
+
if (!this.maxSize && !this.maxBytes) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const oldState = this.queryState.getSnapshot();
|
|
492
|
+
const oldSize = Object.keys(oldState).length;
|
|
493
|
+
if (oldSize <= 1) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const oldByteSize = (0, import_object_sizeof.default)(oldState);
|
|
497
|
+
let newState = oldState;
|
|
498
|
+
let needUpdate = false;
|
|
499
|
+
if (this.maxSize) {
|
|
500
|
+
const numToCut = oldSize - this.maxSize;
|
|
501
|
+
if (numToCut > 0) {
|
|
502
|
+
this.log(
|
|
503
|
+
`enforceSizeLimit for ${this.queryName} needed due to size ${oldSize} > ${this.maxSize}`
|
|
504
|
+
);
|
|
505
|
+
newState = { ...newState };
|
|
506
|
+
needUpdate = true;
|
|
507
|
+
Object.entries(newState).sort(
|
|
508
|
+
(entry1, entry2) => (
|
|
509
|
+
// Sort descending.
|
|
510
|
+
entry2[1].lastUpdatedMs - entry1[1].lastUpdatedMs
|
|
511
|
+
)
|
|
512
|
+
).slice(-numToCut).forEach(([key]) => {
|
|
513
|
+
delete newState[key];
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
if (this.maxBytes && Object.keys(newState).length > 1) {
|
|
518
|
+
const currentByteSize = needUpdate ? (0, import_object_sizeof.default)(newState) : oldByteSize;
|
|
519
|
+
let bytesToCut = currentByteSize - this.maxBytes;
|
|
520
|
+
if (bytesToCut > 0) {
|
|
521
|
+
this.log(
|
|
522
|
+
`enforceSizeLimit for ${this.queryName} needed due to byte size ${currentByteSize.toLocaleString()} > ${this.maxBytes.toLocaleString()}`
|
|
523
|
+
);
|
|
524
|
+
if (!needUpdate) {
|
|
525
|
+
newState = { ...newState };
|
|
526
|
+
needUpdate = true;
|
|
527
|
+
}
|
|
528
|
+
const entriesByTimeAscending = Object.entries(newState).sort(
|
|
529
|
+
(entry1, entry2) => entry1[1].lastUpdatedMs - entry2[1].lastUpdatedMs
|
|
530
|
+
);
|
|
531
|
+
for (
|
|
532
|
+
let i = 0;
|
|
533
|
+
// Leave the last record entriesByTimeAscending[len-1] untouched.
|
|
534
|
+
i < entriesByTimeAscending.length - 1 && bytesToCut > 0;
|
|
535
|
+
i++
|
|
536
|
+
) {
|
|
537
|
+
const key = entriesByTimeAscending[i][0];
|
|
538
|
+
const thisSize = (0, import_object_sizeof.default)(key) + (0, import_object_sizeof.default)(newState[key]);
|
|
539
|
+
delete newState[key];
|
|
540
|
+
bytesToCut -= thisSize;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if (needUpdate) {
|
|
545
|
+
this.queryState.setValue(newState);
|
|
546
|
+
this.log(
|
|
547
|
+
`Trimmed data for ${this.queryName}: size=(${oldSize} -> ${Object.keys(newState).length}) (limit=${this.maxSize}), byteSize=(${oldByteSize.toLocaleString()} -> ${(0, import_object_sizeof.default)(newState).toLocaleString()}) (limit=${this.maxBytes.toLocaleString()})`
|
|
548
|
+
);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
this.log(
|
|
552
|
+
`No need to trim data for ${this.queryName}: size=${oldSize} (limit=${this.maxSize}), byteSize=${oldByteSize.toLocaleString()} (limit=${this.maxBytes.toLocaleString()})`
|
|
553
|
+
);
|
|
413
554
|
}
|
|
414
555
|
};
|
|
415
556
|
var seenQueryNames = /* @__PURE__ */ new Set();
|
|
@@ -420,74 +561,94 @@ function sharedQuery(options) {
|
|
|
420
561
|
seenQueryNames.add(options.queryName);
|
|
421
562
|
return new SharedQuery(options);
|
|
422
563
|
}
|
|
423
|
-
var DEFAULT_QUERY_STATE_ENTRY = {
|
|
564
|
+
var DEFAULT_QUERY_STATE_ENTRY = {
|
|
565
|
+
lastUpdatedMs: 0,
|
|
566
|
+
loading: true
|
|
567
|
+
};
|
|
424
568
|
function useSharedQuery(query, args = []) {
|
|
569
|
+
const stableArgs = useDeepMemo(args);
|
|
425
570
|
const [queryState, setQueryState] = useSharedState(query.queryState);
|
|
426
|
-
const isMounted = (0,
|
|
427
|
-
const queryKey =
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
571
|
+
const isMounted = (0, import_react3.useRef)(true);
|
|
572
|
+
const queryKey = (0, import_react3.useMemo)(
|
|
573
|
+
() => query.getQueryKey(stableArgs),
|
|
574
|
+
[query, stableArgs]
|
|
575
|
+
);
|
|
576
|
+
const queryStateValue = queryState[queryKey];
|
|
577
|
+
const execute = (0, import_react3.useCallback)(
|
|
578
|
+
async (forceRefresh) => {
|
|
579
|
+
query.log(`Begin executing shared query ${queryKey}`);
|
|
580
|
+
setQueryState((prev) => {
|
|
581
|
+
const clone = { ...prev };
|
|
582
|
+
clone[queryKey] = {
|
|
583
|
+
...clone[queryKey] ?? {},
|
|
584
|
+
lastUpdatedMs: Date.now(),
|
|
585
|
+
loading: true
|
|
586
|
+
};
|
|
587
|
+
return clone;
|
|
588
|
+
});
|
|
589
|
+
try {
|
|
590
|
+
const data = await (forceRefresh ? query.updateFromSource(...stableArgs) : query.getCachedOrFetch(...stableArgs));
|
|
591
|
+
if (isMounted.current) {
|
|
592
|
+
setQueryState((prev) => {
|
|
593
|
+
const clone = { ...prev };
|
|
594
|
+
const now = Date.now();
|
|
595
|
+
clone[queryKey] = {
|
|
596
|
+
// Don't keep old error.
|
|
597
|
+
lastUpdatedMs: now,
|
|
598
|
+
loading: false,
|
|
599
|
+
data,
|
|
600
|
+
dataUpdatedMs: now
|
|
601
|
+
};
|
|
602
|
+
return clone;
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
} catch (e) {
|
|
606
|
+
if (isMounted.current) {
|
|
607
|
+
setQueryState((prev) => {
|
|
608
|
+
const clone = { ...prev };
|
|
609
|
+
const now = Date.now();
|
|
610
|
+
clone[queryKey] = {
|
|
611
|
+
// Keep old data.
|
|
612
|
+
...clone[queryKey] ?? {},
|
|
613
|
+
lastUpdatedMs: now,
|
|
614
|
+
loading: false,
|
|
615
|
+
error: e,
|
|
616
|
+
errorUpdatedMs: now
|
|
617
|
+
};
|
|
618
|
+
return clone;
|
|
619
|
+
});
|
|
620
|
+
}
|
|
466
621
|
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
|
|
622
|
+
},
|
|
623
|
+
[query, queryKey, setQueryState, stableArgs]
|
|
624
|
+
);
|
|
625
|
+
(0, import_react3.useEffect)(() => {
|
|
470
626
|
isMounted.current = true;
|
|
471
|
-
void execute();
|
|
627
|
+
void execute(false);
|
|
472
628
|
return () => {
|
|
473
629
|
isMounted.current = false;
|
|
474
630
|
};
|
|
475
631
|
}, [execute]);
|
|
476
|
-
return (0,
|
|
477
|
-
const state =
|
|
632
|
+
return (0, import_react3.useMemo)(() => {
|
|
633
|
+
const state = queryStateValue ?? DEFAULT_QUERY_STATE_ENTRY;
|
|
478
634
|
return {
|
|
479
635
|
...state,
|
|
636
|
+
abortCurrentQuery: (reason) => {
|
|
637
|
+
const controller = query.getAbortController(queryKey);
|
|
638
|
+
controller?.abort(reason);
|
|
639
|
+
return Boolean(controller);
|
|
640
|
+
},
|
|
480
641
|
refetch: () => {
|
|
481
|
-
|
|
642
|
+
void execute(true);
|
|
482
643
|
},
|
|
483
644
|
setData: (data, dataUpdatedMs) => {
|
|
484
645
|
query.setData(queryKey, data, dataUpdatedMs ?? Date.now());
|
|
485
646
|
},
|
|
486
647
|
deleteData: () => {
|
|
487
|
-
query.deleteData(
|
|
648
|
+
query.deleteData(queryKey);
|
|
488
649
|
}
|
|
489
650
|
};
|
|
490
|
-
}, [query, queryKey,
|
|
651
|
+
}, [execute, query, queryKey, queryStateValue]);
|
|
491
652
|
}
|
|
492
653
|
// Annotate the CommonJS export names for ESM import in node:
|
|
493
654
|
0 && (module.exports = {
|