Skip to content

Commit

Permalink
feat: improve error handler
Browse files Browse the repository at this point in the history
  • Loading branch information
mapeveri committed Jan 27, 2024
1 parent 44ee536 commit bd9d563
Show file tree
Hide file tree
Showing 17 changed files with 81 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';
import ConflictException from '@src/shared/domain/exceptions/conflictException';

export default class CountryAlreadyExistsException extends DomainException {
export default class CountryAlreadyExistsException extends ConflictException {
constructor(countryId: string) {
super(`Country with id ${countryId} already exists`, 500, 'country_already_exists');
super(`Country with id ${countryId} already exists`, 'country_already_exists');
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';
import ConflictException from '@src/shared/domain/exceptions/conflictException';

export default class ExpressionAlreadyExistsException extends DomainException {
export default class ExpressionAlreadyExistsException extends ConflictException {
constructor(expressionId: string) {
super(`Expression with id ${expressionId} already exists`, 500, 'expression_already_exists');
super(`Expression with id ${expressionId} already exists`, 'expression_already_exists');
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';
import ConflictException from '@src/shared/domain/exceptions/conflictException';

export default class InvalidUserIdException extends DomainException {
export default class InvalidUserIdException extends ConflictException {
constructor(userId: string) {
super(`Invalid user id ${userId}`, 400, 'invalid_user_id');
super(`Invalid user id ${userId}`, 'invalid_user_id');
}
}
6 changes: 3 additions & 3 deletions src/languages/domain/user/exceptions/loginException.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';
import UnauthorizedException from '@src/shared/domain/exceptions/unauthorizedException';

export default class LoginException extends DomainException {
export default class LoginException extends UnauthorizedException {
constructor() {
super('Invalid login', 403, 'invalid_login');
super('Invalid login', 'invalid_login');
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';
import NotFoundException from '@src/shared/domain/exceptions/notFoundException';

export default class UserDoesNotExistsException extends DomainException {
export default class UserDoesNotExistsException extends NotFoundException {
constructor(userId: string) {
super(`User ${userId} doesn not exists`, 404, 'user_does_not_exists');
super(`User ${userId} doesn not exists`, 'user_does_not_exists');
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';
import ConflictException from '@src/shared/domain/exceptions/conflictException';

export default class WordAlreadyExistsException extends DomainException {
export default class WordAlreadyExistsException extends ConflictException {
constructor(wordId: string) {
super(`Word with id ${wordId} already exists`, 500, 'word_already_exists');
super(`Word with id ${wordId} already exists`, 'word_already_exists');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ export default class ProjectionHandlerNotFoundError extends DomainException {
public message: string = 'Projection handler not found',
public code: string = 'project_handler_not_found',
) {
super(message, 500, code);
super(message, code);
}
}
7 changes: 7 additions & 0 deletions src/shared/domain/exceptions/conflictException.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';

export default class ConflictException extends DomainException {
constructor(public message: string, public code: string) {
super(message, code);
}
}
3 changes: 1 addition & 2 deletions src/shared/domain/exceptions/domainException.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export default class DomainException extends Error {
constructor(public message: string, public status: number, public code: string) {
constructor(public message: string, public code: string) {
super(message);
this.status = status;
this.code = code;
}
}
6 changes: 3 additions & 3 deletions src/shared/domain/exceptions/invalidArgumentException.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomainException from './domainException';
import ConflictException from '@src/shared/domain/exceptions/conflictException';

export default class InvalidArgumentException extends DomainException {
export default class InvalidArgumentException extends ConflictException {
constructor(public message: string = 'Invalid argument', public code: string = 'invalid_argument') {
super(message, 500, code);
super(message, code);
}
}
6 changes: 3 additions & 3 deletions src/shared/domain/exceptions/invalidEmailException.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomainException from './domainException';
import { ConflictException } from '@nestjs/common';

export default class InvalidEmailException extends DomainException {
export default class InvalidEmailException extends ConflictException {
constructor(public message: string = 'Invalid email', public code: string = 'invalid_email') {
super(message, 500, code);
super(message, code);
}
}
7 changes: 7 additions & 0 deletions src/shared/domain/exceptions/notFoundException.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';

export default class NotFoundException extends DomainException {
constructor(public message: string, public code: string) {
super(message, code);
}
}
7 changes: 7 additions & 0 deletions src/shared/domain/exceptions/unauthorizedException.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import DomainException from '@src/shared/domain/exceptions/domainException';

export default class UnauthorizedException extends DomainException {
constructor(public message: string, public code: string) {
super(message, code);
}
}
2 changes: 1 addition & 1 deletion src/shared/domain/loggerInterface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
interface LoggerInterface {
log(message: string): void;
error(message: string, trace: string): void;
error(message: string, trace?: string): void;
warning(message: string): void;
}

Expand Down
32 changes: 30 additions & 2 deletions src/shared/infrastructure/api/filters/nestErrorFilter.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,44 @@
import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common';
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from '@nestjs/common';
import { Response } from 'express';
import ApiExceptionSerializer from '@src/shared/infrastructure/api/serializers/apiExceptionSerializer';
import DomainException from '@src/shared/domain/exceptions/domainException';
import ConflictException from '@src/shared/domain/exceptions/conflictException';
import NotFoundException from '@src/shared/domain/exceptions/notFoundException';
import UnauthorizedException from '@src/shared/domain/exceptions/unauthorizedException';
import LoggerInterface, { LOGGER_INTERFACE } from '@src/shared/domain/loggerInterface';
import { Inject } from '@src/shared/domain/injector/inject.decorator';

@Catch(Error)
export class NestErrorFilter implements ExceptionFilter {
constructor(@Inject(LOGGER_INTERFACE) private readonly logger: LoggerInterface) {}

catch(exception: Error, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();

this.logger.error(`Exception: ${exception}`);

if (exception instanceof ConflictException) {
response.status(HttpStatus.CONFLICT).json(ApiExceptionSerializer.serialize(exception, HttpStatus.CONFLICT));
return;
}

if (exception instanceof NotFoundException) {
response.status(HttpStatus.NOT_FOUND).json(ApiExceptionSerializer.serialize(exception, HttpStatus.NOT_FOUND));
return;
}

if (exception instanceof UnauthorizedException) {
response
.status(HttpStatus.UNAUTHORIZED)
.json(ApiExceptionSerializer.serialize(exception, HttpStatus.UNAUTHORIZED));
return;
}

if (exception instanceof DomainException) {
response.status(exception.status).json(ApiExceptionSerializer.serialize(exception));
response
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.json(ApiExceptionSerializer.serialize(exception, HttpStatus.INTERNAL_SERVER_ERROR));
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import DomainException from '@src/shared/domain/exceptions/domainException';

export default class ApiExceptionSerializer {
public static serialize(error: DomainException): Record<string, any> {
public static serialize(error: DomainException, status: number): Record<string, any> {
return {
statusCode: error.status || 500,
statusCode: status,
message: error.message,
code: error.code,
};
Expand Down
2 changes: 1 addition & 1 deletion src/shared/infrastructure/logger/nestLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class NestLogger extends NestJsLogger implements LoggerInterface
});
}

error(message: string, trace: string) {
error(message: string, trace?: string) {
this.logger.error(message, trace);
}

Expand Down

0 comments on commit bd9d563

Please sign in to comment.