|
1 | | - |
2 | 1 | import _ from 'lodash'; |
3 | 2 | import {type Cache, caching} from 'cache-manager'; |
4 | 3 | import type {CachedFunctionInitializerOptions, CachedFunctionOptions} from './index.d'; |
5 | 4 | import type {AnyFunction, ArgumentPaths} from './paths.d'; |
6 | 5 |
|
7 | 6 | let cache: Cache | undefined; |
8 | 7 |
|
9 | | -export async function getOrInitializeCache(options: CachedFunctionInitializerOptions) { |
10 | | - if (!('store' in options)) { |
| 8 | +export async function initializeCache(options?: CachedFunctionInitializerOptions) { |
| 9 | + if (!cache && !options) { |
| 10 | + throw new Error('cache is not initialized and no options provided'); |
| 11 | + } |
| 12 | + |
| 13 | + if (options && !('store' in options)) { |
11 | 14 | throw new Error('store is required'); |
12 | 15 | } |
13 | 16 |
|
14 | | - cache ||= await ('config' in options ? caching(options.store, options.config) : caching(options.store)); |
| 17 | + cache ||= await ('config' in options! ? caching(options.store, options.config) : caching(options!.store)); |
15 | 18 | return cache; |
16 | 19 | } |
17 | 20 |
|
| 21 | +export function resetCache() { |
| 22 | + cache = undefined; |
| 23 | +} |
| 24 | + |
18 | 25 | export function selectorToCacheKey<F extends AnyFunction>(arguments_: Parameters<F>, selector: ArgumentPaths<F>) { |
19 | 26 | const selectors = _.castArray(selector); |
20 | | - const values = _.at(arguments_, selectors); |
| 27 | + const values = selectors.map(path => { |
| 28 | + const value = _.get(arguments_, path) as unknown; |
| 29 | + if (value === undefined) { |
| 30 | + throw new Error(`Path "${path}" does not exist in the provided arguments.`); |
| 31 | + } |
| 32 | + |
| 33 | + if (typeof value === 'function' || value instanceof Function) { |
| 34 | + throw new TypeError(`Path "${path}" points to a function, which is not serializable.`); |
| 35 | + } |
| 36 | + |
| 37 | + return value; |
| 38 | + }); |
21 | 39 | const result = _.zipObject(selectors, values); |
22 | 40 | return JSON.stringify(result); |
23 | 41 | } |
24 | 42 |
|
25 | 43 | export function cachedFunction<F extends AnyFunction>(function_: F, options: CachedFunctionOptions<F>) { |
26 | | - return (...arguments_: Parameters<F>): ReturnType<F> => { |
| 44 | + return async (...arguments_: Parameters<F>): Promise<ReturnType<F>> => { |
27 | 45 | const cacheKey = selectorToCacheKey(arguments_, options.selector); |
28 | | - console.log({cacheKey}); |
29 | | - return function_(...arguments_); |
| 46 | + |
| 47 | + const cache = await initializeCache(options); |
| 48 | + |
| 49 | + const cacheValue = await cache.get<ReturnType<F>>(cacheKey); |
| 50 | + if (cacheValue !== undefined) { |
| 51 | + return cacheValue; |
| 52 | + } |
| 53 | + |
| 54 | + const result = await function_(...arguments_) as ReturnType<F>; |
| 55 | + await cache.set(cacheKey, result, options.ttl); |
| 56 | + |
| 57 | + return result; |
30 | 58 | }; |
31 | 59 | } |
0 commit comments