diff --git a/src/index.d.ts b/src/index.d.ts index f84e493..8493b36 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -12,6 +12,17 @@ import { */ export type SingleOrArray = T | T[]; +/** + * Represents a logger object. + */ +export type Logger = { + trace: (...args: any) => any; + debug: (...args: any) => any; + info: (...args: any) => any; + warn: (...args: any) => any; + error: (...args: any) => any; +} + /** * Represents any function that takes any number of arguments and returns any value. */ @@ -41,9 +52,8 @@ export type ArgumentPaths = SingleOrArray;} & + ({store: FactoryStore; config: FactoryConfig} | {store: Store}); /** * Options for a cached function. diff --git a/src/index.ts b/src/index.ts index 0ec9747..e756a2f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,9 +8,17 @@ import { } from 'cache-manager'; import { type CachedFunctionInitializerOptions, type CachedFunctionOptions, type CacheableFunction, type ArgumentPaths, + Logger, } from './index.d'; let cache: Cache | undefined; +let logger: Logger = { + info(...args: any) {}, + debug(...args: any) {}, + trace(...args: any) {}, + warn(...args: any) {}, + error(...args: any) {}, +}; /** * Retrieves or initializes the cache. @@ -29,7 +37,13 @@ export async function getOrInitializeCache(options?: CachedFunc throw new Error('Store is not provided in options but is required to initialize the cache'); } + if (options?.logger) { + logger = options.logger as Logger; + } + + logger?.trace({options}, 'Initializing cache'); cache ||= await ('config' in options! ? caching(options.store, options.config) : caching(options!.store)); + logger?.trace('Cache initialized'); return cache as Cache; } @@ -39,6 +53,7 @@ export async function getOrInitializeCache(options?: CachedFunc */ export function resetCache() { cache = undefined; + logger?.warn('You have called resetCache, which is deprecated and basically does nothing. To close any open connections, please retrieve the cache object from getOrInitializeCache and close it directly.'); } /** @@ -54,6 +69,7 @@ export function resetCache() { export function selectorToCacheKey(arguments_: Parameters, selector: ArgumentPaths) { const selectors = _.castArray(selector); if (selectors.length === 0) { + logger?.trace(arguments_, 'No selectors provided, using the entire arguments object as the cache key'); return JSON.stringify(arguments_); } @@ -92,13 +108,18 @@ export function cachedFunction(function_: F, option const cacheKey = selectorToCacheKey(arguments_, cacheOptions.selector!); const cache = await getOrInitializeCache(options as CachedFunctionInitializerOptions); + logger?.trace({cacheOptions, cacheKey}, 'Checking cache'); const cacheValue = await cache.get>(cacheKey); if (!cacheOptions.force && cacheValue !== undefined) { + logger?.trace({cacheOptions, cacheKey}, 'Cache hit'); return cacheValue; } + logger?.trace({cacheOptions, cacheKey}, 'Cache miss'); const result = await function_(...arguments_) as ReturnType; + logger?.trace({cacheOptions, cacheKey}, 'Setting cache'); await cache.set(cacheKey, result, cacheOptions.ttl); + logger?.trace({cacheOptions, cacheKey}, 'Cache set'); return result; }; @@ -143,10 +164,13 @@ export function CacheOptions( descriptor: TypedPropertyDescriptor, ): any => { if (!descriptor.value) { + logger?.warn('CacheOptions decorator is only supported on methods'); return; } descriptor.value.cacheOptions = options; + logger?.trace({options}, 'Cache options set'); + return descriptor; }; } diff --git a/tests/redis.test_.ts b/tests/redis.test_.ts index 2585f94..27df897 100644 --- a/tests/redis.test_.ts +++ b/tests/redis.test_.ts @@ -8,6 +8,7 @@ const cache = await getOrInitializeCache({ host: 'localhost', port: 6379, }), + logger: console }); type Person = {