diff --git a/src/common/exceptions/exception.constant.ts b/src/common/exceptions/exception.constant.ts index e70f4f0..bbf84e2 100644 --- a/src/common/exceptions/exception.constant.ts +++ b/src/common/exceptions/exception.constant.ts @@ -10,6 +10,7 @@ export const GRAPHQL_ERROR_CODES = [ ]; export const PRESERVED_STATUS_CODES = [ + HttpStatus.BAD_REQUEST, HttpStatus.UNAUTHORIZED, HttpStatus.FORBIDDEN, ] as const; diff --git a/src/common/exceptions/exception.factory.ts b/src/common/exceptions/exception.factory.ts index 65a031a..6aace89 100644 --- a/src/common/exceptions/exception.factory.ts +++ b/src/common/exceptions/exception.factory.ts @@ -31,9 +31,8 @@ export const createException = () => { constructor(arg?: ExceptionParams) { super(statusCode, defaultMessage, code); - if (arg) { - this.message = composeExceptionMessage(defaultMessage, arg) as K; - } + const composed = composeExceptionMessage(defaultMessage, arg ?? {}); + this.message = (composed || code) as K; } }; }; diff --git a/src/common/exceptions/exception.format.ts b/src/common/exceptions/exception.format.ts index c29df1b..1c4c806 100644 --- a/src/common/exceptions/exception.format.ts +++ b/src/common/exceptions/exception.format.ts @@ -4,6 +4,8 @@ import { GraphQLError } from 'graphql'; import { PRESERVED_STATUS_CODES } from './exception.constant'; import { + getHttpExceptionCode, + getHttpExceptionMessage, isBaseException, isGraphqlOriginalError, isHttpException, @@ -26,6 +28,14 @@ const determineErrorCondition = (error: GraphQLError) => { }; } + if (isHttpException(error.originalError)) { + const status = error.originalError.getStatus(); + return { + errorStatus: status, + errorCode: getHttpExceptionCode(status), + }; + } + return { errorStatus: HttpStatus.INTERNAL_SERVER_ERROR, errorCode: 'INTERNAL_SERVER_ERROR', @@ -75,6 +85,14 @@ const handleInternalServerError = ( } }; +const determineErrorMessage = (error: GraphQLError): string => { + if (isHttpException(error.originalError)) { + return getHttpExceptionMessage(error.originalError); + } + + return error.message; +}; + const formatError = ( error: GraphQLError, options: { @@ -95,7 +113,7 @@ const formatError = ( options.setHttpStatus(httpStatus); return { - message: error.message, + message: determineErrorMessage(error), locations: error.locations, path: error.path, extensions: { diff --git a/src/common/exceptions/exception.util.ts b/src/common/exceptions/exception.util.ts index 4938318..d5a083b 100644 --- a/src/common/exceptions/exception.util.ts +++ b/src/common/exceptions/exception.util.ts @@ -1,4 +1,4 @@ -import { HttpException } from '@nestjs/common'; +import { HttpException, HttpStatus } from '@nestjs/common'; import { GraphQLErrorExtensions } from 'graphql'; @@ -23,3 +23,29 @@ export const isBaseException = ( export const isHttpException = (error: unknown): error is HttpException => { return error instanceof HttpException; }; + +export const getHttpExceptionCode = (status: number): string => { + return HttpStatus[status] || 'HTTP_ERROR'; +}; + +export const getHttpExceptionMessage = (error: HttpException): string => { + const response = error.getResponse(); + + if (typeof response === 'string') { + return response; + } + + if (typeof response === 'object' && response !== null) { + const { message } = response as { message?: string | string[] }; + + if (Array.isArray(message)) { + return message.join(', '); + } + + if (typeof message === 'string') { + return message; + } + } + + return error.message; +};