cacheable 1.10.3 → 1.10.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/dist/index.cjs +184 -141
- package/dist/index.d.cts +50 -50
- package/dist/index.d.ts +50 -50
- package/dist/index.js +185 -147
- package/package.json +11 -12
package/dist/index.cjs
CHANGED
|
@@ -46,8 +46,118 @@ __export(index_exports, {
|
|
|
46
46
|
wrapSync: () => wrapSync
|
|
47
47
|
});
|
|
48
48
|
module.exports = __toCommonJS(index_exports);
|
|
49
|
-
var import_keyv2 = require("keyv");
|
|
50
49
|
var import_hookified2 = require("hookified");
|
|
50
|
+
var import_keyv2 = require("keyv");
|
|
51
|
+
|
|
52
|
+
// src/hash.ts
|
|
53
|
+
var crypto = __toESM(require("crypto"), 1);
|
|
54
|
+
function hash(object, algorithm = "sha256") {
|
|
55
|
+
const objectString = JSON.stringify(object);
|
|
56
|
+
if (!crypto.getHashes().includes(algorithm)) {
|
|
57
|
+
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
58
|
+
}
|
|
59
|
+
const hasher = crypto.createHash(algorithm);
|
|
60
|
+
hasher.update(objectString);
|
|
61
|
+
return hasher.digest("hex");
|
|
62
|
+
}
|
|
63
|
+
function hashToNumber(object, min = 0, max = 10, algorithm = "sha256") {
|
|
64
|
+
const objectString = JSON.stringify(object);
|
|
65
|
+
if (!crypto.getHashes().includes(algorithm)) {
|
|
66
|
+
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
67
|
+
}
|
|
68
|
+
const hasher = crypto.createHash(algorithm);
|
|
69
|
+
hasher.update(objectString);
|
|
70
|
+
const hashHex = hasher.digest("hex");
|
|
71
|
+
const hashNumber = Number.parseInt(hashHex, 16);
|
|
72
|
+
const range = max - min + 1;
|
|
73
|
+
return min + hashNumber % range;
|
|
74
|
+
}
|
|
75
|
+
function djb2Hash(string_, min = 0, max = 10) {
|
|
76
|
+
let hash2 = 5381;
|
|
77
|
+
for (let i = 0; i < string_.length; i++) {
|
|
78
|
+
hash2 = hash2 * 33 ^ string_.charCodeAt(i);
|
|
79
|
+
}
|
|
80
|
+
const range = max - min + 1;
|
|
81
|
+
return min + Math.abs(hash2) % range;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/keyv-memory.ts
|
|
85
|
+
var import_keyv = require("keyv");
|
|
86
|
+
|
|
87
|
+
// src/memory.ts
|
|
88
|
+
var import_hookified = require("hookified");
|
|
89
|
+
|
|
90
|
+
// src/memory-lru.ts
|
|
91
|
+
var ListNode = class {
|
|
92
|
+
value;
|
|
93
|
+
prev = void 0;
|
|
94
|
+
next = void 0;
|
|
95
|
+
constructor(value) {
|
|
96
|
+
this.value = value;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
var DoublyLinkedList = class {
|
|
100
|
+
head = void 0;
|
|
101
|
+
tail = void 0;
|
|
102
|
+
nodesMap = /* @__PURE__ */ new Map();
|
|
103
|
+
// Add a new node to the front (most recently used)
|
|
104
|
+
addToFront(value) {
|
|
105
|
+
const newNode = new ListNode(value);
|
|
106
|
+
if (this.head) {
|
|
107
|
+
newNode.next = this.head;
|
|
108
|
+
this.head.prev = newNode;
|
|
109
|
+
this.head = newNode;
|
|
110
|
+
} else {
|
|
111
|
+
this.head = this.tail = newNode;
|
|
112
|
+
}
|
|
113
|
+
this.nodesMap.set(value, newNode);
|
|
114
|
+
}
|
|
115
|
+
// Move an existing node to the front (most recently used)
|
|
116
|
+
moveToFront(value) {
|
|
117
|
+
const node = this.nodesMap.get(value);
|
|
118
|
+
if (!node || this.head === node) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (node.prev) {
|
|
122
|
+
node.prev.next = node.next;
|
|
123
|
+
}
|
|
124
|
+
if (node.next) {
|
|
125
|
+
node.next.prev = node.prev;
|
|
126
|
+
}
|
|
127
|
+
if (node === this.tail) {
|
|
128
|
+
this.tail = node.prev;
|
|
129
|
+
}
|
|
130
|
+
node.prev = void 0;
|
|
131
|
+
node.next = this.head;
|
|
132
|
+
if (this.head) {
|
|
133
|
+
this.head.prev = node;
|
|
134
|
+
}
|
|
135
|
+
this.head = node;
|
|
136
|
+
this.tail ??= node;
|
|
137
|
+
}
|
|
138
|
+
// Get the oldest node (tail)
|
|
139
|
+
getOldest() {
|
|
140
|
+
return this.tail ? this.tail.value : void 0;
|
|
141
|
+
}
|
|
142
|
+
// Remove the oldest node (tail)
|
|
143
|
+
removeOldest() {
|
|
144
|
+
if (!this.tail) {
|
|
145
|
+
return void 0;
|
|
146
|
+
}
|
|
147
|
+
const oldValue = this.tail.value;
|
|
148
|
+
if (this.tail.prev) {
|
|
149
|
+
this.tail = this.tail.prev;
|
|
150
|
+
this.tail.next = void 0;
|
|
151
|
+
} else {
|
|
152
|
+
this.head = this.tail = void 0;
|
|
153
|
+
}
|
|
154
|
+
this.nodesMap.delete(oldValue);
|
|
155
|
+
return oldValue;
|
|
156
|
+
}
|
|
157
|
+
get size() {
|
|
158
|
+
return this.nodesMap.size;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
51
161
|
|
|
52
162
|
// src/shorthand-time.ts
|
|
53
163
|
var shorthandToMilliseconds = (shorthand) => {
|
|
@@ -62,7 +172,9 @@ var shorthandToMilliseconds = (shorthand) => {
|
|
|
62
172
|
if (Number.isNaN(Number(shorthand))) {
|
|
63
173
|
const match = /^([\d.]+)\s*(ms|s|m|h|hr|d)$/i.exec(shorthand);
|
|
64
174
|
if (!match) {
|
|
65
|
-
throw new Error(
|
|
175
|
+
throw new Error(
|
|
176
|
+
`Unsupported time format: "${shorthand}". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.`
|
|
177
|
+
);
|
|
66
178
|
}
|
|
67
179
|
const [, value, unit] = match;
|
|
68
180
|
const numericValue = Number.parseFloat(value);
|
|
@@ -114,44 +226,6 @@ var shorthandToTime = (shorthand, fromDate) => {
|
|
|
114
226
|
return fromDate.getTime() + milliseconds;
|
|
115
227
|
};
|
|
116
228
|
|
|
117
|
-
// src/keyv-memory.ts
|
|
118
|
-
var import_keyv = require("keyv");
|
|
119
|
-
|
|
120
|
-
// src/memory.ts
|
|
121
|
-
var import_hookified = require("hookified");
|
|
122
|
-
|
|
123
|
-
// src/hash.ts
|
|
124
|
-
var crypto = __toESM(require("crypto"), 1);
|
|
125
|
-
function hash(object, algorithm = "sha256") {
|
|
126
|
-
const objectString = JSON.stringify(object);
|
|
127
|
-
if (!crypto.getHashes().includes(algorithm)) {
|
|
128
|
-
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
129
|
-
}
|
|
130
|
-
const hasher = crypto.createHash(algorithm);
|
|
131
|
-
hasher.update(objectString);
|
|
132
|
-
return hasher.digest("hex");
|
|
133
|
-
}
|
|
134
|
-
function hashToNumber(object, min = 0, max = 10, algorithm = "sha256") {
|
|
135
|
-
const objectString = JSON.stringify(object);
|
|
136
|
-
if (!crypto.getHashes().includes(algorithm)) {
|
|
137
|
-
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
138
|
-
}
|
|
139
|
-
const hasher = crypto.createHash(algorithm);
|
|
140
|
-
hasher.update(objectString);
|
|
141
|
-
const hashHex = hasher.digest("hex");
|
|
142
|
-
const hashNumber = Number.parseInt(hashHex, 16);
|
|
143
|
-
const range = max - min + 1;
|
|
144
|
-
return min + hashNumber % range;
|
|
145
|
-
}
|
|
146
|
-
function djb2Hash(string_, min = 0, max = 10) {
|
|
147
|
-
let hash2 = 5381;
|
|
148
|
-
for (let i = 0; i < string_.length; i++) {
|
|
149
|
-
hash2 = hash2 * 33 ^ string_.charCodeAt(i);
|
|
150
|
-
}
|
|
151
|
-
const range = max - min + 1;
|
|
152
|
-
return min + Math.abs(hash2) % range;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
229
|
// src/coalesce-async.ts
|
|
156
230
|
var callbacks = /* @__PURE__ */ new Map();
|
|
157
231
|
function hasKey(key) {
|
|
@@ -210,7 +284,7 @@ async function coalesceAsync(key, fnc) {
|
|
|
210
284
|
// src/wrap.ts
|
|
211
285
|
function wrapSync(function_, options) {
|
|
212
286
|
const { ttl, keyPrefix, cache } = options;
|
|
213
|
-
return
|
|
287
|
+
return (...arguments_) => {
|
|
214
288
|
let cacheKey = createWrapKey(function_, arguments_, keyPrefix);
|
|
215
289
|
if (options.createKey) {
|
|
216
290
|
cacheKey = options.createKey(function_, arguments_, options);
|
|
@@ -256,12 +330,16 @@ async function getOrSet(key, function_, options) {
|
|
|
256
330
|
}
|
|
257
331
|
function wrap(function_, options) {
|
|
258
332
|
const { keyPrefix, cache } = options;
|
|
259
|
-
return async
|
|
333
|
+
return async (...arguments_) => {
|
|
260
334
|
let cacheKey = createWrapKey(function_, arguments_, keyPrefix);
|
|
261
335
|
if (options.createKey) {
|
|
262
336
|
cacheKey = options.createKey(function_, arguments_, options);
|
|
263
337
|
}
|
|
264
|
-
return cache.getOrSet(
|
|
338
|
+
return cache.getOrSet(
|
|
339
|
+
cacheKey,
|
|
340
|
+
async () => function_(...arguments_),
|
|
341
|
+
options
|
|
342
|
+
);
|
|
265
343
|
};
|
|
266
344
|
}
|
|
267
345
|
function createWrapKey(function_, arguments_, keyPrefix) {
|
|
@@ -271,79 +349,6 @@ function createWrapKey(function_, arguments_, keyPrefix) {
|
|
|
271
349
|
return `${keyPrefix}::${function_.name}::${hash(arguments_)}`;
|
|
272
350
|
}
|
|
273
351
|
|
|
274
|
-
// src/memory-lru.ts
|
|
275
|
-
var ListNode = class {
|
|
276
|
-
// eslint-disable-next-line @typescript-eslint/parameter-properties
|
|
277
|
-
value;
|
|
278
|
-
prev = void 0;
|
|
279
|
-
next = void 0;
|
|
280
|
-
constructor(value) {
|
|
281
|
-
this.value = value;
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
var DoublyLinkedList = class {
|
|
285
|
-
head = void 0;
|
|
286
|
-
tail = void 0;
|
|
287
|
-
nodesMap = /* @__PURE__ */ new Map();
|
|
288
|
-
// Add a new node to the front (most recently used)
|
|
289
|
-
addToFront(value) {
|
|
290
|
-
const newNode = new ListNode(value);
|
|
291
|
-
if (this.head) {
|
|
292
|
-
newNode.next = this.head;
|
|
293
|
-
this.head.prev = newNode;
|
|
294
|
-
this.head = newNode;
|
|
295
|
-
} else {
|
|
296
|
-
this.head = this.tail = newNode;
|
|
297
|
-
}
|
|
298
|
-
this.nodesMap.set(value, newNode);
|
|
299
|
-
}
|
|
300
|
-
// Move an existing node to the front (most recently used)
|
|
301
|
-
moveToFront(value) {
|
|
302
|
-
const node = this.nodesMap.get(value);
|
|
303
|
-
if (!node || this.head === node) {
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
if (node.prev) {
|
|
307
|
-
node.prev.next = node.next;
|
|
308
|
-
}
|
|
309
|
-
if (node.next) {
|
|
310
|
-
node.next.prev = node.prev;
|
|
311
|
-
}
|
|
312
|
-
if (node === this.tail) {
|
|
313
|
-
this.tail = node.prev;
|
|
314
|
-
}
|
|
315
|
-
node.prev = void 0;
|
|
316
|
-
node.next = this.head;
|
|
317
|
-
if (this.head) {
|
|
318
|
-
this.head.prev = node;
|
|
319
|
-
}
|
|
320
|
-
this.head = node;
|
|
321
|
-
this.tail ??= node;
|
|
322
|
-
}
|
|
323
|
-
// Get the oldest node (tail)
|
|
324
|
-
getOldest() {
|
|
325
|
-
return this.tail ? this.tail.value : void 0;
|
|
326
|
-
}
|
|
327
|
-
// Remove the oldest node (tail)
|
|
328
|
-
removeOldest() {
|
|
329
|
-
if (!this.tail) {
|
|
330
|
-
return void 0;
|
|
331
|
-
}
|
|
332
|
-
const oldValue = this.tail.value;
|
|
333
|
-
if (this.tail.prev) {
|
|
334
|
-
this.tail = this.tail.prev;
|
|
335
|
-
this.tail.next = void 0;
|
|
336
|
-
} else {
|
|
337
|
-
this.head = this.tail = void 0;
|
|
338
|
-
}
|
|
339
|
-
this.nodesMap.delete(oldValue);
|
|
340
|
-
return oldValue;
|
|
341
|
-
}
|
|
342
|
-
get size() {
|
|
343
|
-
return this.nodesMap.size;
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
|
|
347
352
|
// src/memory.ts
|
|
348
353
|
var defaultStoreHashSize = 16;
|
|
349
354
|
var maximumMapSize = 16777216;
|
|
@@ -352,7 +357,10 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
352
357
|
_storeHashSize = defaultStoreHashSize;
|
|
353
358
|
_storeHashAlgorithm = "djb2Hash" /* djb2Hash */;
|
|
354
359
|
// Default is djb2Hash
|
|
355
|
-
_store = Array.from(
|
|
360
|
+
_store = Array.from(
|
|
361
|
+
{ length: this._storeHashSize },
|
|
362
|
+
() => /* @__PURE__ */ new Map()
|
|
363
|
+
);
|
|
356
364
|
_ttl;
|
|
357
365
|
// Turned off by default
|
|
358
366
|
_useClone = true;
|
|
@@ -380,7 +388,12 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
380
388
|
}
|
|
381
389
|
if (options?.lruSize) {
|
|
382
390
|
if (options.lruSize > maximumMapSize) {
|
|
383
|
-
this.emit(
|
|
391
|
+
this.emit(
|
|
392
|
+
"error",
|
|
393
|
+
new Error(
|
|
394
|
+
`LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
|
|
395
|
+
)
|
|
396
|
+
);
|
|
384
397
|
} else {
|
|
385
398
|
this._lruSize = options.lruSize;
|
|
386
399
|
}
|
|
@@ -391,7 +404,10 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
391
404
|
if (options?.storeHashAlgorithm) {
|
|
392
405
|
this._storeHashAlgorithm = options.storeHashAlgorithm;
|
|
393
406
|
}
|
|
394
|
-
this._store = Array.from(
|
|
407
|
+
this._store = Array.from(
|
|
408
|
+
{ length: this._storeHashSize },
|
|
409
|
+
() => /* @__PURE__ */ new Map()
|
|
410
|
+
);
|
|
395
411
|
this.startIntervalCheck();
|
|
396
412
|
}
|
|
397
413
|
/**
|
|
@@ -435,7 +451,12 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
435
451
|
*/
|
|
436
452
|
set lruSize(value) {
|
|
437
453
|
if (value > maximumMapSize) {
|
|
438
|
-
this.emit(
|
|
454
|
+
this.emit(
|
|
455
|
+
"error",
|
|
456
|
+
new Error(
|
|
457
|
+
`LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
|
|
458
|
+
)
|
|
459
|
+
);
|
|
439
460
|
return;
|
|
440
461
|
}
|
|
441
462
|
this._lruSize = value;
|
|
@@ -486,7 +507,10 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
486
507
|
return;
|
|
487
508
|
}
|
|
488
509
|
this._storeHashSize = value;
|
|
489
|
-
this._store = Array.from(
|
|
510
|
+
this._store = Array.from(
|
|
511
|
+
{ length: this._storeHashSize },
|
|
512
|
+
() => /* @__PURE__ */ new Map()
|
|
513
|
+
);
|
|
490
514
|
}
|
|
491
515
|
/**
|
|
492
516
|
* Gets the store hash algorithm
|
|
@@ -507,7 +531,7 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
507
531
|
* @returns {IterableIterator<string>} - The keys
|
|
508
532
|
*/
|
|
509
533
|
get keys() {
|
|
510
|
-
const keys =
|
|
534
|
+
const keys = [];
|
|
511
535
|
for (const store of this._store) {
|
|
512
536
|
for (const key of store.keys()) {
|
|
513
537
|
const item = store.get(key);
|
|
@@ -525,7 +549,7 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
525
549
|
* @returns {IterableIterator<CacheableStoreItem>} - The items
|
|
526
550
|
*/
|
|
527
551
|
get items() {
|
|
528
|
-
const items =
|
|
552
|
+
const items = [];
|
|
529
553
|
for (const store of this._store) {
|
|
530
554
|
for (const item of store.values()) {
|
|
531
555
|
if (this.hasExpired(item)) {
|
|
@@ -571,7 +595,7 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
571
595
|
* @returns {T[]} - The values of the keys
|
|
572
596
|
*/
|
|
573
597
|
getMany(keys) {
|
|
574
|
-
const result =
|
|
598
|
+
const result = [];
|
|
575
599
|
for (const key of keys) {
|
|
576
600
|
result.push(this.get(key));
|
|
577
601
|
}
|
|
@@ -601,7 +625,7 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
601
625
|
* @returns {CacheableStoreItem[]} - The raw values of the keys
|
|
602
626
|
*/
|
|
603
627
|
getManyRaw(keys) {
|
|
604
|
-
const result =
|
|
628
|
+
const result = [];
|
|
605
629
|
for (const key of keys) {
|
|
606
630
|
result.push(this.getRaw(key));
|
|
607
631
|
}
|
|
@@ -652,10 +676,7 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
652
676
|
}
|
|
653
677
|
}
|
|
654
678
|
const item = { key, value, expires };
|
|
655
|
-
store.set(
|
|
656
|
-
key,
|
|
657
|
-
item
|
|
658
|
-
);
|
|
679
|
+
store.set(key, item);
|
|
659
680
|
}
|
|
660
681
|
/**
|
|
661
682
|
* Sets the values of the keys
|
|
@@ -682,7 +703,7 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
682
703
|
* @returns {boolean[]} - If true, the key exists. If false, the key does not exist.
|
|
683
704
|
*/
|
|
684
705
|
hasMany(keys) {
|
|
685
|
-
const result =
|
|
706
|
+
const result = [];
|
|
686
707
|
for (const key of keys) {
|
|
687
708
|
const item = this.get(key);
|
|
688
709
|
result.push(Boolean(item));
|
|
@@ -708,7 +729,7 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
708
729
|
* @returns {T[]} - The values of the keys
|
|
709
730
|
*/
|
|
710
731
|
takeMany(keys) {
|
|
711
|
-
const result =
|
|
732
|
+
const result = [];
|
|
712
733
|
for (const key of keys) {
|
|
713
734
|
result.push(this.take(key));
|
|
714
735
|
}
|
|
@@ -738,7 +759,10 @@ var CacheableMemory = class extends import_hookified.Hookified {
|
|
|
738
759
|
* @returns {void}
|
|
739
760
|
*/
|
|
740
761
|
clear() {
|
|
741
|
-
this._store = Array.from(
|
|
762
|
+
this._store = Array.from(
|
|
763
|
+
{ length: this._storeHashSize },
|
|
764
|
+
() => /* @__PURE__ */ new Map()
|
|
765
|
+
);
|
|
742
766
|
this._lru = new DoublyLinkedList();
|
|
743
767
|
}
|
|
744
768
|
/**
|
|
@@ -1110,28 +1134,24 @@ var CacheableStats = class {
|
|
|
1110
1134
|
}
|
|
1111
1135
|
this._clears++;
|
|
1112
1136
|
}
|
|
1113
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1114
1137
|
incrementVSize(value) {
|
|
1115
1138
|
if (!this._enabled) {
|
|
1116
1139
|
return;
|
|
1117
1140
|
}
|
|
1118
1141
|
this._vsize += this.roughSizeOfObject(value);
|
|
1119
1142
|
}
|
|
1120
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1121
1143
|
decreaseVSize(value) {
|
|
1122
1144
|
if (!this._enabled) {
|
|
1123
1145
|
return;
|
|
1124
1146
|
}
|
|
1125
1147
|
this._vsize -= this.roughSizeOfObject(value);
|
|
1126
1148
|
}
|
|
1127
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1128
1149
|
incrementKSize(key) {
|
|
1129
1150
|
if (!this._enabled) {
|
|
1130
1151
|
return;
|
|
1131
1152
|
}
|
|
1132
1153
|
this._ksize += this.roughSizeOfString(key);
|
|
1133
1154
|
}
|
|
1134
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1135
1155
|
decreaseKSize(key) {
|
|
1136
1156
|
if (!this._enabled) {
|
|
1137
1157
|
return;
|
|
@@ -1450,11 +1470,26 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
1450
1470
|
this.emit("error" /* ERROR */, error);
|
|
1451
1471
|
});
|
|
1452
1472
|
}
|
|
1473
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
1453
1474
|
isKeyvInstance(keyv) {
|
|
1454
1475
|
if (keyv instanceof import_keyv2.Keyv) {
|
|
1455
1476
|
return true;
|
|
1456
1477
|
}
|
|
1457
|
-
const keyvMethods = [
|
|
1478
|
+
const keyvMethods = [
|
|
1479
|
+
"generateIterator",
|
|
1480
|
+
"get",
|
|
1481
|
+
"getMany",
|
|
1482
|
+
"set",
|
|
1483
|
+
"setMany",
|
|
1484
|
+
"delete",
|
|
1485
|
+
"deleteMany",
|
|
1486
|
+
"has",
|
|
1487
|
+
"hasMany",
|
|
1488
|
+
"clear",
|
|
1489
|
+
"disconnect",
|
|
1490
|
+
"serialize",
|
|
1491
|
+
"deserialize"
|
|
1492
|
+
];
|
|
1458
1493
|
return keyvMethods.every((method) => typeof keyv[method] === "function");
|
|
1459
1494
|
}
|
|
1460
1495
|
getNameSpace() {
|
|
@@ -1478,7 +1513,10 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
1478
1513
|
const expires = secondaryResult.expires ?? void 0;
|
|
1479
1514
|
ttl = calculateTtlFromExpiration(cascadeTtl, expires);
|
|
1480
1515
|
const setItem = { key, value: result.value, ttl };
|
|
1481
|
-
await this.hook(
|
|
1516
|
+
await this.hook(
|
|
1517
|
+
"BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */,
|
|
1518
|
+
setItem
|
|
1519
|
+
);
|
|
1482
1520
|
await this._primary.set(setItem.key, setItem.value, setItem.ttl);
|
|
1483
1521
|
}
|
|
1484
1522
|
}
|
|
@@ -1520,7 +1558,10 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
1520
1558
|
}
|
|
1521
1559
|
const ttl = calculateTtlFromExpiration(cascadeTtl, expires);
|
|
1522
1560
|
const setItem = { key, value: result[i].value, ttl };
|
|
1523
|
-
await this.hook(
|
|
1561
|
+
await this.hook(
|
|
1562
|
+
"BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */,
|
|
1563
|
+
setItem
|
|
1564
|
+
);
|
|
1524
1565
|
await this._primary.set(setItem.key, setItem.value, setItem.ttl);
|
|
1525
1566
|
}
|
|
1526
1567
|
}
|
|
@@ -1662,7 +1703,7 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
1662
1703
|
}
|
|
1663
1704
|
if (missingKeys.length > 0 && this._secondary) {
|
|
1664
1705
|
const secondary = await this.hasManyKeyv(this._secondary, keys);
|
|
1665
|
-
for (const [i,
|
|
1706
|
+
for (const [i, _key] of keys.entries()) {
|
|
1666
1707
|
if (!result[i] && secondary[i]) {
|
|
1667
1708
|
result[i] = secondary[i];
|
|
1668
1709
|
}
|
|
@@ -1760,6 +1801,7 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
1760
1801
|
* @param {WrapOptions} [options] The options for the wrap function
|
|
1761
1802
|
* @returns {Function} The wrapped function
|
|
1762
1803
|
*/
|
|
1804
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
1763
1805
|
wrap(function_, options) {
|
|
1764
1806
|
const wrapOptions = {
|
|
1765
1807
|
ttl: options?.ttl ?? this._ttl,
|
|
@@ -1795,6 +1837,7 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
1795
1837
|
* @param {string} algorithm the hash algorithm to use. The default is 'sha256'
|
|
1796
1838
|
* @returns {string} the hash of the object
|
|
1797
1839
|
*/
|
|
1840
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
1798
1841
|
hash(object, algorithm = "sha256") {
|
|
1799
1842
|
return hash(object, algorithm);
|
|
1800
1843
|
}
|
|
@@ -1806,7 +1849,7 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
1806
1849
|
return result;
|
|
1807
1850
|
}
|
|
1808
1851
|
async getManySecondaryRawResults(keys) {
|
|
1809
|
-
let result =
|
|
1852
|
+
let result = [];
|
|
1810
1853
|
if (this._secondary) {
|
|
1811
1854
|
result = await this._secondary.get(keys, { raw: true });
|
|
1812
1855
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
import { KeyvStoreAdapter, StoredData, Keyv, StoredDataRaw } from 'keyv';
|
|
2
|
-
export { Keyv, KeyvHooks, KeyvOptions, KeyvStoreAdapter } from 'keyv';
|
|
3
1
|
import { Hookified } from 'hookified';
|
|
2
|
+
import { Keyv, KeyvStoreAdapter, StoredData, StoredDataRaw } from 'keyv';
|
|
3
|
+
export { Keyv, KeyvHooks, KeyvOptions, KeyvStoreAdapter } from 'keyv';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CacheableItem
|
|
7
|
+
* @typedef {Object} CacheableItem
|
|
8
|
+
* @property {string} key - The key of the cacheable item
|
|
9
|
+
* @property {any} value - The value of the cacheable item
|
|
10
|
+
* @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
|
|
11
|
+
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live. If both are
|
|
12
|
+
* undefined then it will not have a time-to-live.
|
|
13
|
+
*/
|
|
14
|
+
type CacheableItem = {
|
|
15
|
+
key: string;
|
|
16
|
+
value: any;
|
|
17
|
+
ttl?: number | string;
|
|
18
|
+
};
|
|
19
|
+
type CacheableStoreItem = {
|
|
20
|
+
key: string;
|
|
21
|
+
value: any;
|
|
22
|
+
expires?: number;
|
|
23
|
+
};
|
|
4
24
|
|
|
5
25
|
type CacheableOptions$1 = {
|
|
6
26
|
enabled?: boolean;
|
|
@@ -89,26 +109,6 @@ declare class CacheableStats {
|
|
|
89
109
|
resetStoreValues(): void;
|
|
90
110
|
}
|
|
91
111
|
|
|
92
|
-
/**
|
|
93
|
-
* CacheableItem
|
|
94
|
-
* @typedef {Object} CacheableItem
|
|
95
|
-
* @property {string} key - The key of the cacheable item
|
|
96
|
-
* @property {any} value - The value of the cacheable item
|
|
97
|
-
* @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
|
|
98
|
-
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live. If both are
|
|
99
|
-
* undefined then it will not have a time-to-live.
|
|
100
|
-
*/
|
|
101
|
-
type CacheableItem = {
|
|
102
|
-
key: string;
|
|
103
|
-
value: any;
|
|
104
|
-
ttl?: number | string;
|
|
105
|
-
};
|
|
106
|
-
type CacheableStoreItem = {
|
|
107
|
-
key: string;
|
|
108
|
-
value: any;
|
|
109
|
-
expires?: number;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
112
|
type GetOrSetKey = string | ((options?: GetOrSetOptions) => string);
|
|
113
113
|
type GetOrSetFunctionOptions = {
|
|
114
114
|
ttl?: number | string;
|
|
@@ -144,7 +144,7 @@ declare enum StoreHashAlgorithm {
|
|
|
144
144
|
MD5 = "md5",
|
|
145
145
|
djb2Hash = "djb2Hash"
|
|
146
146
|
}
|
|
147
|
-
type StoreHashAlgorithmFunction = (
|
|
147
|
+
type StoreHashAlgorithmFunction = (key: string, storeHashSize: number) => number;
|
|
148
148
|
/**
|
|
149
149
|
* @typedef {Object} CacheableMemoryOptions
|
|
150
150
|
* @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
|
|
@@ -623,19 +623,19 @@ declare class Cacheable extends Hookified {
|
|
|
623
623
|
isKeyvInstance(keyv: any): boolean;
|
|
624
624
|
getNameSpace(): string | undefined;
|
|
625
625
|
/**
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
626
|
+
* Retrieves an entry from the cache, with an optional “raw” mode.
|
|
627
|
+
*
|
|
628
|
+
* Checks the primary store first; if not found and a secondary store is configured,
|
|
629
|
+
* it will fetch from the secondary, repopulate the primary, and return the result.
|
|
630
|
+
*
|
|
631
|
+
* @typeParam T - The expected type of the stored value.
|
|
632
|
+
* @param {string} key - The cache key to retrieve.
|
|
633
|
+
* @param {{ raw?: boolean }} [opts] - Options for retrieval.
|
|
634
|
+
* @param {boolean} [opts.raw=false] - If `true`, returns the full raw data object
|
|
635
|
+
* (`StoredDataRaw<T>`); otherwise returns just the value.
|
|
636
|
+
* @returns {Promise<T | StoredDataRaw<T> | undefined>}
|
|
637
|
+
* A promise that resolves to the cached value (or raw data) if found, or `undefined`.
|
|
638
|
+
*/
|
|
639
639
|
get<T>(key: string, options?: {
|
|
640
640
|
raw?: false;
|
|
641
641
|
}): Promise<T | undefined>;
|
|
@@ -643,20 +643,20 @@ declare class Cacheable extends Hookified {
|
|
|
643
643
|
raw: true;
|
|
644
644
|
}): Promise<StoredDataRaw<T>>;
|
|
645
645
|
/**
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
646
|
+
* Retrieves multiple entries from the cache.
|
|
647
|
+
* Checks the primary store for each key; if a key is missing and a secondary store is configured,
|
|
648
|
+
* it will fetch from the secondary store, repopulate the primary store, and return the results.
|
|
649
|
+
*
|
|
650
|
+
* @typeParam T - The expected type of the stored values.
|
|
651
|
+
* @param {string[]} keys - The cache keys to retrieve.
|
|
652
|
+
* @param {{ raw?: boolean }} [options] - Options for retrieval.
|
|
653
|
+
* @param {boolean} [options.raw=false] - When `true`, returns an array of raw data objects (`StoredDataRaw<T>`);
|
|
654
|
+
* when `false`, returns an array of unwrapped values (`T`) or `undefined` for misses.
|
|
655
|
+
* @returns {Promise<Array<T | undefined>> | Promise<Array<StoredDataRaw<T>>>}
|
|
656
|
+
* A promise that resolves to:
|
|
657
|
+
* - `Array<T | undefined>` if `raw` is `false` (default).
|
|
658
|
+
* - `Array<StoredDataRaw<T>>` if `raw` is `true`.
|
|
659
|
+
*/
|
|
660
660
|
getMany<T>(keys: string[], options?: {
|
|
661
661
|
raw?: false;
|
|
662
662
|
}): Promise<Array<T | undefined>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
import { KeyvStoreAdapter, StoredData, Keyv, StoredDataRaw } from 'keyv';
|
|
2
|
-
export { Keyv, KeyvHooks, KeyvOptions, KeyvStoreAdapter } from 'keyv';
|
|
3
1
|
import { Hookified } from 'hookified';
|
|
2
|
+
import { Keyv, KeyvStoreAdapter, StoredData, StoredDataRaw } from 'keyv';
|
|
3
|
+
export { Keyv, KeyvHooks, KeyvOptions, KeyvStoreAdapter } from 'keyv';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CacheableItem
|
|
7
|
+
* @typedef {Object} CacheableItem
|
|
8
|
+
* @property {string} key - The key of the cacheable item
|
|
9
|
+
* @property {any} value - The value of the cacheable item
|
|
10
|
+
* @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
|
|
11
|
+
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live. If both are
|
|
12
|
+
* undefined then it will not have a time-to-live.
|
|
13
|
+
*/
|
|
14
|
+
type CacheableItem = {
|
|
15
|
+
key: string;
|
|
16
|
+
value: any;
|
|
17
|
+
ttl?: number | string;
|
|
18
|
+
};
|
|
19
|
+
type CacheableStoreItem = {
|
|
20
|
+
key: string;
|
|
21
|
+
value: any;
|
|
22
|
+
expires?: number;
|
|
23
|
+
};
|
|
4
24
|
|
|
5
25
|
type CacheableOptions$1 = {
|
|
6
26
|
enabled?: boolean;
|
|
@@ -89,26 +109,6 @@ declare class CacheableStats {
|
|
|
89
109
|
resetStoreValues(): void;
|
|
90
110
|
}
|
|
91
111
|
|
|
92
|
-
/**
|
|
93
|
-
* CacheableItem
|
|
94
|
-
* @typedef {Object} CacheableItem
|
|
95
|
-
* @property {string} key - The key of the cacheable item
|
|
96
|
-
* @property {any} value - The value of the cacheable item
|
|
97
|
-
* @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
|
|
98
|
-
* format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live. If both are
|
|
99
|
-
* undefined then it will not have a time-to-live.
|
|
100
|
-
*/
|
|
101
|
-
type CacheableItem = {
|
|
102
|
-
key: string;
|
|
103
|
-
value: any;
|
|
104
|
-
ttl?: number | string;
|
|
105
|
-
};
|
|
106
|
-
type CacheableStoreItem = {
|
|
107
|
-
key: string;
|
|
108
|
-
value: any;
|
|
109
|
-
expires?: number;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
112
|
type GetOrSetKey = string | ((options?: GetOrSetOptions) => string);
|
|
113
113
|
type GetOrSetFunctionOptions = {
|
|
114
114
|
ttl?: number | string;
|
|
@@ -144,7 +144,7 @@ declare enum StoreHashAlgorithm {
|
|
|
144
144
|
MD5 = "md5",
|
|
145
145
|
djb2Hash = "djb2Hash"
|
|
146
146
|
}
|
|
147
|
-
type StoreHashAlgorithmFunction = (
|
|
147
|
+
type StoreHashAlgorithmFunction = (key: string, storeHashSize: number) => number;
|
|
148
148
|
/**
|
|
149
149
|
* @typedef {Object} CacheableMemoryOptions
|
|
150
150
|
* @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
|
|
@@ -623,19 +623,19 @@ declare class Cacheable extends Hookified {
|
|
|
623
623
|
isKeyvInstance(keyv: any): boolean;
|
|
624
624
|
getNameSpace(): string | undefined;
|
|
625
625
|
/**
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
626
|
+
* Retrieves an entry from the cache, with an optional “raw” mode.
|
|
627
|
+
*
|
|
628
|
+
* Checks the primary store first; if not found and a secondary store is configured,
|
|
629
|
+
* it will fetch from the secondary, repopulate the primary, and return the result.
|
|
630
|
+
*
|
|
631
|
+
* @typeParam T - The expected type of the stored value.
|
|
632
|
+
* @param {string} key - The cache key to retrieve.
|
|
633
|
+
* @param {{ raw?: boolean }} [opts] - Options for retrieval.
|
|
634
|
+
* @param {boolean} [opts.raw=false] - If `true`, returns the full raw data object
|
|
635
|
+
* (`StoredDataRaw<T>`); otherwise returns just the value.
|
|
636
|
+
* @returns {Promise<T | StoredDataRaw<T> | undefined>}
|
|
637
|
+
* A promise that resolves to the cached value (or raw data) if found, or `undefined`.
|
|
638
|
+
*/
|
|
639
639
|
get<T>(key: string, options?: {
|
|
640
640
|
raw?: false;
|
|
641
641
|
}): Promise<T | undefined>;
|
|
@@ -643,20 +643,20 @@ declare class Cacheable extends Hookified {
|
|
|
643
643
|
raw: true;
|
|
644
644
|
}): Promise<StoredDataRaw<T>>;
|
|
645
645
|
/**
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
646
|
+
* Retrieves multiple entries from the cache.
|
|
647
|
+
* Checks the primary store for each key; if a key is missing and a secondary store is configured,
|
|
648
|
+
* it will fetch from the secondary store, repopulate the primary store, and return the results.
|
|
649
|
+
*
|
|
650
|
+
* @typeParam T - The expected type of the stored values.
|
|
651
|
+
* @param {string[]} keys - The cache keys to retrieve.
|
|
652
|
+
* @param {{ raw?: boolean }} [options] - Options for retrieval.
|
|
653
|
+
* @param {boolean} [options.raw=false] - When `true`, returns an array of raw data objects (`StoredDataRaw<T>`);
|
|
654
|
+
* when `false`, returns an array of unwrapped values (`T`) or `undefined` for misses.
|
|
655
|
+
* @returns {Promise<Array<T | undefined>> | Promise<Array<StoredDataRaw<T>>>}
|
|
656
|
+
* A promise that resolves to:
|
|
657
|
+
* - `Array<T | undefined>` if `raw` is `false` (default).
|
|
658
|
+
* - `Array<StoredDataRaw<T>>` if `raw` is `true`.
|
|
659
|
+
*/
|
|
660
660
|
getMany<T>(keys: string[], options?: {
|
|
661
661
|
raw?: false;
|
|
662
662
|
}): Promise<Array<T | undefined>>;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,116 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { Keyv as Keyv2 } from "keyv";
|
|
3
2
|
import { Hookified as Hookified2 } from "hookified";
|
|
3
|
+
import { Keyv as Keyv2 } from "keyv";
|
|
4
|
+
|
|
5
|
+
// src/hash.ts
|
|
6
|
+
import * as crypto from "crypto";
|
|
7
|
+
function hash(object, algorithm = "sha256") {
|
|
8
|
+
const objectString = JSON.stringify(object);
|
|
9
|
+
if (!crypto.getHashes().includes(algorithm)) {
|
|
10
|
+
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
11
|
+
}
|
|
12
|
+
const hasher = crypto.createHash(algorithm);
|
|
13
|
+
hasher.update(objectString);
|
|
14
|
+
return hasher.digest("hex");
|
|
15
|
+
}
|
|
16
|
+
function hashToNumber(object, min = 0, max = 10, algorithm = "sha256") {
|
|
17
|
+
const objectString = JSON.stringify(object);
|
|
18
|
+
if (!crypto.getHashes().includes(algorithm)) {
|
|
19
|
+
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
20
|
+
}
|
|
21
|
+
const hasher = crypto.createHash(algorithm);
|
|
22
|
+
hasher.update(objectString);
|
|
23
|
+
const hashHex = hasher.digest("hex");
|
|
24
|
+
const hashNumber = Number.parseInt(hashHex, 16);
|
|
25
|
+
const range = max - min + 1;
|
|
26
|
+
return min + hashNumber % range;
|
|
27
|
+
}
|
|
28
|
+
function djb2Hash(string_, min = 0, max = 10) {
|
|
29
|
+
let hash2 = 5381;
|
|
30
|
+
for (let i = 0; i < string_.length; i++) {
|
|
31
|
+
hash2 = hash2 * 33 ^ string_.charCodeAt(i);
|
|
32
|
+
}
|
|
33
|
+
const range = max - min + 1;
|
|
34
|
+
return min + Math.abs(hash2) % range;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/keyv-memory.ts
|
|
38
|
+
import { Keyv } from "keyv";
|
|
39
|
+
|
|
40
|
+
// src/memory.ts
|
|
41
|
+
import { Hookified } from "hookified";
|
|
42
|
+
|
|
43
|
+
// src/memory-lru.ts
|
|
44
|
+
var ListNode = class {
|
|
45
|
+
value;
|
|
46
|
+
prev = void 0;
|
|
47
|
+
next = void 0;
|
|
48
|
+
constructor(value) {
|
|
49
|
+
this.value = value;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var DoublyLinkedList = class {
|
|
53
|
+
head = void 0;
|
|
54
|
+
tail = void 0;
|
|
55
|
+
nodesMap = /* @__PURE__ */ new Map();
|
|
56
|
+
// Add a new node to the front (most recently used)
|
|
57
|
+
addToFront(value) {
|
|
58
|
+
const newNode = new ListNode(value);
|
|
59
|
+
if (this.head) {
|
|
60
|
+
newNode.next = this.head;
|
|
61
|
+
this.head.prev = newNode;
|
|
62
|
+
this.head = newNode;
|
|
63
|
+
} else {
|
|
64
|
+
this.head = this.tail = newNode;
|
|
65
|
+
}
|
|
66
|
+
this.nodesMap.set(value, newNode);
|
|
67
|
+
}
|
|
68
|
+
// Move an existing node to the front (most recently used)
|
|
69
|
+
moveToFront(value) {
|
|
70
|
+
const node = this.nodesMap.get(value);
|
|
71
|
+
if (!node || this.head === node) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (node.prev) {
|
|
75
|
+
node.prev.next = node.next;
|
|
76
|
+
}
|
|
77
|
+
if (node.next) {
|
|
78
|
+
node.next.prev = node.prev;
|
|
79
|
+
}
|
|
80
|
+
if (node === this.tail) {
|
|
81
|
+
this.tail = node.prev;
|
|
82
|
+
}
|
|
83
|
+
node.prev = void 0;
|
|
84
|
+
node.next = this.head;
|
|
85
|
+
if (this.head) {
|
|
86
|
+
this.head.prev = node;
|
|
87
|
+
}
|
|
88
|
+
this.head = node;
|
|
89
|
+
this.tail ??= node;
|
|
90
|
+
}
|
|
91
|
+
// Get the oldest node (tail)
|
|
92
|
+
getOldest() {
|
|
93
|
+
return this.tail ? this.tail.value : void 0;
|
|
94
|
+
}
|
|
95
|
+
// Remove the oldest node (tail)
|
|
96
|
+
removeOldest() {
|
|
97
|
+
if (!this.tail) {
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
const oldValue = this.tail.value;
|
|
101
|
+
if (this.tail.prev) {
|
|
102
|
+
this.tail = this.tail.prev;
|
|
103
|
+
this.tail.next = void 0;
|
|
104
|
+
} else {
|
|
105
|
+
this.head = this.tail = void 0;
|
|
106
|
+
}
|
|
107
|
+
this.nodesMap.delete(oldValue);
|
|
108
|
+
return oldValue;
|
|
109
|
+
}
|
|
110
|
+
get size() {
|
|
111
|
+
return this.nodesMap.size;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
4
114
|
|
|
5
115
|
// src/shorthand-time.ts
|
|
6
116
|
var shorthandToMilliseconds = (shorthand) => {
|
|
@@ -15,7 +125,9 @@ var shorthandToMilliseconds = (shorthand) => {
|
|
|
15
125
|
if (Number.isNaN(Number(shorthand))) {
|
|
16
126
|
const match = /^([\d.]+)\s*(ms|s|m|h|hr|d)$/i.exec(shorthand);
|
|
17
127
|
if (!match) {
|
|
18
|
-
throw new Error(
|
|
128
|
+
throw new Error(
|
|
129
|
+
`Unsupported time format: "${shorthand}". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.`
|
|
130
|
+
);
|
|
19
131
|
}
|
|
20
132
|
const [, value, unit] = match;
|
|
21
133
|
const numericValue = Number.parseFloat(value);
|
|
@@ -67,46 +179,6 @@ var shorthandToTime = (shorthand, fromDate) => {
|
|
|
67
179
|
return fromDate.getTime() + milliseconds;
|
|
68
180
|
};
|
|
69
181
|
|
|
70
|
-
// src/keyv-memory.ts
|
|
71
|
-
import {
|
|
72
|
-
Keyv
|
|
73
|
-
} from "keyv";
|
|
74
|
-
|
|
75
|
-
// src/memory.ts
|
|
76
|
-
import { Hookified } from "hookified";
|
|
77
|
-
|
|
78
|
-
// src/hash.ts
|
|
79
|
-
import * as crypto from "crypto";
|
|
80
|
-
function hash(object, algorithm = "sha256") {
|
|
81
|
-
const objectString = JSON.stringify(object);
|
|
82
|
-
if (!crypto.getHashes().includes(algorithm)) {
|
|
83
|
-
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
84
|
-
}
|
|
85
|
-
const hasher = crypto.createHash(algorithm);
|
|
86
|
-
hasher.update(objectString);
|
|
87
|
-
return hasher.digest("hex");
|
|
88
|
-
}
|
|
89
|
-
function hashToNumber(object, min = 0, max = 10, algorithm = "sha256") {
|
|
90
|
-
const objectString = JSON.stringify(object);
|
|
91
|
-
if (!crypto.getHashes().includes(algorithm)) {
|
|
92
|
-
throw new Error(`Unsupported hash algorithm: '${algorithm}'`);
|
|
93
|
-
}
|
|
94
|
-
const hasher = crypto.createHash(algorithm);
|
|
95
|
-
hasher.update(objectString);
|
|
96
|
-
const hashHex = hasher.digest("hex");
|
|
97
|
-
const hashNumber = Number.parseInt(hashHex, 16);
|
|
98
|
-
const range = max - min + 1;
|
|
99
|
-
return min + hashNumber % range;
|
|
100
|
-
}
|
|
101
|
-
function djb2Hash(string_, min = 0, max = 10) {
|
|
102
|
-
let hash2 = 5381;
|
|
103
|
-
for (let i = 0; i < string_.length; i++) {
|
|
104
|
-
hash2 = hash2 * 33 ^ string_.charCodeAt(i);
|
|
105
|
-
}
|
|
106
|
-
const range = max - min + 1;
|
|
107
|
-
return min + Math.abs(hash2) % range;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
182
|
// src/coalesce-async.ts
|
|
111
183
|
var callbacks = /* @__PURE__ */ new Map();
|
|
112
184
|
function hasKey(key) {
|
|
@@ -165,7 +237,7 @@ async function coalesceAsync(key, fnc) {
|
|
|
165
237
|
// src/wrap.ts
|
|
166
238
|
function wrapSync(function_, options) {
|
|
167
239
|
const { ttl, keyPrefix, cache } = options;
|
|
168
|
-
return
|
|
240
|
+
return (...arguments_) => {
|
|
169
241
|
let cacheKey = createWrapKey(function_, arguments_, keyPrefix);
|
|
170
242
|
if (options.createKey) {
|
|
171
243
|
cacheKey = options.createKey(function_, arguments_, options);
|
|
@@ -211,12 +283,16 @@ async function getOrSet(key, function_, options) {
|
|
|
211
283
|
}
|
|
212
284
|
function wrap(function_, options) {
|
|
213
285
|
const { keyPrefix, cache } = options;
|
|
214
|
-
return async
|
|
286
|
+
return async (...arguments_) => {
|
|
215
287
|
let cacheKey = createWrapKey(function_, arguments_, keyPrefix);
|
|
216
288
|
if (options.createKey) {
|
|
217
289
|
cacheKey = options.createKey(function_, arguments_, options);
|
|
218
290
|
}
|
|
219
|
-
return cache.getOrSet(
|
|
291
|
+
return cache.getOrSet(
|
|
292
|
+
cacheKey,
|
|
293
|
+
async () => function_(...arguments_),
|
|
294
|
+
options
|
|
295
|
+
);
|
|
220
296
|
};
|
|
221
297
|
}
|
|
222
298
|
function createWrapKey(function_, arguments_, keyPrefix) {
|
|
@@ -226,79 +302,6 @@ function createWrapKey(function_, arguments_, keyPrefix) {
|
|
|
226
302
|
return `${keyPrefix}::${function_.name}::${hash(arguments_)}`;
|
|
227
303
|
}
|
|
228
304
|
|
|
229
|
-
// src/memory-lru.ts
|
|
230
|
-
var ListNode = class {
|
|
231
|
-
// eslint-disable-next-line @typescript-eslint/parameter-properties
|
|
232
|
-
value;
|
|
233
|
-
prev = void 0;
|
|
234
|
-
next = void 0;
|
|
235
|
-
constructor(value) {
|
|
236
|
-
this.value = value;
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
var DoublyLinkedList = class {
|
|
240
|
-
head = void 0;
|
|
241
|
-
tail = void 0;
|
|
242
|
-
nodesMap = /* @__PURE__ */ new Map();
|
|
243
|
-
// Add a new node to the front (most recently used)
|
|
244
|
-
addToFront(value) {
|
|
245
|
-
const newNode = new ListNode(value);
|
|
246
|
-
if (this.head) {
|
|
247
|
-
newNode.next = this.head;
|
|
248
|
-
this.head.prev = newNode;
|
|
249
|
-
this.head = newNode;
|
|
250
|
-
} else {
|
|
251
|
-
this.head = this.tail = newNode;
|
|
252
|
-
}
|
|
253
|
-
this.nodesMap.set(value, newNode);
|
|
254
|
-
}
|
|
255
|
-
// Move an existing node to the front (most recently used)
|
|
256
|
-
moveToFront(value) {
|
|
257
|
-
const node = this.nodesMap.get(value);
|
|
258
|
-
if (!node || this.head === node) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
if (node.prev) {
|
|
262
|
-
node.prev.next = node.next;
|
|
263
|
-
}
|
|
264
|
-
if (node.next) {
|
|
265
|
-
node.next.prev = node.prev;
|
|
266
|
-
}
|
|
267
|
-
if (node === this.tail) {
|
|
268
|
-
this.tail = node.prev;
|
|
269
|
-
}
|
|
270
|
-
node.prev = void 0;
|
|
271
|
-
node.next = this.head;
|
|
272
|
-
if (this.head) {
|
|
273
|
-
this.head.prev = node;
|
|
274
|
-
}
|
|
275
|
-
this.head = node;
|
|
276
|
-
this.tail ??= node;
|
|
277
|
-
}
|
|
278
|
-
// Get the oldest node (tail)
|
|
279
|
-
getOldest() {
|
|
280
|
-
return this.tail ? this.tail.value : void 0;
|
|
281
|
-
}
|
|
282
|
-
// Remove the oldest node (tail)
|
|
283
|
-
removeOldest() {
|
|
284
|
-
if (!this.tail) {
|
|
285
|
-
return void 0;
|
|
286
|
-
}
|
|
287
|
-
const oldValue = this.tail.value;
|
|
288
|
-
if (this.tail.prev) {
|
|
289
|
-
this.tail = this.tail.prev;
|
|
290
|
-
this.tail.next = void 0;
|
|
291
|
-
} else {
|
|
292
|
-
this.head = this.tail = void 0;
|
|
293
|
-
}
|
|
294
|
-
this.nodesMap.delete(oldValue);
|
|
295
|
-
return oldValue;
|
|
296
|
-
}
|
|
297
|
-
get size() {
|
|
298
|
-
return this.nodesMap.size;
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
|
|
302
305
|
// src/memory.ts
|
|
303
306
|
var defaultStoreHashSize = 16;
|
|
304
307
|
var maximumMapSize = 16777216;
|
|
@@ -307,7 +310,10 @@ var CacheableMemory = class extends Hookified {
|
|
|
307
310
|
_storeHashSize = defaultStoreHashSize;
|
|
308
311
|
_storeHashAlgorithm = "djb2Hash" /* djb2Hash */;
|
|
309
312
|
// Default is djb2Hash
|
|
310
|
-
_store = Array.from(
|
|
313
|
+
_store = Array.from(
|
|
314
|
+
{ length: this._storeHashSize },
|
|
315
|
+
() => /* @__PURE__ */ new Map()
|
|
316
|
+
);
|
|
311
317
|
_ttl;
|
|
312
318
|
// Turned off by default
|
|
313
319
|
_useClone = true;
|
|
@@ -335,7 +341,12 @@ var CacheableMemory = class extends Hookified {
|
|
|
335
341
|
}
|
|
336
342
|
if (options?.lruSize) {
|
|
337
343
|
if (options.lruSize > maximumMapSize) {
|
|
338
|
-
this.emit(
|
|
344
|
+
this.emit(
|
|
345
|
+
"error",
|
|
346
|
+
new Error(
|
|
347
|
+
`LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
|
|
348
|
+
)
|
|
349
|
+
);
|
|
339
350
|
} else {
|
|
340
351
|
this._lruSize = options.lruSize;
|
|
341
352
|
}
|
|
@@ -346,7 +357,10 @@ var CacheableMemory = class extends Hookified {
|
|
|
346
357
|
if (options?.storeHashAlgorithm) {
|
|
347
358
|
this._storeHashAlgorithm = options.storeHashAlgorithm;
|
|
348
359
|
}
|
|
349
|
-
this._store = Array.from(
|
|
360
|
+
this._store = Array.from(
|
|
361
|
+
{ length: this._storeHashSize },
|
|
362
|
+
() => /* @__PURE__ */ new Map()
|
|
363
|
+
);
|
|
350
364
|
this.startIntervalCheck();
|
|
351
365
|
}
|
|
352
366
|
/**
|
|
@@ -390,7 +404,12 @@ var CacheableMemory = class extends Hookified {
|
|
|
390
404
|
*/
|
|
391
405
|
set lruSize(value) {
|
|
392
406
|
if (value > maximumMapSize) {
|
|
393
|
-
this.emit(
|
|
407
|
+
this.emit(
|
|
408
|
+
"error",
|
|
409
|
+
new Error(
|
|
410
|
+
`LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
|
|
411
|
+
)
|
|
412
|
+
);
|
|
394
413
|
return;
|
|
395
414
|
}
|
|
396
415
|
this._lruSize = value;
|
|
@@ -441,7 +460,10 @@ var CacheableMemory = class extends Hookified {
|
|
|
441
460
|
return;
|
|
442
461
|
}
|
|
443
462
|
this._storeHashSize = value;
|
|
444
|
-
this._store = Array.from(
|
|
463
|
+
this._store = Array.from(
|
|
464
|
+
{ length: this._storeHashSize },
|
|
465
|
+
() => /* @__PURE__ */ new Map()
|
|
466
|
+
);
|
|
445
467
|
}
|
|
446
468
|
/**
|
|
447
469
|
* Gets the store hash algorithm
|
|
@@ -462,7 +484,7 @@ var CacheableMemory = class extends Hookified {
|
|
|
462
484
|
* @returns {IterableIterator<string>} - The keys
|
|
463
485
|
*/
|
|
464
486
|
get keys() {
|
|
465
|
-
const keys =
|
|
487
|
+
const keys = [];
|
|
466
488
|
for (const store of this._store) {
|
|
467
489
|
for (const key of store.keys()) {
|
|
468
490
|
const item = store.get(key);
|
|
@@ -480,7 +502,7 @@ var CacheableMemory = class extends Hookified {
|
|
|
480
502
|
* @returns {IterableIterator<CacheableStoreItem>} - The items
|
|
481
503
|
*/
|
|
482
504
|
get items() {
|
|
483
|
-
const items =
|
|
505
|
+
const items = [];
|
|
484
506
|
for (const store of this._store) {
|
|
485
507
|
for (const item of store.values()) {
|
|
486
508
|
if (this.hasExpired(item)) {
|
|
@@ -526,7 +548,7 @@ var CacheableMemory = class extends Hookified {
|
|
|
526
548
|
* @returns {T[]} - The values of the keys
|
|
527
549
|
*/
|
|
528
550
|
getMany(keys) {
|
|
529
|
-
const result =
|
|
551
|
+
const result = [];
|
|
530
552
|
for (const key of keys) {
|
|
531
553
|
result.push(this.get(key));
|
|
532
554
|
}
|
|
@@ -556,7 +578,7 @@ var CacheableMemory = class extends Hookified {
|
|
|
556
578
|
* @returns {CacheableStoreItem[]} - The raw values of the keys
|
|
557
579
|
*/
|
|
558
580
|
getManyRaw(keys) {
|
|
559
|
-
const result =
|
|
581
|
+
const result = [];
|
|
560
582
|
for (const key of keys) {
|
|
561
583
|
result.push(this.getRaw(key));
|
|
562
584
|
}
|
|
@@ -607,10 +629,7 @@ var CacheableMemory = class extends Hookified {
|
|
|
607
629
|
}
|
|
608
630
|
}
|
|
609
631
|
const item = { key, value, expires };
|
|
610
|
-
store.set(
|
|
611
|
-
key,
|
|
612
|
-
item
|
|
613
|
-
);
|
|
632
|
+
store.set(key, item);
|
|
614
633
|
}
|
|
615
634
|
/**
|
|
616
635
|
* Sets the values of the keys
|
|
@@ -637,7 +656,7 @@ var CacheableMemory = class extends Hookified {
|
|
|
637
656
|
* @returns {boolean[]} - If true, the key exists. If false, the key does not exist.
|
|
638
657
|
*/
|
|
639
658
|
hasMany(keys) {
|
|
640
|
-
const result =
|
|
659
|
+
const result = [];
|
|
641
660
|
for (const key of keys) {
|
|
642
661
|
const item = this.get(key);
|
|
643
662
|
result.push(Boolean(item));
|
|
@@ -663,7 +682,7 @@ var CacheableMemory = class extends Hookified {
|
|
|
663
682
|
* @returns {T[]} - The values of the keys
|
|
664
683
|
*/
|
|
665
684
|
takeMany(keys) {
|
|
666
|
-
const result =
|
|
685
|
+
const result = [];
|
|
667
686
|
for (const key of keys) {
|
|
668
687
|
result.push(this.take(key));
|
|
669
688
|
}
|
|
@@ -693,7 +712,10 @@ var CacheableMemory = class extends Hookified {
|
|
|
693
712
|
* @returns {void}
|
|
694
713
|
*/
|
|
695
714
|
clear() {
|
|
696
|
-
this._store = Array.from(
|
|
715
|
+
this._store = Array.from(
|
|
716
|
+
{ length: this._storeHashSize },
|
|
717
|
+
() => /* @__PURE__ */ new Map()
|
|
718
|
+
);
|
|
697
719
|
this._lru = new DoublyLinkedList();
|
|
698
720
|
}
|
|
699
721
|
/**
|
|
@@ -1065,28 +1087,24 @@ var CacheableStats = class {
|
|
|
1065
1087
|
}
|
|
1066
1088
|
this._clears++;
|
|
1067
1089
|
}
|
|
1068
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1069
1090
|
incrementVSize(value) {
|
|
1070
1091
|
if (!this._enabled) {
|
|
1071
1092
|
return;
|
|
1072
1093
|
}
|
|
1073
1094
|
this._vsize += this.roughSizeOfObject(value);
|
|
1074
1095
|
}
|
|
1075
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1076
1096
|
decreaseVSize(value) {
|
|
1077
1097
|
if (!this._enabled) {
|
|
1078
1098
|
return;
|
|
1079
1099
|
}
|
|
1080
1100
|
this._vsize -= this.roughSizeOfObject(value);
|
|
1081
1101
|
}
|
|
1082
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1083
1102
|
incrementKSize(key) {
|
|
1084
1103
|
if (!this._enabled) {
|
|
1085
1104
|
return;
|
|
1086
1105
|
}
|
|
1087
1106
|
this._ksize += this.roughSizeOfString(key);
|
|
1088
1107
|
}
|
|
1089
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1090
1108
|
decreaseKSize(key) {
|
|
1091
1109
|
if (!this._enabled) {
|
|
1092
1110
|
return;
|
|
@@ -1184,10 +1202,7 @@ function calculateTtlFromExpiration(ttl, expires) {
|
|
|
1184
1202
|
}
|
|
1185
1203
|
|
|
1186
1204
|
// src/index.ts
|
|
1187
|
-
import {
|
|
1188
|
-
KeyvHooks,
|
|
1189
|
-
Keyv as Keyv3
|
|
1190
|
-
} from "keyv";
|
|
1205
|
+
import { Keyv as Keyv3, KeyvHooks } from "keyv";
|
|
1191
1206
|
var CacheableHooks = /* @__PURE__ */ ((CacheableHooks2) => {
|
|
1192
1207
|
CacheableHooks2["BEFORE_SET"] = "BEFORE_SET";
|
|
1193
1208
|
CacheableHooks2["AFTER_SET"] = "AFTER_SET";
|
|
@@ -1408,11 +1423,26 @@ var Cacheable = class extends Hookified2 {
|
|
|
1408
1423
|
this.emit("error" /* ERROR */, error);
|
|
1409
1424
|
});
|
|
1410
1425
|
}
|
|
1426
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
1411
1427
|
isKeyvInstance(keyv) {
|
|
1412
1428
|
if (keyv instanceof Keyv2) {
|
|
1413
1429
|
return true;
|
|
1414
1430
|
}
|
|
1415
|
-
const keyvMethods = [
|
|
1431
|
+
const keyvMethods = [
|
|
1432
|
+
"generateIterator",
|
|
1433
|
+
"get",
|
|
1434
|
+
"getMany",
|
|
1435
|
+
"set",
|
|
1436
|
+
"setMany",
|
|
1437
|
+
"delete",
|
|
1438
|
+
"deleteMany",
|
|
1439
|
+
"has",
|
|
1440
|
+
"hasMany",
|
|
1441
|
+
"clear",
|
|
1442
|
+
"disconnect",
|
|
1443
|
+
"serialize",
|
|
1444
|
+
"deserialize"
|
|
1445
|
+
];
|
|
1416
1446
|
return keyvMethods.every((method) => typeof keyv[method] === "function");
|
|
1417
1447
|
}
|
|
1418
1448
|
getNameSpace() {
|
|
@@ -1436,7 +1466,10 @@ var Cacheable = class extends Hookified2 {
|
|
|
1436
1466
|
const expires = secondaryResult.expires ?? void 0;
|
|
1437
1467
|
ttl = calculateTtlFromExpiration(cascadeTtl, expires);
|
|
1438
1468
|
const setItem = { key, value: result.value, ttl };
|
|
1439
|
-
await this.hook(
|
|
1469
|
+
await this.hook(
|
|
1470
|
+
"BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */,
|
|
1471
|
+
setItem
|
|
1472
|
+
);
|
|
1440
1473
|
await this._primary.set(setItem.key, setItem.value, setItem.ttl);
|
|
1441
1474
|
}
|
|
1442
1475
|
}
|
|
@@ -1478,7 +1511,10 @@ var Cacheable = class extends Hookified2 {
|
|
|
1478
1511
|
}
|
|
1479
1512
|
const ttl = calculateTtlFromExpiration(cascadeTtl, expires);
|
|
1480
1513
|
const setItem = { key, value: result[i].value, ttl };
|
|
1481
|
-
await this.hook(
|
|
1514
|
+
await this.hook(
|
|
1515
|
+
"BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */,
|
|
1516
|
+
setItem
|
|
1517
|
+
);
|
|
1482
1518
|
await this._primary.set(setItem.key, setItem.value, setItem.ttl);
|
|
1483
1519
|
}
|
|
1484
1520
|
}
|
|
@@ -1620,7 +1656,7 @@ var Cacheable = class extends Hookified2 {
|
|
|
1620
1656
|
}
|
|
1621
1657
|
if (missingKeys.length > 0 && this._secondary) {
|
|
1622
1658
|
const secondary = await this.hasManyKeyv(this._secondary, keys);
|
|
1623
|
-
for (const [i,
|
|
1659
|
+
for (const [i, _key] of keys.entries()) {
|
|
1624
1660
|
if (!result[i] && secondary[i]) {
|
|
1625
1661
|
result[i] = secondary[i];
|
|
1626
1662
|
}
|
|
@@ -1718,6 +1754,7 @@ var Cacheable = class extends Hookified2 {
|
|
|
1718
1754
|
* @param {WrapOptions} [options] The options for the wrap function
|
|
1719
1755
|
* @returns {Function} The wrapped function
|
|
1720
1756
|
*/
|
|
1757
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
1721
1758
|
wrap(function_, options) {
|
|
1722
1759
|
const wrapOptions = {
|
|
1723
1760
|
ttl: options?.ttl ?? this._ttl,
|
|
@@ -1753,6 +1790,7 @@ var Cacheable = class extends Hookified2 {
|
|
|
1753
1790
|
* @param {string} algorithm the hash algorithm to use. The default is 'sha256'
|
|
1754
1791
|
* @returns {string} the hash of the object
|
|
1755
1792
|
*/
|
|
1793
|
+
// biome-ignore lint/suspicious/noExplicitAny: type format
|
|
1756
1794
|
hash(object, algorithm = "sha256") {
|
|
1757
1795
|
return hash(object, algorithm);
|
|
1758
1796
|
}
|
|
@@ -1764,7 +1802,7 @@ var Cacheable = class extends Hookified2 {
|
|
|
1764
1802
|
return result;
|
|
1765
1803
|
}
|
|
1766
1804
|
async getManySecondaryRawResults(keys) {
|
|
1767
|
-
let result =
|
|
1805
|
+
let result = [];
|
|
1768
1806
|
if (this._secondary) {
|
|
1769
1807
|
result = await this._secondary.get(keys, { raw: true });
|
|
1770
1808
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cacheable",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.4",
|
|
4
4
|
"description": "High Performance Layer 1 / Layer 2 Caching with Keyv Storage",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -21,22 +21,21 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"private": false,
|
|
23
23
|
"devDependencies": {
|
|
24
|
+
"@biomejs/biome": "^2.2.0",
|
|
24
25
|
"@faker-js/faker": "^9.9.0",
|
|
25
|
-
"@keyv/redis": "^5.
|
|
26
|
-
"@keyv/valkey": "^1.0.
|
|
27
|
-
"@types/
|
|
28
|
-
"@types/node": "^24.1.0",
|
|
26
|
+
"@keyv/redis": "^5.1.1",
|
|
27
|
+
"@keyv/valkey": "^1.0.8",
|
|
28
|
+
"@types/node": "^24.3.0",
|
|
29
29
|
"@vitest/coverage-v8": "^3.2.4",
|
|
30
30
|
"lru-cache": "^11.1.0",
|
|
31
31
|
"rimraf": "^6.0.1",
|
|
32
32
|
"tsup": "^8.5.0",
|
|
33
|
-
"typescript": "^5.
|
|
34
|
-
"vitest": "^3.2.4"
|
|
35
|
-
"xo": "^1.2.1"
|
|
33
|
+
"typescript": "^5.9.2",
|
|
34
|
+
"vitest": "^3.2.4"
|
|
36
35
|
},
|
|
37
36
|
"dependencies": {
|
|
38
|
-
"hookified": "^1.
|
|
39
|
-
"keyv": "^5.
|
|
37
|
+
"hookified": "^1.11.0",
|
|
38
|
+
"keyv": "^5.5.0"
|
|
40
39
|
},
|
|
41
40
|
"keywords": [
|
|
42
41
|
"cacheable",
|
|
@@ -71,8 +70,8 @@
|
|
|
71
70
|
"scripts": {
|
|
72
71
|
"build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
|
|
73
72
|
"prepublish": "pnpm build",
|
|
74
|
-
"test": "
|
|
75
|
-
"test:ci": "
|
|
73
|
+
"test": "biome check --write && vitest run --coverage",
|
|
74
|
+
"test:ci": "biome check && vitest run --coverage",
|
|
76
75
|
"clean": "rimraf ./dist ./coverage ./node_modules"
|
|
77
76
|
}
|
|
78
77
|
}
|