diff --git a/packages/nestlogged-fastify/src/index.ts b/packages/nestlogged-fastify/src/index.ts index cfb8a4f..4c9a9ab 100644 --- a/packages/nestlogged-fastify/src/index.ts +++ b/packages/nestlogged-fastify/src/index.ts @@ -19,4 +19,5 @@ export { LoggedGuard, LoggedInterceptor, LoggedMiddleware, + LoggedExceptionFilter, } from './logged' \ No newline at end of file diff --git a/packages/nestlogged-fastify/src/logged/methods/exception.ts b/packages/nestlogged-fastify/src/logged/methods/exception.ts new file mode 100644 index 0000000..8b7ada6 --- /dev/null +++ b/packages/nestlogged-fastify/src/logged/methods/exception.ts @@ -0,0 +1,75 @@ +import { OverrideBuildOptions } from 'nestlogged/lib/logged/utils'; +import { LoggedMetadata, nestLoggedMetadata } from 'nestlogged/lib/logged/metadata'; +import { scopedLogger, returns, ReturnsReflectData } from 'nestlogged/lib/reflected'; +import { overrideBuild } from '../override'; + +export function LoggedExceptionFilter, R>( + options?: Partial, +) { + return ( + _target: any, + key: string, + descriptor: TypedPropertyDescriptor< + (...args: F) => R + >, + ) => { + const fn = descriptor.value; + + if (!fn || typeof fn !== 'function') { + console.warn( + `LoggedExceptionFilter 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( + 'exception', + fn, + _target, + { + scopedLoggerInjectableParam, + loggedParams: [], + }, + _target.constructor.name, + returnsData, + newMetadata, + ); + + _target[key] = overrideFunction; + descriptor.value = overrideFunction; + + Reflect.defineMetadata(nestLoggedMetadata, newMetadata, _target, key); + all.forEach(([k, v]) => { + Reflect.defineMetadata(k, v, _target[key]); + Reflect.defineMetadata(k, v, descriptor.value); + }); + }; +} diff --git a/packages/nestlogged-fastify/src/logged/methods/index.ts b/packages/nestlogged-fastify/src/logged/methods/index.ts index 9aeedf1..d4631ad 100644 --- a/packages/nestlogged-fastify/src/logged/methods/index.ts +++ b/packages/nestlogged-fastify/src/logged/methods/index.ts @@ -3,3 +3,4 @@ export { LoggedRoute } from './route'; export { LoggedGuard } from './guard'; export { LoggedInterceptor } from './interceptor'; export { LoggedMiddleware } from './middleware'; +export { LoggedExceptionFilter } from './exception'; \ No newline at end of file diff --git a/packages/nestlogged-fastify/src/logged/override.ts b/packages/nestlogged-fastify/src/logged/override.ts index 0f3e31c..8e27407 100644 --- a/packages/nestlogged-fastify/src/logged/override.ts +++ b/packages/nestlogged-fastify/src/logged/override.ts @@ -26,7 +26,7 @@ export function overrideBuild, R>( route: string, ): (...args: F) => R; export function overrideBuild, R>( - type: 'function' | 'guard' | 'interceptor' | 'middleware', + type: 'function' | 'guard' | 'interceptor' | 'middleware' | 'exception', originalFunction: (...args: F) => R, _target: any, metadatas: FunctionMetadata, @@ -70,9 +70,9 @@ export function overrideBuild, R>( } } else { // special, can access to request object - if (type === 'guard' || type === 'interceptor') { + if (type === 'guard' || type === 'interceptor' || type === 'exception') { // args[0] == ExecutionContext - const ctx = args[0] as ExecutionContext; + const ctx = args[type === 'exception' ? 1 : 0] as ExecutionContext; if (ctx.getType() !== 'http') { injectedLogger.error( 'Cannot inject logger: Request type is not http',