feat(nestlogged-fastify): add LoggedExceptionFilter

This commit is contained in:
Shinwoo PARK 2025-03-30 03:34:22 +09:00
parent 20cabd0be8
commit 834b304354
4 changed files with 80 additions and 3 deletions

View File

@ -19,4 +19,5 @@ export {
LoggedGuard, LoggedGuard,
LoggedInterceptor, LoggedInterceptor,
LoggedMiddleware, LoggedMiddleware,
LoggedExceptionFilter,
} from './logged' } from './logged'

View File

@ -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<F extends Array<any>, R>(
options?: Partial<OverrideBuildOptions>,
) {
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);
});
};
}

View File

@ -3,3 +3,4 @@ export { LoggedRoute } from './route';
export { LoggedGuard } from './guard'; export { LoggedGuard } from './guard';
export { LoggedInterceptor } from './interceptor'; export { LoggedInterceptor } from './interceptor';
export { LoggedMiddleware } from './middleware'; export { LoggedMiddleware } from './middleware';
export { LoggedExceptionFilter } from './exception';

View File

@ -26,7 +26,7 @@ export function overrideBuild<F extends Array<any>, R>(
route: string, route: string,
): (...args: F) => R; ): (...args: F) => R;
export function overrideBuild<F extends Array<any>, R>( export function overrideBuild<F extends Array<any>, R>(
type: 'function' | 'guard' | 'interceptor' | 'middleware', type: 'function' | 'guard' | 'interceptor' | 'middleware' | 'exception',
originalFunction: (...args: F) => R, originalFunction: (...args: F) => R,
_target: any, _target: any,
metadatas: FunctionMetadata, metadatas: FunctionMetadata,
@ -70,9 +70,9 @@ export function overrideBuild<F extends Array<any>, R>(
} }
} else { } else {
// special, can access to request object // special, can access to request object
if (type === 'guard' || type === 'interceptor') { if (type === 'guard' || type === 'interceptor' || type === 'exception') {
// args[0] == ExecutionContext // args[0] == ExecutionContext
const ctx = args[0] as ExecutionContext; const ctx = args[type === 'exception' ? 1 : 0] as ExecutionContext;
if (ctx.getType() !== 'http') { if (ctx.getType() !== 'http') {
injectedLogger.error( injectedLogger.error(
'Cannot inject logger: Request type is not http', 'Cannot inject logger: Request type is not http',