@ztimson/utils 0.27.4 → 0.27.5
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/dist/cache.d.ts +8 -2
- package/dist/index.cjs +93 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +93 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cache.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export type CacheOptions = {
|
|
|
9
9
|
} | string;
|
|
10
10
|
/** Keep or delete cached items once expired, defaults to delete */
|
|
11
11
|
expiryPolicy?: 'delete' | 'keep';
|
|
12
|
+
/** Least Recently Used size limit */
|
|
13
|
+
sizeLimit?: number;
|
|
12
14
|
};
|
|
13
15
|
export type CachedValue<T> = T & {
|
|
14
16
|
_expired?: boolean;
|
|
@@ -19,12 +21,14 @@ export type CachedValue<T> = T & {
|
|
|
19
21
|
export declare class Cache<K extends string | number | symbol, T> {
|
|
20
22
|
readonly key?: keyof T | undefined;
|
|
21
23
|
readonly options: CacheOptions;
|
|
24
|
+
private _loading;
|
|
22
25
|
private store;
|
|
26
|
+
private timers;
|
|
27
|
+
private lruOrder;
|
|
23
28
|
/** Support index lookups */
|
|
24
29
|
[key: string | number | symbol]: CachedValue<T> | any;
|
|
25
30
|
/** Whether cache is complete */
|
|
26
31
|
complete: boolean;
|
|
27
|
-
private _loading;
|
|
28
32
|
/** Await initial loading */
|
|
29
33
|
loading: Promise<void>;
|
|
30
34
|
/**
|
|
@@ -35,6 +39,8 @@ export declare class Cache<K extends string | number | symbol, T> {
|
|
|
35
39
|
constructor(key?: keyof T | undefined, options?: CacheOptions);
|
|
36
40
|
private getKey;
|
|
37
41
|
private save;
|
|
42
|
+
private clearTimer;
|
|
43
|
+
private touchLRU;
|
|
38
44
|
/**
|
|
39
45
|
* Get all cached items
|
|
40
46
|
* @return {T[]} Array of items
|
|
@@ -109,5 +115,5 @@ export declare class Cache<K extends string | number | symbol, T> {
|
|
|
109
115
|
* Get all cached items
|
|
110
116
|
* @return {T[]} Array of items
|
|
111
117
|
*/
|
|
112
|
-
values: CachedValue<T>[];
|
|
118
|
+
values: (expired?: boolean) => CachedValue<T>[];
|
|
113
119
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -456,17 +456,19 @@ ${opts.message || this.desc}`;
|
|
|
456
456
|
* @param options
|
|
457
457
|
*/
|
|
458
458
|
constructor(key, options = {}) {
|
|
459
|
-
__publicField(this, "
|
|
459
|
+
__publicField(this, "_loading");
|
|
460
|
+
__publicField(this, "store", /* @__PURE__ */ new Map());
|
|
461
|
+
__publicField(this, "timers", /* @__PURE__ */ new Map());
|
|
462
|
+
__publicField(this, "lruOrder", []);
|
|
460
463
|
/** Whether cache is complete */
|
|
461
464
|
__publicField(this, "complete", false);
|
|
462
|
-
__publicField(this, "_loading");
|
|
463
465
|
/** Await initial loading */
|
|
464
466
|
__publicField(this, "loading", new Promise((r) => this._loading = r));
|
|
465
467
|
/**
|
|
466
468
|
* Get all cached items
|
|
467
469
|
* @return {T[]} Array of items
|
|
468
470
|
*/
|
|
469
|
-
__publicField(this, "values", this.all
|
|
471
|
+
__publicField(this, "values", this.all);
|
|
470
472
|
var _a, _b, _c, _d;
|
|
471
473
|
this.key = key;
|
|
472
474
|
this.options = options;
|
|
@@ -478,14 +480,18 @@ ${opts.message || this.desc}`;
|
|
|
478
480
|
const persists = this.options.persistentStorage;
|
|
479
481
|
const table = await persists.storage.createTable({ name: persists.key, key: this.key });
|
|
480
482
|
const rows = await table.getAll();
|
|
481
|
-
|
|
483
|
+
for (const row of rows) this.store.set(this.getKey(row), row);
|
|
482
484
|
this._loading();
|
|
483
485
|
})();
|
|
484
486
|
} else if (((_d = (_c = this.options.persistentStorage) == null ? void 0 : _c.storage) == null ? void 0 : _d.getItem) != void 0) {
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
487
|
+
const { storage, key: key2 } = this.options.persistentStorage;
|
|
488
|
+
const stored = storage.getItem(key2);
|
|
489
|
+
if (stored != null) {
|
|
490
|
+
try {
|
|
491
|
+
const obj = JSON.parse(stored);
|
|
492
|
+
for (const k of Object.keys(obj)) this.store.set(k, obj[k]);
|
|
493
|
+
} catch {
|
|
494
|
+
}
|
|
489
495
|
}
|
|
490
496
|
this._loading();
|
|
491
497
|
}
|
|
@@ -515,26 +521,50 @@ ${opts.message || this.desc}`;
|
|
|
515
521
|
if (!!(persists == null ? void 0 : persists.storage)) {
|
|
516
522
|
if (((_a = persists.storage) == null ? void 0 : _a.database) != void 0) {
|
|
517
523
|
persists.storage.createTable({ name: persists.key, key: this.key }).then((table) => {
|
|
518
|
-
if (key) {
|
|
519
|
-
const value = this.get(key);
|
|
524
|
+
if (key !== void 0) {
|
|
525
|
+
const value = this.get(key, true);
|
|
520
526
|
if (value != null) table.set(value, key);
|
|
521
527
|
else table.delete(key);
|
|
522
528
|
} else {
|
|
523
529
|
table.clear();
|
|
524
|
-
this.all().forEach((row) => table.add(row));
|
|
530
|
+
this.all(true).forEach((row) => table.add(row));
|
|
525
531
|
}
|
|
526
532
|
});
|
|
527
533
|
} else if (((_b = persists.storage) == null ? void 0 : _b.setItem) != void 0) {
|
|
528
|
-
|
|
534
|
+
const obj = {};
|
|
535
|
+
for (const [k, v] of this.store.entries()) obj[k] = v;
|
|
536
|
+
persists.storage.setItem(persists.key, JSONSanitize(obj));
|
|
529
537
|
}
|
|
530
538
|
}
|
|
531
539
|
}
|
|
540
|
+
clearTimer(key) {
|
|
541
|
+
const t = this.timers.get(key);
|
|
542
|
+
if (t) {
|
|
543
|
+
clearTimeout(t);
|
|
544
|
+
this.timers.delete(key);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
touchLRU(key) {
|
|
548
|
+
if (!this.options.sizeLimit || this.options.sizeLimit <= 0) return;
|
|
549
|
+
const idx = this.lruOrder.indexOf(key);
|
|
550
|
+
if (idx >= 0) this.lruOrder.splice(idx, 1);
|
|
551
|
+
this.lruOrder.push(key);
|
|
552
|
+
while (this.lruOrder.length > (this.options.sizeLimit || 0)) {
|
|
553
|
+
const lru = this.lruOrder.shift();
|
|
554
|
+
if (lru !== void 0) this.delete(lru);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
532
557
|
/**
|
|
533
558
|
* Get all cached items
|
|
534
559
|
* @return {T[]} Array of items
|
|
535
560
|
*/
|
|
536
561
|
all(expired) {
|
|
537
|
-
|
|
562
|
+
const out = [];
|
|
563
|
+
for (const v of this.store.values()) {
|
|
564
|
+
const val = v;
|
|
565
|
+
if (expired || !(val == null ? void 0 : val._expired)) out.push(deepCopy(val));
|
|
566
|
+
}
|
|
567
|
+
return out;
|
|
538
568
|
}
|
|
539
569
|
/**
|
|
540
570
|
* Add a new item to the cache. Like set, but finds key automatically
|
|
@@ -564,7 +594,10 @@ ${opts.message || this.desc}`;
|
|
|
564
594
|
*/
|
|
565
595
|
clear() {
|
|
566
596
|
this.complete = false;
|
|
567
|
-
this.
|
|
597
|
+
for (const [k, t] of this.timers) clearTimeout(t);
|
|
598
|
+
this.timers.clear();
|
|
599
|
+
this.lruOrder = [];
|
|
600
|
+
this.store.clear();
|
|
568
601
|
this.save();
|
|
569
602
|
return this;
|
|
570
603
|
}
|
|
@@ -573,7 +606,10 @@ ${opts.message || this.desc}`;
|
|
|
573
606
|
* @param {K} key Item's primary key
|
|
574
607
|
*/
|
|
575
608
|
delete(key) {
|
|
576
|
-
|
|
609
|
+
this.clearTimer(key);
|
|
610
|
+
const idx = this.lruOrder.indexOf(key);
|
|
611
|
+
if (idx >= 0) this.lruOrder.splice(idx, 1);
|
|
612
|
+
this.store.delete(key);
|
|
577
613
|
this.save(key);
|
|
578
614
|
return this;
|
|
579
615
|
}
|
|
@@ -582,7 +618,12 @@ ${opts.message || this.desc}`;
|
|
|
582
618
|
* @return {[K, T][]} Key-value pairs array
|
|
583
619
|
*/
|
|
584
620
|
entries(expired) {
|
|
585
|
-
|
|
621
|
+
const out = [];
|
|
622
|
+
for (const [k, v] of this.store.entries()) {
|
|
623
|
+
const val = v;
|
|
624
|
+
if (expired || !(val == null ? void 0 : val._expired)) out.push([k, deepCopy(val)]);
|
|
625
|
+
}
|
|
626
|
+
return out;
|
|
586
627
|
}
|
|
587
628
|
/**
|
|
588
629
|
* Manually expire a cached item
|
|
@@ -591,8 +632,12 @@ ${opts.message || this.desc}`;
|
|
|
591
632
|
expire(key) {
|
|
592
633
|
this.complete = false;
|
|
593
634
|
if (this.options.expiryPolicy == "keep") {
|
|
594
|
-
this.store
|
|
595
|
-
|
|
635
|
+
const v = this.store.get(key);
|
|
636
|
+
if (v) {
|
|
637
|
+
v._expired = true;
|
|
638
|
+
this.store.set(key, v);
|
|
639
|
+
this.save(key);
|
|
640
|
+
}
|
|
596
641
|
} else this.delete(key);
|
|
597
642
|
return this;
|
|
598
643
|
}
|
|
@@ -603,7 +648,11 @@ ${opts.message || this.desc}`;
|
|
|
603
648
|
* @returns {T | undefined} Cached item or undefined if nothing matched
|
|
604
649
|
*/
|
|
605
650
|
find(filter, expired) {
|
|
606
|
-
|
|
651
|
+
for (const v of this.store.values()) {
|
|
652
|
+
const row = v;
|
|
653
|
+
if ((expired || !row._expired) && includes(row, filter)) return deepCopy(row);
|
|
654
|
+
}
|
|
655
|
+
return void 0;
|
|
607
656
|
}
|
|
608
657
|
/**
|
|
609
658
|
* Get item from the cache
|
|
@@ -612,7 +661,10 @@ ${opts.message || this.desc}`;
|
|
|
612
661
|
* @return {T} Cached item
|
|
613
662
|
*/
|
|
614
663
|
get(key, expired) {
|
|
615
|
-
const
|
|
664
|
+
const raw = this.store.get(key);
|
|
665
|
+
if (raw == null) return null;
|
|
666
|
+
const cached = deepCopy(raw);
|
|
667
|
+
this.touchLRU(key);
|
|
616
668
|
if (expired || !(cached == null ? void 0 : cached._expired)) return cached;
|
|
617
669
|
return null;
|
|
618
670
|
}
|
|
@@ -621,17 +673,23 @@ ${opts.message || this.desc}`;
|
|
|
621
673
|
* @return {K[]} Array of keys
|
|
622
674
|
*/
|
|
623
675
|
keys(expired) {
|
|
624
|
-
|
|
676
|
+
const out = [];
|
|
677
|
+
for (const [k, v] of this.store.entries()) {
|
|
678
|
+
const val = v;
|
|
679
|
+
if (expired || !(val == null ? void 0 : val._expired)) out.push(k);
|
|
680
|
+
}
|
|
681
|
+
return out;
|
|
625
682
|
}
|
|
626
683
|
/**
|
|
627
684
|
* Get map of cached items
|
|
628
685
|
* @return {Record<K, T>}
|
|
629
686
|
*/
|
|
630
687
|
map(expired) {
|
|
631
|
-
const copy =
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
688
|
+
const copy = {};
|
|
689
|
+
for (const [k, v] of this.store.entries()) {
|
|
690
|
+
const val = v;
|
|
691
|
+
if (expired || !(val == null ? void 0 : val._expired)) copy[k] = deepCopy(val);
|
|
692
|
+
}
|
|
635
693
|
return copy;
|
|
636
694
|
}
|
|
637
695
|
/**
|
|
@@ -643,12 +701,17 @@ ${opts.message || this.desc}`;
|
|
|
643
701
|
*/
|
|
644
702
|
set(key, value, ttl = this.options.ttl) {
|
|
645
703
|
if (this.options.expiryPolicy == "keep") delete value._expired;
|
|
646
|
-
this.
|
|
704
|
+
this.clearTimer(key);
|
|
705
|
+
this.store.set(key, value);
|
|
706
|
+
this.touchLRU(key);
|
|
647
707
|
this.save(key);
|
|
648
|
-
if (ttl)
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
708
|
+
if (ttl) {
|
|
709
|
+
const t = setTimeout(() => {
|
|
710
|
+
this.expire(key);
|
|
711
|
+
this.save(key);
|
|
712
|
+
}, (ttl || 0) * 1e3);
|
|
713
|
+
this.timers.set(key, t);
|
|
714
|
+
}
|
|
652
715
|
return this;
|
|
653
716
|
}
|
|
654
717
|
}
|