diff --git a/src/app.module.ts b/src/app.module.ts index 1c40684..227a402 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core'; +import { APP_FILTER, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core'; import { AppInterceptor } from '@/modules/core/providers/app.interceptor'; @@ -9,6 +9,7 @@ import { database } from './config'; import { DEFAULT_VALIDATION_CONFIG } from './modules/content/constants'; import { ContentModule } from './modules/content/content.module'; import { CoreModule } from './modules/core/core.module'; +import { AppFilter } from './modules/core/providers/app.filter'; import { AppPipe } from './modules/core/providers/app.pipe'; import { DatabaseModule } from './modules/database/database.module'; @@ -23,6 +24,10 @@ import { DatabaseModule } from './modules/database/database.module'; provide: APP_INTERCEPTOR, useClass: AppInterceptor, }, + { + provide: APP_FILTER, + useClass: AppFilter, + }, ], }) export class AppModule {} diff --git a/src/modules/core/providers/app.filter.ts b/src/modules/core/providers/app.filter.ts new file mode 100644 index 0000000..fe6b2c2 --- /dev/null +++ b/src/modules/core/providers/app.filter.ts @@ -0,0 +1,38 @@ +import { ArgumentsHost, HttpException, HttpStatus, Type } from '@nestjs/common'; +import { BaseExceptionFilter } from '@nestjs/core'; +import { isObject } from 'lodash'; +import { EntityNotFoundError, EntityPropertyNotFoundError, QueryFailedError } from 'typeorm'; + +export class AppFilter extends BaseExceptionFilter { + protected resExceptions: Array<{ class: Type; status?: number } | Type> = [ + { class: EntityNotFoundError, status: HttpStatus.NOT_FOUND }, + { class: QueryFailedError, status: HttpStatus.BAD_REQUEST }, + { class: EntityPropertyNotFoundError, status: HttpStatus.BAD_REQUEST }, + ]; + + // eslint-disable-next-line consistent-return + catch(exception: T, host: ArgumentsHost) { + const applicationRef = + this.applicationRef || (this.httpAdapterHost && this.httpAdapterHost.httpAdapter)!; + const resException = this.resExceptions.find((item) => + 'class' in item ? exception instanceof item.class : exception instanceof item, + ); + if (!resException && !(exception instanceof HttpException)) { + return this.handleUnknownError(exception, host, applicationRef); + } + let res: string | object = ''; + let status = HttpStatus.INTERNAL_SERVER_ERROR; + if (exception instanceof HttpException) { + res = exception.getResponse(); + status = exception.getStatus(); + } else if (resException) { + const e = exception as unknown as Error; + res = e.message; + if ('class' in resException && resException.status) { + status = resException.status; + } + } + const message = isObject(res) ? res : { statusCode: status, message: res }; + applicationRef!.reply(host.getArgByIndex(1), message, status); + } +}