cacheable 2.1.1 → 2.2.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 +114 -8
- package/dist/index.cjs +31 -31
- package/dist/index.d.cts +16 -8
- package/dist/index.d.ts +16 -8
- package/dist/index.js +34 -35
- package/package.json +15 -16
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
|
|
|
@@ -517,7 +622,8 @@ _This does not enable statistics for your layer 2 cache as that is a distributed
|
|
|
517
622
|
* `removeHook(hook)`: Removes a hook.
|
|
518
623
|
* `on(event, callback)`: Listens for an event.
|
|
519
624
|
* `removeListener(event, callback)`: Removes a listener.
|
|
520
|
-
* `hash(object: any, algorithm = '
|
|
625
|
+
* `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`.
|
|
626
|
+
* `hashSync(object: any, algorithm = 'djb2'): string`: Synchronously hashes an object with a non-cryptographic algorithm (djb2, fnv1, murmer, crc32). Default is `djb2`.
|
|
521
627
|
* `primary`: The primary store for the cache (layer 1) defaults to in-memory by Keyv.
|
|
522
628
|
* `secondary`: The secondary store for the cache (layer 2) usually a persistent cache by Keyv.
|
|
523
629
|
* `namespace`: The namespace for the cache. Default is `undefined`. This will set the namespace for the primary and secondary stores.
|
|
@@ -544,7 +650,7 @@ To learn more go to [@cacheable/memory](https://cacheable.org/docs/memory/)
|
|
|
544
650
|
|
|
545
651
|
# Wrap / Memoization for Sync and Async Functions
|
|
546
652
|
|
|
547
|
-
`Cacheable` and `CacheableMemory` has a feature called `wrap` that comes from [@cacheable/
|
|
653
|
+
`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
654
|
|
|
549
655
|
```javascript
|
|
550
656
|
import { Cacheable } from 'cacheable';
|
|
@@ -637,11 +743,11 @@ If you would like to generate your own key for the wrapped function you can set
|
|
|
637
743
|
|
|
638
744
|
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
745
|
|
|
640
|
-
To learn more visit [@cacheable/
|
|
746
|
+
To learn more visit [@cacheable/utils](https://cacheable.org/docs/utils/)
|
|
641
747
|
|
|
642
748
|
# Get Or Set Memoization Function
|
|
643
749
|
|
|
644
|
-
The `getOrSet` method that comes from [@cacheable/
|
|
750
|
+
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
751
|
|
|
646
752
|
```typescript
|
|
647
753
|
export type GetOrSetFunctionOptions = {
|
|
@@ -677,17 +783,17 @@ const function_ = async () => Math.random() * 100;
|
|
|
677
783
|
const value = await cache.getOrSet(generateKey(), function_, { ttl: '1h' });
|
|
678
784
|
```
|
|
679
785
|
|
|
680
|
-
To learn more go to [@cacheable/
|
|
786
|
+
To learn more go to [@cacheable/utils](https://cacheable.org/docs/utils/)
|
|
681
787
|
|
|
682
788
|
# v1 to v2 Changes
|
|
683
789
|
|
|
684
|
-
`cacheable` is now using `@cacheable/utils
|
|
790
|
+
`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
791
|
|
|
686
792
|
* `get()` and `getMany()` no longer have the `raw` option but instead we have built out `getRaw()` and `getManyRaw()` to use.
|
|
687
793
|
* 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
|
|
794
|
+
* `Keyv` v5.5+ is now the recommended supported version as we are using its native `getMany*`, `getRaw*`, and `hasMany` methods for improved performance
|
|
689
795
|
* `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
|
|
796
|
+
* `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
797
|
|
|
692
798
|
# How to Contribute
|
|
693
799
|
|
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: () =>
|
|
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: () =>
|
|
42
|
-
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");
|
|
@@ -149,7 +148,6 @@ var CacheableSync = class extends import_hookified.Hookified {
|
|
|
149
148
|
};
|
|
150
149
|
|
|
151
150
|
// src/index.ts
|
|
152
|
-
var import_memoize2 = require("@cacheable/memoize");
|
|
153
151
|
var import_memory2 = require("@cacheable/memory");
|
|
154
152
|
var import_utils2 = require("@cacheable/utils");
|
|
155
153
|
var import_keyv2 = require("keyv");
|
|
@@ -677,7 +675,7 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
677
675
|
* @returns {Promise<boolean[]>} Whether the keys exist
|
|
678
676
|
*/
|
|
679
677
|
async hasMany(keys) {
|
|
680
|
-
const result = await this.
|
|
678
|
+
const result = await this._primary.hasMany(keys);
|
|
681
679
|
const missingKeys = [];
|
|
682
680
|
for (const [i, key] of keys.entries()) {
|
|
683
681
|
if (!result[i] && this._secondary) {
|
|
@@ -685,7 +683,7 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
685
683
|
}
|
|
686
684
|
}
|
|
687
685
|
if (missingKeys.length > 0 && this._secondary) {
|
|
688
|
-
const secondary = await this.
|
|
686
|
+
const secondary = await this._secondary.hasMany(keys);
|
|
689
687
|
for (const [i, _key] of keys.entries()) {
|
|
690
688
|
if (!result[i] && secondary[i]) {
|
|
691
689
|
result[i] = secondary[i];
|
|
@@ -795,6 +793,7 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
795
793
|
if (this._secondary) {
|
|
796
794
|
promises.push(this._secondary.disconnect());
|
|
797
795
|
}
|
|
796
|
+
promises.push(this._sync?.qified.disconnect());
|
|
798
797
|
await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
|
|
799
798
|
}
|
|
800
799
|
/**
|
|
@@ -809,18 +808,16 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
809
808
|
wrap(function_, options) {
|
|
810
809
|
const cacheAdapter = {
|
|
811
810
|
get: async (key) => this.get(key),
|
|
811
|
+
/* v8 ignore next -- @preserve */
|
|
812
812
|
has: async (key) => this.has(key),
|
|
813
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
|
|
814
813
|
set: async (key, value, ttl) => {
|
|
815
814
|
await this.set(key, value, ttl);
|
|
816
815
|
},
|
|
817
|
-
/*
|
|
818
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
|
|
816
|
+
/* v8 ignore next -- @preserve */
|
|
819
817
|
on: (event, listener) => {
|
|
820
818
|
this.on(event, listener);
|
|
821
819
|
},
|
|
822
|
-
/*
|
|
823
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
|
|
820
|
+
/* v8 ignore next -- @preserve */
|
|
824
821
|
emit: (event, ...args) => this.emit(event, ...args)
|
|
825
822
|
};
|
|
826
823
|
const wrapOptions = {
|
|
@@ -832,7 +829,7 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
832
829
|
cacheId: this._cacheId,
|
|
833
830
|
serialize: options?.serialize
|
|
834
831
|
};
|
|
835
|
-
return (0,
|
|
832
|
+
return (0, import_utils.wrap)(function_, wrapOptions);
|
|
836
833
|
}
|
|
837
834
|
/**
|
|
838
835
|
* Retrieves the value associated with the given key from the cache. If the key is not found,
|
|
@@ -847,18 +844,15 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
847
844
|
async getOrSet(key, function_, options) {
|
|
848
845
|
const cacheAdapter = {
|
|
849
846
|
get: async (key2) => this.get(key2),
|
|
847
|
+
/* v8 ignore next -- @preserve */
|
|
850
848
|
has: async (key2) => this.has(key2),
|
|
851
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
|
|
852
849
|
set: async (key2, value, ttl) => {
|
|
853
850
|
await this.set(key2, value, ttl);
|
|
854
851
|
},
|
|
855
|
-
/*
|
|
856
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
|
|
852
|
+
/* v8 ignore next -- @preserve */
|
|
857
853
|
on: (event, listener) => {
|
|
858
854
|
this.on(event, listener);
|
|
859
855
|
},
|
|
860
|
-
/* c8 ignore stop */
|
|
861
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
|
|
862
856
|
emit: (event, ...args) => this.emit(event, ...args)
|
|
863
857
|
};
|
|
864
858
|
const getOrSetOptions = {
|
|
@@ -868,17 +862,29 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
868
862
|
cacheErrors: options?.cacheErrors,
|
|
869
863
|
throwErrors: options?.throwErrors
|
|
870
864
|
};
|
|
871
|
-
return (0,
|
|
865
|
+
return (0, import_utils.getOrSet)(key, function_, getOrSetOptions);
|
|
872
866
|
}
|
|
873
867
|
/**
|
|
874
|
-
* Will hash an object using the specified
|
|
868
|
+
* Will hash an object asynchronously using the specified cryptographic algorithm.
|
|
869
|
+
* Use this for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
|
|
870
|
+
* For non-cryptographic algorithms, use hashSync() for better performance.
|
|
875
871
|
* @param {any} object the object to hash
|
|
876
|
-
* @param {string} algorithm the hash algorithm to use. The default is '
|
|
872
|
+
* @param {string} algorithm the hash algorithm to use. The default is 'SHA-256'
|
|
873
|
+
* @returns {Promise<string>} the hash of the object
|
|
874
|
+
*/
|
|
875
|
+
async hash(object, algorithm = import_utils.HashAlgorithm.SHA256) {
|
|
876
|
+
return (0, import_utils.hash)(object, { algorithm });
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Will hash an object synchronously using the specified non-cryptographic algorithm.
|
|
880
|
+
* Use this for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
|
|
881
|
+
* For cryptographic algorithms, use hash() instead.
|
|
882
|
+
* @param {any} object the object to hash
|
|
883
|
+
* @param {string} algorithm the hash algorithm to use. The default is 'djb2'
|
|
877
884
|
* @returns {string} the hash of the object
|
|
878
885
|
*/
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
return (0, import_utils.hash)(object, { algorithm: validAlgorithm });
|
|
886
|
+
hashSync(object, algorithm = import_utils.HashAlgorithm.DJB2) {
|
|
887
|
+
return (0, import_utils.hashSync)(object, { algorithm });
|
|
882
888
|
}
|
|
883
889
|
async setManyKeyv(keyv, items) {
|
|
884
890
|
const entries = [];
|
|
@@ -889,13 +895,6 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
889
895
|
await keyv.setMany(entries);
|
|
890
896
|
return true;
|
|
891
897
|
}
|
|
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
898
|
/**
|
|
900
899
|
* Processes a single key from secondary store for getRaw operation
|
|
901
900
|
* @param primary - the primary store to use
|
|
@@ -1085,3 +1084,4 @@ var Cacheable = class extends import_hookified2.Hookified {
|
|
|
1085
1084
|
wrap,
|
|
1086
1085
|
wrapSync
|
|
1087
1086
|
});
|
|
1087
|
+
/* v8 ignore next -- @preserve */
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { WrapFunctionOptions, GetOrSetKey, GetOrSetFunctionOptions } from '@cacheable/
|
|
2
|
-
export { GetOrSetFunctionOptions, GetOrSetKey, GetOrSetOptions, WrapOptions, WrapSyncOptions, getOrSet, wrap, wrapSync } from '@cacheable/
|
|
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';
|
|
@@ -408,14 +406,24 @@ declare class Cacheable extends Hookified {
|
|
|
408
406
|
*/
|
|
409
407
|
getOrSet<T>(key: GetOrSetKey, function_: () => Promise<T>, options?: GetOrSetFunctionOptions): Promise<T | undefined>;
|
|
410
408
|
/**
|
|
411
|
-
* Will hash an object using the specified
|
|
409
|
+
* Will hash an object asynchronously using the specified cryptographic algorithm.
|
|
410
|
+
* Use this for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
|
|
411
|
+
* For non-cryptographic algorithms, use hashSync() for better performance.
|
|
412
412
|
* @param {any} object the object to hash
|
|
413
|
-
* @param {string} algorithm the hash algorithm to use. The default is '
|
|
413
|
+
* @param {string} algorithm the hash algorithm to use. The default is 'SHA-256'
|
|
414
|
+
* @returns {Promise<string>} the hash of the object
|
|
415
|
+
*/
|
|
416
|
+
hash(object: any, algorithm?: HashAlgorithm): Promise<string>;
|
|
417
|
+
/**
|
|
418
|
+
* Will hash an object synchronously using the specified non-cryptographic algorithm.
|
|
419
|
+
* Use this for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
|
|
420
|
+
* For cryptographic algorithms, use hash() instead.
|
|
421
|
+
* @param {any} object the object to hash
|
|
422
|
+
* @param {string} algorithm the hash algorithm to use. The default is 'djb2'
|
|
414
423
|
* @returns {string} the hash of the object
|
|
415
424
|
*/
|
|
416
|
-
|
|
425
|
+
hashSync(object: any, algorithm?: HashAlgorithm): string;
|
|
417
426
|
private setManyKeyv;
|
|
418
|
-
private hasManyKeyv;
|
|
419
427
|
/**
|
|
420
428
|
* Processes a single key from secondary store for getRaw operation
|
|
421
429
|
* @param primary - the primary store to use
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { WrapFunctionOptions, GetOrSetKey, GetOrSetFunctionOptions } from '@cacheable/
|
|
2
|
-
export { GetOrSetFunctionOptions, GetOrSetKey, GetOrSetOptions, WrapOptions, WrapSyncOptions, getOrSet, wrap, wrapSync } from '@cacheable/
|
|
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';
|
|
@@ -408,14 +406,24 @@ declare class Cacheable extends Hookified {
|
|
|
408
406
|
*/
|
|
409
407
|
getOrSet<T>(key: GetOrSetKey, function_: () => Promise<T>, options?: GetOrSetFunctionOptions): Promise<T | undefined>;
|
|
410
408
|
/**
|
|
411
|
-
* Will hash an object using the specified
|
|
409
|
+
* Will hash an object asynchronously using the specified cryptographic algorithm.
|
|
410
|
+
* Use this for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
|
|
411
|
+
* For non-cryptographic algorithms, use hashSync() for better performance.
|
|
412
412
|
* @param {any} object the object to hash
|
|
413
|
-
* @param {string} algorithm the hash algorithm to use. The default is '
|
|
413
|
+
* @param {string} algorithm the hash algorithm to use. The default is 'SHA-256'
|
|
414
|
+
* @returns {Promise<string>} the hash of the object
|
|
415
|
+
*/
|
|
416
|
+
hash(object: any, algorithm?: HashAlgorithm): Promise<string>;
|
|
417
|
+
/**
|
|
418
|
+
* Will hash an object synchronously using the specified non-cryptographic algorithm.
|
|
419
|
+
* Use this for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
|
|
420
|
+
* For cryptographic algorithms, use hash() instead.
|
|
421
|
+
* @param {any} object the object to hash
|
|
422
|
+
* @param {string} algorithm the hash algorithm to use. The default is 'djb2'
|
|
414
423
|
* @returns {string} the hash of the object
|
|
415
424
|
*/
|
|
416
|
-
|
|
425
|
+
hashSync(object: any, algorithm?: HashAlgorithm): string;
|
|
417
426
|
private setManyKeyv;
|
|
418
|
-
private hasManyKeyv;
|
|
419
427
|
/**
|
|
420
428
|
* Processes a single key from secondary store for getRaw operation
|
|
421
429
|
* @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 {
|
|
@@ -119,11 +118,6 @@ var CacheableSync = class extends Hookified {
|
|
|
119
118
|
};
|
|
120
119
|
|
|
121
120
|
// src/index.ts
|
|
122
|
-
import {
|
|
123
|
-
getOrSet as getOrSet2,
|
|
124
|
-
wrap as wrap2,
|
|
125
|
-
wrapSync
|
|
126
|
-
} from "@cacheable/memoize";
|
|
127
121
|
import {
|
|
128
122
|
CacheableMemory,
|
|
129
123
|
createKeyv as createKeyv2,
|
|
@@ -132,11 +126,14 @@ import {
|
|
|
132
126
|
import {
|
|
133
127
|
calculateTtlFromExpiration as calculateTtlFromExpiration2,
|
|
134
128
|
getCascadingTtl as getCascadingTtl2,
|
|
129
|
+
getOrSet as getOrSet2,
|
|
135
130
|
HashAlgorithm as HashAlgorithm2,
|
|
136
131
|
hash as hash2,
|
|
137
132
|
Stats,
|
|
138
133
|
shorthandToMilliseconds as shorthandToMilliseconds2,
|
|
139
|
-
shorthandToTime
|
|
134
|
+
shorthandToTime,
|
|
135
|
+
wrap as wrap2,
|
|
136
|
+
wrapSync
|
|
140
137
|
} from "@cacheable/utils";
|
|
141
138
|
import { Keyv as Keyv2, KeyvHooks } from "keyv";
|
|
142
139
|
var Cacheable = class extends Hookified2 {
|
|
@@ -663,7 +660,7 @@ var Cacheable = class extends Hookified2 {
|
|
|
663
660
|
* @returns {Promise<boolean[]>} Whether the keys exist
|
|
664
661
|
*/
|
|
665
662
|
async hasMany(keys) {
|
|
666
|
-
const result = await this.
|
|
663
|
+
const result = await this._primary.hasMany(keys);
|
|
667
664
|
const missingKeys = [];
|
|
668
665
|
for (const [i, key] of keys.entries()) {
|
|
669
666
|
if (!result[i] && this._secondary) {
|
|
@@ -671,7 +668,7 @@ var Cacheable = class extends Hookified2 {
|
|
|
671
668
|
}
|
|
672
669
|
}
|
|
673
670
|
if (missingKeys.length > 0 && this._secondary) {
|
|
674
|
-
const secondary = await this.
|
|
671
|
+
const secondary = await this._secondary.hasMany(keys);
|
|
675
672
|
for (const [i, _key] of keys.entries()) {
|
|
676
673
|
if (!result[i] && secondary[i]) {
|
|
677
674
|
result[i] = secondary[i];
|
|
@@ -781,6 +778,7 @@ var Cacheable = class extends Hookified2 {
|
|
|
781
778
|
if (this._secondary) {
|
|
782
779
|
promises.push(this._secondary.disconnect());
|
|
783
780
|
}
|
|
781
|
+
promises.push(this._sync?.qified.disconnect());
|
|
784
782
|
await (this._nonBlocking ? Promise.race(promises) : Promise.all(promises));
|
|
785
783
|
}
|
|
786
784
|
/**
|
|
@@ -795,18 +793,16 @@ var Cacheable = class extends Hookified2 {
|
|
|
795
793
|
wrap(function_, options) {
|
|
796
794
|
const cacheAdapter = {
|
|
797
795
|
get: async (key) => this.get(key),
|
|
796
|
+
/* v8 ignore next -- @preserve */
|
|
798
797
|
has: async (key) => this.has(key),
|
|
799
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
|
|
800
798
|
set: async (key, value, ttl) => {
|
|
801
799
|
await this.set(key, value, ttl);
|
|
802
800
|
},
|
|
803
|
-
/*
|
|
804
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
|
|
801
|
+
/* v8 ignore next -- @preserve */
|
|
805
802
|
on: (event, listener) => {
|
|
806
803
|
this.on(event, listener);
|
|
807
804
|
},
|
|
808
|
-
/*
|
|
809
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
|
|
805
|
+
/* v8 ignore next -- @preserve */
|
|
810
806
|
emit: (event, ...args) => this.emit(event, ...args)
|
|
811
807
|
};
|
|
812
808
|
const wrapOptions = {
|
|
@@ -833,18 +829,15 @@ var Cacheable = class extends Hookified2 {
|
|
|
833
829
|
async getOrSet(key, function_, options) {
|
|
834
830
|
const cacheAdapter = {
|
|
835
831
|
get: async (key2) => this.get(key2),
|
|
832
|
+
/* v8 ignore next -- @preserve */
|
|
836
833
|
has: async (key2) => this.has(key2),
|
|
837
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
|
|
838
834
|
set: async (key2, value, ttl) => {
|
|
839
835
|
await this.set(key2, value, ttl);
|
|
840
836
|
},
|
|
841
|
-
/*
|
|
842
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance interface
|
|
837
|
+
/* v8 ignore next -- @preserve */
|
|
843
838
|
on: (event, listener) => {
|
|
844
839
|
this.on(event, listener);
|
|
845
840
|
},
|
|
846
|
-
/* c8 ignore stop */
|
|
847
|
-
// biome-ignore lint/suspicious/noExplicitAny: CacheInstance requires any type
|
|
848
841
|
emit: (event, ...args) => this.emit(event, ...args)
|
|
849
842
|
};
|
|
850
843
|
const getOrSetOptions = {
|
|
@@ -857,14 +850,26 @@ var Cacheable = class extends Hookified2 {
|
|
|
857
850
|
return getOrSet(key, function_, getOrSetOptions);
|
|
858
851
|
}
|
|
859
852
|
/**
|
|
860
|
-
* Will hash an object using the specified
|
|
853
|
+
* Will hash an object asynchronously using the specified cryptographic algorithm.
|
|
854
|
+
* Use this for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
|
|
855
|
+
* For non-cryptographic algorithms, use hashSync() for better performance.
|
|
856
|
+
* @param {any} object the object to hash
|
|
857
|
+
* @param {string} algorithm the hash algorithm to use. The default is 'SHA-256'
|
|
858
|
+
* @returns {Promise<string>} the hash of the object
|
|
859
|
+
*/
|
|
860
|
+
async hash(object, algorithm = HashAlgorithm.SHA256) {
|
|
861
|
+
return hash(object, { algorithm });
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Will hash an object synchronously using the specified non-cryptographic algorithm.
|
|
865
|
+
* Use this for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
|
|
866
|
+
* For cryptographic algorithms, use hash() instead.
|
|
861
867
|
* @param {any} object the object to hash
|
|
862
|
-
* @param {string} algorithm the hash algorithm to use. The default is '
|
|
868
|
+
* @param {string} algorithm the hash algorithm to use. The default is 'djb2'
|
|
863
869
|
* @returns {string} the hash of the object
|
|
864
870
|
*/
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
return hash(object, { algorithm: validAlgorithm });
|
|
871
|
+
hashSync(object, algorithm = HashAlgorithm.DJB2) {
|
|
872
|
+
return hashSync(object, { algorithm });
|
|
868
873
|
}
|
|
869
874
|
async setManyKeyv(keyv, items) {
|
|
870
875
|
const entries = [];
|
|
@@ -875,13 +880,6 @@ var Cacheable = class extends Hookified2 {
|
|
|
875
880
|
await keyv.setMany(entries);
|
|
876
881
|
return true;
|
|
877
882
|
}
|
|
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
883
|
/**
|
|
886
884
|
* Processes a single key from secondary store for getRaw operation
|
|
887
885
|
* @param primary - the primary store to use
|
|
@@ -1070,3 +1068,4 @@ export {
|
|
|
1070
1068
|
wrap2 as wrap,
|
|
1071
1069
|
wrapSync
|
|
1072
1070
|
};
|
|
1071
|
+
/* v8 ignore next -- @preserve */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cacheable",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "High Performance Layer 1 / Layer 2 Caching with Keyv Storage",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -21,26 +21,25 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"private": false,
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@biomejs/biome": "^2.
|
|
24
|
+
"@biomejs/biome": "^2.3.5",
|
|
25
25
|
"@faker-js/faker": "^10.1.0",
|
|
26
|
-
"@keyv/redis": "^5.1.
|
|
27
|
-
"@keyv/valkey": "^1.0.
|
|
28
|
-
"@qified/redis": "^0.5.
|
|
29
|
-
"@types/node": "^24.
|
|
30
|
-
"@vitest/coverage-v8": "^
|
|
26
|
+
"@keyv/redis": "^5.1.4",
|
|
27
|
+
"@keyv/valkey": "^1.0.11",
|
|
28
|
+
"@qified/redis": "^0.5.2",
|
|
29
|
+
"@types/node": "^24.10.1",
|
|
30
|
+
"@vitest/coverage-v8": "^4.0.9",
|
|
31
31
|
"lru-cache": "^11.2.2",
|
|
32
|
-
"rimraf": "^6.0
|
|
33
|
-
"tsup": "^8.5.
|
|
32
|
+
"rimraf": "^6.1.0",
|
|
33
|
+
"tsup": "^8.5.1",
|
|
34
34
|
"typescript": "^5.9.3",
|
|
35
|
-
"vitest": "^
|
|
35
|
+
"vitest": "^4.0.9"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"hookified": "^1.
|
|
39
|
-
"keyv": "^5.5.
|
|
40
|
-
"qified": "^0.5.
|
|
41
|
-
"@cacheable/
|
|
42
|
-
"@cacheable/
|
|
43
|
-
"@cacheable/utils": "^2.1.0"
|
|
38
|
+
"hookified": "^1.13.0",
|
|
39
|
+
"keyv": "^5.5.4",
|
|
40
|
+
"qified": "^0.5.2",
|
|
41
|
+
"@cacheable/memory": "^2.0.5",
|
|
42
|
+
"@cacheable/utils": "^2.3.0"
|
|
44
43
|
},
|
|
45
44
|
"keywords": [
|
|
46
45
|
"cacheable",
|