1
+
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+
1
4
import _ from 'lodash' ;
2
- import { type Cache , caching , type Store } from 'cache-manager' ;
5
+ import {
6
+ type Cache , caching , type Store ,
7
+ } from 'cache-manager' ;
3
8
import type { CachedFunctionInitializerOptions , CachedFunctionOptions } from './index.d' ;
4
- import type { AnyFunction , ArgumentPaths } from './paths.d' ;
9
+ import type { AnyFunction as CacheableFunction , ArgumentPaths } from './paths.d' ;
5
10
6
11
let cache : Cache | undefined ;
7
12
@@ -19,11 +24,14 @@ export async function getOrInitializeCache<S extends Store>(options?: CachedFunc
19
24
return cache as Cache < S > ;
20
25
}
21
26
27
+ /**
28
+ * @deprecated To close any open connections, please retrieve the cache object from `getOrInitializeCache` and close it directly.
29
+ */
22
30
export function resetCache ( ) {
23
31
cache = undefined ;
24
32
}
25
33
26
- export function selectorToCacheKey < F extends AnyFunction > ( arguments_ : Parameters < F > , selector : ArgumentPaths < F > ) {
34
+ export function selectorToCacheKey < F extends CacheableFunction > ( arguments_ : Parameters < F > , selector : ArgumentPaths < F > ) {
27
35
const selectors = _ . castArray ( selector ) ;
28
36
if ( selectors . length === 0 ) {
29
37
return JSON . stringify ( arguments_ ) ;
@@ -45,26 +53,47 @@ export function selectorToCacheKey<F extends AnyFunction>(arguments_: Parameters
45
53
return JSON . stringify ( result ) ;
46
54
}
47
55
48
- export function cachedFunction < F extends AnyFunction > ( function_ : F , options : CachedFunctionOptions < F > ) {
56
+ export function cachedFunction < F extends CacheableFunction > ( function_ : F , options ? : CachedFunctionOptions < F > ) {
49
57
return async ( ...arguments_ : Parameters < F > ) : Promise < ReturnType < F > > => {
50
- const selector = options . selector ?? function_ . cacheKeys ?? [ ] ;
51
- const cacheKey = selectorToCacheKey ( arguments_ , selector ) ;
58
+ const cacheOptions = _ . merge ( { } , options ?? { } , function_ . cacheOptions ?? { } ) ;
59
+ if ( _ . keys ( cacheOptions ) . length === 0 ) {
60
+ throw new Error ( 'No cache options provided, either use the @CacheOptions decorator or provide options to cachedFunction directly.' ) ;
61
+ }
62
+
63
+ const cacheKey = selectorToCacheKey ( arguments_ , cacheOptions . selector ! ) ;
52
64
const cache = await getOrInitializeCache ( options as CachedFunctionInitializerOptions ) ;
53
65
54
66
const cacheValue = await cache . get < ReturnType < F > > ( cacheKey ) ;
55
- if ( cacheValue !== undefined ) {
67
+ if ( ! cacheOptions . force && cacheValue !== undefined ) {
56
68
return cacheValue ;
57
69
}
58
70
59
71
const result = await function_ ( ...arguments_ ) as ReturnType < F > ;
60
- await cache . set ( cacheKey , result , options . ttl ) ;
72
+ await cache . set ( cacheKey , result , cacheOptions . ttl ) ;
61
73
62
74
return result ;
63
75
} ;
64
76
}
65
77
66
- export function cacheKeys < F extends AnyFunction > ( function_ : F , ...selector : Array < ArgumentPaths < F > > ) {
67
- const selectors = _ ( selector ) . flatMap ( ) . value ( ) ;
68
- function_ . cacheKeys = selectors ;
69
- return function_ ;
78
+ // eslint-disable-next-line @typescript-eslint/naming-convention
79
+ export function CacheOptions < F extends CacheableFunction > (
80
+ selectorOrOptions : ArgumentPaths < F > | CachedFunctionOptions < F > ,
81
+ ttl ?: number ,
82
+ ) {
83
+ const options = ( _ . isArrayLike ( selectorOrOptions ) || _ . isString ( selectorOrOptions ) )
84
+ ? { selector : selectorOrOptions , ttl}
85
+ : selectorOrOptions as CachedFunctionOptions < F > ;
86
+
87
+ return (
88
+ _target : any ,
89
+ _propertyKey : string | symbol ,
90
+ descriptor : TypedPropertyDescriptor < F > ,
91
+ ) : any => {
92
+ if ( ! descriptor . value ) {
93
+ return ;
94
+ }
95
+
96
+ descriptor . value . cacheOptions = options ;
97
+ return descriptor ;
98
+ } ;
70
99
}
0 commit comments