cacheable 2.1.1 → 2.3.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/README.md CHANGED
@@ -32,6 +32,7 @@
32
32
  * [Storage Tiering and Caching](#storage-tiering-and-caching)
33
33
  * [TTL Propagation and Storage Tiering](#ttl-propagation-and-storage-tiering)
34
34
  * [Shorthand for Time to Live (ttl)](#shorthand-for-time-to-live-ttl)
35
+ * [Iteration on Primary and Secondary Stores](#iteration-on-primary-and-secondary-stores)
35
36
  * [Non-Blocking Operations](#non-blocking-operations)
36
37
  * [Non-Blocking with @keyv/redis](#non-blocking-with-keyvredis)
37
38
  * [CacheableSync - Distributed Updates](#cacheablesync---distributed-updates)
@@ -279,6 +280,110 @@ raws.forEach((entry, idx) => {
279
280
  });
280
281
  ```
281
282
 
283
+ ## Checking multiple keys with hasMany
284
+
285
+ The `hasMany` method allows you to efficiently check if multiple keys exist in the cache. It leverages Keyv's native `hasMany` support for optimal performance:
286
+
287
+ ```typescript
288
+ import { Cacheable } from 'cacheable';
289
+
290
+ const cache = new Cacheable();
291
+
292
+ // set some values
293
+ await cache.set('user:1', { name: 'Alice' });
294
+ await cache.set('user:2', { name: 'Bob' });
295
+
296
+ // check if multiple keys exist
297
+ const exists = await cache.hasMany(['user:1', 'user:2', 'user:3']);
298
+ console.log(exists); // [true, true, false]
299
+ ```
300
+
301
+ The `hasMany` method returns an array of booleans in the same order as the input keys. This is particularly useful when you need to verify the existence of multiple cache entries before performing batch operations.
302
+
303
+ # Iteration on Primary and Secondary Stores
304
+
305
+ The `Cacheable` class exposes both `primary` and `secondary` Keyv instances, which support iteration over their stored entries using the `iterator()` method. This allows you to access and process all keys and values in either storage layer.
306
+
307
+ **Important Notes:**
308
+ - Not all storage adapters support iteration. Always check if `iterator` exists before using it.
309
+ - The iterator automatically filters by namespace, skips expired entries (and deletes them), and deserializes values.
310
+ - **Performance Warning:** Be careful when using `iterator()` as it can cause performance issues with large datasets.
311
+
312
+ ## Basic Iteration Example
313
+
314
+ ```typescript
315
+ import { Cacheable } from 'cacheable';
316
+ import KeyvRedis from '@keyv/redis';
317
+
318
+ // Create cache with primary (in-memory) and secondary (Redis) stores
319
+ const secondary = new KeyvRedis('redis://user:pass@localhost:6379');
320
+ const cache = new Cacheable({ secondary });
321
+
322
+ // Add some data
323
+ await cache.set('user:1', { name: 'Alice', role: 'admin' });
324
+ await cache.set('user:2', { name: 'Bob', role: 'user' });
325
+ await cache.set('session:abc', { userId: '1', active: true });
326
+
327
+ // Iterate over primary store (in-memory)
328
+ console.log('Primary store contents:');
329
+ if (cache.primary.iterator) {
330
+ for await (const [key, value] of cache.primary.iterator()) {
331
+ console.log(` ${key}:`, JSON.stringify(value));
332
+ }
333
+ }
334
+
335
+ // Iterate over secondary store (Redis)
336
+ console.log('\nSecondary store contents:');
337
+ if (cache.secondary?.iterator) {
338
+ for await (const [key, value] of cache.secondary.iterator()) {
339
+ console.log(` ${key}:`, JSON.stringify(value));
340
+ }
341
+ }
342
+ ```
343
+
344
+ ## Safe Iteration Helper
345
+
346
+ Here's a recommended helper function for safe iteration that checks for store availability and iterator support:
347
+
348
+ ```typescript
349
+ import { Cacheable } from 'cacheable';
350
+ import type { Keyv } from 'keyv';
351
+
352
+ async function iterateStore(store: Keyv | undefined, storeName: string) {
353
+ if (!store) {
354
+ console.log(`${storeName} store not configured`);
355
+ return;
356
+ }
357
+
358
+ if (!store.iterator) {
359
+ console.log(`${storeName} store does not support iteration`);
360
+ return;
361
+ }
362
+
363
+ console.log(`${storeName} store entries:`);
364
+ for await (const [key, value] of store.iterator()) {
365
+ console.log(` ${key}:`, value);
366
+ }
367
+ }
368
+
369
+ // Usage
370
+ const cache = new Cacheable({ /* options */ });
371
+ await iterateStore(cache.primary, 'Primary');
372
+ await iterateStore(cache.secondary, 'Secondary');
373
+ ```
374
+
375
+ ## Storage Adapter Support
376
+
377
+ The `iterator()` method is available when:
378
+ - The store is a Map instance (has Symbol.iterator)
379
+ - The store implements an `iterator()` method (e.g., Redis, Valkey, etc.)
380
+ - The store is a supported iterable adapter
381
+
382
+ Common stores that support iteration:
383
+ - In-memory (Map-based stores)
384
+ - @keyv/redis
385
+ - @keyv/valkey
386
+ - Other Keyv adapters that implement the iterator interface
282
387
 
283
388
  # Non-Blocking Operations
284
389
 
@@ -442,6 +547,45 @@ const cache = new Cacheable({
442
547
  });
443
548
  ```
444
549
 
550
+ ## Namespace Isolation with Sync
551
+
552
+ When multiple services share the same Redis instance (or other message provider), you can use namespaces to isolate cache synchronization events between services. This prevents one service's cache updates from affecting another service's cache.
553
+
554
+ ```javascript
555
+ import { Cacheable } from 'cacheable';
556
+ import { RedisMessageProvider } from '@qified/redis';
557
+
558
+ const provider = new RedisMessageProvider({
559
+ connection: { host: 'localhost', port: 6379 }
560
+ });
561
+
562
+ // Service 1 with namespace
563
+ const serviceA = new Cacheable({
564
+ namespace: 'service-a',
565
+ sync: { qified: provider }
566
+ });
567
+
568
+ // Service 2 with different namespace
569
+ const serviceB = new Cacheable({
570
+ namespace: 'service-b',
571
+ sync: { qified: provider }
572
+ });
573
+
574
+ // Set value in service A
575
+ await serviceA.set('config', { timeout: 5000 });
576
+
577
+ // Service B won't receive this update because it has a different namespace
578
+ const value = await serviceB.get('config'); // undefined
579
+ ```
580
+
581
+ **How Namespace Isolation Works:**
582
+ - Without namespaces, sync events use channel names like `cache:set` and `cache:delete`
583
+ - With namespaces, events are prefixed: `service-a::cache:set`, `service-b::cache:set`
584
+ - Services only subscribe to events matching their namespace, ensuring complete isolation
585
+ - Namespaces can be static strings or functions that return strings
586
+
587
+ **Note:** The namespace is automatically passed from Cacheable to CacheableSync, so you only need to set it once in the Cacheable options.
588
+
445
589
  ## How Sync Works
446
590
 
447
591
  1. **SET Operations**: When you call `cache.set()` or `cache.setMany()`, the cache:
@@ -517,7 +661,8 @@ _This does not enable statistics for your layer 2 cache as that is a distributed
517
661
  * `removeHook(hook)`: Removes a hook.
518
662
  * `on(event, callback)`: Listens for an event.
519
663
  * `removeListener(event, callback)`: Removes a listener.
520
- * `hash(object: any, algorithm = 'sha256'): string`: Hashes an object with the algorithm. Default is `sha256`.
664
+ * `hash(object: any, algorithm = 'SHA-256'): Promise<string>`: Asynchronously hashes an object with a cryptographic algorithm (SHA-256, SHA-384, SHA-512). Default is `SHA-256`.
665
+ * `hashSync(object: any, algorithm = 'djb2'): string`: Synchronously hashes an object with a non-cryptographic algorithm (djb2, fnv1, murmer, crc32). Default is `djb2`.
521
666
  * `primary`: The primary store for the cache (layer 1) defaults to in-memory by Keyv.
522
667
  * `secondary`: The secondary store for the cache (layer 2) usually a persistent cache by Keyv.
523
668
  * `namespace`: The namespace for the cache. Default is `undefined`. This will set the namespace for the primary and secondary stores.
@@ -544,7 +689,7 @@ To learn more go to [@cacheable/memory](https://cacheable.org/docs/memory/)
544
689
 
545
690
  # Wrap / Memoization for Sync and Async Functions
546
691
 
547
- `Cacheable` and `CacheableMemory` has a feature called `wrap` that comes from [@cacheable/memoize](https://cacheable.org/docs/memoize/) and allows you to wrap a function in a cache. This is useful for memoization and caching the results of a function. You can wrap a `sync` or `async` function in a cache. Here is an example of how to use the `wrap` function:
692
+ `Cacheable` and `CacheableMemory` has a feature called `wrap` that comes from [@cacheable/utils](https://cacheable.org/docs/utils/) and allows you to wrap a function in a cache. This is useful for memoization and caching the results of a function. You can wrap a `sync` or `async` function in a cache. Here is an example of how to use the `wrap` function:
548
693
 
549
694
  ```javascript
550
695
  import { Cacheable } from 'cacheable';
@@ -637,11 +782,11 @@ If you would like to generate your own key for the wrapped function you can set
637
782
 
638
783
  We will pass in the `function` that is being wrapped, the `arguments` passed to the function, and the `options` used to wrap the function. You can then use these to generate a custom key for the cache.
639
784
 
640
- To learn more visit [@cacheable/memoize](https://cacheable.org/docs/memoize/)
785
+ To learn more visit [@cacheable/utils](https://cacheable.org/docs/utils/)
641
786
 
642
787
  # Get Or Set Memoization Function
643
788
 
644
- The `getOrSet` method that comes from [@cacheable/memoize](https://cacheable.org/docs/memoize/) provides a convenient way to implement the cache-aside pattern. It attempts to retrieve a value from cache, and if not found, calls the provided function to compute the value and store it in cache before returning it. Here are the options:
789
+ The `getOrSet` method that comes from [@cacheable/utils](https://cacheable.org/docs/utils/) provides a convenient way to implement the cache-aside pattern. It attempts to retrieve a value from cache, and if not found, calls the provided function to compute the value and store it in cache before returning it. Here are the options:
645
790
 
646
791
  ```typescript
647
792
  export type GetOrSetFunctionOptions = {
@@ -677,17 +822,17 @@ const function_ = async () => Math.random() * 100;
677
822
  const value = await cache.getOrSet(generateKey(), function_, { ttl: '1h' });
678
823
  ```
679
824
 
680
- To learn more go to [@cacheable/memoize](https://cacheable.org/docs/memoize/)
825
+ To learn more go to [@cacheable/utils](https://cacheable.org/docs/utils/)
681
826
 
682
827
  # v1 to v2 Changes
683
828
 
684
- `cacheable` is now using `@cacheable/utils`, `@cacheable/memoize`, and `@cacheable/memory` for its core functionality as we are moving to this modular architecture and plan to eventually have these modules across `cache-manager` and `flat-cache`. In addition there are some breaking changes:
829
+ `cacheable` is now using `@cacheable/utils` and `@cacheable/memory` for its core functionality as we are moving to this modular architecture and plan to eventually have these modules across `cache-manager` and `flat-cache`. In addition there are some breaking changes:
685
830
 
686
831
  * `get()` and `getMany()` no longer have the `raw` option but instead we have built out `getRaw()` and `getManyRaw()` to use.
687
832
  * All `get` related functions now support `nonBlocking` which means if `nonBlocking: true` the primary store will return what it has and then in the background will work to sync from secondary storage for any misses. You can disable this by setting at the `get` function level the option `nonBlocking: false` which will look for any missing keys in the secondary.
688
- * `Keyv` v5.5+ is now the recommended supported version as we are using its native `getMany*` and `getRaw*`
833
+ * `Keyv` v5.5+ is now the recommended supported version as we are using its native `getMany*`, `getRaw*`, and `hasMany` methods for improved performance
689
834
  * `Wrap` and `getOrSet` have been updated with more robust options including the ability to use your own `serialize` function for creating the key in `wrap`.
690
- * `hash` has now been updated with robust options and also an enum for setting the algorithm.
835
+ * `hash` has been split into async (`hash()` and `hashToNumber()`) and sync (`hashSync()` and `hashToNumberSync()`) methods. MD5 support has been removed. Now uses Hashery library with support for additional algorithms (SHA-384, FNV1, MURMER, CRC32).
691
836
 
692
837
  # How to Contribute
693
838
 
package/dist/index.cjs CHANGED
@@ -34,15 +34,14 @@ __export(index_exports, {
34
34
  calculateTtlFromExpiration: () => import_utils2.calculateTtlFromExpiration,
35
35
  createKeyv: () => import_memory2.createKeyv,
36
36
  getCascadingTtl: () => import_utils2.getCascadingTtl,
37
- getOrSet: () => import_memoize2.getOrSet,
37
+ getOrSet: () => import_utils2.getOrSet,
38
38
  hash: () => import_utils2.hash,
39
39
  shorthandToMilliseconds: () => import_utils2.shorthandToMilliseconds,
40
40
  shorthandToTime: () => import_utils2.shorthandToTime,
41
- wrap: () => import_memoize2.wrap,
42
- wrapSync: () => import_memoize2.wrapSync
41
+ wrap: () => import_utils2.wrap,
42
+ wrapSync: () => import_utils2.wrapSync
43
43
  });
44
44
  module.exports = __toCommonJS(index_exports);
45
- var import_memoize = require("@cacheable/memoize");
46
45
  var import_memory = require("@cacheable/memory");
47
46
  var import_utils = require("@cacheable/utils");
48
47
  var import_hookified2 = require("hookified");
@@ -79,12 +78,16 @@ var CacheableSyncEvents = /* @__PURE__ */ ((CacheableSyncEvents2) => {
79
78
  })(CacheableSyncEvents || {});
80
79
  var CacheableSync = class extends import_hookified.Hookified {
81
80
  _qified = new import_qified.Qified();
81
+ _namespace;
82
+ _storage;
83
+ _cacheId;
82
84
  /**
83
85
  * Creates an instance of CacheableSync
84
86
  * @param options - Configuration options for CacheableSync
85
87
  */
86
88
  constructor(options) {
87
89
  super(options);
90
+ this._namespace = options.namespace;
88
91
  this._qified = this.createQified(options.qified);
89
92
  }
90
93
  /**
@@ -101,12 +104,36 @@ var CacheableSync = class extends import_hookified.Hookified {
101
104
  set qified(value) {
102
105
  this._qified = this.createQified(value);
103
106
  }
107
+ /**
108
+ * Gets the namespace for sync events
109
+ * @returns The namespace or undefined if not set
110
+ */
111
+ get namespace() {
112
+ return this._namespace;
113
+ }
114
+ /**
115
+ * Sets the namespace for sync events and resubscribes if needed
116
+ * @param namespace - The namespace string or function
117
+ */
118
+ set namespace(namespace) {
119
+ if (this._storage && this._cacheId) {
120
+ const oldSetEvent = this.getPrefixedEvent("cache:set" /* SET */);
121
+ const oldDeleteEvent = this.getPrefixedEvent("cache:delete" /* DELETE */);
122
+ void this._qified.unsubscribe(oldSetEvent);
123
+ void this._qified.unsubscribe(oldDeleteEvent);
124
+ }
125
+ this._namespace = namespace;
126
+ if (this._storage && this._cacheId) {
127
+ this.subscribe(this._storage, this._cacheId);
128
+ }
129
+ }
104
130
  /**
105
131
  * Publishes a cache event to all the cache instances
106
132
  * @param data - The cache item data containing cacheId, key, value, and optional ttl
107
133
  */
108
134
  async publish(event, data) {
109
- await this._qified.publish(event, {
135
+ const eventName = this.getPrefixedEvent(event);
136
+ await this._qified.publish(eventName, {
110
137
  id: crypto.randomUUID(),
111
138
  data
112
139
  });
@@ -117,7 +144,11 @@ var CacheableSync = class extends import_hookified.Hookified {
117
144
  * @param cacheId - The cache ID to identify this instance
118
145
  */
119
146
  subscribe(storage, cacheId) {
120
- this._qified.subscribe("cache:set" /* SET */, {
147
+ this._storage = storage;
148
+ this._cacheId = cacheId;
149
+ const setEvent = this.getPrefixedEvent("cache:set" /* SET */);
150
+ const deleteEvent = this.getPrefixedEvent("cache:delete" /* DELETE */);
151
+ this._qified.subscribe(setEvent, {
121
152
  handler: async (message) => {
122
153
  const data = message.data;
123
154
  if (data.cacheId !== cacheId) {
@@ -125,7 +156,7 @@ var CacheableSync = class extends import_hookified.Hookified {
125
156
  }
126
157
  }
127
158
  });
128
- this._qified.subscribe("cache:delete" /* DELETE */, {
159
+ this._qified.subscribe(deleteEvent, {
129
160
  handler: async (message) => {
130
161
  const data = message.data;
131
162
  if (data.cacheId !== cacheId) {
@@ -146,10 +177,28 @@ var CacheableSync = class extends import_hookified.Hookified {
146
177
  const providers = Array.isArray(value) ? value : [value];
147
178
  return new import_qified.Qified({ messageProviders: providers });
148
179
  }
180
+ /**
181
+ * Gets the namespace prefix to use for event names
182
+ * @returns The resolved namespace string or undefined
183
+ */
184
+ getNamespace() {
185
+ if (typeof this._namespace === "function") {
186
+ return this._namespace();
187
+ }
188
+ return this._namespace;
189
+ }
190
+ /**
191
+ * Prefixes an event name with the namespace if one is set
192
+ * @param event - The event to prefix
193
+ * @returns The prefixed event name or the original event
194
+ */
195
+ getPrefixedEvent(event) {
196
+ const ns = this.getNamespace();
197
+ return ns ? `${ns}::${event}` : event;
198
+ }
149
199
  };
150
200
 
151
201
  // src/index.ts
152
- var import_memoize2 = require("@cacheable/memoize");
153
202
  var import_memory2 = require("@cacheable/memory");
154
203
  var import_utils2 = require("@cacheable/utils");
155
204
  var import_keyv2 = require("keyv");
@@ -194,7 +243,10 @@ var Cacheable = class extends import_hookified2.Hookified {
194
243
  }
195
244
  }
196
245
  if (options?.sync) {
197
- this._sync = options.sync instanceof CacheableSync ? options.sync : new CacheableSync(options.sync);
246
+ this._sync = options.sync instanceof CacheableSync ? options.sync : new CacheableSync({
247
+ ...options.sync,
248
+ namespace: options.namespace
249
+ });
198
250
  this._sync.subscribe(this._primary, this._cacheId);
199
251
  }
200
252
  }
@@ -216,6 +268,9 @@ var Cacheable = class extends import_hookified2.Hookified {
216
268
  if (this._secondary) {
217
269
  this._secondary.namespace = this.getNameSpace();
218
270
  }
271
+ if (this._sync) {
272
+ this._sync.namespace = namespace;
273
+ }
219
274
  }
220
275
  /**
221
276
  * The statistics for the cacheable instance
@@ -677,7 +732,7 @@ var Cacheable = class extends import_hookified2.Hookified {
677
732
  * @returns {Promise<boolean[]>} Whether the keys exist
678
733
  */
679
734
  async hasMany(keys) {
680
- const result = await this.hasManyKeyv(this._primary, keys);
735
+ const result = await this._primary.hasMany(keys);
681
736
  const missingKeys = [];
682
737
  for (const [i, key] of keys.entries()) {
683
738
  if (!result[i] && this._secondary) {
@@ -685,7 +740,7 @@ var Cacheable = class extends import_hookified2.Hookified {
685
740
  }
686
741
  }
687
742
  if (missingKeys.length > 0 && this._secondary) {
688
- const secondary = await this.hasManyKeyv(this._secondary, keys);
743
+ const secondary = await this._secondary.hasMany(keys);
689
744
  for (const [i, _key] of keys.entries()) {
690
745
  if (!result[i] && secondary[i]) {
691
746
  result[i] = secondary[i];
@@ -795,6 +850,7 @@ var Cacheable = class extends import_hookified2.Hookified {
795
850
  if (this._secondary) {
796
851
  promises.push(this._secondary.disconnect());
797
852
  }
853
+ promises.push(this._sync?.qified.disconnect());
798
854
  await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
799
855
  }
800
856
  /**
@@ -809,18 +865,16 @@ var Cacheable = class extends import_hookified2.Hookified {
809
865
  wrap(function_, options) {
810
866
  const cacheAdapter = {
811
867
  get: async (key) => this.get(key),
868
+ /* v8 ignore next -- @preserve */
812
869
  has: async (key) => this.has(key),
813
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
814
870
  set: async (key, value, ttl) => {
815
871
  await this.set(key, value, ttl);
816
872
  },
817
- /* c8 ignore start */
818
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
873
+ /* v8 ignore next -- @preserve */
819
874
  on: (event, listener) => {
820
875
  this.on(event, listener);
821
876
  },
822
- /* c8 ignore stop */
823
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
877
+ /* v8 ignore next -- @preserve */
824
878
  emit: (event, ...args) => this.emit(event, ...args)
825
879
  };
826
880
  const wrapOptions = {
@@ -832,7 +886,7 @@ var Cacheable = class extends import_hookified2.Hookified {
832
886
  cacheId: this._cacheId,
833
887
  serialize: options?.serialize
834
888
  };
835
- return (0, import_memoize.wrap)(function_, wrapOptions);
889
+ return (0, import_utils.wrap)(function_, wrapOptions);
836
890
  }
837
891
  /**
838
892
  * Retrieves the value associated with the given key from the cache. If the key is not found,
@@ -847,18 +901,15 @@ var Cacheable = class extends import_hookified2.Hookified {
847
901
  async getOrSet(key, function_, options) {
848
902
  const cacheAdapter = {
849
903
  get: async (key2) => this.get(key2),
904
+ /* v8 ignore next -- @preserve */
850
905
  has: async (key2) => this.has(key2),
851
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
852
906
  set: async (key2, value, ttl) => {
853
907
  await this.set(key2, value, ttl);
854
908
  },
855
- /* c8 ignore start */
856
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
909
+ /* v8 ignore next -- @preserve */
857
910
  on: (event, listener) => {
858
911
  this.on(event, listener);
859
912
  },
860
- /* c8 ignore stop */
861
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
862
913
  emit: (event, ...args) => this.emit(event, ...args)
863
914
  };
864
915
  const getOrSetOptions = {
@@ -868,17 +919,29 @@ var Cacheable = class extends import_hookified2.Hookified {
868
919
  cacheErrors: options?.cacheErrors,
869
920
  throwErrors: options?.throwErrors
870
921
  };
871
- return (0, import_memoize.getOrSet)(key, function_, getOrSetOptions);
922
+ return (0, import_utils.getOrSet)(key, function_, getOrSetOptions);
923
+ }
924
+ /**
925
+ * Will hash an object asynchronously using the specified cryptographic algorithm.
926
+ * Use this for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
927
+ * For non-cryptographic algorithms, use hashSync() for better performance.
928
+ * @param {any} object the object to hash
929
+ * @param {string} algorithm the hash algorithm to use. The default is 'SHA-256'
930
+ * @returns {Promise<string>} the hash of the object
931
+ */
932
+ async hash(object, algorithm = import_utils.HashAlgorithm.SHA256) {
933
+ return (0, import_utils.hash)(object, { algorithm });
872
934
  }
873
935
  /**
874
- * Will hash an object using the specified algorithm. The default algorithm is 'sha256'.
936
+ * Will hash an object synchronously using the specified non-cryptographic algorithm.
937
+ * Use this for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
938
+ * For cryptographic algorithms, use hash() instead.
875
939
  * @param {any} object the object to hash
876
- * @param {string} algorithm the hash algorithm to use. The default is 'sha256'
940
+ * @param {string} algorithm the hash algorithm to use. The default is 'djb2'
877
941
  * @returns {string} the hash of the object
878
942
  */
879
- hash(object, algorithm = import_utils.HashAlgorithm.SHA256) {
880
- const validAlgorithm = Object.values(import_utils.HashAlgorithm).includes(algorithm) ? algorithm : import_utils.HashAlgorithm.SHA256;
881
- return (0, import_utils.hash)(object, { algorithm: validAlgorithm });
943
+ hashSync(object, algorithm = import_utils.HashAlgorithm.DJB2) {
944
+ return (0, import_utils.hashSync)(object, { algorithm });
882
945
  }
883
946
  async setManyKeyv(keyv, items) {
884
947
  const entries = [];
@@ -889,13 +952,6 @@ var Cacheable = class extends import_hookified2.Hookified {
889
952
  await keyv.setMany(entries);
890
953
  return true;
891
954
  }
892
- async hasManyKeyv(keyv, keys) {
893
- const promises = [];
894
- for (const key of keys) {
895
- promises.push(keyv.has(key));
896
- }
897
- return Promise.all(promises);
898
- }
899
955
  /**
900
956
  * Processes a single key from secondary store for getRaw operation
901
957
  * @param primary - the primary store to use
@@ -1085,3 +1141,4 @@ var Cacheable = class extends import_hookified2.Hookified {
1085
1141
  wrap,
1086
1142
  wrapSync
1087
1143
  });
1144
+ /* v8 ignore next -- @preserve */
package/dist/index.d.cts CHANGED
@@ -1,7 +1,5 @@
1
- import { WrapFunctionOptions, GetOrSetKey, GetOrSetFunctionOptions } from '@cacheable/memoize';
2
- export { GetOrSetFunctionOptions, GetOrSetKey, GetOrSetOptions, WrapOptions, WrapSyncOptions, getOrSet, wrap, wrapSync } from '@cacheable/memoize';
3
- import { Stats, CacheableItem, HashAlgorithm } from '@cacheable/utils';
4
- export { CacheableItem, Stats as CacheableStats, HashAlgorithm, calculateTtlFromExpiration, getCascadingTtl, hash, shorthandToMilliseconds, shorthandToTime } from '@cacheable/utils';
1
+ import { Stats, CacheableItem, WrapFunctionOptions, GetOrSetKey, GetOrSetFunctionOptions, HashAlgorithm } from '@cacheable/utils';
2
+ export { CacheableItem, Stats as CacheableStats, GetOrSetFunctionOptions, GetOrSetKey, GetOrSetOptions, HashAlgorithm, WrapOptions, WrapSyncOptions, calculateTtlFromExpiration, getCascadingTtl, getOrSet, hash, shorthandToMilliseconds, shorthandToTime, wrap, wrapSync } from '@cacheable/utils';
5
3
  import { Hookified, HookifiedOptions } from 'hookified';
6
4
  import { Keyv, KeyvStoreAdapter, StoredDataRaw } from 'keyv';
7
5
  export { Keyv, KeyvHooks, KeyvOptions, KeyvStoreAdapter } from 'keyv';
@@ -24,6 +22,11 @@ type CacheableSyncOptions = {
24
22
  * Qified instance or message provider(s) for synchronization
25
23
  */
26
24
  qified: Qified | MessageProvider | MessageProvider[];
25
+ /**
26
+ * The namespace for sync events. It can be a string or a function that returns a string.
27
+ * When set, event names will be prefixed with the namespace (e.g., "my-namespace::cache:set")
28
+ */
29
+ namespace?: string | (() => string);
27
30
  } & HookifiedOptions;
28
31
  type CacheableSyncItem = {
29
32
  cacheId: string;
@@ -37,6 +40,9 @@ type CacheableSyncItem = {
37
40
  */
38
41
  declare class CacheableSync extends Hookified {
39
42
  private _qified;
43
+ private _namespace?;
44
+ private _storage?;
45
+ private _cacheId?;
40
46
  /**
41
47
  * Creates an instance of CacheableSync
42
48
  * @param options - Configuration options for CacheableSync
@@ -52,6 +58,16 @@ declare class CacheableSync extends Hookified {
52
58
  * @param value - Either an existing Qified instance or MessageProvider(s)
53
59
  */
54
60
  set qified(value: Qified | MessageProvider | MessageProvider[]);
61
+ /**
62
+ * Gets the namespace for sync events
63
+ * @returns The namespace or undefined if not set
64
+ */
65
+ get namespace(): string | (() => string) | undefined;
66
+ /**
67
+ * Sets the namespace for sync events and resubscribes if needed
68
+ * @param namespace - The namespace string or function
69
+ */
70
+ set namespace(namespace: string | (() => string) | undefined);
55
71
  /**
56
72
  * Publishes a cache event to all the cache instances
57
73
  * @param data - The cache item data containing cacheId, key, value, and optional ttl
@@ -69,6 +85,17 @@ declare class CacheableSync extends Hookified {
69
85
  * @returns A Qified instance configured with the provided message provider(s)
70
86
  */
71
87
  createQified(value: Qified | MessageProvider | MessageProvider[]): Qified;
88
+ /**
89
+ * Gets the namespace prefix to use for event names
90
+ * @returns The resolved namespace string or undefined
91
+ */
92
+ private getNamespace;
93
+ /**
94
+ * Prefixes an event name with the namespace if one is set
95
+ * @param event - The event to prefix
96
+ * @returns The prefixed event name or the original event
97
+ */
98
+ private getPrefixedEvent;
72
99
  }
73
100
 
74
101
  type CacheableOptions = {
@@ -408,14 +435,24 @@ declare class Cacheable extends Hookified {
408
435
  */
409
436
  getOrSet<T>(key: GetOrSetKey, function_: () => Promise<T>, options?: GetOrSetFunctionOptions): Promise<T | undefined>;
410
437
  /**
411
- * Will hash an object using the specified algorithm. The default algorithm is 'sha256'.
438
+ * Will hash an object asynchronously using the specified cryptographic algorithm.
439
+ * Use this for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
440
+ * For non-cryptographic algorithms, use hashSync() for better performance.
441
+ * @param {any} object the object to hash
442
+ * @param {string} algorithm the hash algorithm to use. The default is 'SHA-256'
443
+ * @returns {Promise<string>} the hash of the object
444
+ */
445
+ hash(object: any, algorithm?: HashAlgorithm): Promise<string>;
446
+ /**
447
+ * Will hash an object synchronously using the specified non-cryptographic algorithm.
448
+ * Use this for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
449
+ * For cryptographic algorithms, use hash() instead.
412
450
  * @param {any} object the object to hash
413
- * @param {string} algorithm the hash algorithm to use. The default is 'sha256'
451
+ * @param {string} algorithm the hash algorithm to use. The default is 'djb2'
414
452
  * @returns {string} the hash of the object
415
453
  */
416
- hash(object: any, algorithm?: HashAlgorithm): string;
454
+ hashSync(object: any, algorithm?: HashAlgorithm): string;
417
455
  private setManyKeyv;
418
- private hasManyKeyv;
419
456
  /**
420
457
  * Processes a single key from secondary store for getRaw operation
421
458
  * @param primary - the primary store to use
package/dist/index.d.ts CHANGED
@@ -1,7 +1,5 @@
1
- import { WrapFunctionOptions, GetOrSetKey, GetOrSetFunctionOptions } from '@cacheable/memoize';
2
- export { GetOrSetFunctionOptions, GetOrSetKey, GetOrSetOptions, WrapOptions, WrapSyncOptions, getOrSet, wrap, wrapSync } from '@cacheable/memoize';
3
- import { Stats, CacheableItem, HashAlgorithm } from '@cacheable/utils';
4
- export { CacheableItem, Stats as CacheableStats, HashAlgorithm, calculateTtlFromExpiration, getCascadingTtl, hash, shorthandToMilliseconds, shorthandToTime } from '@cacheable/utils';
1
+ import { Stats, CacheableItem, WrapFunctionOptions, GetOrSetKey, GetOrSetFunctionOptions, HashAlgorithm } from '@cacheable/utils';
2
+ export { CacheableItem, Stats as CacheableStats, GetOrSetFunctionOptions, GetOrSetKey, GetOrSetOptions, HashAlgorithm, WrapOptions, WrapSyncOptions, calculateTtlFromExpiration, getCascadingTtl, getOrSet, hash, shorthandToMilliseconds, shorthandToTime, wrap, wrapSync } from '@cacheable/utils';
5
3
  import { Hookified, HookifiedOptions } from 'hookified';
6
4
  import { Keyv, KeyvStoreAdapter, StoredDataRaw } from 'keyv';
7
5
  export { Keyv, KeyvHooks, KeyvOptions, KeyvStoreAdapter } from 'keyv';
@@ -24,6 +22,11 @@ type CacheableSyncOptions = {
24
22
  * Qified instance or message provider(s) for synchronization
25
23
  */
26
24
  qified: Qified | MessageProvider | MessageProvider[];
25
+ /**
26
+ * The namespace for sync events. It can be a string or a function that returns a string.
27
+ * When set, event names will be prefixed with the namespace (e.g., "my-namespace::cache:set")
28
+ */
29
+ namespace?: string | (() => string);
27
30
  } & HookifiedOptions;
28
31
  type CacheableSyncItem = {
29
32
  cacheId: string;
@@ -37,6 +40,9 @@ type CacheableSyncItem = {
37
40
  */
38
41
  declare class CacheableSync extends Hookified {
39
42
  private _qified;
43
+ private _namespace?;
44
+ private _storage?;
45
+ private _cacheId?;
40
46
  /**
41
47
  * Creates an instance of CacheableSync
42
48
  * @param options - Configuration options for CacheableSync
@@ -52,6 +58,16 @@ declare class CacheableSync extends Hookified {
52
58
  * @param value - Either an existing Qified instance or MessageProvider(s)
53
59
  */
54
60
  set qified(value: Qified | MessageProvider | MessageProvider[]);
61
+ /**
62
+ * Gets the namespace for sync events
63
+ * @returns The namespace or undefined if not set
64
+ */
65
+ get namespace(): string | (() => string) | undefined;
66
+ /**
67
+ * Sets the namespace for sync events and resubscribes if needed
68
+ * @param namespace - The namespace string or function
69
+ */
70
+ set namespace(namespace: string | (() => string) | undefined);
55
71
  /**
56
72
  * Publishes a cache event to all the cache instances
57
73
  * @param data - The cache item data containing cacheId, key, value, and optional ttl
@@ -69,6 +85,17 @@ declare class CacheableSync extends Hookified {
69
85
  * @returns A Qified instance configured with the provided message provider(s)
70
86
  */
71
87
  createQified(value: Qified | MessageProvider | MessageProvider[]): Qified;
88
+ /**
89
+ * Gets the namespace prefix to use for event names
90
+ * @returns The resolved namespace string or undefined
91
+ */
92
+ private getNamespace;
93
+ /**
94
+ * Prefixes an event name with the namespace if one is set
95
+ * @param event - The event to prefix
96
+ * @returns The prefixed event name or the original event
97
+ */
98
+ private getPrefixedEvent;
72
99
  }
73
100
 
74
101
  type CacheableOptions = {
@@ -408,14 +435,24 @@ declare class Cacheable extends Hookified {
408
435
  */
409
436
  getOrSet<T>(key: GetOrSetKey, function_: () => Promise<T>, options?: GetOrSetFunctionOptions): Promise<T | undefined>;
410
437
  /**
411
- * Will hash an object using the specified algorithm. The default algorithm is 'sha256'.
438
+ * Will hash an object asynchronously using the specified cryptographic algorithm.
439
+ * Use this for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
440
+ * For non-cryptographic algorithms, use hashSync() for better performance.
441
+ * @param {any} object the object to hash
442
+ * @param {string} algorithm the hash algorithm to use. The default is 'SHA-256'
443
+ * @returns {Promise<string>} the hash of the object
444
+ */
445
+ hash(object: any, algorithm?: HashAlgorithm): Promise<string>;
446
+ /**
447
+ * Will hash an object synchronously using the specified non-cryptographic algorithm.
448
+ * Use this for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
449
+ * For cryptographic algorithms, use hash() instead.
412
450
  * @param {any} object the object to hash
413
- * @param {string} algorithm the hash algorithm to use. The default is 'sha256'
451
+ * @param {string} algorithm the hash algorithm to use. The default is 'djb2'
414
452
  * @returns {string} the hash of the object
415
453
  */
416
- hash(object: any, algorithm?: HashAlgorithm): string;
454
+ hashSync(object: any, algorithm?: HashAlgorithm): string;
417
455
  private setManyKeyv;
418
- private hasManyKeyv;
419
456
  /**
420
457
  * Processes a single key from secondary store for getRaw operation
421
458
  * @param primary - the primary store to use
package/dist/index.js CHANGED
@@ -1,17 +1,16 @@
1
1
  // src/index.ts
2
- import {
3
- getOrSet,
4
- wrap
5
- } from "@cacheable/memoize";
6
2
  import { createKeyv } from "@cacheable/memory";
7
3
  import {
8
4
  Stats as CacheableStats,
9
5
  calculateTtlFromExpiration,
10
6
  getCascadingTtl,
7
+ getOrSet,
11
8
  HashAlgorithm,
12
9
  hash,
10
+ hashSync,
13
11
  isKeyvInstance,
14
- shorthandToMilliseconds
12
+ shorthandToMilliseconds,
13
+ wrap
15
14
  } from "@cacheable/utils";
16
15
  import { Hookified as Hookified2 } from "hookified";
17
16
  import {
@@ -49,12 +48,16 @@ var CacheableSyncEvents = /* @__PURE__ */ ((CacheableSyncEvents2) => {
49
48
  })(CacheableSyncEvents || {});
50
49
  var CacheableSync = class extends Hookified {
51
50
  _qified = new Qified();
51
+ _namespace;
52
+ _storage;
53
+ _cacheId;
52
54
  /**
53
55
  * Creates an instance of CacheableSync
54
56
  * @param options - Configuration options for CacheableSync
55
57
  */
56
58
  constructor(options) {
57
59
  super(options);
60
+ this._namespace = options.namespace;
58
61
  this._qified = this.createQified(options.qified);
59
62
  }
60
63
  /**
@@ -71,12 +74,36 @@ var CacheableSync = class extends Hookified {
71
74
  set qified(value) {
72
75
  this._qified = this.createQified(value);
73
76
  }
77
+ /**
78
+ * Gets the namespace for sync events
79
+ * @returns The namespace or undefined if not set
80
+ */
81
+ get namespace() {
82
+ return this._namespace;
83
+ }
84
+ /**
85
+ * Sets the namespace for sync events and resubscribes if needed
86
+ * @param namespace - The namespace string or function
87
+ */
88
+ set namespace(namespace) {
89
+ if (this._storage && this._cacheId) {
90
+ const oldSetEvent = this.getPrefixedEvent("cache:set" /* SET */);
91
+ const oldDeleteEvent = this.getPrefixedEvent("cache:delete" /* DELETE */);
92
+ void this._qified.unsubscribe(oldSetEvent);
93
+ void this._qified.unsubscribe(oldDeleteEvent);
94
+ }
95
+ this._namespace = namespace;
96
+ if (this._storage && this._cacheId) {
97
+ this.subscribe(this._storage, this._cacheId);
98
+ }
99
+ }
74
100
  /**
75
101
  * Publishes a cache event to all the cache instances
76
102
  * @param data - The cache item data containing cacheId, key, value, and optional ttl
77
103
  */
78
104
  async publish(event, data) {
79
- await this._qified.publish(event, {
105
+ const eventName = this.getPrefixedEvent(event);
106
+ await this._qified.publish(eventName, {
80
107
  id: crypto.randomUUID(),
81
108
  data
82
109
  });
@@ -87,7 +114,11 @@ var CacheableSync = class extends Hookified {
87
114
  * @param cacheId - The cache ID to identify this instance
88
115
  */
89
116
  subscribe(storage, cacheId) {
90
- this._qified.subscribe("cache:set" /* SET */, {
117
+ this._storage = storage;
118
+ this._cacheId = cacheId;
119
+ const setEvent = this.getPrefixedEvent("cache:set" /* SET */);
120
+ const deleteEvent = this.getPrefixedEvent("cache:delete" /* DELETE */);
121
+ this._qified.subscribe(setEvent, {
91
122
  handler: async (message) => {
92
123
  const data = message.data;
93
124
  if (data.cacheId !== cacheId) {
@@ -95,7 +126,7 @@ var CacheableSync = class extends Hookified {
95
126
  }
96
127
  }
97
128
  });
98
- this._qified.subscribe("cache:delete" /* DELETE */, {
129
+ this._qified.subscribe(deleteEvent, {
99
130
  handler: async (message) => {
100
131
  const data = message.data;
101
132
  if (data.cacheId !== cacheId) {
@@ -116,14 +147,28 @@ var CacheableSync = class extends Hookified {
116
147
  const providers = Array.isArray(value) ? value : [value];
117
148
  return new Qified({ messageProviders: providers });
118
149
  }
150
+ /**
151
+ * Gets the namespace prefix to use for event names
152
+ * @returns The resolved namespace string or undefined
153
+ */
154
+ getNamespace() {
155
+ if (typeof this._namespace === "function") {
156
+ return this._namespace();
157
+ }
158
+ return this._namespace;
159
+ }
160
+ /**
161
+ * Prefixes an event name with the namespace if one is set
162
+ * @param event - The event to prefix
163
+ * @returns The prefixed event name or the original event
164
+ */
165
+ getPrefixedEvent(event) {
166
+ const ns = this.getNamespace();
167
+ return ns ? `${ns}::${event}` : event;
168
+ }
119
169
  };
120
170
 
121
171
  // src/index.ts
122
- import {
123
- getOrSet as getOrSet2,
124
- wrap as wrap2,
125
- wrapSync
126
- } from "@cacheable/memoize";
127
172
  import {
128
173
  CacheableMemory,
129
174
  createKeyv as createKeyv2,
@@ -132,11 +177,14 @@ import {
132
177
  import {
133
178
  calculateTtlFromExpiration as calculateTtlFromExpiration2,
134
179
  getCascadingTtl as getCascadingTtl2,
180
+ getOrSet as getOrSet2,
135
181
  HashAlgorithm as HashAlgorithm2,
136
182
  hash as hash2,
137
183
  Stats,
138
184
  shorthandToMilliseconds as shorthandToMilliseconds2,
139
- shorthandToTime
185
+ shorthandToTime,
186
+ wrap as wrap2,
187
+ wrapSync
140
188
  } from "@cacheable/utils";
141
189
  import { Keyv as Keyv2, KeyvHooks } from "keyv";
142
190
  var Cacheable = class extends Hookified2 {
@@ -180,7 +228,10 @@ var Cacheable = class extends Hookified2 {
180
228
  }
181
229
  }
182
230
  if (options?.sync) {
183
- this._sync = options.sync instanceof CacheableSync ? options.sync : new CacheableSync(options.sync);
231
+ this._sync = options.sync instanceof CacheableSync ? options.sync : new CacheableSync({
232
+ ...options.sync,
233
+ namespace: options.namespace
234
+ });
184
235
  this._sync.subscribe(this._primary, this._cacheId);
185
236
  }
186
237
  }
@@ -202,6 +253,9 @@ var Cacheable = class extends Hookified2 {
202
253
  if (this._secondary) {
203
254
  this._secondary.namespace = this.getNameSpace();
204
255
  }
256
+ if (this._sync) {
257
+ this._sync.namespace = namespace;
258
+ }
205
259
  }
206
260
  /**
207
261
  * The statistics for the cacheable instance
@@ -663,7 +717,7 @@ var Cacheable = class extends Hookified2 {
663
717
  * @returns {Promise<boolean[]>} Whether the keys exist
664
718
  */
665
719
  async hasMany(keys) {
666
- const result = await this.hasManyKeyv(this._primary, keys);
720
+ const result = await this._primary.hasMany(keys);
667
721
  const missingKeys = [];
668
722
  for (const [i, key] of keys.entries()) {
669
723
  if (!result[i] && this._secondary) {
@@ -671,7 +725,7 @@ var Cacheable = class extends Hookified2 {
671
725
  }
672
726
  }
673
727
  if (missingKeys.length > 0 && this._secondary) {
674
- const secondary = await this.hasManyKeyv(this._secondary, keys);
728
+ const secondary = await this._secondary.hasMany(keys);
675
729
  for (const [i, _key] of keys.entries()) {
676
730
  if (!result[i] && secondary[i]) {
677
731
  result[i] = secondary[i];
@@ -781,6 +835,7 @@ var Cacheable = class extends Hookified2 {
781
835
  if (this._secondary) {
782
836
  promises.push(this._secondary.disconnect());
783
837
  }
838
+ promises.push(this._sync?.qified.disconnect());
784
839
  await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
785
840
  }
786
841
  /**
@@ -795,18 +850,16 @@ var Cacheable = class extends Hookified2 {
795
850
  wrap(function_, options) {
796
851
  const cacheAdapter = {
797
852
  get: async (key) => this.get(key),
853
+ /* v8 ignore next -- @preserve */
798
854
  has: async (key) => this.has(key),
799
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
800
855
  set: async (key, value, ttl) => {
801
856
  await this.set(key, value, ttl);
802
857
  },
803
- /* c8 ignore start */
804
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
858
+ /* v8 ignore next -- @preserve */
805
859
  on: (event, listener) => {
806
860
  this.on(event, listener);
807
861
  },
808
- /* c8 ignore stop */
809
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
862
+ /* v8 ignore next -- @preserve */
810
863
  emit: (event, ...args) => this.emit(event, ...args)
811
864
  };
812
865
  const wrapOptions = {
@@ -833,18 +886,15 @@ var Cacheable = class extends Hookified2 {
833
886
  async getOrSet(key, function_, options) {
834
887
  const cacheAdapter = {
835
888
  get: async (key2) => this.get(key2),
889
+ /* v8 ignore next -- @preserve */
836
890
  has: async (key2) => this.has(key2),
837
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
838
891
  set: async (key2, value, ttl) => {
839
892
  await this.set(key2, value, ttl);
840
893
  },
841
- /* c8 ignore start */
842
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
894
+ /* v8 ignore next -- @preserve */
843
895
  on: (event, listener) => {
844
896
  this.on(event, listener);
845
897
  },
846
- /* c8 ignore stop */
847
- // biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
848
898
  emit: (event, ...args) => this.emit(event, ...args)
849
899
  };
850
900
  const getOrSetOptions = {
@@ -857,14 +907,26 @@ var Cacheable = class extends Hookified2 {
857
907
  return getOrSet(key, function_, getOrSetOptions);
858
908
  }
859
909
  /**
860
- * Will hash an object using the specified algorithm. The default algorithm is 'sha256'.
910
+ * Will hash an object asynchronously using the specified cryptographic algorithm.
911
+ * Use this for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
912
+ * For non-cryptographic algorithms, use hashSync() for better performance.
861
913
  * @param {any} object the object to hash
862
- * @param {string} algorithm the hash algorithm to use. The default is 'sha256'
914
+ * @param {string} algorithm the hash algorithm to use. The default is 'SHA-256'
915
+ * @returns {Promise<string>} the hash of the object
916
+ */
917
+ async hash(object, algorithm = HashAlgorithm.SHA256) {
918
+ return hash(object, { algorithm });
919
+ }
920
+ /**
921
+ * Will hash an object synchronously using the specified non-cryptographic algorithm.
922
+ * Use this for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
923
+ * For cryptographic algorithms, use hash() instead.
924
+ * @param {any} object the object to hash
925
+ * @param {string} algorithm the hash algorithm to use. The default is 'djb2'
863
926
  * @returns {string} the hash of the object
864
927
  */
865
- hash(object, algorithm = HashAlgorithm.SHA256) {
866
- const validAlgorithm = Object.values(HashAlgorithm).includes(algorithm) ? algorithm : HashAlgorithm.SHA256;
867
- return hash(object, { algorithm: validAlgorithm });
928
+ hashSync(object, algorithm = HashAlgorithm.DJB2) {
929
+ return hashSync(object, { algorithm });
868
930
  }
869
931
  async setManyKeyv(keyv, items) {
870
932
  const entries = [];
@@ -875,13 +937,6 @@ var Cacheable = class extends Hookified2 {
875
937
  await keyv.setMany(entries);
876
938
  return true;
877
939
  }
878
- async hasManyKeyv(keyv, keys) {
879
- const promises = [];
880
- for (const key of keys) {
881
- promises.push(keyv.has(key));
882
- }
883
- return Promise.all(promises);
884
- }
885
940
  /**
886
941
  * Processes a single key from secondary store for getRaw operation
887
942
  * @param primary - the primary store to use
@@ -1070,3 +1125,4 @@ export {
1070
1125
  wrap2 as wrap,
1071
1126
  wrapSync
1072
1127
  };
1128
+ /* v8 ignore next -- @preserve */
package/package.json CHANGED
@@ -1,15 +1,21 @@
1
1
  {
2
2
  "name": "cacheable",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "High Performance Layer 1 / Layer 2 Caching with Keyv Storage",
5
5
  "type": "module",
6
- "main": "./dist/index.cjs",
6
+ "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "require": "./dist/index.cjs",
12
- "import": "./dist/index.js"
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
13
19
  }
14
20
  },
15
21
  "repository": {
@@ -21,26 +27,25 @@
21
27
  "license": "MIT",
22
28
  "private": false,
23
29
  "devDependencies": {
24
- "@biomejs/biome": "^2.2.6",
30
+ "@biomejs/biome": "^2.3.5",
25
31
  "@faker-js/faker": "^10.1.0",
26
- "@keyv/redis": "^5.1.3",
27
- "@keyv/valkey": "^1.0.10",
28
- "@qified/redis": "^0.5.0",
29
- "@types/node": "^24.8.1",
30
- "@vitest/coverage-v8": "^3.2.4",
32
+ "@keyv/redis": "^5.1.4",
33
+ "@keyv/valkey": "^1.0.11",
34
+ "@qified/redis": "^0.5.2",
35
+ "@types/node": "^24.10.1",
36
+ "@vitest/coverage-v8": "^4.0.9",
31
37
  "lru-cache": "^11.2.2",
32
- "rimraf": "^6.0.1",
33
- "tsup": "^8.5.0",
38
+ "rimraf": "^6.1.0",
39
+ "tsup": "^8.5.1",
34
40
  "typescript": "^5.9.3",
35
- "vitest": "^3.2.4"
41
+ "vitest": "^4.0.9"
36
42
  },
37
43
  "dependencies": {
38
- "hookified": "^1.12.2",
39
- "keyv": "^5.5.3",
40
- "qified": "^0.5.0",
41
- "@cacheable/memoize": "^2.0.3",
42
- "@cacheable/memory": "^2.0.3",
43
- "@cacheable/utils": "^2.1.0"
44
+ "hookified": "^1.13.0",
45
+ "keyv": "^5.5.4",
46
+ "qified": "^0.5.2",
47
+ "@cacheable/memory": "^2.0.6",
48
+ "@cacheable/utils": "^2.3.2"
44
49
  },
45
50
  "keywords": [
46
51
  "cacheable",