From 1203f3f7f3e0da2ac853c3bda99772dddd873cba Mon Sep 17 00:00:00 2001 From: Tyler Clendenin Date: Mon, 2 Aug 2021 19:10:42 -0400 Subject: [PATCH] feat: add default type to api error responses --- lib/decorators/api-response.decorator.ts | 20 ++ lib/types/error-responses.dto.ts | 233 +++++++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 lib/types/error-responses.dto.ts diff --git a/lib/decorators/api-response.decorator.ts b/lib/decorators/api-response.decorator.ts index 061bfa39d..595d0dd30 100644 --- a/lib/decorators/api-response.decorator.ts +++ b/lib/decorators/api-response.decorator.ts @@ -9,6 +9,8 @@ import { } from '../interfaces/open-api-spec.interface'; import { getTypeIsArrayTuple } from './helpers'; +import * as ErrorResponseDtos from '../types/error-responses.dto'; + export interface ApiResponseMetadata extends Omit { status?: number | 'default'; @@ -117,18 +119,21 @@ export const ApiBadRequestResponse = (options: ApiResponseOptions = {}) => export const ApiUnauthorizedResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.UnauthorizedResponseDto, ...options, status: HttpStatus.UNAUTHORIZED }); export const ApiTooManyRequestsResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.TooManyRequestsResponseDto, ...options, status: HttpStatus.TOO_MANY_REQUESTS }); export const ApiNotFoundResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.NotFoundResponseDto, ...options, status: HttpStatus.NOT_FOUND }); @@ -137,54 +142,63 @@ export const ApiInternalServerErrorResponse = ( options: ApiResponseOptions = {} ) => ApiResponse({ + type: ErrorResponseDtos.InternalServerErrorResponseDto, ...options, status: HttpStatus.INTERNAL_SERVER_ERROR }); export const ApiBadGatewayResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.BadGatewayResponseDto, ...options, status: HttpStatus.BAD_GATEWAY }); export const ApiConflictResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.ConflictResponseDto, ...options, status: HttpStatus.CONFLICT }); export const ApiForbiddenResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.ForbiddenResponseDto, ...options, status: HttpStatus.FORBIDDEN }); export const ApiGatewayTimeoutResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.GatewayTimeoutResponseDto, ...options, status: HttpStatus.GATEWAY_TIMEOUT }); export const ApiGoneResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.GoneResponseDto, ...options, status: HttpStatus.GONE }); export const ApiMethodNotAllowedResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.MethodNotAllowedResponseDto, ...options, status: HttpStatus.METHOD_NOT_ALLOWED }); export const ApiNotAcceptableResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.NotAcceptableResponseDto, ...options, status: HttpStatus.NOT_ACCEPTABLE }); export const ApiNotImplementedResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.NotImplementedResponseDto, ...options, status: HttpStatus.NOT_IMPLEMENTED }); @@ -193,18 +207,21 @@ export const ApiPreconditionFailedResponse = ( options: ApiResponseOptions = {} ) => ApiResponse({ + type: ErrorResponseDtos.PreconditionFailedResponseDto, ...options, status: HttpStatus.PRECONDITION_FAILED }); export const ApiPayloadTooLargeResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.PayloadTooLargeResponseDto, ...options, status: HttpStatus.PAYLOAD_TOO_LARGE }); export const ApiRequestTimeoutResponse = (options: ApiResponseOptions = {}) => ApiResponse({ + type: ErrorResponseDtos.RequestTimeoutResponseDto, ...options, status: HttpStatus.REQUEST_TIMEOUT }); @@ -213,6 +230,7 @@ export const ApiServiceUnavailableResponse = ( options: ApiResponseOptions = {} ) => ApiResponse({ + type: ErrorResponseDtos.ServiceUnavailableResponseDto, ...options, status: HttpStatus.SERVICE_UNAVAILABLE }); @@ -221,6 +239,7 @@ export const ApiUnprocessableEntityResponse = ( options: ApiResponseOptions = {} ) => ApiResponse({ + type: ErrorResponseDtos.UnprocessableEntityResponseDto, ...options, status: HttpStatus.UNPROCESSABLE_ENTITY }); @@ -229,6 +248,7 @@ export const ApiUnsupportedMediaTypeResponse = ( options: ApiResponseOptions = {} ) => ApiResponse({ + type: ErrorResponseDtos.UnsupportedMediaTypeResponseDto, ...options, status: HttpStatus.UNSUPPORTED_MEDIA_TYPE }); diff --git a/lib/types/error-responses.dto.ts b/lib/types/error-responses.dto.ts new file mode 100644 index 000000000..e50d9d4cd --- /dev/null +++ b/lib/types/error-responses.dto.ts @@ -0,0 +1,233 @@ +import { HttpStatus } from '@nestjs/common/enums/http-status.enum'; +import { ApiProperty } from "../decorators"; + +export class BadRequestResponseDto { + @ApiProperty({ + enum: [HttpStatus.BAD_REQUEST] + }) + statusCode: number + + @ApiProperty() + message: string[]; + + @ApiProperty({ + enum: ['Bad Request'] + }) + error: string; +} + +export class UnauthorizedResponseDto { + @ApiProperty({ + enum: [HttpStatus.UNAUTHORIZED] + }) + statusCode: number + + @ApiProperty({ + enum: ['Unauthorized'] + }) + message: string; +} + +export class TooManyRequestsResponseDto { + @ApiProperty({ + enum: [HttpStatus.TOO_MANY_REQUESTS] + }) + statusCode: number + + @ApiProperty({ + enum: ['Too Many Requests'] + }) + message: string; +} + +export class NotFoundResponseDto { + @ApiProperty({ + enum: [HttpStatus.NOT_FOUND] + }) + statusCode: number + + @ApiProperty({ + enum: ['Not Found'] + }) + message: string; +} + +export class InternalServerErrorResponseDto { + @ApiProperty({ + enum: [HttpStatus.INTERNAL_SERVER_ERROR] + }) + statusCode: number + + @ApiProperty({ + enum: ['Internal Server Error'] + }) + message: string; +} + +export class BadGatewayResponseDto { + @ApiProperty({ + enum: [HttpStatus.BAD_GATEWAY] + }) + statusCode: number + + @ApiProperty({ + enum: ['Bad Gateway'] + }) + message: string; +} + +export class ConflictResponseDto { + @ApiProperty({ + enum: [HttpStatus.CONFLICT] + }) + statusCode: number + + @ApiProperty({ + enum: ['Conflict'] + }) + message: string; +} + +export class ForbiddenResponseDto { + @ApiProperty({ + enum: [HttpStatus.FORBIDDEN] + }) + statusCode: number + + @ApiProperty({ + enum: ['Forbidden'] + }) + message: string; +} + +export class GatewayTimeoutResponseDto { + @ApiProperty({ + enum: [HttpStatus.GATEWAY_TIMEOUT] + }) + statusCode: number + + @ApiProperty({ + enum: ['Gateway Timeout'] + }) + message: string; +} + +export class GoneResponseDto { + @ApiProperty({ + enum: [HttpStatus.GONE] + }) + statusCode: number + + @ApiProperty({ + enum: ['Gone'] + }) + message: string; +} + +export class MethodNotAllowedResponseDto { + @ApiProperty({ + enum: [HttpStatus.METHOD_NOT_ALLOWED] + }) + statusCode: number + + @ApiProperty({ + enum: ['Method Not Allowed'] + }) + message: string; +} + +export class NotAcceptableResponseDto { + @ApiProperty({ + enum: [HttpStatus.NOT_ACCEPTABLE] + }) + statusCode: number + + @ApiProperty({ + enum: ['Not Acceptable'] + }) + message: string; +} + +export class NotImplementedResponseDto { + @ApiProperty({ + enum: [HttpStatus.NOT_IMPLEMENTED] + }) + statusCode: number + + @ApiProperty({ + enum: ['Not Implemented'] + }) + message: string; +} + +export class PreconditionFailedResponseDto { + @ApiProperty({ + enum: [HttpStatus.PRECONDITION_FAILED] + }) + statusCode: number + + @ApiProperty({ + enum: ['Precondition Failed'] + }) + message: string; +} + +export class PayloadTooLargeResponseDto { + @ApiProperty({ + enum: [HttpStatus.PAYLOAD_TOO_LARGE] + }) + statusCode: number + + @ApiProperty({ + enum: ['Payload Too Large'] + }) + message: string; +} + +export class RequestTimeoutResponseDto { + @ApiProperty({ + enum: [HttpStatus.REQUEST_TIMEOUT] + }) + statusCode: number + + @ApiProperty({ + enum: ['Request Timeout'] + }) + message: string; +} + +export class ServiceUnavailableResponseDto { + @ApiProperty({ + enum: [HttpStatus.SERVICE_UNAVAILABLE] + }) + statusCode: number + + @ApiProperty({ + enum: ['Service Unavailable'] + }) + message: string; +} + +export class UnprocessableEntityResponseDto { + @ApiProperty({ + enum: [HttpStatus.UNPROCESSABLE_ENTITY] + }) + statusCode: number + + @ApiProperty({ + enum: ['Unprocessable Entity'] + }) + message: string; +} + +export class UnsupportedMediaTypeResponseDto { + @ApiProperty({ + enum: [HttpStatus.UNSUPPORTED_MEDIA_TYPE] + }) + statusCode: number + + @ApiProperty({ + enum: ['Unsupported Media Type'] + }) + message: string; +}