cacheable 1.8.4 → 1.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  [<img align="center" src="https://cacheable.org/logo.svg" alt="Cacheable" />](https://github.com/jaredwray/cacheable)
2
2
 
3
- # Cacheable
4
-
5
- > Simple Caching Engine using Keyv
3
+ > High Performance Layer 1 / Layer 2 Caching with Keyv Storage
6
4
 
7
5
  [![codecov](https://codecov.io/gh/jaredwray/cacheable/graph/badge.svg?token=lWZ9OBQ7GM)](https://codecov.io/gh/jaredwray/cacheable)
8
6
  [![tests](https://github.com/jaredwray/cacheable/actions/workflows/tests.yml/badge.svg)](https://github.com/jaredwray/cacheable/actions/workflows/tests.yml)
@@ -347,11 +345,24 @@ const cache = new CacheableMemory();
347
345
  const wrappedFunction = cache.wrap(syncFunction, { ttl: '1h', key: 'syncFunction' });
348
346
  console.log(wrappedFunction(2)); // 4
349
347
  console.log(wrappedFunction(2)); // 4 from cache
350
- console.log(cache.get('syncFunction')); // 4
351
348
  ```
352
349
 
353
350
  In this example we are wrapping a `sync` function in a cache with a `ttl` of `1 hour`. This will cache the result of the function for `1 hour` and then expire the value. You can also set the `key` property in the `wrap()` options to set a custom key for the cache.
354
351
 
352
+ When an error occurs in the function it will not cache the value and will return the error. This is useful if you want to cache the results of a function but not cache the error. If you want it to cache the error you can set the `cacheError` property to `true` in the `wrap()` options. This is disabled by default.
353
+
354
+ ```javascript
355
+ import { CacheableMemory } from 'cacheable';
356
+ const syncFunction = (value: number) => {
357
+ throw new Error('error');
358
+ };
359
+
360
+ const cache = new CacheableMemory();
361
+ const wrappedFunction = cache.wrap(syncFunction, { ttl: '1h', key: 'syncFunction', cacheError: true });
362
+ console.log(wrappedFunction()); // error
363
+ console.log(wrappedFunction()); // error from cache
364
+ ```
365
+
355
366
  # Keyv Storage Adapter - KeyvCacheableMemory
356
367
 
357
368
  `cacheable` comes with a built-in storage adapter for Keyv called `KeyvCacheableMemory`. This takes `CacheableMemory` and creates a storage adapter for Keyv. This is useful if you want to use `CacheableMemory` as a storage adapter for Keyv. Here is an example of how to use `KeyvCacheableMemory`:
@@ -362,7 +373,7 @@ import { KeyvCacheableMemory } from 'cacheable';
362
373
 
363
374
  const keyv = new Keyv({ store: new KeyvCacheableMemory() });
364
375
  await keyv.set('foo', 'bar');
365
- const value = await keyv.get('key');
376
+ const value = await keyv.get('foo');
366
377
  console.log(value); // bar
367
378
  ```
368
379
 
package/dist/index.cjs CHANGED
@@ -35,17 +35,18 @@ __export(src_exports, {
35
35
  CacheableHooks: () => CacheableHooks,
36
36
  CacheableMemory: () => CacheableMemory,
37
37
  CacheableStats: () => CacheableStats,
38
- Keyv: () => import_keyv2.Keyv,
38
+ Keyv: () => import_keyv3.Keyv,
39
39
  KeyvCacheableMemory: () => KeyvCacheableMemory,
40
- KeyvHooks: () => import_keyv2.KeyvHooks,
40
+ KeyvHooks: () => import_keyv3.KeyvHooks,
41
+ createKeyv: () => createKeyv,
41
42
  shorthandToMilliseconds: () => shorthandToMilliseconds,
42
43
  shorthandToTime: () => shorthandToTime,
43
44
  wrap: () => wrap,
44
45
  wrapSync: () => wrapSync
45
46
  });
46
47
  module.exports = __toCommonJS(src_exports);
47
- var import_keyv = require("keyv");
48
- var import_hookified = require("hookified");
48
+ var import_keyv2 = require("keyv");
49
+ var import_hookified2 = require("hookified");
49
50
 
50
51
  // src/shorthand-time.ts
51
52
  var shorthandToMilliseconds = (shorthand) => {
@@ -114,6 +115,12 @@ var shorthandToTime = (shorthand, fromDate) => {
114
115
  return fromDate.getTime() + milliseconds;
115
116
  };
116
117
 
118
+ // src/keyv-memory.ts
119
+ var import_keyv = require("keyv");
120
+
121
+ // src/memory.ts
122
+ var import_hookified = require("hookified");
123
+
117
124
  // src/hash.ts
118
125
  var crypto = __toESM(require("crypto"), 1);
119
126
  function hash(object, algorithm = "sha256") {
@@ -188,8 +195,15 @@ function wrapSync(function_, options) {
188
195
  const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
189
196
  let value = cache.get(cacheKey);
190
197
  if (value === void 0) {
191
- value = function_(...arguments_);
192
- cache.set(cacheKey, value, ttl);
198
+ try {
199
+ value = function_(...arguments_);
200
+ cache.set(cacheKey, value, ttl);
201
+ } catch (error) {
202
+ cache.emit("error", error);
203
+ if (options.cacheErrors) {
204
+ cache.set(cacheKey, error, ttl);
205
+ }
206
+ }
193
207
  }
194
208
  return value;
195
209
  };
@@ -198,17 +212,21 @@ function wrap(function_, options) {
198
212
  const { ttl, keyPrefix, cache } = options;
199
213
  return async function(...arguments_) {
200
214
  let value;
201
- try {
202
- const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
203
- value = await cache.get(cacheKey);
204
- if (value === void 0) {
205
- value = await coalesceAsync(cacheKey, async () => {
215
+ const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
216
+ value = await cache.get(cacheKey);
217
+ if (value === void 0) {
218
+ value = await coalesceAsync(cacheKey, async () => {
219
+ try {
206
220
  const result = await function_(...arguments_);
207
221
  await cache.set(cacheKey, result, ttl);
208
222
  return result;
209
- });
210
- }
211
- } catch {
223
+ } catch (error) {
224
+ cache.emit("error", error);
225
+ if (options.cacheErrors) {
226
+ await cache.set(cacheKey, error, ttl);
227
+ }
228
+ }
229
+ });
212
230
  }
213
231
  return value;
214
232
  };
@@ -294,7 +312,7 @@ var DoublyLinkedList = class {
294
312
  };
295
313
 
296
314
  // src/memory.ts
297
- var CacheableMemory = class {
315
+ var CacheableMemory = class extends import_hookified.Hookified {
298
316
  _lru = new DoublyLinkedList();
299
317
  _hashCache = /* @__PURE__ */ new Map();
300
318
  _hash0 = /* @__PURE__ */ new Map();
@@ -322,6 +340,7 @@ var CacheableMemory = class {
322
340
  * @param {CacheableMemoryOptions} [options] - The options for the CacheableMemory
323
341
  */
324
342
  constructor(options) {
343
+ super();
325
344
  if (options?.ttl) {
326
345
  this.setTtl(options.ttl);
327
346
  }
@@ -481,7 +500,8 @@ var CacheableMemory = class {
481
500
  * Sets the value of the key
482
501
  * @param {string} key - The key to set the value
483
502
  * @param {any} value - The value to set
484
- * @param {number|string} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable.
503
+ * @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.
504
+ * If you want to set expire directly you can do that by setting the expire property in the SetOptions.
485
505
  * 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.
486
506
  * @returns {void}
487
507
  */
@@ -489,9 +509,21 @@ var CacheableMemory = class {
489
509
  const store = this.getStore(key);
490
510
  let expires;
491
511
  if (ttl !== void 0 || this._ttl !== void 0) {
492
- const finalTtl = shorthandToTime(ttl ?? this._ttl);
493
- if (finalTtl !== void 0) {
494
- expires = finalTtl;
512
+ if (typeof ttl === "object") {
513
+ if (ttl.expire) {
514
+ expires = typeof ttl.expire === "number" ? ttl.expire : ttl.expire.getTime();
515
+ }
516
+ if (ttl.ttl) {
517
+ const finalTtl = shorthandToTime(ttl.ttl);
518
+ if (finalTtl !== void 0) {
519
+ expires = finalTtl;
520
+ }
521
+ }
522
+ } else {
523
+ const finalTtl = shorthandToTime(ttl ?? this._ttl);
524
+ if (finalTtl !== void 0) {
525
+ expires = finalTtl;
526
+ }
495
527
  }
496
528
  }
497
529
  if (this._lruSize > 0) {
@@ -742,9 +774,12 @@ var CacheableMemory = class {
742
774
  */
743
775
  startIntervalCheck() {
744
776
  if (this._checkInterval > 0) {
777
+ if (this._interval) {
778
+ clearInterval(this._interval);
779
+ }
745
780
  this._interval = setInterval(() => {
746
781
  this.checkExpiration();
747
- }, this._checkInterval);
782
+ }, this._checkInterval).unref();
748
783
  }
749
784
  }
750
785
  /**
@@ -867,6 +902,7 @@ var KeyvCacheableMemory = class {
867
902
  return this.getStore(this._namespace).has(key);
868
903
  }
869
904
  on(event, listener) {
905
+ this.getStore(this._namespace).on(event, listener);
870
906
  return this;
871
907
  }
872
908
  getStore(namespace) {
@@ -879,6 +915,18 @@ var KeyvCacheableMemory = class {
879
915
  return this._nCache.get(namespace);
880
916
  }
881
917
  };
918
+ function createKeyv(options) {
919
+ const store = new KeyvCacheableMemory(options);
920
+ const namespace = options?.namespace;
921
+ let ttl;
922
+ if (options?.ttl && Number.isInteger(options.ttl)) {
923
+ ttl = options?.ttl;
924
+ }
925
+ const keyv = new import_keyv.Keyv({ store, namespace, ttl });
926
+ keyv.serialize = void 0;
927
+ keyv.deserialize = void 0;
928
+ return keyv;
929
+ }
882
930
 
883
931
  // src/stats.ts
884
932
  var CacheableStats = class {
@@ -1098,7 +1146,7 @@ var CacheableStats = class {
1098
1146
  };
1099
1147
 
1100
1148
  // src/index.ts
1101
- var import_keyv2 = require("keyv");
1149
+ var import_keyv3 = require("keyv");
1102
1150
  var CacheableHooks = /* @__PURE__ */ ((CacheableHooks2) => {
1103
1151
  CacheableHooks2["BEFORE_SET"] = "BEFORE_SET";
1104
1152
  CacheableHooks2["AFTER_SET"] = "AFTER_SET";
@@ -1114,8 +1162,8 @@ var CacheableEvents = /* @__PURE__ */ ((CacheableEvents2) => {
1114
1162
  CacheableEvents2["ERROR"] = "error";
1115
1163
  return CacheableEvents2;
1116
1164
  })(CacheableEvents || {});
1117
- var Cacheable = class extends import_hookified.Hookified {
1118
- _primary = new import_keyv.Keyv({ store: new KeyvCacheableMemory() });
1165
+ var Cacheable = class extends import_hookified2.Hookified {
1166
+ _primary = createKeyv();
1119
1167
  _secondary;
1120
1168
  _nonBlocking = false;
1121
1169
  _ttl;
@@ -1274,7 +1322,10 @@ var Cacheable = class extends import_hookified.Hookified {
1274
1322
  * @returns {void}
1275
1323
  */
1276
1324
  setPrimary(primary) {
1277
- this._primary = primary instanceof import_keyv.Keyv ? primary : new import_keyv.Keyv(primary);
1325
+ this._primary = primary instanceof import_keyv2.Keyv ? primary : new import_keyv2.Keyv(primary);
1326
+ this._primary.on("error", (error) => {
1327
+ this.emit("error" /* ERROR */, error);
1328
+ });
1278
1329
  }
1279
1330
  /**
1280
1331
  * Sets the secondary store for the cacheable instance. If it is set to undefined then the secondary store is disabled.
@@ -1282,7 +1333,10 @@ var Cacheable = class extends import_hookified.Hookified {
1282
1333
  * @returns {void}
1283
1334
  */
1284
1335
  setSecondary(secondary) {
1285
- this._secondary = secondary instanceof import_keyv.Keyv ? secondary : new import_keyv.Keyv(secondary);
1336
+ this._secondary = secondary instanceof import_keyv2.Keyv ? secondary : new import_keyv2.Keyv(secondary);
1337
+ this._secondary.on("error", (error) => {
1338
+ this.emit("error" /* ERROR */, error);
1339
+ });
1286
1340
  }
1287
1341
  getNameSpace() {
1288
1342
  if (typeof this._namespace === "function") {
@@ -1643,6 +1697,7 @@ var Cacheable = class extends import_hookified.Hookified {
1643
1697
  Keyv,
1644
1698
  KeyvCacheableMemory,
1645
1699
  KeyvHooks,
1700
+ createKeyv,
1646
1701
  shorthandToMilliseconds,
1647
1702
  shorthandToTime,
1648
1703
  wrap,
package/dist/index.d.cts CHANGED
@@ -112,6 +112,7 @@ type CacheableStoreItem = {
112
112
  type WrapFunctionOptions = {
113
113
  ttl?: number | string;
114
114
  keyPrefix?: string;
115
+ cacheErrors?: boolean;
115
116
  };
116
117
  type WrapOptions = WrapFunctionOptions & {
117
118
  cache: Cacheable;
@@ -138,7 +139,11 @@ type CacheableMemoryOptions = {
138
139
  lruSize?: number;
139
140
  checkInterval?: number;
140
141
  };
141
- declare class CacheableMemory {
142
+ type SetOptions = {
143
+ ttl?: number | string;
144
+ expire?: number | Date;
145
+ };
146
+ declare class CacheableMemory extends Hookified {
142
147
  private _lru;
143
148
  private readonly _hashCache;
144
149
  private readonly _hash0;
@@ -244,11 +249,12 @@ declare class CacheableMemory {
244
249
  * Sets the value of the key
245
250
  * @param {string} key - The key to set the value
246
251
  * @param {any} value - The value to set
247
- * @param {number|string} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable.
252
+ * @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.
253
+ * If you want to set expire directly you can do that by setting the expire property in the SetOptions.
248
254
  * 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.
249
255
  * @returns {void}
250
256
  */
251
- set(key: string, value: any, ttl?: number | string): void;
257
+ set(key: string, value: any, ttl?: number | string | SetOptions): void;
252
258
  /**
253
259
  * Sets the values of the keys
254
260
  * @param {CacheableItem[]} items - The items to set
@@ -398,6 +404,12 @@ declare class KeyvCacheableMemory implements KeyvStoreAdapter {
398
404
  on(event: string, listener: (...arguments_: any[]) => void): this;
399
405
  getStore(namespace?: string): CacheableMemory;
400
406
  }
407
+ /**
408
+ * Creates a new Keyv instance with a new KeyvCacheableMemory store. This also removes the serialize/deserialize methods from the Keyv instance for optimization.
409
+ * @param options
410
+ * @returns
411
+ */
412
+ declare function createKeyv(options?: KeyvCacheableMemoryOptions): Keyv;
401
413
 
402
414
  declare const shorthandToMilliseconds: (shorthand?: string | number) => number | undefined;
403
415
  declare const shorthandToTime: (shorthand?: string | number, fromDate?: Date) => number;
@@ -635,4 +647,4 @@ declare class Cacheable extends Hookified {
635
647
  private setTtl;
636
648
  }
637
649
 
638
- export { Cacheable, CacheableEvents, CacheableHooks, type CacheableItem, CacheableMemory, type CacheableMemoryOptions, type CacheableOptions, CacheableStats, KeyvCacheableMemory, type WrapOptions, type WrapSyncOptions, shorthandToMilliseconds, shorthandToTime, wrap, wrapSync };
650
+ export { Cacheable, CacheableEvents, CacheableHooks, type CacheableItem, CacheableMemory, type CacheableMemoryOptions, type CacheableOptions, CacheableStats, KeyvCacheableMemory, type WrapOptions, type WrapSyncOptions, createKeyv, shorthandToMilliseconds, shorthandToTime, wrap, wrapSync };
package/dist/index.d.ts CHANGED
@@ -112,6 +112,7 @@ type CacheableStoreItem = {
112
112
  type WrapFunctionOptions = {
113
113
  ttl?: number | string;
114
114
  keyPrefix?: string;
115
+ cacheErrors?: boolean;
115
116
  };
116
117
  type WrapOptions = WrapFunctionOptions & {
117
118
  cache: Cacheable;
@@ -138,7 +139,11 @@ type CacheableMemoryOptions = {
138
139
  lruSize?: number;
139
140
  checkInterval?: number;
140
141
  };
141
- declare class CacheableMemory {
142
+ type SetOptions = {
143
+ ttl?: number | string;
144
+ expire?: number | Date;
145
+ };
146
+ declare class CacheableMemory extends Hookified {
142
147
  private _lru;
143
148
  private readonly _hashCache;
144
149
  private readonly _hash0;
@@ -244,11 +249,12 @@ declare class CacheableMemory {
244
249
  * Sets the value of the key
245
250
  * @param {string} key - The key to set the value
246
251
  * @param {any} value - The value to set
247
- * @param {number|string} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable.
252
+ * @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.
253
+ * If you want to set expire directly you can do that by setting the expire property in the SetOptions.
248
254
  * 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.
249
255
  * @returns {void}
250
256
  */
251
- set(key: string, value: any, ttl?: number | string): void;
257
+ set(key: string, value: any, ttl?: number | string | SetOptions): void;
252
258
  /**
253
259
  * Sets the values of the keys
254
260
  * @param {CacheableItem[]} items - The items to set
@@ -398,6 +404,12 @@ declare class KeyvCacheableMemory implements KeyvStoreAdapter {
398
404
  on(event: string, listener: (...arguments_: any[]) => void): this;
399
405
  getStore(namespace?: string): CacheableMemory;
400
406
  }
407
+ /**
408
+ * Creates a new Keyv instance with a new KeyvCacheableMemory store. This also removes the serialize/deserialize methods from the Keyv instance for optimization.
409
+ * @param options
410
+ * @returns
411
+ */
412
+ declare function createKeyv(options?: KeyvCacheableMemoryOptions): Keyv;
401
413
 
402
414
  declare const shorthandToMilliseconds: (shorthand?: string | number) => number | undefined;
403
415
  declare const shorthandToTime: (shorthand?: string | number, fromDate?: Date) => number;
@@ -635,4 +647,4 @@ declare class Cacheable extends Hookified {
635
647
  private setTtl;
636
648
  }
637
649
 
638
- export { Cacheable, CacheableEvents, CacheableHooks, type CacheableItem, CacheableMemory, type CacheableMemoryOptions, type CacheableOptions, CacheableStats, KeyvCacheableMemory, type WrapOptions, type WrapSyncOptions, shorthandToMilliseconds, shorthandToTime, wrap, wrapSync };
650
+ export { Cacheable, CacheableEvents, CacheableHooks, type CacheableItem, CacheableMemory, type CacheableMemoryOptions, type CacheableOptions, CacheableStats, KeyvCacheableMemory, type WrapOptions, type WrapSyncOptions, createKeyv, shorthandToMilliseconds, shorthandToTime, wrap, wrapSync };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/index.ts
2
- import { Keyv } from "keyv";
3
- import { Hookified } from "hookified";
2
+ import { Keyv as Keyv2 } from "keyv";
3
+ import { Hookified as Hookified2 } from "hookified";
4
4
 
5
5
  // src/shorthand-time.ts
6
6
  var shorthandToMilliseconds = (shorthand) => {
@@ -69,6 +69,14 @@ var shorthandToTime = (shorthand, fromDate) => {
69
69
  return fromDate.getTime() + milliseconds;
70
70
  };
71
71
 
72
+ // src/keyv-memory.ts
73
+ import {
74
+ Keyv
75
+ } from "keyv";
76
+
77
+ // src/memory.ts
78
+ import { Hookified } from "hookified";
79
+
72
80
  // src/hash.ts
73
81
  import * as crypto from "node:crypto";
74
82
  function hash(object, algorithm = "sha256") {
@@ -143,8 +151,15 @@ function wrapSync(function_, options) {
143
151
  const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
144
152
  let value = cache.get(cacheKey);
145
153
  if (value === void 0) {
146
- value = function_(...arguments_);
147
- cache.set(cacheKey, value, ttl);
154
+ try {
155
+ value = function_(...arguments_);
156
+ cache.set(cacheKey, value, ttl);
157
+ } catch (error) {
158
+ cache.emit("error", error);
159
+ if (options.cacheErrors) {
160
+ cache.set(cacheKey, error, ttl);
161
+ }
162
+ }
148
163
  }
149
164
  return value;
150
165
  };
@@ -153,17 +168,21 @@ function wrap(function_, options) {
153
168
  const { ttl, keyPrefix, cache } = options;
154
169
  return async function(...arguments_) {
155
170
  let value;
156
- try {
157
- const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
158
- value = await cache.get(cacheKey);
159
- if (value === void 0) {
160
- value = await coalesceAsync(cacheKey, async () => {
171
+ const cacheKey = createWrapKey(function_, arguments_, keyPrefix);
172
+ value = await cache.get(cacheKey);
173
+ if (value === void 0) {
174
+ value = await coalesceAsync(cacheKey, async () => {
175
+ try {
161
176
  const result = await function_(...arguments_);
162
177
  await cache.set(cacheKey, result, ttl);
163
178
  return result;
164
- });
165
- }
166
- } catch {
179
+ } catch (error) {
180
+ cache.emit("error", error);
181
+ if (options.cacheErrors) {
182
+ await cache.set(cacheKey, error, ttl);
183
+ }
184
+ }
185
+ });
167
186
  }
168
187
  return value;
169
188
  };
@@ -249,7 +268,7 @@ var DoublyLinkedList = class {
249
268
  };
250
269
 
251
270
  // src/memory.ts
252
- var CacheableMemory = class {
271
+ var CacheableMemory = class extends Hookified {
253
272
  _lru = new DoublyLinkedList();
254
273
  _hashCache = /* @__PURE__ */ new Map();
255
274
  _hash0 = /* @__PURE__ */ new Map();
@@ -277,6 +296,7 @@ var CacheableMemory = class {
277
296
  * @param {CacheableMemoryOptions} [options] - The options for the CacheableMemory
278
297
  */
279
298
  constructor(options) {
299
+ super();
280
300
  if (options?.ttl) {
281
301
  this.setTtl(options.ttl);
282
302
  }
@@ -436,7 +456,8 @@ var CacheableMemory = class {
436
456
  * Sets the value of the key
437
457
  * @param {string} key - The key to set the value
438
458
  * @param {any} value - The value to set
439
- * @param {number|string} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable.
459
+ * @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.
460
+ * If you want to set expire directly you can do that by setting the expire property in the SetOptions.
440
461
  * 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.
441
462
  * @returns {void}
442
463
  */
@@ -444,9 +465,21 @@ var CacheableMemory = class {
444
465
  const store = this.getStore(key);
445
466
  let expires;
446
467
  if (ttl !== void 0 || this._ttl !== void 0) {
447
- const finalTtl = shorthandToTime(ttl ?? this._ttl);
448
- if (finalTtl !== void 0) {
449
- expires = finalTtl;
468
+ if (typeof ttl === "object") {
469
+ if (ttl.expire) {
470
+ expires = typeof ttl.expire === "number" ? ttl.expire : ttl.expire.getTime();
471
+ }
472
+ if (ttl.ttl) {
473
+ const finalTtl = shorthandToTime(ttl.ttl);
474
+ if (finalTtl !== void 0) {
475
+ expires = finalTtl;
476
+ }
477
+ }
478
+ } else {
479
+ const finalTtl = shorthandToTime(ttl ?? this._ttl);
480
+ if (finalTtl !== void 0) {
481
+ expires = finalTtl;
482
+ }
450
483
  }
451
484
  }
452
485
  if (this._lruSize > 0) {
@@ -697,9 +730,12 @@ var CacheableMemory = class {
697
730
  */
698
731
  startIntervalCheck() {
699
732
  if (this._checkInterval > 0) {
733
+ if (this._interval) {
734
+ clearInterval(this._interval);
735
+ }
700
736
  this._interval = setInterval(() => {
701
737
  this.checkExpiration();
702
- }, this._checkInterval);
738
+ }, this._checkInterval).unref();
703
739
  }
704
740
  }
705
741
  /**
@@ -822,6 +858,7 @@ var KeyvCacheableMemory = class {
822
858
  return this.getStore(this._namespace).has(key);
823
859
  }
824
860
  on(event, listener) {
861
+ this.getStore(this._namespace).on(event, listener);
825
862
  return this;
826
863
  }
827
864
  getStore(namespace) {
@@ -834,6 +871,18 @@ var KeyvCacheableMemory = class {
834
871
  return this._nCache.get(namespace);
835
872
  }
836
873
  };
874
+ function createKeyv(options) {
875
+ const store = new KeyvCacheableMemory(options);
876
+ const namespace = options?.namespace;
877
+ let ttl;
878
+ if (options?.ttl && Number.isInteger(options.ttl)) {
879
+ ttl = options?.ttl;
880
+ }
881
+ const keyv = new Keyv({ store, namespace, ttl });
882
+ keyv.serialize = void 0;
883
+ keyv.deserialize = void 0;
884
+ return keyv;
885
+ }
837
886
 
838
887
  // src/stats.ts
839
888
  var CacheableStats = class {
@@ -1055,7 +1104,7 @@ var CacheableStats = class {
1055
1104
  // src/index.ts
1056
1105
  import {
1057
1106
  KeyvHooks,
1058
- Keyv as Keyv2
1107
+ Keyv as Keyv3
1059
1108
  } from "keyv";
1060
1109
  var CacheableHooks = /* @__PURE__ */ ((CacheableHooks2) => {
1061
1110
  CacheableHooks2["BEFORE_SET"] = "BEFORE_SET";
@@ -1072,8 +1121,8 @@ var CacheableEvents = /* @__PURE__ */ ((CacheableEvents2) => {
1072
1121
  CacheableEvents2["ERROR"] = "error";
1073
1122
  return CacheableEvents2;
1074
1123
  })(CacheableEvents || {});
1075
- var Cacheable = class extends Hookified {
1076
- _primary = new Keyv({ store: new KeyvCacheableMemory() });
1124
+ var Cacheable = class extends Hookified2 {
1125
+ _primary = createKeyv();
1077
1126
  _secondary;
1078
1127
  _nonBlocking = false;
1079
1128
  _ttl;
@@ -1232,7 +1281,10 @@ var Cacheable = class extends Hookified {
1232
1281
  * @returns {void}
1233
1282
  */
1234
1283
  setPrimary(primary) {
1235
- this._primary = primary instanceof Keyv ? primary : new Keyv(primary);
1284
+ this._primary = primary instanceof Keyv2 ? primary : new Keyv2(primary);
1285
+ this._primary.on("error", (error) => {
1286
+ this.emit("error" /* ERROR */, error);
1287
+ });
1236
1288
  }
1237
1289
  /**
1238
1290
  * Sets the secondary store for the cacheable instance. If it is set to undefined then the secondary store is disabled.
@@ -1240,7 +1292,10 @@ var Cacheable = class extends Hookified {
1240
1292
  * @returns {void}
1241
1293
  */
1242
1294
  setSecondary(secondary) {
1243
- this._secondary = secondary instanceof Keyv ? secondary : new Keyv(secondary);
1295
+ this._secondary = secondary instanceof Keyv2 ? secondary : new Keyv2(secondary);
1296
+ this._secondary.on("error", (error) => {
1297
+ this.emit("error" /* ERROR */, error);
1298
+ });
1244
1299
  }
1245
1300
  getNameSpace() {
1246
1301
  if (typeof this._namespace === "function") {
@@ -1597,9 +1652,10 @@ export {
1597
1652
  CacheableHooks,
1598
1653
  CacheableMemory,
1599
1654
  CacheableStats,
1600
- Keyv2 as Keyv,
1655
+ Keyv3 as Keyv,
1601
1656
  KeyvCacheableMemory,
1602
1657
  KeyvHooks,
1658
+ createKeyv,
1603
1659
  shorthandToMilliseconds,
1604
1660
  shorthandToTime,
1605
1661
  wrap,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cacheable",
3
- "version": "1.8.4",
4
- "description": "Simple Caching Engine using Keyv",
3
+ "version": "1.8.6",
4
+ "description": "High Performance Layer 1 / Layer 2 Caching with Keyv Storage",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
@@ -21,18 +21,18 @@
21
21
  "license": "MIT",
22
22
  "private": false,
23
23
  "devDependencies": {
24
- "@keyv/redis": "^3.0.1",
25
- "@types/node": "^22.9.0",
26
- "@vitest/coverage-v8": "^2.1.4",
24
+ "@keyv/redis": "^4.0.2",
25
+ "@types/node": "^22.10.2",
26
+ "@vitest/coverage-v8": "^2.1.8",
27
27
  "lru-cache": "^11.0.2",
28
28
  "rimraf": "^6.0.1",
29
29
  "tsup": "^8.3.5",
30
- "typescript": "^5.6.3",
31
- "vitest": "^2.1.4",
32
- "xo": "^0.59.3"
30
+ "typescript": "^5.7.2",
31
+ "vitest": "^2.1.8",
32
+ "xo": "^0.60.0"
33
33
  },
34
34
  "dependencies": {
35
- "hookified": "^1.5.0",
35
+ "hookified": "^1.5.1",
36
36
  "keyv": "^5.2.1"
37
37
  },
38
38
  "keywords": [
@@ -67,6 +67,7 @@
67
67
  ],
68
68
  "scripts": {
69
69
  "build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
70
+ "prepublish": "pnpm build",
70
71
  "test": "xo --fix && vitest run --coverage",
71
72
  "test:ci": "xo && vitest run",
72
73
  "clean": "rimraf ./dist ./coverage ./node_modules"