cacheable 1.8.1 → 1.8.2
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 +8 -2
- package/dist/index.cjs +132 -64
- package/dist/index.d.cts +62 -37
- package/dist/index.d.ts +62 -37
- package/dist/index.js +132 -64
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -192,6 +192,7 @@ The following options are available for you to configure `cacheable`:
|
|
|
192
192
|
* `nonBlocking`: If the secondary store is non-blocking. Default is `false`.
|
|
193
193
|
* `stats`: To enable statistics for this instance. Default is `false`.
|
|
194
194
|
* `ttl`: The default time to live for the cache in milliseconds. Default is `undefined` which is disabled.
|
|
195
|
+
* `namespace`: The namespace for the cache. Default is `undefined`.
|
|
195
196
|
|
|
196
197
|
# Cacheable Statistics (Instance Only)
|
|
197
198
|
|
|
@@ -233,6 +234,7 @@ _This does not enable statistics for your layer 2 cache as that is a distributed
|
|
|
233
234
|
* `hash(object: any, algorithm = 'sha256'): string`: Hashes an object with the algorithm. Default is `sha256`.
|
|
234
235
|
* `primary`: The primary store for the cache (layer 1) defaults to in-memory by Keyv.
|
|
235
236
|
* `secondary`: The secondary store for the cache (layer 2) usually a persistent cache by Keyv.
|
|
237
|
+
* `namespace`: The namespace for the cache. Default is `undefined`. This will set the namespace for the primary and secondary stores.
|
|
236
238
|
* `nonBlocking`: If the secondary store is non-blocking. Default is `false`.
|
|
237
239
|
* `stats`: The statistics for this instance which includes `hits`, `misses`, `sets`, `deletes`, `clears`, `errors`, `count`, `vsize`, `ksize`.
|
|
238
240
|
|
|
@@ -296,11 +298,15 @@ By default we use lazy expiration deletion which means on `get` and `getMany` ty
|
|
|
296
298
|
```javascript
|
|
297
299
|
import { Cacheable } from 'cacheable';
|
|
298
300
|
const asyncFunction = async (value: number) => {
|
|
299
|
-
return
|
|
301
|
+
return Math.random() * value;
|
|
300
302
|
};
|
|
301
303
|
|
|
302
304
|
const cache = new Cacheable();
|
|
303
|
-
const
|
|
305
|
+
const options = {
|
|
306
|
+
ttl: '1h', // 1 hour
|
|
307
|
+
keyPrefix: 'p1', // key prefix. This is used if you have multiple functions and need to set a unique prefix.
|
|
308
|
+
}
|
|
309
|
+
const wrappedFunction = cache.wrap(asyncFunction, options);
|
|
304
310
|
console.log(await wrappedFunction(2)); // 4
|
|
305
311
|
console.log(await wrappedFunction(2)); // 4 from cache
|
|
306
312
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -114,11 +114,23 @@ var shorthandToTime = (shorthand, fromDate) => {
|
|
|
114
114
|
return fromDate.getTime() + milliseconds;
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
+
// src/hash.ts
|
|
118
|
+
var crypto = __toESM(require("crypto"), 1);
|
|
119
|
+
function hash(object, algorithm = "sha256") {
|
|
120
|
+
const objectString = JSON.stringify(object);
|
|
121
|
+
if (!crypto.getHashes().includes(algorithm)) {
|
|
122
|
+
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
123
|
+
}
|
|
124
|
+
const hasher = crypto.createHash(algorithm);
|
|
125
|
+
hasher.update(objectString);
|
|
126
|
+
return hasher.digest("hex");
|
|
127
|
+
}
|
|
128
|
+
|
|
117
129
|
// src/wrap.ts
|
|
118
130
|
function wrapSync(function_, options) {
|
|
119
|
-
const { ttl,
|
|
131
|
+
const { ttl, keyPrefix, cache } = options;
|
|
120
132
|
return function(...arguments_) {
|
|
121
|
-
const cacheKey =
|
|
133
|
+
const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
|
|
122
134
|
let value = cache.get(cacheKey);
|
|
123
135
|
if (value === void 0) {
|
|
124
136
|
value = function_(...arguments_);
|
|
@@ -128,9 +140,9 @@ function wrapSync(function_, options) {
|
|
|
128
140
|
};
|
|
129
141
|
}
|
|
130
142
|
function wrap(function_, options) {
|
|
131
|
-
const { ttl,
|
|
143
|
+
const { ttl, keyPrefix, cache } = options;
|
|
132
144
|
return async function(...arguments_) {
|
|
133
|
-
const cacheKey =
|
|
145
|
+
const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
|
|
134
146
|
let value = await cache.get(cacheKey);
|
|
135
147
|
if (value === void 0) {
|
|
136
148
|
value = await function_(...arguments_);
|
|
@@ -139,6 +151,12 @@ function wrap(function_, options) {
|
|
|
139
151
|
return value;
|
|
140
152
|
};
|
|
141
153
|
}
|
|
154
|
+
function createWrapKey(function_, arguments_, keyPrefix) {
|
|
155
|
+
if (!keyPrefix) {
|
|
156
|
+
return `${function_.name}::${hash(arguments_)}`;
|
|
157
|
+
}
|
|
158
|
+
return `${keyPrefix}::${function_.name}::${hash(arguments_)}`;
|
|
159
|
+
}
|
|
142
160
|
|
|
143
161
|
// src/memory-lru.ts
|
|
144
162
|
var ListNode = class {
|
|
@@ -213,20 +231,9 @@ var DoublyLinkedList = class {
|
|
|
213
231
|
}
|
|
214
232
|
};
|
|
215
233
|
|
|
216
|
-
// src/hash.ts
|
|
217
|
-
var crypto = __toESM(require("crypto"), 1);
|
|
218
|
-
function hash(object, algorithm = "sha256") {
|
|
219
|
-
const objectString = JSON.stringify(object);
|
|
220
|
-
if (!crypto.getHashes().includes(algorithm)) {
|
|
221
|
-
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
222
|
-
}
|
|
223
|
-
const hasher = crypto.createHash(algorithm);
|
|
224
|
-
hasher.update(objectString);
|
|
225
|
-
return hasher.digest("hex");
|
|
226
|
-
}
|
|
227
|
-
|
|
228
234
|
// src/memory.ts
|
|
229
235
|
var CacheableMemory = class {
|
|
236
|
+
_lru = new DoublyLinkedList();
|
|
230
237
|
_hashCache = /* @__PURE__ */ new Map();
|
|
231
238
|
_hash0 = /* @__PURE__ */ new Map();
|
|
232
239
|
_hash1 = /* @__PURE__ */ new Map();
|
|
@@ -238,7 +245,6 @@ var CacheableMemory = class {
|
|
|
238
245
|
_hash7 = /* @__PURE__ */ new Map();
|
|
239
246
|
_hash8 = /* @__PURE__ */ new Map();
|
|
240
247
|
_hash9 = /* @__PURE__ */ new Map();
|
|
241
|
-
_lru = new DoublyLinkedList();
|
|
242
248
|
_ttl;
|
|
243
249
|
// Turned off by default
|
|
244
250
|
_useClone = true;
|
|
@@ -440,12 +446,11 @@ var CacheableMemory = class {
|
|
|
440
446
|
}
|
|
441
447
|
}
|
|
442
448
|
}
|
|
443
|
-
|
|
449
|
+
const item = { key, value, expires };
|
|
450
|
+
store.set(
|
|
444
451
|
key,
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
expires
|
|
448
|
-
});
|
|
452
|
+
item
|
|
453
|
+
);
|
|
449
454
|
}
|
|
450
455
|
/**
|
|
451
456
|
* Sets the values of the keys
|
|
@@ -539,34 +544,24 @@ var CacheableMemory = class {
|
|
|
539
544
|
this._hash8.clear();
|
|
540
545
|
this._hash9.clear();
|
|
541
546
|
this._hashCache.clear();
|
|
542
|
-
|
|
543
|
-
/**
|
|
544
|
-
* Hash the key. this is used to determine which store to use (internal use)
|
|
545
|
-
* @param {string} key - The key to hash
|
|
546
|
-
* @returns {number} - The hash number
|
|
547
|
-
*/
|
|
548
|
-
hashKey(key) {
|
|
549
|
-
const cacheHashNumber = this._hashCache.get(key);
|
|
550
|
-
if (cacheHashNumber) {
|
|
551
|
-
return cacheHashNumber;
|
|
552
|
-
}
|
|
553
|
-
let hash2 = 0;
|
|
554
|
-
const primeMultiplier = 31;
|
|
555
|
-
for (let i = 0; i < key.length; i++) {
|
|
556
|
-
hash2 = hash2 * primeMultiplier + key.charCodeAt(i);
|
|
557
|
-
}
|
|
558
|
-
const result = Math.abs(hash2) % 10;
|
|
559
|
-
this._hashCache.set(key, result);
|
|
560
|
-
return result;
|
|
547
|
+
this._lru = new DoublyLinkedList();
|
|
561
548
|
}
|
|
562
549
|
/**
|
|
563
550
|
* Get the store based on the key (internal use)
|
|
564
551
|
* @param {string} key - The key to get the store
|
|
565
|
-
* @returns {
|
|
552
|
+
* @returns {CacheableHashStore} - The store
|
|
566
553
|
*/
|
|
567
554
|
getStore(key) {
|
|
568
|
-
const
|
|
569
|
-
|
|
555
|
+
const hash2 = this.hashKey(key);
|
|
556
|
+
return this.getStoreFromHash(hash2);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Get the store based on the hash (internal use)
|
|
560
|
+
* @param {number} hash
|
|
561
|
+
* @returns {Map<string, CacheableStoreItem>}
|
|
562
|
+
*/
|
|
563
|
+
getStoreFromHash(hash2) {
|
|
564
|
+
switch (hash2) {
|
|
570
565
|
case 1: {
|
|
571
566
|
return this._hash1;
|
|
572
567
|
}
|
|
@@ -599,6 +594,25 @@ var CacheableMemory = class {
|
|
|
599
594
|
}
|
|
600
595
|
}
|
|
601
596
|
}
|
|
597
|
+
/**
|
|
598
|
+
* Hash the key (internal use)
|
|
599
|
+
* @param key
|
|
600
|
+
* @returns {number} from 0 to 9
|
|
601
|
+
*/
|
|
602
|
+
hashKey(key) {
|
|
603
|
+
const cacheHashNumber = this._hashCache.get(key);
|
|
604
|
+
if (cacheHashNumber) {
|
|
605
|
+
return cacheHashNumber;
|
|
606
|
+
}
|
|
607
|
+
let hash2 = 0;
|
|
608
|
+
const primeMultiplier = 31;
|
|
609
|
+
for (let i = 0; i < key.length; i++) {
|
|
610
|
+
hash2 = hash2 * primeMultiplier + key.charCodeAt(i);
|
|
611
|
+
}
|
|
612
|
+
const result = Math.abs(hash2) % 10;
|
|
613
|
+
this._hashCache.set(key, result);
|
|
614
|
+
return result;
|
|
615
|
+
}
|
|
602
616
|
/**
|
|
603
617
|
* Clone the value. This is for internal use
|
|
604
618
|
* @param {any} value - The value to clone
|
|
@@ -697,10 +711,10 @@ var CacheableMemory = class {
|
|
|
697
711
|
* @param {Object} [options] - The options to wrap
|
|
698
712
|
* @returns {Function} - The wrapped function
|
|
699
713
|
*/
|
|
700
|
-
wrap(function_, options
|
|
714
|
+
wrap(function_, options) {
|
|
701
715
|
const wrapOptions = {
|
|
702
716
|
ttl: options.ttl,
|
|
703
|
-
|
|
717
|
+
keyPrefix: options.keyPrefix,
|
|
704
718
|
cache: this
|
|
705
719
|
};
|
|
706
720
|
return wrapSync(function_, wrapOptions);
|
|
@@ -716,8 +730,7 @@ var CacheableMemory = class {
|
|
|
716
730
|
return result;
|
|
717
731
|
}
|
|
718
732
|
concatStores() {
|
|
719
|
-
|
|
720
|
-
return result;
|
|
733
|
+
return new Map([...this._hash0, ...this._hash1, ...this._hash2, ...this._hash3, ...this._hash4, ...this._hash5, ...this._hash6, ...this._hash7, ...this._hash8, ...this._hash9]);
|
|
721
734
|
}
|
|
722
735
|
setTtl(ttl) {
|
|
723
736
|
if (typeof ttl === "string" || ttl === void 0) {
|
|
@@ -738,48 +751,71 @@ var KeyvCacheableMemory = class {
|
|
|
738
751
|
lruSize: 0,
|
|
739
752
|
checkInterval: 0
|
|
740
753
|
};
|
|
741
|
-
|
|
742
|
-
|
|
754
|
+
_defaultCache = new CacheableMemory();
|
|
755
|
+
_nCache = /* @__PURE__ */ new Map();
|
|
756
|
+
_namespace;
|
|
743
757
|
constructor(options) {
|
|
744
758
|
if (options) {
|
|
745
759
|
this.opts = options;
|
|
746
|
-
this.
|
|
760
|
+
this._defaultCache = new CacheableMemory(options);
|
|
761
|
+
if (options.namespace) {
|
|
762
|
+
this._namespace = options.namespace;
|
|
763
|
+
this._nCache.set(this._namespace, new CacheableMemory(options));
|
|
764
|
+
}
|
|
747
765
|
}
|
|
748
766
|
}
|
|
767
|
+
get namespace() {
|
|
768
|
+
return this._namespace;
|
|
769
|
+
}
|
|
770
|
+
set namespace(value) {
|
|
771
|
+
this._namespace = value;
|
|
772
|
+
}
|
|
773
|
+
get store() {
|
|
774
|
+
return this.getStore(this._namespace);
|
|
775
|
+
}
|
|
749
776
|
async get(key) {
|
|
750
|
-
const result = this.
|
|
777
|
+
const result = this.getStore(this._namespace).get(key);
|
|
751
778
|
if (result) {
|
|
752
779
|
return result;
|
|
753
780
|
}
|
|
754
781
|
return void 0;
|
|
755
782
|
}
|
|
756
783
|
async getMany(keys) {
|
|
757
|
-
const result = this.
|
|
784
|
+
const result = this.getStore(this._namespace).getMany(keys);
|
|
758
785
|
return result;
|
|
759
786
|
}
|
|
760
787
|
async set(key, value, ttl) {
|
|
761
|
-
this.
|
|
788
|
+
this.getStore(this._namespace).set(key, value, ttl);
|
|
762
789
|
}
|
|
763
790
|
async setMany(values) {
|
|
764
|
-
this.
|
|
791
|
+
this.getStore(this._namespace).setMany(values);
|
|
765
792
|
}
|
|
766
793
|
async delete(key) {
|
|
767
|
-
this.
|
|
794
|
+
this.getStore(this._namespace).delete(key);
|
|
768
795
|
return true;
|
|
769
796
|
}
|
|
770
797
|
async deleteMany(key) {
|
|
771
|
-
this.
|
|
798
|
+
this.getStore(this._namespace).deleteMany(key);
|
|
772
799
|
return true;
|
|
773
800
|
}
|
|
774
801
|
async clear() {
|
|
775
|
-
this.
|
|
802
|
+
this.getStore(this._namespace).clear();
|
|
776
803
|
}
|
|
777
804
|
async has(key) {
|
|
778
|
-
return this.
|
|
805
|
+
return this.getStore(this._namespace).has(key);
|
|
779
806
|
}
|
|
780
807
|
on(event, listener) {
|
|
781
808
|
return this;
|
|
782
809
|
}
|
|
810
|
+
getStore(namespace) {
|
|
811
|
+
if (!namespace) {
|
|
812
|
+
return this._defaultCache;
|
|
813
|
+
}
|
|
814
|
+
if (!this._nCache.has(namespace)) {
|
|
815
|
+
this._nCache.set(namespace, new CacheableMemory(this.opts));
|
|
816
|
+
}
|
|
817
|
+
return this._nCache.get(namespace);
|
|
818
|
+
}
|
|
783
819
|
};
|
|
784
820
|
|
|
785
821
|
// src/stats.ts
|
|
@@ -1022,6 +1058,7 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
1022
1058
|
_nonBlocking = false;
|
|
1023
1059
|
_ttl;
|
|
1024
1060
|
_stats = new CacheableStats({ enabled: false });
|
|
1061
|
+
_namespace;
|
|
1025
1062
|
/**
|
|
1026
1063
|
* Creates a new cacheable instance
|
|
1027
1064
|
* @param {CacheableOptions} [options] The options for the cacheable instance
|
|
@@ -1043,6 +1080,32 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
1043
1080
|
if (options?.ttl) {
|
|
1044
1081
|
this.setTtl(options.ttl);
|
|
1045
1082
|
}
|
|
1083
|
+
if (options?.namespace) {
|
|
1084
|
+
this._namespace = options.namespace;
|
|
1085
|
+
this._primary.namespace = this.getNameSpace();
|
|
1086
|
+
if (this._secondary) {
|
|
1087
|
+
this._secondary.namespace = this.getNameSpace();
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* The namespace for the cacheable instance
|
|
1093
|
+
* @returns {string | (() => string) | undefined} The namespace for the cacheable instance
|
|
1094
|
+
*/
|
|
1095
|
+
get namespace() {
|
|
1096
|
+
return this._namespace;
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Sets the namespace for the cacheable instance
|
|
1100
|
+
* @param {string | (() => string) | undefined} namespace The namespace for the cacheable instance
|
|
1101
|
+
* @returns {void}
|
|
1102
|
+
*/
|
|
1103
|
+
set namespace(namespace) {
|
|
1104
|
+
this._namespace = namespace;
|
|
1105
|
+
this._primary.namespace = this.getNameSpace();
|
|
1106
|
+
if (this._secondary) {
|
|
1107
|
+
this._secondary.namespace = this.getNameSpace();
|
|
1108
|
+
}
|
|
1046
1109
|
}
|
|
1047
1110
|
/**
|
|
1048
1111
|
* The statistics for the cacheable instance
|
|
@@ -1159,6 +1222,12 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
1159
1222
|
setSecondary(secondary) {
|
|
1160
1223
|
this._secondary = secondary instanceof import_keyv.Keyv ? secondary : new import_keyv.Keyv(secondary);
|
|
1161
1224
|
}
|
|
1225
|
+
getNameSpace() {
|
|
1226
|
+
if (typeof this._namespace === "function") {
|
|
1227
|
+
return this._namespace();
|
|
1228
|
+
}
|
|
1229
|
+
return this._namespace;
|
|
1230
|
+
}
|
|
1162
1231
|
/**
|
|
1163
1232
|
* Gets the value of the key. If the key does not exist in the primary store then it will check the secondary store.
|
|
1164
1233
|
* @param {string} key The key to get the value of
|
|
@@ -1236,9 +1305,8 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
1236
1305
|
* Sets the value of the key. If the secondary store is set then it will also set the value in the secondary store.
|
|
1237
1306
|
* @param {string} key the key to set the value of
|
|
1238
1307
|
* @param {T} value The value to set
|
|
1239
|
-
* @param {number | string} [ttl]
|
|
1240
|
-
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
|
|
1241
|
-
* undefined then it will not have a time-to-live.
|
|
1308
|
+
* @param {number | string} [ttl] set a number it is miliseconds, set a string it is a human-readable
|
|
1309
|
+
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
|
|
1242
1310
|
* @returns {boolean} Whether the value was set
|
|
1243
1311
|
*/
|
|
1244
1312
|
async set(key, value, ttl) {
|
|
@@ -1452,10 +1520,10 @@ var Cacheable = class extends import_hookified.Hookified {
|
|
|
1452
1520
|
* @param {WrapOptions} [options] The options for the wrap function
|
|
1453
1521
|
* @returns {Function} The wrapped function
|
|
1454
1522
|
*/
|
|
1455
|
-
wrap(function_, options
|
|
1523
|
+
wrap(function_, options) {
|
|
1456
1524
|
const wrapOptions = {
|
|
1457
1525
|
ttl: options.ttl,
|
|
1458
|
-
|
|
1526
|
+
keyPrefix: options.keyPrefix,
|
|
1459
1527
|
cache: this
|
|
1460
1528
|
};
|
|
1461
1529
|
return wrap(function_, wrapOptions);
|
package/dist/index.d.cts
CHANGED
|
@@ -109,6 +109,24 @@ type CacheableStoreItem = {
|
|
|
109
109
|
expires?: number;
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
+
type WrapOptions = {
|
|
113
|
+
ttl?: number | string;
|
|
114
|
+
keyPrefix?: string;
|
|
115
|
+
cache: Cacheable;
|
|
116
|
+
};
|
|
117
|
+
type WrapSyncOptions = {
|
|
118
|
+
ttl?: number | string;
|
|
119
|
+
keyPrefix?: string;
|
|
120
|
+
cache: CacheableMemory;
|
|
121
|
+
};
|
|
122
|
+
type WrapFunctionOptions = {
|
|
123
|
+
ttl?: number | string;
|
|
124
|
+
keyPrefix: string;
|
|
125
|
+
};
|
|
126
|
+
type AnyFunction = (...arguments_: any[]) => any;
|
|
127
|
+
declare function wrapSync<T>(function_: AnyFunction, options: WrapSyncOptions): AnyFunction;
|
|
128
|
+
declare function wrap<T>(function_: AnyFunction, options: WrapOptions): AnyFunction;
|
|
129
|
+
|
|
112
130
|
/**
|
|
113
131
|
* @typedef {Object} CacheableMemoryOptions
|
|
114
132
|
* @property {number|string} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable
|
|
@@ -125,6 +143,7 @@ type CacheableMemoryOptions = {
|
|
|
125
143
|
checkInterval?: number;
|
|
126
144
|
};
|
|
127
145
|
declare class CacheableMemory {
|
|
146
|
+
private _lru;
|
|
128
147
|
private readonly _hashCache;
|
|
129
148
|
private readonly _hash0;
|
|
130
149
|
private readonly _hash1;
|
|
@@ -136,7 +155,6 @@ declare class CacheableMemory {
|
|
|
136
155
|
private readonly _hash7;
|
|
137
156
|
private readonly _hash8;
|
|
138
157
|
private readonly _hash9;
|
|
139
|
-
private readonly _lru;
|
|
140
158
|
private _ttl;
|
|
141
159
|
private _useClone;
|
|
142
160
|
private _lruSize;
|
|
@@ -282,18 +300,24 @@ declare class CacheableMemory {
|
|
|
282
300
|
* @returns {void}
|
|
283
301
|
*/
|
|
284
302
|
clear(): void;
|
|
285
|
-
/**
|
|
286
|
-
* Hash the key. this is used to determine which store to use (internal use)
|
|
287
|
-
* @param {string} key - The key to hash
|
|
288
|
-
* @returns {number} - The hash number
|
|
289
|
-
*/
|
|
290
|
-
hashKey(key: string): number;
|
|
291
303
|
/**
|
|
292
304
|
* Get the store based on the key (internal use)
|
|
293
305
|
* @param {string} key - The key to get the store
|
|
294
|
-
* @returns {
|
|
306
|
+
* @returns {CacheableHashStore} - The store
|
|
295
307
|
*/
|
|
296
|
-
getStore(key: string): Map<string,
|
|
308
|
+
getStore(key: string): Map<string, CacheableStoreItem>;
|
|
309
|
+
/**
|
|
310
|
+
* Get the store based on the hash (internal use)
|
|
311
|
+
* @param {number} hash
|
|
312
|
+
* @returns {Map<string, CacheableStoreItem>}
|
|
313
|
+
*/
|
|
314
|
+
getStoreFromHash(hash: number): Map<string, CacheableStoreItem>;
|
|
315
|
+
/**
|
|
316
|
+
* Hash the key (internal use)
|
|
317
|
+
* @param key
|
|
318
|
+
* @returns {number} from 0 to 9
|
|
319
|
+
*/
|
|
320
|
+
hashKey(key: string): number;
|
|
297
321
|
/**
|
|
298
322
|
* Clone the value. This is for internal use
|
|
299
323
|
* @param {any} value - The value to clone
|
|
@@ -345,20 +369,24 @@ declare class CacheableMemory {
|
|
|
345
369
|
* @param {Object} [options] - The options to wrap
|
|
346
370
|
* @returns {Function} - The wrapped function
|
|
347
371
|
*/
|
|
348
|
-
wrap<T>(function_: (...arguments_: any[]) => T, options
|
|
349
|
-
ttl?: number;
|
|
350
|
-
key?: string;
|
|
351
|
-
}): (...arguments_: any[]) => T;
|
|
372
|
+
wrap<T>(function_: (...arguments_: any[]) => T, options: WrapFunctionOptions): (...arguments_: any[]) => T;
|
|
352
373
|
private isPrimitive;
|
|
353
374
|
private concatStores;
|
|
354
375
|
private setTtl;
|
|
355
376
|
}
|
|
356
377
|
|
|
378
|
+
type KeyvCacheableMemoryOptions = CacheableMemoryOptions & {
|
|
379
|
+
namespace?: string;
|
|
380
|
+
};
|
|
357
381
|
declare class KeyvCacheableMemory implements KeyvStoreAdapter {
|
|
358
382
|
opts: CacheableMemoryOptions;
|
|
359
|
-
|
|
360
|
-
private readonly
|
|
361
|
-
|
|
383
|
+
private readonly _defaultCache;
|
|
384
|
+
private readonly _nCache;
|
|
385
|
+
private _namespace?;
|
|
386
|
+
constructor(options?: KeyvCacheableMemoryOptions);
|
|
387
|
+
get namespace(): string | undefined;
|
|
388
|
+
set namespace(value: string | undefined);
|
|
389
|
+
get store(): CacheableMemory;
|
|
362
390
|
get<Value>(key: string): Promise<StoredData<Value> | undefined>;
|
|
363
391
|
getMany<Value>(keys: string[]): Promise<Array<StoredData<Value | undefined>>>;
|
|
364
392
|
set(key: string, value: any, ttl?: number): Promise<void>;
|
|
@@ -372,25 +400,12 @@ declare class KeyvCacheableMemory implements KeyvStoreAdapter {
|
|
|
372
400
|
clear(): Promise<void>;
|
|
373
401
|
has?(key: string): Promise<boolean>;
|
|
374
402
|
on(event: string, listener: (...arguments_: any[]) => void): this;
|
|
403
|
+
getStore(namespace?: string): CacheableMemory;
|
|
375
404
|
}
|
|
376
405
|
|
|
377
406
|
declare const shorthandToMilliseconds: (shorthand?: string | number) => number | undefined;
|
|
378
407
|
declare const shorthandToTime: (shorthand?: string | number, fromDate?: Date) => number;
|
|
379
408
|
|
|
380
|
-
type WrapOptions = {
|
|
381
|
-
ttl?: number | string;
|
|
382
|
-
key?: string;
|
|
383
|
-
cache: Cacheable;
|
|
384
|
-
};
|
|
385
|
-
type WrapSyncOptions = {
|
|
386
|
-
ttl?: number | string;
|
|
387
|
-
key?: string;
|
|
388
|
-
cache: CacheableMemory;
|
|
389
|
-
};
|
|
390
|
-
type AnyFunction = (...arguments_: any[]) => any;
|
|
391
|
-
declare function wrapSync<T>(function_: AnyFunction, options: WrapSyncOptions): AnyFunction;
|
|
392
|
-
declare function wrap<T>(function_: AnyFunction, options: WrapOptions): AnyFunction;
|
|
393
|
-
|
|
394
409
|
declare enum CacheableHooks {
|
|
395
410
|
BEFORE_SET = "BEFORE_SET",
|
|
396
411
|
AFTER_SET = "AFTER_SET",
|
|
@@ -410,6 +425,7 @@ type CacheableOptions = {
|
|
|
410
425
|
stats?: boolean;
|
|
411
426
|
nonBlocking?: boolean;
|
|
412
427
|
ttl?: number | string;
|
|
428
|
+
namespace?: string | (() => string);
|
|
413
429
|
};
|
|
414
430
|
declare class Cacheable extends Hookified {
|
|
415
431
|
private _primary;
|
|
@@ -417,11 +433,23 @@ declare class Cacheable extends Hookified {
|
|
|
417
433
|
private _nonBlocking;
|
|
418
434
|
private _ttl?;
|
|
419
435
|
private readonly _stats;
|
|
436
|
+
private _namespace?;
|
|
420
437
|
/**
|
|
421
438
|
* Creates a new cacheable instance
|
|
422
439
|
* @param {CacheableOptions} [options] The options for the cacheable instance
|
|
423
440
|
*/
|
|
424
441
|
constructor(options?: CacheableOptions);
|
|
442
|
+
/**
|
|
443
|
+
* The namespace for the cacheable instance
|
|
444
|
+
* @returns {string | (() => string) | undefined} The namespace for the cacheable instance
|
|
445
|
+
*/
|
|
446
|
+
get namespace(): string | (() => string) | undefined;
|
|
447
|
+
/**
|
|
448
|
+
* Sets the namespace for the cacheable instance
|
|
449
|
+
* @param {string | (() => string) | undefined} namespace The namespace for the cacheable instance
|
|
450
|
+
* @returns {void}
|
|
451
|
+
*/
|
|
452
|
+
set namespace(namespace: string | (() => string) | undefined);
|
|
425
453
|
/**
|
|
426
454
|
* The statistics for the cacheable instance
|
|
427
455
|
* @returns {CacheableStats} The statistics for the cacheable instance
|
|
@@ -515,6 +543,7 @@ declare class Cacheable extends Hookified {
|
|
|
515
543
|
* @returns {void}
|
|
516
544
|
*/
|
|
517
545
|
setSecondary(secondary: Keyv | KeyvStoreAdapter): void;
|
|
546
|
+
getNameSpace(): string | undefined;
|
|
518
547
|
/**
|
|
519
548
|
* Gets the value of the key. If the key does not exist in the primary store then it will check the secondary store.
|
|
520
549
|
* @param {string} key The key to get the value of
|
|
@@ -531,9 +560,8 @@ declare class Cacheable extends Hookified {
|
|
|
531
560
|
* Sets the value of the key. If the secondary store is set then it will also set the value in the secondary store.
|
|
532
561
|
* @param {string} key the key to set the value of
|
|
533
562
|
* @param {T} value The value to set
|
|
534
|
-
* @param {number | string} [ttl]
|
|
535
|
-
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
|
|
536
|
-
* undefined then it will not have a time-to-live.
|
|
563
|
+
* @param {number | string} [ttl] set a number it is miliseconds, set a string it is a human-readable
|
|
564
|
+
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
|
|
537
565
|
* @returns {boolean} Whether the value was set
|
|
538
566
|
*/
|
|
539
567
|
set<T>(key: string, value: T, ttl?: number | string): Promise<boolean>;
|
|
@@ -597,10 +625,7 @@ declare class Cacheable extends Hookified {
|
|
|
597
625
|
* @param {WrapOptions} [options] The options for the wrap function
|
|
598
626
|
* @returns {Function} The wrapped function
|
|
599
627
|
*/
|
|
600
|
-
wrap<T>(function_: (...arguments_: any[]) => T, options
|
|
601
|
-
ttl?: number;
|
|
602
|
-
key?: string;
|
|
603
|
-
}): (...arguments_: any[]) => T;
|
|
628
|
+
wrap<T>(function_: (...arguments_: any[]) => T, options: WrapFunctionOptions): (...arguments_: any[]) => T;
|
|
604
629
|
/**
|
|
605
630
|
* Will hash an object using the specified algorithm. The default algorithm is 'sha256'.
|
|
606
631
|
* @param {any} object the object to hash
|
package/dist/index.d.ts
CHANGED
|
@@ -109,6 +109,24 @@ type CacheableStoreItem = {
|
|
|
109
109
|
expires?: number;
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
+
type WrapOptions = {
|
|
113
|
+
ttl?: number | string;
|
|
114
|
+
keyPrefix?: string;
|
|
115
|
+
cache: Cacheable;
|
|
116
|
+
};
|
|
117
|
+
type WrapSyncOptions = {
|
|
118
|
+
ttl?: number | string;
|
|
119
|
+
keyPrefix?: string;
|
|
120
|
+
cache: CacheableMemory;
|
|
121
|
+
};
|
|
122
|
+
type WrapFunctionOptions = {
|
|
123
|
+
ttl?: number | string;
|
|
124
|
+
keyPrefix: string;
|
|
125
|
+
};
|
|
126
|
+
type AnyFunction = (...arguments_: any[]) => any;
|
|
127
|
+
declare function wrapSync<T>(function_: AnyFunction, options: WrapSyncOptions): AnyFunction;
|
|
128
|
+
declare function wrap<T>(function_: AnyFunction, options: WrapOptions): AnyFunction;
|
|
129
|
+
|
|
112
130
|
/**
|
|
113
131
|
* @typedef {Object} CacheableMemoryOptions
|
|
114
132
|
* @property {number|string} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable
|
|
@@ -125,6 +143,7 @@ type CacheableMemoryOptions = {
|
|
|
125
143
|
checkInterval?: number;
|
|
126
144
|
};
|
|
127
145
|
declare class CacheableMemory {
|
|
146
|
+
private _lru;
|
|
128
147
|
private readonly _hashCache;
|
|
129
148
|
private readonly _hash0;
|
|
130
149
|
private readonly _hash1;
|
|
@@ -136,7 +155,6 @@ declare class CacheableMemory {
|
|
|
136
155
|
private readonly _hash7;
|
|
137
156
|
private readonly _hash8;
|
|
138
157
|
private readonly _hash9;
|
|
139
|
-
private readonly _lru;
|
|
140
158
|
private _ttl;
|
|
141
159
|
private _useClone;
|
|
142
160
|
private _lruSize;
|
|
@@ -282,18 +300,24 @@ declare class CacheableMemory {
|
|
|
282
300
|
* @returns {void}
|
|
283
301
|
*/
|
|
284
302
|
clear(): void;
|
|
285
|
-
/**
|
|
286
|
-
* Hash the key. this is used to determine which store to use (internal use)
|
|
287
|
-
* @param {string} key - The key to hash
|
|
288
|
-
* @returns {number} - The hash number
|
|
289
|
-
*/
|
|
290
|
-
hashKey(key: string): number;
|
|
291
303
|
/**
|
|
292
304
|
* Get the store based on the key (internal use)
|
|
293
305
|
* @param {string} key - The key to get the store
|
|
294
|
-
* @returns {
|
|
306
|
+
* @returns {CacheableHashStore} - The store
|
|
295
307
|
*/
|
|
296
|
-
getStore(key: string): Map<string,
|
|
308
|
+
getStore(key: string): Map<string, CacheableStoreItem>;
|
|
309
|
+
/**
|
|
310
|
+
* Get the store based on the hash (internal use)
|
|
311
|
+
* @param {number} hash
|
|
312
|
+
* @returns {Map<string, CacheableStoreItem>}
|
|
313
|
+
*/
|
|
314
|
+
getStoreFromHash(hash: number): Map<string, CacheableStoreItem>;
|
|
315
|
+
/**
|
|
316
|
+
* Hash the key (internal use)
|
|
317
|
+
* @param key
|
|
318
|
+
* @returns {number} from 0 to 9
|
|
319
|
+
*/
|
|
320
|
+
hashKey(key: string): number;
|
|
297
321
|
/**
|
|
298
322
|
* Clone the value. This is for internal use
|
|
299
323
|
* @param {any} value - The value to clone
|
|
@@ -345,20 +369,24 @@ declare class CacheableMemory {
|
|
|
345
369
|
* @param {Object} [options] - The options to wrap
|
|
346
370
|
* @returns {Function} - The wrapped function
|
|
347
371
|
*/
|
|
348
|
-
wrap<T>(function_: (...arguments_: any[]) => T, options
|
|
349
|
-
ttl?: number;
|
|
350
|
-
key?: string;
|
|
351
|
-
}): (...arguments_: any[]) => T;
|
|
372
|
+
wrap<T>(function_: (...arguments_: any[]) => T, options: WrapFunctionOptions): (...arguments_: any[]) => T;
|
|
352
373
|
private isPrimitive;
|
|
353
374
|
private concatStores;
|
|
354
375
|
private setTtl;
|
|
355
376
|
}
|
|
356
377
|
|
|
378
|
+
type KeyvCacheableMemoryOptions = CacheableMemoryOptions & {
|
|
379
|
+
namespace?: string;
|
|
380
|
+
};
|
|
357
381
|
declare class KeyvCacheableMemory implements KeyvStoreAdapter {
|
|
358
382
|
opts: CacheableMemoryOptions;
|
|
359
|
-
|
|
360
|
-
private readonly
|
|
361
|
-
|
|
383
|
+
private readonly _defaultCache;
|
|
384
|
+
private readonly _nCache;
|
|
385
|
+
private _namespace?;
|
|
386
|
+
constructor(options?: KeyvCacheableMemoryOptions);
|
|
387
|
+
get namespace(): string | undefined;
|
|
388
|
+
set namespace(value: string | undefined);
|
|
389
|
+
get store(): CacheableMemory;
|
|
362
390
|
get<Value>(key: string): Promise<StoredData<Value> | undefined>;
|
|
363
391
|
getMany<Value>(keys: string[]): Promise<Array<StoredData<Value | undefined>>>;
|
|
364
392
|
set(key: string, value: any, ttl?: number): Promise<void>;
|
|
@@ -372,25 +400,12 @@ declare class KeyvCacheableMemory implements KeyvStoreAdapter {
|
|
|
372
400
|
clear(): Promise<void>;
|
|
373
401
|
has?(key: string): Promise<boolean>;
|
|
374
402
|
on(event: string, listener: (...arguments_: any[]) => void): this;
|
|
403
|
+
getStore(namespace?: string): CacheableMemory;
|
|
375
404
|
}
|
|
376
405
|
|
|
377
406
|
declare const shorthandToMilliseconds: (shorthand?: string | number) => number | undefined;
|
|
378
407
|
declare const shorthandToTime: (shorthand?: string | number, fromDate?: Date) => number;
|
|
379
408
|
|
|
380
|
-
type WrapOptions = {
|
|
381
|
-
ttl?: number | string;
|
|
382
|
-
key?: string;
|
|
383
|
-
cache: Cacheable;
|
|
384
|
-
};
|
|
385
|
-
type WrapSyncOptions = {
|
|
386
|
-
ttl?: number | string;
|
|
387
|
-
key?: string;
|
|
388
|
-
cache: CacheableMemory;
|
|
389
|
-
};
|
|
390
|
-
type AnyFunction = (...arguments_: any[]) => any;
|
|
391
|
-
declare function wrapSync<T>(function_: AnyFunction, options: WrapSyncOptions): AnyFunction;
|
|
392
|
-
declare function wrap<T>(function_: AnyFunction, options: WrapOptions): AnyFunction;
|
|
393
|
-
|
|
394
409
|
declare enum CacheableHooks {
|
|
395
410
|
BEFORE_SET = "BEFORE_SET",
|
|
396
411
|
AFTER_SET = "AFTER_SET",
|
|
@@ -410,6 +425,7 @@ type CacheableOptions = {
|
|
|
410
425
|
stats?: boolean;
|
|
411
426
|
nonBlocking?: boolean;
|
|
412
427
|
ttl?: number | string;
|
|
428
|
+
namespace?: string | (() => string);
|
|
413
429
|
};
|
|
414
430
|
declare class Cacheable extends Hookified {
|
|
415
431
|
private _primary;
|
|
@@ -417,11 +433,23 @@ declare class Cacheable extends Hookified {
|
|
|
417
433
|
private _nonBlocking;
|
|
418
434
|
private _ttl?;
|
|
419
435
|
private readonly _stats;
|
|
436
|
+
private _namespace?;
|
|
420
437
|
/**
|
|
421
438
|
* Creates a new cacheable instance
|
|
422
439
|
* @param {CacheableOptions} [options] The options for the cacheable instance
|
|
423
440
|
*/
|
|
424
441
|
constructor(options?: CacheableOptions);
|
|
442
|
+
/**
|
|
443
|
+
* The namespace for the cacheable instance
|
|
444
|
+
* @returns {string | (() => string) | undefined} The namespace for the cacheable instance
|
|
445
|
+
*/
|
|
446
|
+
get namespace(): string | (() => string) | undefined;
|
|
447
|
+
/**
|
|
448
|
+
* Sets the namespace for the cacheable instance
|
|
449
|
+
* @param {string | (() => string) | undefined} namespace The namespace for the cacheable instance
|
|
450
|
+
* @returns {void}
|
|
451
|
+
*/
|
|
452
|
+
set namespace(namespace: string | (() => string) | undefined);
|
|
425
453
|
/**
|
|
426
454
|
* The statistics for the cacheable instance
|
|
427
455
|
* @returns {CacheableStats} The statistics for the cacheable instance
|
|
@@ -515,6 +543,7 @@ declare class Cacheable extends Hookified {
|
|
|
515
543
|
* @returns {void}
|
|
516
544
|
*/
|
|
517
545
|
setSecondary(secondary: Keyv | KeyvStoreAdapter): void;
|
|
546
|
+
getNameSpace(): string | undefined;
|
|
518
547
|
/**
|
|
519
548
|
* Gets the value of the key. If the key does not exist in the primary store then it will check the secondary store.
|
|
520
549
|
* @param {string} key The key to get the value of
|
|
@@ -531,9 +560,8 @@ declare class Cacheable extends Hookified {
|
|
|
531
560
|
* Sets the value of the key. If the secondary store is set then it will also set the value in the secondary store.
|
|
532
561
|
* @param {string} key the key to set the value of
|
|
533
562
|
* @param {T} value The value to set
|
|
534
|
-
* @param {number | string} [ttl]
|
|
535
|
-
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
|
|
536
|
-
* undefined then it will not have a time-to-live.
|
|
563
|
+
* @param {number | string} [ttl] set a number it is miliseconds, set a string it is a human-readable
|
|
564
|
+
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
|
|
537
565
|
* @returns {boolean} Whether the value was set
|
|
538
566
|
*/
|
|
539
567
|
set<T>(key: string, value: T, ttl?: number | string): Promise<boolean>;
|
|
@@ -597,10 +625,7 @@ declare class Cacheable extends Hookified {
|
|
|
597
625
|
* @param {WrapOptions} [options] The options for the wrap function
|
|
598
626
|
* @returns {Function} The wrapped function
|
|
599
627
|
*/
|
|
600
|
-
wrap<T>(function_: (...arguments_: any[]) => T, options
|
|
601
|
-
ttl?: number;
|
|
602
|
-
key?: string;
|
|
603
|
-
}): (...arguments_: any[]) => T;
|
|
628
|
+
wrap<T>(function_: (...arguments_: any[]) => T, options: WrapFunctionOptions): (...arguments_: any[]) => T;
|
|
604
629
|
/**
|
|
605
630
|
* Will hash an object using the specified algorithm. The default algorithm is 'sha256'.
|
|
606
631
|
* @param {any} object the object to hash
|
package/dist/index.js
CHANGED
|
@@ -69,11 +69,23 @@ var shorthandToTime = (shorthand, fromDate) => {
|
|
|
69
69
|
return fromDate.getTime() + milliseconds;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
+
// src/hash.ts
|
|
73
|
+
import * as crypto from "node:crypto";
|
|
74
|
+
function hash(object, algorithm = "sha256") {
|
|
75
|
+
const objectString = JSON.stringify(object);
|
|
76
|
+
if (!crypto.getHashes().includes(algorithm)) {
|
|
77
|
+
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
78
|
+
}
|
|
79
|
+
const hasher = crypto.createHash(algorithm);
|
|
80
|
+
hasher.update(objectString);
|
|
81
|
+
return hasher.digest("hex");
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
// src/wrap.ts
|
|
73
85
|
function wrapSync(function_, options) {
|
|
74
|
-
const { ttl,
|
|
86
|
+
const { ttl, keyPrefix, cache } = options;
|
|
75
87
|
return function(...arguments_) {
|
|
76
|
-
const cacheKey =
|
|
88
|
+
const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
|
|
77
89
|
let value = cache.get(cacheKey);
|
|
78
90
|
if (value === void 0) {
|
|
79
91
|
value = function_(...arguments_);
|
|
@@ -83,9 +95,9 @@ function wrapSync(function_, options) {
|
|
|
83
95
|
};
|
|
84
96
|
}
|
|
85
97
|
function wrap(function_, options) {
|
|
86
|
-
const { ttl,
|
|
98
|
+
const { ttl, keyPrefix, cache } = options;
|
|
87
99
|
return async function(...arguments_) {
|
|
88
|
-
const cacheKey =
|
|
100
|
+
const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
|
|
89
101
|
let value = await cache.get(cacheKey);
|
|
90
102
|
if (value === void 0) {
|
|
91
103
|
value = await function_(...arguments_);
|
|
@@ -94,6 +106,12 @@ function wrap(function_, options) {
|
|
|
94
106
|
return value;
|
|
95
107
|
};
|
|
96
108
|
}
|
|
109
|
+
function createWrapKey(function_, arguments_, keyPrefix) {
|
|
110
|
+
if (!keyPrefix) {
|
|
111
|
+
return `${function_.name}::${hash(arguments_)}`;
|
|
112
|
+
}
|
|
113
|
+
return `${keyPrefix}::${function_.name}::${hash(arguments_)}`;
|
|
114
|
+
}
|
|
97
115
|
|
|
98
116
|
// src/memory-lru.ts
|
|
99
117
|
var ListNode = class {
|
|
@@ -168,20 +186,9 @@ var DoublyLinkedList = class {
|
|
|
168
186
|
}
|
|
169
187
|
};
|
|
170
188
|
|
|
171
|
-
// src/hash.ts
|
|
172
|
-
import * as crypto from "node:crypto";
|
|
173
|
-
function hash(object, algorithm = "sha256") {
|
|
174
|
-
const objectString = JSON.stringify(object);
|
|
175
|
-
if (!crypto.getHashes().includes(algorithm)) {
|
|
176
|
-
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
177
|
-
}
|
|
178
|
-
const hasher = crypto.createHash(algorithm);
|
|
179
|
-
hasher.update(objectString);
|
|
180
|
-
return hasher.digest("hex");
|
|
181
|
-
}
|
|
182
|
-
|
|
183
189
|
// src/memory.ts
|
|
184
190
|
var CacheableMemory = class {
|
|
191
|
+
_lru = new DoublyLinkedList();
|
|
185
192
|
_hashCache = /* @__PURE__ */ new Map();
|
|
186
193
|
_hash0 = /* @__PURE__ */ new Map();
|
|
187
194
|
_hash1 = /* @__PURE__ */ new Map();
|
|
@@ -193,7 +200,6 @@ var CacheableMemory = class {
|
|
|
193
200
|
_hash7 = /* @__PURE__ */ new Map();
|
|
194
201
|
_hash8 = /* @__PURE__ */ new Map();
|
|
195
202
|
_hash9 = /* @__PURE__ */ new Map();
|
|
196
|
-
_lru = new DoublyLinkedList();
|
|
197
203
|
_ttl;
|
|
198
204
|
// Turned off by default
|
|
199
205
|
_useClone = true;
|
|
@@ -395,12 +401,11 @@ var CacheableMemory = class {
|
|
|
395
401
|
}
|
|
396
402
|
}
|
|
397
403
|
}
|
|
398
|
-
|
|
404
|
+
const item = { key, value, expires };
|
|
405
|
+
store.set(
|
|
399
406
|
key,
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
expires
|
|
403
|
-
});
|
|
407
|
+
item
|
|
408
|
+
);
|
|
404
409
|
}
|
|
405
410
|
/**
|
|
406
411
|
* Sets the values of the keys
|
|
@@ -494,34 +499,24 @@ var CacheableMemory = class {
|
|
|
494
499
|
this._hash8.clear();
|
|
495
500
|
this._hash9.clear();
|
|
496
501
|
this._hashCache.clear();
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* Hash the key. this is used to determine which store to use (internal use)
|
|
500
|
-
* @param {string} key - The key to hash
|
|
501
|
-
* @returns {number} - The hash number
|
|
502
|
-
*/
|
|
503
|
-
hashKey(key) {
|
|
504
|
-
const cacheHashNumber = this._hashCache.get(key);
|
|
505
|
-
if (cacheHashNumber) {
|
|
506
|
-
return cacheHashNumber;
|
|
507
|
-
}
|
|
508
|
-
let hash2 = 0;
|
|
509
|
-
const primeMultiplier = 31;
|
|
510
|
-
for (let i = 0; i < key.length; i++) {
|
|
511
|
-
hash2 = hash2 * primeMultiplier + key.charCodeAt(i);
|
|
512
|
-
}
|
|
513
|
-
const result = Math.abs(hash2) % 10;
|
|
514
|
-
this._hashCache.set(key, result);
|
|
515
|
-
return result;
|
|
502
|
+
this._lru = new DoublyLinkedList();
|
|
516
503
|
}
|
|
517
504
|
/**
|
|
518
505
|
* Get the store based on the key (internal use)
|
|
519
506
|
* @param {string} key - The key to get the store
|
|
520
|
-
* @returns {
|
|
507
|
+
* @returns {CacheableHashStore} - The store
|
|
521
508
|
*/
|
|
522
509
|
getStore(key) {
|
|
523
|
-
const
|
|
524
|
-
|
|
510
|
+
const hash2 = this.hashKey(key);
|
|
511
|
+
return this.getStoreFromHash(hash2);
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Get the store based on the hash (internal use)
|
|
515
|
+
* @param {number} hash
|
|
516
|
+
* @returns {Map<string, CacheableStoreItem>}
|
|
517
|
+
*/
|
|
518
|
+
getStoreFromHash(hash2) {
|
|
519
|
+
switch (hash2) {
|
|
525
520
|
case 1: {
|
|
526
521
|
return this._hash1;
|
|
527
522
|
}
|
|
@@ -554,6 +549,25 @@ var CacheableMemory = class {
|
|
|
554
549
|
}
|
|
555
550
|
}
|
|
556
551
|
}
|
|
552
|
+
/**
|
|
553
|
+
* Hash the key (internal use)
|
|
554
|
+
* @param key
|
|
555
|
+
* @returns {number} from 0 to 9
|
|
556
|
+
*/
|
|
557
|
+
hashKey(key) {
|
|
558
|
+
const cacheHashNumber = this._hashCache.get(key);
|
|
559
|
+
if (cacheHashNumber) {
|
|
560
|
+
return cacheHashNumber;
|
|
561
|
+
}
|
|
562
|
+
let hash2 = 0;
|
|
563
|
+
const primeMultiplier = 31;
|
|
564
|
+
for (let i = 0; i < key.length; i++) {
|
|
565
|
+
hash2 = hash2 * primeMultiplier + key.charCodeAt(i);
|
|
566
|
+
}
|
|
567
|
+
const result = Math.abs(hash2) % 10;
|
|
568
|
+
this._hashCache.set(key, result);
|
|
569
|
+
return result;
|
|
570
|
+
}
|
|
557
571
|
/**
|
|
558
572
|
* Clone the value. This is for internal use
|
|
559
573
|
* @param {any} value - The value to clone
|
|
@@ -652,10 +666,10 @@ var CacheableMemory = class {
|
|
|
652
666
|
* @param {Object} [options] - The options to wrap
|
|
653
667
|
* @returns {Function} - The wrapped function
|
|
654
668
|
*/
|
|
655
|
-
wrap(function_, options
|
|
669
|
+
wrap(function_, options) {
|
|
656
670
|
const wrapOptions = {
|
|
657
671
|
ttl: options.ttl,
|
|
658
|
-
|
|
672
|
+
keyPrefix: options.keyPrefix,
|
|
659
673
|
cache: this
|
|
660
674
|
};
|
|
661
675
|
return wrapSync(function_, wrapOptions);
|
|
@@ -671,8 +685,7 @@ var CacheableMemory = class {
|
|
|
671
685
|
return result;
|
|
672
686
|
}
|
|
673
687
|
concatStores() {
|
|
674
|
-
|
|
675
|
-
return result;
|
|
688
|
+
return new Map([...this._hash0, ...this._hash1, ...this._hash2, ...this._hash3, ...this._hash4, ...this._hash5, ...this._hash6, ...this._hash7, ...this._hash8, ...this._hash9]);
|
|
676
689
|
}
|
|
677
690
|
setTtl(ttl) {
|
|
678
691
|
if (typeof ttl === "string" || ttl === void 0) {
|
|
@@ -693,48 +706,71 @@ var KeyvCacheableMemory = class {
|
|
|
693
706
|
lruSize: 0,
|
|
694
707
|
checkInterval: 0
|
|
695
708
|
};
|
|
696
|
-
|
|
697
|
-
|
|
709
|
+
_defaultCache = new CacheableMemory();
|
|
710
|
+
_nCache = /* @__PURE__ */ new Map();
|
|
711
|
+
_namespace;
|
|
698
712
|
constructor(options) {
|
|
699
713
|
if (options) {
|
|
700
714
|
this.opts = options;
|
|
701
|
-
this.
|
|
715
|
+
this._defaultCache = new CacheableMemory(options);
|
|
716
|
+
if (options.namespace) {
|
|
717
|
+
this._namespace = options.namespace;
|
|
718
|
+
this._nCache.set(this._namespace, new CacheableMemory(options));
|
|
719
|
+
}
|
|
702
720
|
}
|
|
703
721
|
}
|
|
722
|
+
get namespace() {
|
|
723
|
+
return this._namespace;
|
|
724
|
+
}
|
|
725
|
+
set namespace(value) {
|
|
726
|
+
this._namespace = value;
|
|
727
|
+
}
|
|
728
|
+
get store() {
|
|
729
|
+
return this.getStore(this._namespace);
|
|
730
|
+
}
|
|
704
731
|
async get(key) {
|
|
705
|
-
const result = this.
|
|
732
|
+
const result = this.getStore(this._namespace).get(key);
|
|
706
733
|
if (result) {
|
|
707
734
|
return result;
|
|
708
735
|
}
|
|
709
736
|
return void 0;
|
|
710
737
|
}
|
|
711
738
|
async getMany(keys) {
|
|
712
|
-
const result = this.
|
|
739
|
+
const result = this.getStore(this._namespace).getMany(keys);
|
|
713
740
|
return result;
|
|
714
741
|
}
|
|
715
742
|
async set(key, value, ttl) {
|
|
716
|
-
this.
|
|
743
|
+
this.getStore(this._namespace).set(key, value, ttl);
|
|
717
744
|
}
|
|
718
745
|
async setMany(values) {
|
|
719
|
-
this.
|
|
746
|
+
this.getStore(this._namespace).setMany(values);
|
|
720
747
|
}
|
|
721
748
|
async delete(key) {
|
|
722
|
-
this.
|
|
749
|
+
this.getStore(this._namespace).delete(key);
|
|
723
750
|
return true;
|
|
724
751
|
}
|
|
725
752
|
async deleteMany(key) {
|
|
726
|
-
this.
|
|
753
|
+
this.getStore(this._namespace).deleteMany(key);
|
|
727
754
|
return true;
|
|
728
755
|
}
|
|
729
756
|
async clear() {
|
|
730
|
-
this.
|
|
757
|
+
this.getStore(this._namespace).clear();
|
|
731
758
|
}
|
|
732
759
|
async has(key) {
|
|
733
|
-
return this.
|
|
760
|
+
return this.getStore(this._namespace).has(key);
|
|
734
761
|
}
|
|
735
762
|
on(event, listener) {
|
|
736
763
|
return this;
|
|
737
764
|
}
|
|
765
|
+
getStore(namespace) {
|
|
766
|
+
if (!namespace) {
|
|
767
|
+
return this._defaultCache;
|
|
768
|
+
}
|
|
769
|
+
if (!this._nCache.has(namespace)) {
|
|
770
|
+
this._nCache.set(namespace, new CacheableMemory(this.opts));
|
|
771
|
+
}
|
|
772
|
+
return this._nCache.get(namespace);
|
|
773
|
+
}
|
|
738
774
|
};
|
|
739
775
|
|
|
740
776
|
// src/stats.ts
|
|
@@ -980,6 +1016,7 @@ var Cacheable = class extends Hookified {
|
|
|
980
1016
|
_nonBlocking = false;
|
|
981
1017
|
_ttl;
|
|
982
1018
|
_stats = new CacheableStats({ enabled: false });
|
|
1019
|
+
_namespace;
|
|
983
1020
|
/**
|
|
984
1021
|
* Creates a new cacheable instance
|
|
985
1022
|
* @param {CacheableOptions} [options] The options for the cacheable instance
|
|
@@ -1001,6 +1038,32 @@ var Cacheable = class extends Hookified {
|
|
|
1001
1038
|
if (options?.ttl) {
|
|
1002
1039
|
this.setTtl(options.ttl);
|
|
1003
1040
|
}
|
|
1041
|
+
if (options?.namespace) {
|
|
1042
|
+
this._namespace = options.namespace;
|
|
1043
|
+
this._primary.namespace = this.getNameSpace();
|
|
1044
|
+
if (this._secondary) {
|
|
1045
|
+
this._secondary.namespace = this.getNameSpace();
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* The namespace for the cacheable instance
|
|
1051
|
+
* @returns {string | (() => string) | undefined} The namespace for the cacheable instance
|
|
1052
|
+
*/
|
|
1053
|
+
get namespace() {
|
|
1054
|
+
return this._namespace;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Sets the namespace for the cacheable instance
|
|
1058
|
+
* @param {string | (() => string) | undefined} namespace The namespace for the cacheable instance
|
|
1059
|
+
* @returns {void}
|
|
1060
|
+
*/
|
|
1061
|
+
set namespace(namespace) {
|
|
1062
|
+
this._namespace = namespace;
|
|
1063
|
+
this._primary.namespace = this.getNameSpace();
|
|
1064
|
+
if (this._secondary) {
|
|
1065
|
+
this._secondary.namespace = this.getNameSpace();
|
|
1066
|
+
}
|
|
1004
1067
|
}
|
|
1005
1068
|
/**
|
|
1006
1069
|
* The statistics for the cacheable instance
|
|
@@ -1117,6 +1180,12 @@ var Cacheable = class extends Hookified {
|
|
|
1117
1180
|
setSecondary(secondary) {
|
|
1118
1181
|
this._secondary = secondary instanceof Keyv ? secondary : new Keyv(secondary);
|
|
1119
1182
|
}
|
|
1183
|
+
getNameSpace() {
|
|
1184
|
+
if (typeof this._namespace === "function") {
|
|
1185
|
+
return this._namespace();
|
|
1186
|
+
}
|
|
1187
|
+
return this._namespace;
|
|
1188
|
+
}
|
|
1120
1189
|
/**
|
|
1121
1190
|
* Gets the value of the key. If the key does not exist in the primary store then it will check the secondary store.
|
|
1122
1191
|
* @param {string} key The key to get the value of
|
|
@@ -1194,9 +1263,8 @@ var Cacheable = class extends Hookified {
|
|
|
1194
1263
|
* Sets the value of the key. If the secondary store is set then it will also set the value in the secondary store.
|
|
1195
1264
|
* @param {string} key the key to set the value of
|
|
1196
1265
|
* @param {T} value The value to set
|
|
1197
|
-
* @param {number | string} [ttl]
|
|
1198
|
-
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
|
|
1199
|
-
* undefined then it will not have a time-to-live.
|
|
1266
|
+
* @param {number | string} [ttl] set a number it is miliseconds, set a string it is a human-readable
|
|
1267
|
+
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
|
|
1200
1268
|
* @returns {boolean} Whether the value was set
|
|
1201
1269
|
*/
|
|
1202
1270
|
async set(key, value, ttl) {
|
|
@@ -1410,10 +1478,10 @@ var Cacheable = class extends Hookified {
|
|
|
1410
1478
|
* @param {WrapOptions} [options] The options for the wrap function
|
|
1411
1479
|
* @returns {Function} The wrapped function
|
|
1412
1480
|
*/
|
|
1413
|
-
wrap(function_, options
|
|
1481
|
+
wrap(function_, options) {
|
|
1414
1482
|
const wrapOptions = {
|
|
1415
1483
|
ttl: options.ttl,
|
|
1416
|
-
|
|
1484
|
+
keyPrefix: options.keyPrefix,
|
|
1417
1485
|
cache: this
|
|
1418
1486
|
};
|
|
1419
1487
|
return wrap(function_, wrapOptions);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cacheable",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
4
4
|
"description": "Simple Caching Engine using Keyv",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -22,18 +22,18 @@
|
|
|
22
22
|
"private": false,
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@keyv/redis": "^3.0.1",
|
|
25
|
-
"@types/node": "^22.
|
|
26
|
-
"@vitest/coverage-v8": "^2.1.
|
|
25
|
+
"@types/node": "^22.8.1",
|
|
26
|
+
"@vitest/coverage-v8": "^2.1.3",
|
|
27
27
|
"lru-cache": "^11.0.1",
|
|
28
28
|
"rimraf": "^6.0.1",
|
|
29
|
-
"tsup": "^8.3.
|
|
30
|
-
"typescript": "^5.6.
|
|
31
|
-
"vitest": "^2.1.
|
|
29
|
+
"tsup": "^8.3.5",
|
|
30
|
+
"typescript": "^5.6.3",
|
|
31
|
+
"vitest": "^2.1.3",
|
|
32
32
|
"xo": "^0.59.3"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"hookified": "^1.
|
|
36
|
-
"keyv": "^5.
|
|
35
|
+
"hookified": "^1.4.0",
|
|
36
|
+
"keyv": "^5.1.2"
|
|
37
37
|
},
|
|
38
38
|
"keywords": [
|
|
39
39
|
"cacheable",
|