cacheable 1.10.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,1908 +1 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- Cacheable: () => Cacheable,
34
- CacheableEvents: () => CacheableEvents,
35
- CacheableHooks: () => CacheableHooks,
36
- CacheableMemory: () => CacheableMemory,
37
- CacheableStats: () => CacheableStats,
38
- Keyv: () => import_keyv3.Keyv,
39
- KeyvCacheableMemory: () => KeyvCacheableMemory,
40
- KeyvHooks: () => import_keyv3.KeyvHooks,
41
- createKeyv: () => createKeyv,
42
- getOrSet: () => getOrSet,
43
- shorthandToMilliseconds: () => shorthandToMilliseconds,
44
- shorthandToTime: () => shorthandToTime,
45
- wrap: () => wrap,
46
- wrapSync: () => wrapSync
47
- });
48
- module.exports = __toCommonJS(index_exports);
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
- };
161
-
162
- // src/shorthand-time.ts
163
- var shorthandToMilliseconds = (shorthand) => {
164
- let milliseconds;
165
- if (shorthand === void 0) {
166
- return void 0;
167
- }
168
- if (typeof shorthand === "number") {
169
- milliseconds = shorthand;
170
- } else if (typeof shorthand === "string") {
171
- shorthand = shorthand.trim();
172
- if (Number.isNaN(Number(shorthand))) {
173
- const match = /^([\d.]+)\s*(ms|s|m|h|hr|d)$/i.exec(shorthand);
174
- if (!match) {
175
- throw new Error(
176
- `Unsupported time format: "${shorthand}". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.`
177
- );
178
- }
179
- const [, value, unit] = match;
180
- const numericValue = Number.parseFloat(value);
181
- const unitLower = unit.toLowerCase();
182
- switch (unitLower) {
183
- case "ms": {
184
- milliseconds = numericValue;
185
- break;
186
- }
187
- case "s": {
188
- milliseconds = numericValue * 1e3;
189
- break;
190
- }
191
- case "m": {
192
- milliseconds = numericValue * 1e3 * 60;
193
- break;
194
- }
195
- case "h": {
196
- milliseconds = numericValue * 1e3 * 60 * 60;
197
- break;
198
- }
199
- case "hr": {
200
- milliseconds = numericValue * 1e3 * 60 * 60;
201
- break;
202
- }
203
- case "d": {
204
- milliseconds = numericValue * 1e3 * 60 * 60 * 24;
205
- break;
206
- }
207
- /* c8 ignore next 3 */
208
- default: {
209
- milliseconds = Number(shorthand);
210
- }
211
- }
212
- } else {
213
- milliseconds = Number(shorthand);
214
- }
215
- } else {
216
- throw new TypeError("Time must be a string or a number.");
217
- }
218
- return milliseconds;
219
- };
220
- var shorthandToTime = (shorthand, fromDate) => {
221
- fromDate ??= /* @__PURE__ */ new Date();
222
- const milliseconds = shorthandToMilliseconds(shorthand);
223
- if (milliseconds === void 0) {
224
- return fromDate.getTime();
225
- }
226
- return fromDate.getTime() + milliseconds;
227
- };
228
-
229
- // src/coalesce-async.ts
230
- var callbacks = /* @__PURE__ */ new Map();
231
- function hasKey(key) {
232
- return callbacks.has(key);
233
- }
234
- function addKey(key) {
235
- callbacks.set(key, []);
236
- }
237
- function removeKey(key) {
238
- callbacks.delete(key);
239
- }
240
- function addCallbackToKey(key, callback) {
241
- const stash = getCallbacksByKey(key);
242
- stash.push(callback);
243
- callbacks.set(key, stash);
244
- }
245
- function getCallbacksByKey(key) {
246
- return callbacks.get(key) ?? [];
247
- }
248
- async function enqueue(key) {
249
- return new Promise((resolve, reject) => {
250
- const callback = { resolve, reject };
251
- addCallbackToKey(key, callback);
252
- });
253
- }
254
- function dequeue(key) {
255
- const stash = getCallbacksByKey(key);
256
- removeKey(key);
257
- return stash;
258
- }
259
- function coalesce(options) {
260
- const { key, error, result } = options;
261
- for (const callback of dequeue(key)) {
262
- if (error) {
263
- callback.reject(error);
264
- } else {
265
- callback.resolve(result);
266
- }
267
- }
268
- }
269
- async function coalesceAsync(key, fnc) {
270
- if (!hasKey(key)) {
271
- addKey(key);
272
- try {
273
- const result = await Promise.resolve(fnc());
274
- coalesce({ key, result });
275
- return result;
276
- } catch (error) {
277
- coalesce({ key, error });
278
- throw error;
279
- }
280
- }
281
- return enqueue(key);
282
- }
283
-
284
- // src/wrap.ts
285
- function wrapSync(function_, options) {
286
- const { ttl, keyPrefix, cache } = options;
287
- return (...arguments_) => {
288
- let cacheKey = createWrapKey(function_, arguments_, keyPrefix);
289
- if (options.createKey) {
290
- cacheKey = options.createKey(function_, arguments_, options);
291
- }
292
- let value = cache.get(cacheKey);
293
- if (value === void 0) {
294
- try {
295
- value = function_(...arguments_);
296
- cache.set(cacheKey, value, ttl);
297
- } catch (error) {
298
- cache.emit("error", error);
299
- if (options.cacheErrors) {
300
- cache.set(cacheKey, error, ttl);
301
- }
302
- }
303
- }
304
- return value;
305
- };
306
- }
307
- async function getOrSet(key, function_, options) {
308
- const keyString = typeof key === "function" ? key(options) : key;
309
- let value = await options.cache.get(keyString);
310
- if (value === void 0) {
311
- const cacheId = options.cacheId ?? "default";
312
- const coalesceKey = `${cacheId}::${keyString}`;
313
- value = await coalesceAsync(coalesceKey, async () => {
314
- try {
315
- const result = await function_();
316
- await options.cache.set(keyString, result, options.ttl);
317
- return result;
318
- } catch (error) {
319
- options.cache.emit("error", error);
320
- if (options.cacheErrors) {
321
- await options.cache.set(keyString, error, options.ttl);
322
- }
323
- if (options.throwErrors) {
324
- throw error;
325
- }
326
- }
327
- });
328
- }
329
- return value;
330
- }
331
- function wrap(function_, options) {
332
- const { keyPrefix, cache } = options;
333
- return async (...arguments_) => {
334
- let cacheKey = createWrapKey(function_, arguments_, keyPrefix);
335
- if (options.createKey) {
336
- cacheKey = options.createKey(function_, arguments_, options);
337
- }
338
- return cache.getOrSet(
339
- cacheKey,
340
- async () => function_(...arguments_),
341
- options
342
- );
343
- };
344
- }
345
- function createWrapKey(function_, arguments_, keyPrefix) {
346
- if (!keyPrefix) {
347
- return `${function_.name}::${hash(arguments_)}`;
348
- }
349
- return `${keyPrefix}::${function_.name}::${hash(arguments_)}`;
350
- }
351
-
352
- // src/memory.ts
353
- var defaultStoreHashSize = 16;
354
- var maximumMapSize = 16777216;
355
- var CacheableMemory = class extends import_hookified.Hookified {
356
- _lru = new DoublyLinkedList();
357
- _storeHashSize = defaultStoreHashSize;
358
- _storeHashAlgorithm = "djb2Hash" /* djb2Hash */;
359
- // Default is djb2Hash
360
- _store = Array.from(
361
- { length: this._storeHashSize },
362
- () => /* @__PURE__ */ new Map()
363
- );
364
- _ttl;
365
- // Turned off by default
366
- _useClone = true;
367
- // Turned on by default
368
- _lruSize = 0;
369
- // Turned off by default
370
- _checkInterval = 0;
371
- // Turned off by default
372
- _interval = 0;
373
- // Turned off by default
374
- /**
375
- * @constructor
376
- * @param {CacheableMemoryOptions} [options] - The options for the CacheableMemory
377
- */
378
- constructor(options) {
379
- super();
380
- if (options?.ttl) {
381
- this.setTtl(options.ttl);
382
- }
383
- if (options?.useClone !== void 0) {
384
- this._useClone = options.useClone;
385
- }
386
- if (options?.storeHashSize && options.storeHashSize > 0) {
387
- this._storeHashSize = options.storeHashSize;
388
- }
389
- if (options?.lruSize) {
390
- if (options.lruSize > maximumMapSize) {
391
- this.emit(
392
- "error",
393
- new Error(
394
- `LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
395
- )
396
- );
397
- } else {
398
- this._lruSize = options.lruSize;
399
- }
400
- }
401
- if (options?.checkInterval) {
402
- this._checkInterval = options.checkInterval;
403
- }
404
- if (options?.storeHashAlgorithm) {
405
- this._storeHashAlgorithm = options.storeHashAlgorithm;
406
- }
407
- this._store = Array.from(
408
- { length: this._storeHashSize },
409
- () => /* @__PURE__ */ new Map()
410
- );
411
- this.startIntervalCheck();
412
- }
413
- /**
414
- * Gets the time-to-live
415
- * @returns {number|string|undefined} - The time-to-live in miliseconds or a human-readable format. If undefined, it will not have a time-to-live.
416
- */
417
- get ttl() {
418
- return this._ttl;
419
- }
420
- /**
421
- * Sets the time-to-live
422
- * @param {number|string|undefined} value - The time-to-live in miliseconds or a human-readable format (example '1s' = 1 second, '1h' = 1 hour). If undefined, it will not have a time-to-live.
423
- */
424
- set ttl(value) {
425
- this.setTtl(value);
426
- }
427
- /**
428
- * Gets whether to use clone
429
- * @returns {boolean} - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
430
- */
431
- get useClone() {
432
- return this._useClone;
433
- }
434
- /**
435
- * Sets whether to use clone
436
- * @param {boolean} value - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
437
- */
438
- set useClone(value) {
439
- this._useClone = value;
440
- }
441
- /**
442
- * Gets the size of the LRU cache
443
- * @returns {number} - The size of the LRU cache. If set to 0, it will not use LRU cache. Default is 0. If you are using LRU then the limit is based on Map() size 17mm.
444
- */
445
- get lruSize() {
446
- return this._lruSize;
447
- }
448
- /**
449
- * Sets the size of the LRU cache
450
- * @param {number} value - The size of the LRU cache. If set to 0, it will not use LRU cache. Default is 0. If you are using LRU then the limit is based on Map() size 17mm.
451
- */
452
- set lruSize(value) {
453
- if (value > maximumMapSize) {
454
- this.emit(
455
- "error",
456
- new Error(
457
- `LRU size cannot be larger than ${maximumMapSize} due to Map limitations.`
458
- )
459
- );
460
- return;
461
- }
462
- this._lruSize = value;
463
- if (this._lruSize === 0) {
464
- this._lru = new DoublyLinkedList();
465
- return;
466
- }
467
- this.lruResize();
468
- }
469
- /**
470
- * Gets the check interval
471
- * @returns {number} - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
472
- */
473
- get checkInterval() {
474
- return this._checkInterval;
475
- }
476
- /**
477
- * Sets the check interval
478
- * @param {number} value - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
479
- */
480
- set checkInterval(value) {
481
- this._checkInterval = value;
482
- }
483
- /**
484
- * Gets the size of the cache
485
- * @returns {number} - The size of the cache
486
- */
487
- get size() {
488
- let size = 0;
489
- for (const store of this._store) {
490
- size += store.size;
491
- }
492
- return size;
493
- }
494
- /**
495
- * Gets the number of hash stores
496
- * @returns {number} - The number of hash stores
497
- */
498
- get storeHashSize() {
499
- return this._storeHashSize;
500
- }
501
- /**
502
- * Sets the number of hash stores. This will recreate the store and all data will be cleared
503
- * @param {number} value - The number of hash stores
504
- */
505
- set storeHashSize(value) {
506
- if (value === this._storeHashSize) {
507
- return;
508
- }
509
- this._storeHashSize = value;
510
- this._store = Array.from(
511
- { length: this._storeHashSize },
512
- () => /* @__PURE__ */ new Map()
513
- );
514
- }
515
- /**
516
- * Gets the store hash algorithm
517
- * @returns {StoreHashAlgorithm | StoreHashAlgorithmFunction} - The store hash algorithm
518
- */
519
- get storeHashAlgorithm() {
520
- return this._storeHashAlgorithm;
521
- }
522
- /**
523
- * Sets the store hash algorithm. This will recreate the store and all data will be cleared
524
- * @param {StoreHashAlgorithm | StoreHashAlgorithmFunction} value - The store hash algorithm
525
- */
526
- set storeHashAlgorithm(value) {
527
- this._storeHashAlgorithm = value;
528
- }
529
- /**
530
- * Gets the keys
531
- * @returns {IterableIterator<string>} - The keys
532
- */
533
- get keys() {
534
- const keys = [];
535
- for (const store of this._store) {
536
- for (const key of store.keys()) {
537
- const item = store.get(key);
538
- if (item && this.hasExpired(item)) {
539
- store.delete(key);
540
- continue;
541
- }
542
- keys.push(key);
543
- }
544
- }
545
- return keys.values();
546
- }
547
- /**
548
- * Gets the items
549
- * @returns {IterableIterator<CacheableStoreItem>} - The items
550
- */
551
- get items() {
552
- const items = [];
553
- for (const store of this._store) {
554
- for (const item of store.values()) {
555
- if (this.hasExpired(item)) {
556
- store.delete(item.key);
557
- continue;
558
- }
559
- items.push(item);
560
- }
561
- }
562
- return items.values();
563
- }
564
- /**
565
- * Gets the store
566
- * @returns {Array<Map<string, CacheableStoreItem>>} - The store
567
- */
568
- get store() {
569
- return this._store;
570
- }
571
- /**
572
- * Gets the value of the key
573
- * @param {string} key - The key to get the value
574
- * @returns {T | undefined} - The value of the key
575
- */
576
- get(key) {
577
- const store = this.getStore(key);
578
- const item = store.get(key);
579
- if (!item) {
580
- return void 0;
581
- }
582
- if (item.expires && Date.now() > item.expires) {
583
- store.delete(key);
584
- return void 0;
585
- }
586
- this.lruMoveToFront(key);
587
- if (!this._useClone) {
588
- return item.value;
589
- }
590
- return this.clone(item.value);
591
- }
592
- /**
593
- * Gets the values of the keys
594
- * @param {string[]} keys - The keys to get the values
595
- * @returns {T[]} - The values of the keys
596
- */
597
- getMany(keys) {
598
- const result = [];
599
- for (const key of keys) {
600
- result.push(this.get(key));
601
- }
602
- return result;
603
- }
604
- /**
605
- * Gets the raw value of the key
606
- * @param {string} key - The key to get the value
607
- * @returns {CacheableStoreItem | undefined} - The raw value of the key
608
- */
609
- getRaw(key) {
610
- const store = this.getStore(key);
611
- const item = store.get(key);
612
- if (!item) {
613
- return void 0;
614
- }
615
- if (item.expires && item.expires && Date.now() > item.expires) {
616
- store.delete(key);
617
- return void 0;
618
- }
619
- this.lruMoveToFront(key);
620
- return item;
621
- }
622
- /**
623
- * Gets the raw values of the keys
624
- * @param {string[]} keys - The keys to get the values
625
- * @returns {CacheableStoreItem[]} - The raw values of the keys
626
- */
627
- getManyRaw(keys) {
628
- const result = [];
629
- for (const key of keys) {
630
- result.push(this.getRaw(key));
631
- }
632
- return result;
633
- }
634
- /**
635
- * Sets the value of the key
636
- * @param {string} key - The key to set the value
637
- * @param {any} value - The value to set
638
- * @param {number|string|SetOptions} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable.
639
- * If you want to set expire directly you can do that by setting the expire property in the SetOptions.
640
- * If you set undefined, it will use the default time-to-live. If both are undefined then it will not have a time-to-live.
641
- * @returns {void}
642
- */
643
- set(key, value, ttl) {
644
- const store = this.getStore(key);
645
- let expires;
646
- if (ttl !== void 0 || this._ttl !== void 0) {
647
- if (typeof ttl === "object") {
648
- if (ttl.expire) {
649
- expires = typeof ttl.expire === "number" ? ttl.expire : ttl.expire.getTime();
650
- }
651
- if (ttl.ttl) {
652
- const finalTtl = shorthandToTime(ttl.ttl);
653
- if (finalTtl !== void 0) {
654
- expires = finalTtl;
655
- }
656
- }
657
- } else {
658
- const finalTtl = shorthandToTime(ttl ?? this._ttl);
659
- if (finalTtl !== void 0) {
660
- expires = finalTtl;
661
- }
662
- }
663
- }
664
- if (this._lruSize > 0) {
665
- if (store.has(key)) {
666
- this.lruMoveToFront(key);
667
- } else {
668
- this.lruAddToFront(key);
669
- if (this._lru.size > this._lruSize) {
670
- const oldestKey = this._lru.getOldest();
671
- if (oldestKey) {
672
- this._lru.removeOldest();
673
- this.delete(oldestKey);
674
- }
675
- }
676
- }
677
- }
678
- const item = { key, value, expires };
679
- store.set(key, item);
680
- }
681
- /**
682
- * Sets the values of the keys
683
- * @param {CacheableItem[]} items - The items to set
684
- * @returns {void}
685
- */
686
- setMany(items) {
687
- for (const item of items) {
688
- this.set(item.key, item.value, item.ttl);
689
- }
690
- }
691
- /**
692
- * Checks if the key exists
693
- * @param {string} key - The key to check
694
- * @returns {boolean} - If true, the key exists. If false, the key does not exist.
695
- */
696
- has(key) {
697
- const item = this.get(key);
698
- return Boolean(item);
699
- }
700
- /**
701
- * @function hasMany
702
- * @param {string[]} keys - The keys to check
703
- * @returns {boolean[]} - If true, the key exists. If false, the key does not exist.
704
- */
705
- hasMany(keys) {
706
- const result = [];
707
- for (const key of keys) {
708
- const item = this.get(key);
709
- result.push(Boolean(item));
710
- }
711
- return result;
712
- }
713
- /**
714
- * Take will get the key and delete the entry from cache
715
- * @param {string} key - The key to take
716
- * @returns {T | undefined} - The value of the key
717
- */
718
- take(key) {
719
- const item = this.get(key);
720
- if (!item) {
721
- return void 0;
722
- }
723
- this.delete(key);
724
- return item;
725
- }
726
- /**
727
- * TakeMany will get the keys and delete the entries from cache
728
- * @param {string[]} keys - The keys to take
729
- * @returns {T[]} - The values of the keys
730
- */
731
- takeMany(keys) {
732
- const result = [];
733
- for (const key of keys) {
734
- result.push(this.take(key));
735
- }
736
- return result;
737
- }
738
- /**
739
- * Delete the key
740
- * @param {string} key - The key to delete
741
- * @returns {void}
742
- */
743
- delete(key) {
744
- const store = this.getStore(key);
745
- store.delete(key);
746
- }
747
- /**
748
- * Delete the keys
749
- * @param {string[]} keys - The keys to delete
750
- * @returns {void}
751
- */
752
- deleteMany(keys) {
753
- for (const key of keys) {
754
- this.delete(key);
755
- }
756
- }
757
- /**
758
- * Clear the cache
759
- * @returns {void}
760
- */
761
- clear() {
762
- this._store = Array.from(
763
- { length: this._storeHashSize },
764
- () => /* @__PURE__ */ new Map()
765
- );
766
- this._lru = new DoublyLinkedList();
767
- }
768
- /**
769
- * Get the store based on the key (internal use)
770
- * @param {string} key - The key to get the store
771
- * @returns {CacheableHashStore} - The store
772
- */
773
- getStore(key) {
774
- const hash2 = this.getKeyStoreHash(key);
775
- this._store[hash2] ||= /* @__PURE__ */ new Map();
776
- return this._store[hash2];
777
- }
778
- /**
779
- * Hash the key for which store to go to (internal use)
780
- * @param {string} key - The key to hash
781
- * Available algorithms are: SHA256, SHA1, MD5, and djb2Hash.
782
- * @returns {number} - The hashed key as a number
783
- */
784
- getKeyStoreHash(key) {
785
- if (this._store.length === 1) {
786
- return 0;
787
- }
788
- if (this._storeHashAlgorithm === "djb2Hash" /* djb2Hash */) {
789
- return djb2Hash(key, 0, this._storeHashSize);
790
- }
791
- if (typeof this._storeHashAlgorithm === "function") {
792
- return this._storeHashAlgorithm(key, this._storeHashSize);
793
- }
794
- return hashToNumber(key, 0, this._storeHashSize, this._storeHashAlgorithm);
795
- }
796
- /**
797
- * Clone the value. This is for internal use
798
- * @param {any} value - The value to clone
799
- * @returns {any} - The cloned value
800
- */
801
- clone(value) {
802
- if (this.isPrimitive(value)) {
803
- return value;
804
- }
805
- return structuredClone(value);
806
- }
807
- /**
808
- * Add to the front of the LRU cache. This is for internal use
809
- * @param {string} key - The key to add to the front
810
- * @returns {void}
811
- */
812
- lruAddToFront(key) {
813
- if (this._lruSize === 0) {
814
- return;
815
- }
816
- this._lru.addToFront(key);
817
- }
818
- /**
819
- * Move to the front of the LRU cache. This is for internal use
820
- * @param {string} key - The key to move to the front
821
- * @returns {void}
822
- */
823
- lruMoveToFront(key) {
824
- if (this._lruSize === 0) {
825
- return;
826
- }
827
- this._lru.moveToFront(key);
828
- }
829
- /**
830
- * Resize the LRU cache. This is for internal use.
831
- * @returns {void}
832
- */
833
- lruResize() {
834
- while (this._lru.size > this._lruSize) {
835
- const oldestKey = this._lru.getOldest();
836
- if (oldestKey) {
837
- this._lru.removeOldest();
838
- this.delete(oldestKey);
839
- }
840
- }
841
- }
842
- /**
843
- * Check for expiration. This is for internal use
844
- * @returns {void}
845
- */
846
- checkExpiration() {
847
- for (const store of this._store) {
848
- for (const item of store.values()) {
849
- if (item.expires && Date.now() > item.expires) {
850
- store.delete(item.key);
851
- }
852
- }
853
- }
854
- }
855
- /**
856
- * Start the interval check. This is for internal use
857
- * @returns {void}
858
- */
859
- startIntervalCheck() {
860
- if (this._checkInterval > 0) {
861
- if (this._interval) {
862
- clearInterval(this._interval);
863
- }
864
- this._interval = setInterval(() => {
865
- this.checkExpiration();
866
- }, this._checkInterval).unref();
867
- }
868
- }
869
- /**
870
- * Stop the interval check. This is for internal use
871
- * @returns {void}
872
- */
873
- stopIntervalCheck() {
874
- if (this._interval) {
875
- clearInterval(this._interval);
876
- }
877
- this._interval = 0;
878
- this._checkInterval = 0;
879
- }
880
- /**
881
- * Wrap the function for caching
882
- * @param {Function} function_ - The function to wrap
883
- * @param {Object} [options] - The options to wrap
884
- * @returns {Function} - The wrapped function
885
- */
886
- wrap(function_, options) {
887
- const wrapOptions = {
888
- ttl: options?.ttl ?? this._ttl,
889
- keyPrefix: options?.keyPrefix,
890
- cache: this
891
- };
892
- return wrapSync(function_, wrapOptions);
893
- }
894
- isPrimitive(value) {
895
- const result = false;
896
- if (value === null || value === void 0) {
897
- return true;
898
- }
899
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
900
- return true;
901
- }
902
- return result;
903
- }
904
- setTtl(ttl) {
905
- if (typeof ttl === "string" || ttl === void 0) {
906
- this._ttl = ttl;
907
- } else if (ttl > 0) {
908
- this._ttl = ttl;
909
- } else {
910
- this._ttl = void 0;
911
- }
912
- }
913
- hasExpired(item) {
914
- if (item.expires && Date.now() > item.expires) {
915
- return true;
916
- }
917
- return false;
918
- }
919
- };
920
-
921
- // src/keyv-memory.ts
922
- var KeyvCacheableMemory = class {
923
- opts = {
924
- ttl: 0,
925
- useClone: true,
926
- lruSize: 0,
927
- checkInterval: 0
928
- };
929
- _defaultCache = new CacheableMemory();
930
- _nCache = /* @__PURE__ */ new Map();
931
- _namespace;
932
- constructor(options) {
933
- if (options) {
934
- this.opts = options;
935
- this._defaultCache = new CacheableMemory(options);
936
- if (options.namespace) {
937
- this._namespace = options.namespace;
938
- this._nCache.set(this._namespace, new CacheableMemory(options));
939
- }
940
- }
941
- }
942
- get namespace() {
943
- return this._namespace;
944
- }
945
- set namespace(value) {
946
- this._namespace = value;
947
- }
948
- get store() {
949
- return this.getStore(this._namespace);
950
- }
951
- async get(key) {
952
- const result = this.getStore(this._namespace).get(key);
953
- if (result) {
954
- return result;
955
- }
956
- return void 0;
957
- }
958
- async getMany(keys) {
959
- const result = this.getStore(this._namespace).getMany(keys);
960
- return result;
961
- }
962
- async set(key, value, ttl) {
963
- this.getStore(this._namespace).set(key, value, ttl);
964
- }
965
- async setMany(values) {
966
- this.getStore(this._namespace).setMany(values);
967
- }
968
- async delete(key) {
969
- this.getStore(this._namespace).delete(key);
970
- return true;
971
- }
972
- async deleteMany(key) {
973
- this.getStore(this._namespace).deleteMany(key);
974
- return true;
975
- }
976
- async clear() {
977
- this.getStore(this._namespace).clear();
978
- }
979
- async has(key) {
980
- return this.getStore(this._namespace).has(key);
981
- }
982
- on(event, listener) {
983
- this.getStore(this._namespace).on(event, listener);
984
- return this;
985
- }
986
- getStore(namespace) {
987
- if (!namespace) {
988
- return this._defaultCache;
989
- }
990
- if (!this._nCache.has(namespace)) {
991
- this._nCache.set(namespace, new CacheableMemory(this.opts));
992
- }
993
- return this._nCache.get(namespace);
994
- }
995
- };
996
- function createKeyv(options) {
997
- const store = new KeyvCacheableMemory(options);
998
- const namespace = options?.namespace;
999
- let ttl;
1000
- if (options?.ttl && Number.isInteger(options.ttl)) {
1001
- ttl = options?.ttl;
1002
- }
1003
- const keyv = new import_keyv.Keyv({ store, namespace, ttl });
1004
- keyv.serialize = void 0;
1005
- keyv.deserialize = void 0;
1006
- return keyv;
1007
- }
1008
-
1009
- // src/stats.ts
1010
- var CacheableStats = class {
1011
- _hits = 0;
1012
- _misses = 0;
1013
- _gets = 0;
1014
- _sets = 0;
1015
- _deletes = 0;
1016
- _clears = 0;
1017
- _vsize = 0;
1018
- _ksize = 0;
1019
- _count = 0;
1020
- _enabled = false;
1021
- constructor(options) {
1022
- if (options?.enabled) {
1023
- this._enabled = options.enabled;
1024
- }
1025
- }
1026
- /**
1027
- * @returns {boolean} - Whether the stats are enabled
1028
- */
1029
- get enabled() {
1030
- return this._enabled;
1031
- }
1032
- /**
1033
- * @param {boolean} enabled - Whether to enable the stats
1034
- */
1035
- set enabled(enabled) {
1036
- this._enabled = enabled;
1037
- }
1038
- /**
1039
- * @returns {number} - The number of hits
1040
- * @readonly
1041
- */
1042
- get hits() {
1043
- return this._hits;
1044
- }
1045
- /**
1046
- * @returns {number} - The number of misses
1047
- * @readonly
1048
- */
1049
- get misses() {
1050
- return this._misses;
1051
- }
1052
- /**
1053
- * @returns {number} - The number of gets
1054
- * @readonly
1055
- */
1056
- get gets() {
1057
- return this._gets;
1058
- }
1059
- /**
1060
- * @returns {number} - The number of sets
1061
- * @readonly
1062
- */
1063
- get sets() {
1064
- return this._sets;
1065
- }
1066
- /**
1067
- * @returns {number} - The number of deletes
1068
- * @readonly
1069
- */
1070
- get deletes() {
1071
- return this._deletes;
1072
- }
1073
- /**
1074
- * @returns {number} - The number of clears
1075
- * @readonly
1076
- */
1077
- get clears() {
1078
- return this._clears;
1079
- }
1080
- /**
1081
- * @returns {number} - The vsize (value size) of the cache instance
1082
- * @readonly
1083
- */
1084
- get vsize() {
1085
- return this._vsize;
1086
- }
1087
- /**
1088
- * @returns {number} - The ksize (key size) of the cache instance
1089
- * @readonly
1090
- */
1091
- get ksize() {
1092
- return this._ksize;
1093
- }
1094
- /**
1095
- * @returns {number} - The count of the cache instance
1096
- * @readonly
1097
- */
1098
- get count() {
1099
- return this._count;
1100
- }
1101
- incrementHits() {
1102
- if (!this._enabled) {
1103
- return;
1104
- }
1105
- this._hits++;
1106
- }
1107
- incrementMisses() {
1108
- if (!this._enabled) {
1109
- return;
1110
- }
1111
- this._misses++;
1112
- }
1113
- incrementGets() {
1114
- if (!this._enabled) {
1115
- return;
1116
- }
1117
- this._gets++;
1118
- }
1119
- incrementSets() {
1120
- if (!this._enabled) {
1121
- return;
1122
- }
1123
- this._sets++;
1124
- }
1125
- incrementDeletes() {
1126
- if (!this._enabled) {
1127
- return;
1128
- }
1129
- this._deletes++;
1130
- }
1131
- incrementClears() {
1132
- if (!this._enabled) {
1133
- return;
1134
- }
1135
- this._clears++;
1136
- }
1137
- incrementVSize(value) {
1138
- if (!this._enabled) {
1139
- return;
1140
- }
1141
- this._vsize += this.roughSizeOfObject(value);
1142
- }
1143
- decreaseVSize(value) {
1144
- if (!this._enabled) {
1145
- return;
1146
- }
1147
- this._vsize -= this.roughSizeOfObject(value);
1148
- }
1149
- incrementKSize(key) {
1150
- if (!this._enabled) {
1151
- return;
1152
- }
1153
- this._ksize += this.roughSizeOfString(key);
1154
- }
1155
- decreaseKSize(key) {
1156
- if (!this._enabled) {
1157
- return;
1158
- }
1159
- this._ksize -= this.roughSizeOfString(key);
1160
- }
1161
- incrementCount() {
1162
- if (!this._enabled) {
1163
- return;
1164
- }
1165
- this._count++;
1166
- }
1167
- decreaseCount() {
1168
- if (!this._enabled) {
1169
- return;
1170
- }
1171
- this._count--;
1172
- }
1173
- setCount(count) {
1174
- if (!this._enabled) {
1175
- return;
1176
- }
1177
- this._count = count;
1178
- }
1179
- roughSizeOfString(value) {
1180
- return value.length * 2;
1181
- }
1182
- roughSizeOfObject(object) {
1183
- const objectList = [];
1184
- const stack = [object];
1185
- let bytes = 0;
1186
- while (stack.length > 0) {
1187
- const value = stack.pop();
1188
- if (typeof value === "boolean") {
1189
- bytes += 4;
1190
- } else if (typeof value === "string") {
1191
- bytes += value.length * 2;
1192
- } else if (typeof value === "number") {
1193
- bytes += 8;
1194
- } else if (typeof value === "object" && value !== null && !objectList.includes(value)) {
1195
- objectList.push(value);
1196
- for (const key in value) {
1197
- bytes += key.length * 2;
1198
- stack.push(value[key]);
1199
- }
1200
- }
1201
- }
1202
- return bytes;
1203
- }
1204
- reset() {
1205
- this._hits = 0;
1206
- this._misses = 0;
1207
- this._gets = 0;
1208
- this._sets = 0;
1209
- this._deletes = 0;
1210
- this._clears = 0;
1211
- this._vsize = 0;
1212
- this._ksize = 0;
1213
- this._count = 0;
1214
- }
1215
- resetStoreValues() {
1216
- this._vsize = 0;
1217
- this._ksize = 0;
1218
- this._count = 0;
1219
- }
1220
- };
1221
-
1222
- // src/ttl.ts
1223
- function getTtlFromExpires(expires) {
1224
- if (expires === void 0 || expires === null) {
1225
- return void 0;
1226
- }
1227
- const now = Date.now();
1228
- if (expires < now) {
1229
- return void 0;
1230
- }
1231
- return expires - now;
1232
- }
1233
- function getCascadingTtl(cacheableTtl, primaryTtl, secondaryTtl) {
1234
- return secondaryTtl ?? primaryTtl ?? shorthandToMilliseconds(cacheableTtl);
1235
- }
1236
- function calculateTtlFromExpiration(ttl, expires) {
1237
- const ttlFromExpires = getTtlFromExpires(expires);
1238
- const expiresFromTtl = ttl ? Date.now() + ttl : void 0;
1239
- if (ttlFromExpires === void 0) {
1240
- return ttl;
1241
- }
1242
- if (expiresFromTtl === void 0) {
1243
- return ttlFromExpires;
1244
- }
1245
- if (expires > expiresFromTtl) {
1246
- return ttl;
1247
- }
1248
- return ttlFromExpires;
1249
- }
1250
-
1251
- // src/index.ts
1252
- var import_keyv3 = require("keyv");
1253
- var CacheableHooks = /* @__PURE__ */ ((CacheableHooks2) => {
1254
- CacheableHooks2["BEFORE_SET"] = "BEFORE_SET";
1255
- CacheableHooks2["AFTER_SET"] = "AFTER_SET";
1256
- CacheableHooks2["BEFORE_SET_MANY"] = "BEFORE_SET_MANY";
1257
- CacheableHooks2["AFTER_SET_MANY"] = "AFTER_SET_MANY";
1258
- CacheableHooks2["BEFORE_GET"] = "BEFORE_GET";
1259
- CacheableHooks2["AFTER_GET"] = "AFTER_GET";
1260
- CacheableHooks2["BEFORE_GET_MANY"] = "BEFORE_GET_MANY";
1261
- CacheableHooks2["AFTER_GET_MANY"] = "AFTER_GET_MANY";
1262
- CacheableHooks2["BEFORE_SECONDARY_SETS_PRIMARY"] = "BEFORE_SECONDARY_SETS_PRIMARY";
1263
- return CacheableHooks2;
1264
- })(CacheableHooks || {});
1265
- var CacheableEvents = /* @__PURE__ */ ((CacheableEvents2) => {
1266
- CacheableEvents2["ERROR"] = "error";
1267
- return CacheableEvents2;
1268
- })(CacheableEvents || {});
1269
- var Cacheable = class extends import_hookified2.Hookified {
1270
- _primary = createKeyv();
1271
- _secondary;
1272
- _nonBlocking = false;
1273
- _ttl;
1274
- _stats = new CacheableStats({ enabled: false });
1275
- _namespace;
1276
- _cacheId = Math.random().toString(36).slice(2);
1277
- /**
1278
- * Creates a new cacheable instance
1279
- * @param {CacheableOptions} [options] The options for the cacheable instance
1280
- */
1281
- constructor(options) {
1282
- super();
1283
- if (options?.primary) {
1284
- this.setPrimary(options.primary);
1285
- }
1286
- if (options?.secondary) {
1287
- this.setSecondary(options.secondary);
1288
- }
1289
- if (options?.nonBlocking) {
1290
- this._nonBlocking = options.nonBlocking;
1291
- }
1292
- if (options?.stats) {
1293
- this._stats.enabled = options.stats;
1294
- }
1295
- if (options?.ttl) {
1296
- this.setTtl(options.ttl);
1297
- }
1298
- if (options?.cacheId) {
1299
- this._cacheId = options.cacheId;
1300
- }
1301
- if (options?.namespace) {
1302
- this._namespace = options.namespace;
1303
- this._primary.namespace = this.getNameSpace();
1304
- if (this._secondary) {
1305
- this._secondary.namespace = this.getNameSpace();
1306
- }
1307
- }
1308
- }
1309
- /**
1310
- * The namespace for the cacheable instance
1311
- * @returns {string | (() => string) | undefined} The namespace for the cacheable instance
1312
- */
1313
- get namespace() {
1314
- return this._namespace;
1315
- }
1316
- /**
1317
- * Sets the namespace for the cacheable instance
1318
- * @param {string | (() => string) | undefined} namespace The namespace for the cacheable instance
1319
- * @returns {void}
1320
- */
1321
- set namespace(namespace) {
1322
- this._namespace = namespace;
1323
- this._primary.namespace = this.getNameSpace();
1324
- if (this._secondary) {
1325
- this._secondary.namespace = this.getNameSpace();
1326
- }
1327
- }
1328
- /**
1329
- * The statistics for the cacheable instance
1330
- * @returns {CacheableStats} The statistics for the cacheable instance
1331
- */
1332
- get stats() {
1333
- return this._stats;
1334
- }
1335
- /**
1336
- * The primary store for the cacheable instance
1337
- * @returns {Keyv} The primary store for the cacheable instance
1338
- */
1339
- get primary() {
1340
- return this._primary;
1341
- }
1342
- /**
1343
- * Sets the primary store for the cacheable instance
1344
- * @param {Keyv} primary The primary store for the cacheable instance
1345
- */
1346
- set primary(primary) {
1347
- this._primary = primary;
1348
- }
1349
- /**
1350
- * The secondary store for the cacheable instance
1351
- * @returns {Keyv | undefined} The secondary store for the cacheable instance
1352
- */
1353
- get secondary() {
1354
- return this._secondary;
1355
- }
1356
- /**
1357
- * Sets the secondary store for the cacheable instance. If it is set to undefined then the secondary store is disabled.
1358
- * @param {Keyv | undefined} secondary The secondary store for the cacheable instance
1359
- * @returns {void}
1360
- */
1361
- set secondary(secondary) {
1362
- this._secondary = secondary;
1363
- }
1364
- /**
1365
- * Gets whether the secondary store is non-blocking mode. It is set to false by default.
1366
- * If it is set to true then the secondary store will not block the primary store.
1367
- *
1368
- * [Learn more about non-blocking mode](https://cacheable.org/docs/cacheable/#non-blocking-operations).
1369
- *
1370
- * @returns {boolean} Whether the cacheable instance is non-blocking
1371
- */
1372
- get nonBlocking() {
1373
- return this._nonBlocking;
1374
- }
1375
- /**
1376
- * Sets whether the secondary store is non-blocking mode. It is set to false by default.
1377
- * If it is set to true then the secondary store will not block the primary store.
1378
- *
1379
- * [Learn more about non-blocking mode](https://cacheable.org/docs/cacheable/#non-blocking-operations).
1380
- *
1381
- * @param {boolean} nonBlocking Whether the cacheable instance is non-blocking
1382
- * @returns {void}
1383
- */
1384
- set nonBlocking(nonBlocking) {
1385
- this._nonBlocking = nonBlocking;
1386
- }
1387
- /**
1388
- * The time-to-live for the cacheable instance and will be used as the default value.
1389
- * can be a number in milliseconds or a human-readable format such as `1s` for 1 second or `1h` for 1 hour
1390
- * or undefined if there is no time-to-live.
1391
- *
1392
- * [Learn more about time-to-live](https://cacheable.org/docs/cacheable/#shorthand-for-time-to-live-ttl).
1393
- *
1394
- * @returns {number | string | undefined} The time-to-live for the cacheable instance in milliseconds, human-readable format or undefined
1395
- * @example
1396
- * ```typescript
1397
- * const cacheable = new Cacheable({ ttl: '1h' });
1398
- * console.log(cacheable.ttl); // 1h
1399
- * ```
1400
- */
1401
- get ttl() {
1402
- return this._ttl;
1403
- }
1404
- /**
1405
- * Sets the time-to-live for the cacheable instance and will be used as the default value.
1406
- * If you set a number it is miliseconds, if you set a string it is a human-readable
1407
- * format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that
1408
- * there is no time-to-live.
1409
- *
1410
- * [Learn more about time-to-live](https://cacheable.org/docs/cacheable/#shorthand-for-time-to-live-ttl).
1411
- *
1412
- * @param {number | string | undefined} ttl The time-to-live for the cacheable instance
1413
- * @example
1414
- * ```typescript
1415
- * const cacheable = new Cacheable();
1416
- * cacheable.ttl = '1h'; // Set the time-to-live to 1 hour
1417
- * ```
1418
- * or setting the time-to-live in milliseconds
1419
- * ```typescript
1420
- * const cacheable = new Cacheable();
1421
- * cacheable.ttl = 3600000; // Set the time-to-live to 1 hour
1422
- * ```
1423
- */
1424
- set ttl(ttl) {
1425
- this.setTtl(ttl);
1426
- }
1427
- /**
1428
- * The cacheId for the cacheable instance. This is primarily used for the wrap function to not have conflicts.
1429
- * If it is not set then it will be a random string that is generated
1430
- * @returns {string} The cacheId for the cacheable instance
1431
- */
1432
- get cacheId() {
1433
- return this._cacheId;
1434
- }
1435
- /**
1436
- * Sets the cacheId for the cacheable instance. This is primarily used for the wrap function to not have conflicts.
1437
- * If it is not set then it will be a random string that is generated
1438
- * @param {string} cacheId The cacheId for the cacheable instance
1439
- */
1440
- set cacheId(cacheId) {
1441
- this._cacheId = cacheId;
1442
- }
1443
- /**
1444
- * Sets the primary store for the cacheable instance
1445
- * @param {Keyv | KeyvStoreAdapter} primary The primary store for the cacheable instance
1446
- * @returns {void}
1447
- */
1448
- setPrimary(primary) {
1449
- if (this.isKeyvInstance(primary)) {
1450
- this._primary = primary;
1451
- } else {
1452
- this._primary = new import_keyv2.Keyv(primary);
1453
- }
1454
- this._primary.on("error", (error) => {
1455
- this.emit("error" /* ERROR */, error);
1456
- });
1457
- }
1458
- /**
1459
- * Sets the secondary store for the cacheable instance. If it is set to undefined then the secondary store is disabled.
1460
- * @param {Keyv | KeyvStoreAdapter} secondary The secondary store for the cacheable instance
1461
- * @returns {void}
1462
- */
1463
- setSecondary(secondary) {
1464
- if (this.isKeyvInstance(secondary)) {
1465
- this._secondary = secondary;
1466
- } else {
1467
- this._secondary = new import_keyv2.Keyv(secondary);
1468
- }
1469
- this._secondary.on("error", (error) => {
1470
- this.emit("error" /* ERROR */, error);
1471
- });
1472
- }
1473
- // biome-ignore lint/suspicious/noExplicitAny: type format
1474
- isKeyvInstance(keyv) {
1475
- if (keyv instanceof import_keyv2.Keyv) {
1476
- return true;
1477
- }
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
- ];
1493
- return keyvMethods.every((method) => typeof keyv[method] === "function");
1494
- }
1495
- getNameSpace() {
1496
- if (typeof this._namespace === "function") {
1497
- return this._namespace();
1498
- }
1499
- return this._namespace;
1500
- }
1501
- async get(key, options = {}) {
1502
- let result;
1503
- const { raw = false } = options;
1504
- try {
1505
- await this.hook("BEFORE_GET" /* BEFORE_GET */, key);
1506
- result = await this._primary.get(key, { raw: true });
1507
- let ttl;
1508
- if (!result && this._secondary) {
1509
- const secondaryResult = await this.getSecondaryRawResults(key);
1510
- if (secondaryResult?.value) {
1511
- result = secondaryResult;
1512
- const cascadeTtl = getCascadingTtl(this._ttl, this._primary.ttl);
1513
- const expires = secondaryResult.expires ?? void 0;
1514
- ttl = calculateTtlFromExpiration(cascadeTtl, expires);
1515
- const setItem = { key, value: result.value, ttl };
1516
- await this.hook(
1517
- "BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */,
1518
- setItem
1519
- );
1520
- await this._primary.set(setItem.key, setItem.value, setItem.ttl);
1521
- }
1522
- }
1523
- await this.hook("AFTER_GET" /* AFTER_GET */, { key, result, ttl });
1524
- } catch (error) {
1525
- this.emit("error" /* ERROR */, error);
1526
- }
1527
- if (this.stats.enabled) {
1528
- if (result) {
1529
- this._stats.incrementHits();
1530
- } else {
1531
- this._stats.incrementMisses();
1532
- }
1533
- this.stats.incrementGets();
1534
- }
1535
- return raw ? result : result?.value;
1536
- }
1537
- async getMany(keys, options = {}) {
1538
- let result = [];
1539
- const { raw = false } = options;
1540
- try {
1541
- await this.hook("BEFORE_GET_MANY" /* BEFORE_GET_MANY */, keys);
1542
- result = await this._primary.get(keys, { raw: true });
1543
- if (this._secondary) {
1544
- const missingKeys = [];
1545
- for (const [i, key] of keys.entries()) {
1546
- if (!result[i]) {
1547
- missingKeys.push(key);
1548
- }
1549
- }
1550
- const secondaryResults = await this.getManySecondaryRawResults(missingKeys);
1551
- for await (const [i, key] of keys.entries()) {
1552
- if (!result[i] && secondaryResults[i]) {
1553
- result[i] = secondaryResults[i];
1554
- const cascadeTtl = getCascadingTtl(this._ttl, this._primary.ttl);
1555
- let { expires } = secondaryResults[i];
1556
- if (expires === null) {
1557
- expires = void 0;
1558
- }
1559
- const ttl = calculateTtlFromExpiration(cascadeTtl, expires);
1560
- const setItem = { key, value: result[i].value, ttl };
1561
- await this.hook(
1562
- "BEFORE_SECONDARY_SETS_PRIMARY" /* BEFORE_SECONDARY_SETS_PRIMARY */,
1563
- setItem
1564
- );
1565
- await this._primary.set(setItem.key, setItem.value, setItem.ttl);
1566
- }
1567
- }
1568
- }
1569
- await this.hook("AFTER_GET_MANY" /* AFTER_GET_MANY */, { keys, result });
1570
- } catch (error) {
1571
- this.emit("error" /* ERROR */, error);
1572
- }
1573
- if (this.stats.enabled) {
1574
- for (const item of result) {
1575
- if (item) {
1576
- this._stats.incrementHits();
1577
- } else {
1578
- this._stats.incrementMisses();
1579
- }
1580
- }
1581
- this.stats.incrementGets();
1582
- }
1583
- return raw ? result : result.map((item) => item?.value);
1584
- }
1585
- /**
1586
- * Sets the value of the key. If the secondary store is set then it will also set the value in the secondary store.
1587
- * @param {string} key the key to set the value of
1588
- * @param {T} value The value to set
1589
- * @param {number | string} [ttl] set a number it is miliseconds, set a string it is a human-readable
1590
- * format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live.
1591
- * @returns {boolean} Whether the value was set
1592
- */
1593
- async set(key, value, ttl) {
1594
- let result = false;
1595
- const finalTtl = shorthandToMilliseconds(ttl ?? this._ttl);
1596
- try {
1597
- const item = { key, value, ttl: finalTtl };
1598
- await this.hook("BEFORE_SET" /* BEFORE_SET */, item);
1599
- const promises = [];
1600
- promises.push(this._primary.set(item.key, item.value, item.ttl));
1601
- if (this._secondary) {
1602
- promises.push(this._secondary.set(item.key, item.value, item.ttl));
1603
- }
1604
- if (this._nonBlocking) {
1605
- result = await Promise.race(promises);
1606
- } else {
1607
- const results = await Promise.all(promises);
1608
- result = results[0];
1609
- }
1610
- await this.hook("AFTER_SET" /* AFTER_SET */, item);
1611
- } catch (error) {
1612
- this.emit("error" /* ERROR */, error);
1613
- }
1614
- if (this.stats.enabled) {
1615
- this.stats.incrementKSize(key);
1616
- this.stats.incrementCount();
1617
- this.stats.incrementVSize(value);
1618
- this.stats.incrementSets();
1619
- }
1620
- return result;
1621
- }
1622
- /**
1623
- * Sets the values of the keys. If the secondary store is set then it will also set the values in the secondary store.
1624
- * @param {CacheableItem[]} items The items to set
1625
- * @returns {boolean} Whether the values were set
1626
- */
1627
- async setMany(items) {
1628
- let result = false;
1629
- try {
1630
- await this.hook("BEFORE_SET_MANY" /* BEFORE_SET_MANY */, items);
1631
- result = await this.setManyKeyv(this._primary, items);
1632
- if (this._secondary) {
1633
- if (this._nonBlocking) {
1634
- this.setManyKeyv(this._secondary, items);
1635
- } else {
1636
- await this.setManyKeyv(this._secondary, items);
1637
- }
1638
- }
1639
- await this.hook("AFTER_SET_MANY" /* AFTER_SET_MANY */, items);
1640
- } catch (error) {
1641
- this.emit("error" /* ERROR */, error);
1642
- }
1643
- if (this.stats.enabled) {
1644
- for (const item of items) {
1645
- this.stats.incrementKSize(item.key);
1646
- this.stats.incrementCount();
1647
- this.stats.incrementVSize(item.value);
1648
- }
1649
- }
1650
- return result;
1651
- }
1652
- /**
1653
- * Takes the value of the key and deletes the key. If the key does not exist then it will return undefined.
1654
- * @param {string} key The key to take the value of
1655
- * @returns {Promise<T | undefined>} The value of the key or undefined if the key does not exist
1656
- */
1657
- async take(key) {
1658
- const result = await this.get(key);
1659
- await this.delete(key);
1660
- return result;
1661
- }
1662
- /**
1663
- * Takes the values of the keys and deletes the keys. If the key does not exist then it will return undefined.
1664
- * @param {string[]} keys The keys to take the values of
1665
- * @returns {Promise<Array<T | undefined>>} The values of the keys or undefined if the key does not exist
1666
- */
1667
- async takeMany(keys) {
1668
- const result = await this.getMany(keys);
1669
- await this.deleteMany(keys);
1670
- return result;
1671
- }
1672
- /**
1673
- * Checks if the key exists in the primary store. If it does not exist then it will check the secondary store.
1674
- * @param {string} key The key to check
1675
- * @returns {Promise<boolean>} Whether the key exists
1676
- */
1677
- async has(key) {
1678
- const promises = [];
1679
- promises.push(this._primary.has(key));
1680
- if (this._secondary) {
1681
- promises.push(this._secondary.has(key));
1682
- }
1683
- const resultAll = await Promise.all(promises);
1684
- for (const result of resultAll) {
1685
- if (result) {
1686
- return true;
1687
- }
1688
- }
1689
- return false;
1690
- }
1691
- /**
1692
- * Checks if the keys exist in the primary store. If it does not exist then it will check the secondary store.
1693
- * @param {string[]} keys The keys to check
1694
- * @returns {Promise<boolean[]>} Whether the keys exist
1695
- */
1696
- async hasMany(keys) {
1697
- const result = await this.hasManyKeyv(this._primary, keys);
1698
- const missingKeys = [];
1699
- for (const [i, key] of keys.entries()) {
1700
- if (!result[i] && this._secondary) {
1701
- missingKeys.push(key);
1702
- }
1703
- }
1704
- if (missingKeys.length > 0 && this._secondary) {
1705
- const secondary = await this.hasManyKeyv(this._secondary, keys);
1706
- for (const [i, _key] of keys.entries()) {
1707
- if (!result[i] && secondary[i]) {
1708
- result[i] = secondary[i];
1709
- }
1710
- }
1711
- }
1712
- return result;
1713
- }
1714
- /**
1715
- * Deletes the key from the primary store. If the secondary store is set then it will also delete the key from the secondary store.
1716
- * @param {string} key The key to delete
1717
- * @returns {Promise<boolean>} Whether the key was deleted
1718
- */
1719
- async delete(key) {
1720
- let result = false;
1721
- const promises = [];
1722
- if (this.stats.enabled) {
1723
- const statResult = await this._primary.get(key);
1724
- if (statResult) {
1725
- this.stats.decreaseKSize(key);
1726
- this.stats.decreaseVSize(statResult);
1727
- this.stats.decreaseCount();
1728
- this.stats.incrementDeletes();
1729
- }
1730
- }
1731
- promises.push(this._primary.delete(key));
1732
- if (this._secondary) {
1733
- promises.push(this._secondary.delete(key));
1734
- }
1735
- if (this.nonBlocking) {
1736
- result = await Promise.race(promises);
1737
- } else {
1738
- const resultAll = await Promise.all(promises);
1739
- result = resultAll[0];
1740
- }
1741
- return result;
1742
- }
1743
- /**
1744
- * Deletes the keys from the primary store. If the secondary store is set then it will also delete the keys from the secondary store.
1745
- * @param {string[]} keys The keys to delete
1746
- * @returns {Promise<boolean>} Whether the keys were deleted
1747
- */
1748
- async deleteMany(keys) {
1749
- if (this.stats.enabled) {
1750
- const statResult = await this._primary.get(keys);
1751
- for (const key of keys) {
1752
- this.stats.decreaseKSize(key);
1753
- this.stats.decreaseVSize(statResult);
1754
- this.stats.decreaseCount();
1755
- this.stats.incrementDeletes();
1756
- }
1757
- }
1758
- const result = await this.deleteManyKeyv(this._primary, keys);
1759
- if (this._secondary) {
1760
- if (this._nonBlocking) {
1761
- this.deleteManyKeyv(this._secondary, keys);
1762
- } else {
1763
- await this.deleteManyKeyv(this._secondary, keys);
1764
- }
1765
- }
1766
- return result;
1767
- }
1768
- /**
1769
- * Clears the primary store. If the secondary store is set then it will also clear the secondary store.
1770
- * @returns {Promise<void>}
1771
- */
1772
- async clear() {
1773
- const promises = [];
1774
- promises.push(this._primary.clear());
1775
- if (this._secondary) {
1776
- promises.push(this._secondary.clear());
1777
- }
1778
- await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
1779
- if (this.stats.enabled) {
1780
- this._stats.resetStoreValues();
1781
- this._stats.incrementClears();
1782
- }
1783
- }
1784
- /**
1785
- * Disconnects the primary store. If the secondary store is set then it will also disconnect the secondary store.
1786
- * @returns {Promise<void>}
1787
- */
1788
- async disconnect() {
1789
- const promises = [];
1790
- promises.push(this._primary.disconnect());
1791
- if (this._secondary) {
1792
- promises.push(this._secondary.disconnect());
1793
- }
1794
- await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
1795
- }
1796
- /**
1797
- * Wraps a function with caching
1798
- *
1799
- * [Learn more about wrapping functions](https://cacheable.org/docs/cacheable/#wrap--memoization-for-sync-and-async-functions).
1800
- * @param {Function} function_ The function to wrap
1801
- * @param {WrapOptions} [options] The options for the wrap function
1802
- * @returns {Function} The wrapped function
1803
- */
1804
- // biome-ignore lint/suspicious/noExplicitAny: type format
1805
- wrap(function_, options) {
1806
- const wrapOptions = {
1807
- ttl: options?.ttl ?? this._ttl,
1808
- keyPrefix: options?.keyPrefix,
1809
- cache: this,
1810
- cacheId: this._cacheId
1811
- };
1812
- return wrap(function_, wrapOptions);
1813
- }
1814
- /**
1815
- * Retrieves the value associated with the given key from the cache. If the key is not found,
1816
- * invokes the provided function to calculate the value, stores it in the cache, and then returns it.
1817
- *
1818
- * @param {GetOrSetKey} key - The key to retrieve or set in the cache. This can also be a function that returns a string key.
1819
- * If a function is provided, it will be called with the cache options to generate the key.
1820
- * @param {() => Promise<T>} function_ - The asynchronous function that computes the value to be cached if the key does not exist.
1821
- * @param {GetOrSetFunctionOptions} [options] - Optional settings for caching, such as the time to live (TTL) or whether to cache errors.
1822
- * @return {Promise<T | undefined>} - A promise that resolves to the cached or newly computed value, or undefined if an error occurs and caching is not configured for errors.
1823
- */
1824
- async getOrSet(key, function_, options) {
1825
- const getOrSetOptions = {
1826
- cache: this,
1827
- cacheId: this._cacheId,
1828
- ttl: options?.ttl ?? this._ttl,
1829
- cacheErrors: options?.cacheErrors,
1830
- throwErrors: options?.throwErrors
1831
- };
1832
- return getOrSet(key, function_, getOrSetOptions);
1833
- }
1834
- /**
1835
- * Will hash an object using the specified algorithm. The default algorithm is 'sha256'.
1836
- * @param {any} object the object to hash
1837
- * @param {string} algorithm the hash algorithm to use. The default is 'sha256'
1838
- * @returns {string} the hash of the object
1839
- */
1840
- // biome-ignore lint/suspicious/noExplicitAny: type format
1841
- hash(object, algorithm = "sha256") {
1842
- return hash(object, algorithm);
1843
- }
1844
- async getSecondaryRawResults(key) {
1845
- let result;
1846
- if (this._secondary) {
1847
- result = await this._secondary.get(key, { raw: true });
1848
- }
1849
- return result;
1850
- }
1851
- async getManySecondaryRawResults(keys) {
1852
- let result = [];
1853
- if (this._secondary) {
1854
- result = await this._secondary.get(keys, { raw: true });
1855
- }
1856
- return result;
1857
- }
1858
- async deleteManyKeyv(keyv, keys) {
1859
- const promises = [];
1860
- for (const key of keys) {
1861
- promises.push(keyv.delete(key));
1862
- }
1863
- await Promise.all(promises);
1864
- return true;
1865
- }
1866
- async setManyKeyv(keyv, items) {
1867
- const promises = [];
1868
- for (const item of items) {
1869
- const finalTtl = shorthandToMilliseconds(item.ttl ?? this._ttl);
1870
- promises.push(keyv.set(item.key, item.value, finalTtl));
1871
- }
1872
- await Promise.all(promises);
1873
- return true;
1874
- }
1875
- async hasManyKeyv(keyv, keys) {
1876
- const promises = [];
1877
- for (const key of keys) {
1878
- promises.push(keyv.has(key));
1879
- }
1880
- return Promise.all(promises);
1881
- }
1882
- setTtl(ttl) {
1883
- if (typeof ttl === "string" || ttl === void 0) {
1884
- this._ttl = ttl;
1885
- } else if (ttl > 0) {
1886
- this._ttl = ttl;
1887
- } else {
1888
- this._ttl = void 0;
1889
- }
1890
- }
1891
- };
1892
- // Annotate the CommonJS export names for ESM import in node:
1893
- 0 && (module.exports = {
1894
- Cacheable,
1895
- CacheableEvents,
1896
- CacheableHooks,
1897
- CacheableMemory,
1898
- CacheableStats,
1899
- Keyv,
1900
- KeyvCacheableMemory,
1901
- KeyvHooks,
1902
- createKeyv,
1903
- getOrSet,
1904
- shorthandToMilliseconds,
1905
- shorthandToTime,
1906
- wrap,
1907
- wrapSync
1908
- });
1
+ "use strict";var A=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var I=(u,t)=>{for(var i in t)A(u,i,{get:t[i],enumerable:!0})},G=(u,t,i,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of F(t))!B.call(u,s)&&s!==i&&A(u,s,{get:()=>t[s],enumerable:!(e=K(t,s))||e.enumerable});return u};var P=u=>G(A({},"__esModule",{value:!0}),u);var C={};I(C,{Cacheable:()=>w,CacheableEvents:()=>R,CacheableHooks:()=>E,CacheableMemory:()=>m.CacheableMemory,CacheableStats:()=>h.Stats,HashAlgorithm:()=>h.HashAlgorithm,Keyv:()=>T.Keyv,KeyvCacheableMemory:()=>m.KeyvCacheableMemory,KeyvHooks:()=>T.KeyvHooks,calculateTtlFromExpiration:()=>h.calculateTtlFromExpiration,createKeyv:()=>m.createKeyv,getCascadingTtl:()=>h.getCascadingTtl,getOrSet:()=>_.getOrSet,hash:()=>h.hash,shorthandToMilliseconds:()=>h.shorthandToMilliseconds,shorthandToTime:()=>h.shorthandToTime,wrap:()=>_.wrap,wrapSync:()=>_.wrapSync});module.exports=P(C);var g=require("@cacheable/memoize"),O=require("@cacheable/memory"),l=require("@cacheable/utils"),M=require("hookified"),f=require("keyv");var E=(o=>(o.BEFORE_SET="BEFORE_SET",o.AFTER_SET="AFTER_SET",o.BEFORE_SET_MANY="BEFORE_SET_MANY",o.AFTER_SET_MANY="AFTER_SET_MANY",o.BEFORE_GET="BEFORE_GET",o.AFTER_GET="AFTER_GET",o.BEFORE_GET_MANY="BEFORE_GET_MANY",o.AFTER_GET_MANY="AFTER_GET_MANY",o.BEFORE_SECONDARY_SETS_PRIMARY="BEFORE_SECONDARY_SETS_PRIMARY",o))(E||{}),R=(e=>(e.ERROR="error",e.CACHE_HIT="cache:hit",e.CACHE_MISS="cache:miss",e))(R||{});var _=require("@cacheable/memoize"),m=require("@cacheable/memory"),h=require("@cacheable/utils"),T=require("keyv"),w=class extends M.Hookified{_primary=(0,O.createKeyv)();_secondary;_nonBlocking=!1;_ttl;_stats=new l.Stats({enabled:!1});_namespace;_cacheId=Math.random().toString(36).slice(2);constructor(t){super(),t?.primary&&this.setPrimary(t.primary),t?.secondary&&this.setSecondary(t.secondary),t?.nonBlocking&&(this._nonBlocking=t.nonBlocking),t?.stats&&(this._stats.enabled=t.stats),t?.ttl&&this.setTtl(t.ttl),t?.cacheId&&(this._cacheId=t.cacheId),t?.namespace&&(this._namespace=t.namespace,this._primary.namespace=this.getNameSpace(),this._secondary&&(this._secondary.namespace=this.getNameSpace()))}get namespace(){return this._namespace}set namespace(t){this._namespace=t,this._primary.namespace=this.getNameSpace(),this._secondary&&(this._secondary.namespace=this.getNameSpace())}get stats(){return this._stats}get primary(){return this._primary}set primary(t){this._primary=t}get secondary(){return this._secondary}set secondary(t){this._secondary=t}get nonBlocking(){return this._nonBlocking}set nonBlocking(t){this._nonBlocking=t}get ttl(){return this._ttl}set ttl(t){this.setTtl(t)}get cacheId(){return this._cacheId}set cacheId(t){this._cacheId=t}setPrimary(t){this.isKeyvInstance(t)?this._primary=t:this._primary=new f.Keyv(t),this._primary.on("error",i=>{this.emit("error",i)})}setSecondary(t){this.isKeyvInstance(t)?this._secondary=t:this._secondary=new f.Keyv(t),this._secondary.on("error",i=>{this.emit("error",i)})}isKeyvInstance(t){return t instanceof f.Keyv?!0:["generateIterator","get","getMany","set","setMany","delete","deleteMany","has","hasMany","clear","disconnect","serialize","deserialize"].every(e=>typeof t[e]=="function")}getNameSpace(){return typeof this._namespace=="function"?this._namespace():this._namespace}async get(t,i){return(await this.getRaw(t,i))?.value}async getRaw(t,i){let e;try{await this.hook("BEFORE_GET",t),e=await this._primary.getRaw(t);let s;e?this.emit("cache:hit",{key:t,value:e.value,store:"primary"}):this.emit("cache:miss",{key:t,store:"primary"});let n=i?.nonBlocking??this._nonBlocking;if(!e&&this._secondary){let a;n?a=await this.processSecondaryForGetRawNonBlocking(this._primary,this._secondary,t):a=await this.processSecondaryForGetRaw(this._primary,this._secondary,t),a&&(e=a.result,s=a.ttl)}await this.hook("AFTER_GET",{key:t,result:e,ttl:s})}catch(s){this.emit("error",s)}return this.stats.enabled&&(e?this._stats.incrementHits():this._stats.incrementMisses(),this.stats.incrementGets()),e}async getManyRaw(t,i){let e=[];try{await this.hook("BEFORE_GET_MANY",t),e=await this._primary.getManyRaw(t);for(let[n,a]of t.entries())e[n]?this.emit("cache:hit",{key:a,value:e[n].value,store:"primary"}):this.emit("cache:miss",{key:a,store:"primary"});let s=i?.nonBlocking??this._nonBlocking;this._secondary&&(s?await this.processSecondaryForGetManyRawNonBlocking(this._primary,this._secondary,t,e):await this.processSecondaryForGetManyRaw(this._primary,this._secondary,t,e)),await this.hook("AFTER_GET_MANY",{keys:t,result:e})}catch(s){this.emit("error",s)}if(this.stats.enabled){for(let s of e)s?this._stats.incrementHits():this._stats.incrementMisses();this.stats.incrementGets()}return e}async getMany(t,i){return(await this.getManyRaw(t,i)).map(s=>s?.value)}async set(t,i,e){let s=!1,n=(0,l.shorthandToMilliseconds)(e??this._ttl);try{let a={key:t,value:i,ttl:n};await this.hook("BEFORE_SET",a);let r=[];if(r.push(this._primary.set(a.key,a.value,a.ttl)),this._secondary&&r.push(this._secondary.set(a.key,a.value,a.ttl)),this._nonBlocking){s=await Promise.race(r);for(let c of r)c.catch(o=>{this.emit("error",o)})}else s=(await Promise.all(r))[0];await this.hook("AFTER_SET",a)}catch(a){this.emit("error",a)}return this.stats.enabled&&(this.stats.incrementKSize(t),this.stats.incrementCount(),this.stats.incrementVSize(i),this.stats.incrementSets()),s}async setMany(t){let i=!1;try{await this.hook("BEFORE_SET_MANY",t),i=await this.setManyKeyv(this._primary,t),this._secondary&&(this._nonBlocking?this.setManyKeyv(this._secondary,t).catch(e=>{this.emit("error",e)}):await this.setManyKeyv(this._secondary,t)),await this.hook("AFTER_SET_MANY",t)}catch(e){this.emit("error",e)}if(this.stats.enabled)for(let e of t)this.stats.incrementKSize(e.key),this.stats.incrementCount(),this.stats.incrementVSize(e.value);return i}async take(t){let i=await this.get(t);return await this.delete(t),i}async takeMany(t){let i=await this.getMany(t);return await this.deleteMany(t),i}async has(t){let i=[];i.push(this._primary.has(t)),this._secondary&&i.push(this._secondary.has(t));let e=await Promise.all(i);for(let s of e)if(s)return!0;return!1}async hasMany(t){let i=await this.hasManyKeyv(this._primary,t),e=[];for(let[s,n]of t.entries())!i[s]&&this._secondary&&e.push(n);if(e.length>0&&this._secondary){let s=await this.hasManyKeyv(this._secondary,t);for(let[n,a]of t.entries())!i[n]&&s[n]&&(i[n]=s[n])}return i}async delete(t){let i=!1,e=[];if(this.stats.enabled){let s=await this._primary.get(t);s&&(this.stats.decreaseKSize(t),this.stats.decreaseVSize(s),this.stats.decreaseCount(),this.stats.incrementDeletes())}if(e.push(this._primary.delete(t)),this._secondary&&e.push(this._secondary.delete(t)),this.nonBlocking){i=await Promise.race(e);for(let s of e)s.catch(n=>{this.emit("error",n)})}else i=(await Promise.all(e))[0];return i}async deleteMany(t){if(this.stats.enabled){let e=await this._primary.get(t);for(let s of t)this.stats.decreaseKSize(s),this.stats.decreaseVSize(e),this.stats.decreaseCount(),this.stats.incrementDeletes()}let i=await this._primary.deleteMany(t);return this._secondary&&(this._nonBlocking?this._secondary.deleteMany(t).catch(e=>{this.emit("error",e)}):await this._secondary.deleteMany(t)),i}async clear(){let t=[];t.push(this._primary.clear()),this._secondary&&t.push(this._secondary.clear()),await(this._nonBlocking?Promise.race(t):Promise.all(t)),this.stats.enabled&&(this._stats.resetStoreValues(),this._stats.incrementClears())}async disconnect(){let t=[];t.push(this._primary.disconnect()),this._secondary&&t.push(this._secondary.disconnect()),await(this._nonBlocking?Promise.race(t):Promise.all(t))}wrap(t,i){let e={get:async n=>this.get(n),has:async n=>this.has(n),set:async(n,a,r)=>{await this.set(n,a,r)},on:(n,a)=>{this.on(n,a)},emit:(n,...a)=>this.emit(n,...a)},s={ttl:i?.ttl??this._ttl,keyPrefix:i?.keyPrefix,createKey:i?.createKey,cacheErrors:i?.cacheErrors,cache:e,cacheId:this._cacheId,serialize:i?.serialize};return(0,g.wrap)(t,s)}async getOrSet(t,i,e){let n={cache:{get:async a=>this.get(a),has:async a=>this.has(a),set:async(a,r,c)=>{await this.set(a,r,c)},on:(a,r)=>{this.on(a,r)},emit:(a,...r)=>this.emit(a,...r)},cacheId:this._cacheId,ttl:e?.ttl??this._ttl,cacheErrors:e?.cacheErrors,throwErrors:e?.throwErrors};return(0,g.getOrSet)(t,i,n)}hash(t,i=l.HashAlgorithm.SHA256){let e=Object.values(l.HashAlgorithm).includes(i)?i:l.HashAlgorithm.SHA256;return(0,l.hash)(t,{algorithm:e})}async setManyKeyv(t,i){let e=[];for(let s of i){let n=(0,l.shorthandToMilliseconds)(s.ttl??this._ttl);e.push({key:s.key,value:s.value,ttl:n})}return await t.setMany(e),!0}async hasManyKeyv(t,i){let e=[];for(let s of i)e.push(t.has(s));return Promise.all(e)}async processSecondaryForGetRaw(t,i,e){let s=await i.getRaw(e);if(s?.value){this.emit("cache:hit",{key:e,value:s.value,store:"secondary"});let n=(0,l.getCascadingTtl)(this._ttl,this._primary.ttl),a=s.expires??void 0,r=(0,l.calculateTtlFromExpiration)(n,a),c={key:e,value:s.value,ttl:r};return await this.hook("BEFORE_SECONDARY_SETS_PRIMARY",c),await t.set(c.key,c.value,c.ttl),{result:s,ttl:r}}else{this.emit("cache:miss",{key:e,store:"secondary"});return}}async processSecondaryForGetRawNonBlocking(t,i,e){let s=await i.getRaw(e);if(s?.value){this.emit("cache:hit",{key:e,value:s.value,store:"secondary"});let n=(0,l.getCascadingTtl)(this._ttl,this._primary.ttl),a=s.expires??void 0,r=(0,l.calculateTtlFromExpiration)(n,a),c={key:e,value:s.value,ttl:r};return this.hook("BEFORE_SECONDARY_SETS_PRIMARY",c).then(async()=>{await t.set(c.key,c.value,c.ttl)}).catch(o=>{this.emit("error",o)}),{result:s,ttl:r}}else{this.emit("cache:miss",{key:e,store:"secondary"});return}}async processSecondaryForGetManyRaw(t,i,e,s){let n=[];for(let[c,o]of e.entries())s[c]||n.push(o);let a=await i.getManyRaw(n),r=0;for await(let[c,o]of e.entries())if(!s[c]){let y=a[r];if(y&&y.value!==void 0){s[c]=y,this.emit("cache:hit",{key:o,value:y.value,store:"secondary"});let S=(0,l.getCascadingTtl)(this._ttl,this._primary.ttl),{expires:d}=y;d===null&&(d=void 0);let v=(0,l.calculateTtlFromExpiration)(S,d),p={key:o,value:y.value,ttl:v};await this.hook("BEFORE_SECONDARY_SETS_PRIMARY",p),await t.set(p.key,p.value,p.ttl)}else this.emit("cache:miss",{key:o,store:"secondary"});r++}}async processSecondaryForGetManyRawNonBlocking(t,i,e,s){let n=[];for(let[c,o]of e.entries())s[c]||n.push(o);let a=await i.getManyRaw(n),r=0;for await(let[c,o]of e.entries())if(!s[c]){let y=a[r];if(y&&y.value!==void 0){s[c]=y,this.emit("cache:hit",{key:o,value:y.value,store:"secondary"});let S=(0,l.getCascadingTtl)(this._ttl,this._primary.ttl),{expires:d}=y;d===null&&(d=void 0);let v=(0,l.calculateTtlFromExpiration)(S,d),p={key:o,value:y.value,ttl:v};this.hook("BEFORE_SECONDARY_SETS_PRIMARY",p).then(async()=>{await t.set(p.key,p.value,p.ttl)}).catch(b=>{this.emit("error",b)})}else this.emit("cache:miss",{key:o,store:"secondary"});r++}}setTtl(t){typeof t=="string"||t===void 0?this._ttl=t:t>0?this._ttl=t:this._ttl=void 0}};0&&(module.exports={Cacheable,CacheableEvents,CacheableHooks,CacheableMemory,CacheableStats,HashAlgorithm,Keyv,KeyvCacheableMemory,KeyvHooks,calculateTtlFromExpiration,createKeyv,getCascadingTtl,getOrSet,hash,shorthandToMilliseconds,shorthandToTime,wrap,wrapSync});