From c74ad2b1195acbe16b09c6ae1db433d9dba74194 Mon Sep 17 00:00:00 2001 From: Shinwoo PARK Date: Wed, 19 Mar 2025 15:10:20 +0900 Subject: [PATCH] feat: add LoggedMiddleware --- src/logged.ts | 97 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 6 deletions(-) diff --git a/src/logged.ts b/src/logged.ts index 0ce31ce..9141fc9 100644 --- a/src/logged.ts +++ b/src/logged.ts @@ -161,19 +161,28 @@ class LoggedMetadata { } } -type BuildType = 'route' | 'function' | 'guard' | 'interceptor'; +type BuildType = 'route' | 'function' | 'guard' | 'interceptor' | 'middleware'; const callLogIdentifyMessageDictionary: Record = { route: 'HIT HTTP', function: 'CALL', guard: 'HIT GUARD', - interceptor: 'HIT INTERCEPTOR' + interceptor: 'HIT INTERCEPTOR', + middleware: 'HIT MIDDLEWARE', } -function createCallLogIdentifyMessage(type: 'route' | 'guard' | 'interceptor', key: string, route: string) +function createCallLogIdentifyMessage(type: 'route', key: string, route: string) +function createCallLogIdentifyMessage(type: 'guard' | 'interceptor' | 'middleware', route: string) function createCallLogIdentifyMessage(type: 'function', key: string) -function createCallLogIdentifyMessage(type: BuildType, key: string, route?: string) { - return `${callLogIdentifyMessageDictionary[type]} ${type === 'route' ? `${route} (${key})` : type === 'guard' ? `${route}` : key}` +function createCallLogIdentifyMessage(type: BuildType, key?: string, route?: string) { + if (type === 'route') + return `${callLogIdentifyMessageDictionary[type]} ${route} (${key})` + if (type === 'guard' || type === 'interceptor' || type === 'middleware') + return `${callLogIdentifyMessageDictionary[type]} ${route}` + if (type === 'function') + return `${callLogIdentifyMessageDictionary[type]} ${key}`; + + return callLogIdentifyMessageDictionary[type]; } function overrideBuild, R>( @@ -187,7 +196,7 @@ function overrideBuild, R>( route: string, ): (...args: F) => R; function overrideBuild, R>( - type: 'function' | 'guard' | 'interceptor', + type: 'function' | 'guard' | 'interceptor' | 'middleware', originalFunction: (...args: F) => R, baseLogger: Logger, metadatas: FunctionMetadata, @@ -640,6 +649,82 @@ export function LoggedInterceptor, R>(options?: Partial { + Reflect.defineMetadata(k, v, _target[key]); + Reflect.defineMetadata(k, v, descriptor.value); + }); + } +} + +export function LoggedMiddleware, R>(options?: Partial) { + return ( + _target: any, + key: string, + descriptor: TypedPropertyDescriptor<(context: ExecutionContext, ...args: F) => R> + ) => { + loggerInit(_target); + + const logger: Logger = _target.logger; + + const fn = descriptor.value; + + if (!fn || typeof fn!== "function") { + logger.warn( + `LoggedMiddleware decorator applied to non-function property: ${key}` + ); + return; + } + + const logMetadata: LoggedMetadata | undefined = Reflect.getOwnMetadata( + nestLoggedMetadata, + _target, + key + ) + if (logMetadata) { + // already applied, override instead + logMetadata.updateOption(options) + return + } + const newMetadata = new LoggedMetadata(options); + + const all = Reflect.getMetadataKeys(fn).map((k) => [ + k, + Reflect.getMetadata(k, fn), + ]); + + const scopedLoggerInjectableParam: number = Reflect.getOwnMetadata( + scopedLogger, + _target, + key + ); + + const returnsData: ReturnsReflectData[] | true = Reflect.getOwnMetadata( + returns, + fn + ); + + const overrideFunction = overrideBuild( + 'middleware', + fn, + logger, + { + scopedLoggerInjectableParam, + loggedParams: [], + }, + key, + returnsData, + newMetadata, + ); + + _target[key] = overrideFunction; + descriptor.value = overrideFunction; + Reflect.defineMetadata( nestLoggedMetadata, newMetadata,