Tratamento de Erros
A biblioteca fornece um sistema robusto de tratamento de erros usando RequestResult (Either pattern) que retorna erros em vez de lançá-los com throw.
Erros Predefinidos
1. ResourceNotFoundError
Lançado quando um recurso não é encontrado.
import { ResourceNotFoundError } from '@koalarx/nest/core/errors/resource-not-found.error'
return failure(new ResourceNotFoundError('Pessoa'))
// Retorna: 404 Not Found2. ConflictError
Lançado quando há conflito (ex: duplicação de dados).
import { ConflictError } from '@koalarx/nest/core/errors/conflict.error'
throw new ConflictError('Email already registered')
// Retorna: 409 Conflict3. BadRequestError
Lançado quando a requisição contém dados inválidos (via Zod).
import { BadRequestError } from '@koalarx/nest/core/errors/bad-request.error'
throw new BadRequestError('Invalid user data')
// Retorna: 400 Bad Request4. NotAllowedError
Lançado quando a operação não é permitida.
import { NotAllowedError } from '@koalarx/nest/core/errors/not-allowed.error'
throw new NotAllowedError('This action is not allowed')
// Retorna: 400 Bad Request5. WrongCredentialsError
Lançado quando credenciais são inválidas.
import { WrongCredentialsError } from '@koalarx/nest/core/errors/wrong-credentials.error'
throw new WrongCredentialsError('Invalid email or password')
// Retorna: 401 Unauthorized6. NoContentError
Lançado quando não há conteúdo para retornar.
import { NoContentError } from '@koalarx/nest/core/errors/no-content.error'
throw new NoContentError('No content available')
// Retorna: 204 No ContentUsar RequestResult (Either Pattern)
A biblioteca usa RequestResult<Error, Success> para retornar sucesso ou erro sem exceções:
import { failure, ok, RequestResult } from '@koalarx/nest/core/request-overflow/request-result'
import { ResourceNotFoundError } from '@koalarx/nest/core/errors/resource-not-found.error'
@Injectable()
export class ReadPersonHandler extends RequestHandlerBase<
number,
RequestResult<ResourceNotFoundError, ReadPersonResponse>
> {
constructor(
private readonly repository: IPersonRepository,
private readonly mapper: AutoMappingService,
) {
super()
}
async handle(
id: number,
): Promise<RequestResult<ResourceNotFoundError, ReadPersonResponse>> {
// Buscar no repositório
const person = await this.repository.read(id)
// Retornar erro se não encontrar
if (!person) {
return failure(new ResourceNotFoundError('Pessoa'))
}
// Mapear e retornar sucesso
return ok(this.mapper.map(person, Person, ReadPersonResponse))
}
}No Controller
O controller verifica isFailure() e lança o erro se necessário:
@Get(':id')
async handle(@Param('id') id: number): Promise<ReadPersonResponse> {
const response = await this.handler.handle(id)
// Se falhou, lança a exceção (que é capturada pelos filtros)
if (response.isFailure()) {
throw response.value
}
// Senão, retorna o sucesso
return response.value
}Criar Erro Customizado
// src/domain/errors/custom-error.ts
import { HttpStatus } from '@nestjs/common'
import { ErrorBase } from '@koalarx/nest/core/errors/error.base'
export class CustomError extends ErrorBase {
public statusCode: number = HttpStatus.FORBIDDEN
constructor(message: string, data?: any) {
super(message, data)
this.name = 'CustomError'
}
}Use o erro customizado:
return failure(new CustomError('Custom error message'))E registre no filtro de domínio se necessário (customize o filtro existente).
Filtros de Exceção
Os filtros são registrados automaticamente pelo KoalaNestModule:
1. Domain Errors Filter
Captura e trata erros de domínio (ResourceNotFoundError, ConflictError, etc) quando lançados.
Resposta exemplo:
{
"statusCode": 404,
"message": "Pessoa",
"data": null
}2. Prisma Validation Exception Filter
Captura erros do Prisma e os converte em mensagens legíveis.
Erros tratados:
P2002: Duplicação de dados única → 409 ConflictP2003: Violação de chave estrangeira → 400 Bad RequestP2025: Registro não encontrado → 404 Not Found
Resposta exemplo:
{
"statusCode": 409,
"message": "Unique constraint failed"
}3. Zod Errors Filter
Captura e trata erros de validação Zod no validator.
Resposta exemplo:
{
"statusCode": 400,
"message": "Dados enviados inválidos",
"errors": [
"name is required",
"email invalid email"
]
}4. Global Exception Filter
Captura todas as exceções não tratadas.
Resposta exemplo:
{
"statusCode": 500,
"message": "Internal server error",
"timestamp": "2024-01-01T10:00:00.000Z",
"path": "/users"
}Exemplo Completo
// src/application/user/read/read-user.handler.ts
import { Injectable } from '@nestjs/common'
import { ResourceNotFoundError } from '@koalarx/nest/core/errors/resource-not-found.error'
import { failure, ok, RequestResult } from '@koalarx/nest/core/request-overflow/request-result'
import { AutoMappingService } from '@koalarx/nest/core/mapping/auto-mapping.service'
import { User } from '@/domain/entities/user/user'
import { IUserRepository } from '@/domain/repositories/iuser.repository'
import { ReadUserResponse } from './read-user.response'
@Injectable()
export class ReadUserHandler extends RequestHandlerBase<
number,
RequestResult<ResourceNotFoundError, ReadUserResponse>
> {
constructor(
private readonly repository: IUserRepository,
private readonly mapper: AutoMappingService,
) {
super()
}
async handle(
id: number,
): Promise<RequestResult<ResourceNotFoundError, ReadUserResponse>> {
// Buscar usuário
const user = await this.repository.read(id)
// Retornar erro se não encontrar
if (!user) {
return failure(new ResourceNotFoundError('Usuário não encontrado'))
}
// Mapear e retornar sucesso
return ok(this.mapper.map(user, User, ReadUserResponse))
}
}// src/host/controllers/user/read-user.controller.ts
@Get(':id')
@ApiResponse({ type: ReadUserResponse })
async handle(@Param('id') id: number): Promise<ReadUserResponse> {
const response = await this.handler.handle(id)
// Se falhou, lança exceção (capturada pelos filtros)
if (response.isFailure()) {
throw response.value
}
return response.value
}Tratamento de Erros do Validator (Zod)
Erros de validação são automaticamente capturados pelo ZodErrorsFilter:
export class CreateUserValidator extends RequestValidatorBase<CreateUserRequest> {
protected get schema(): ZodType<any, ZodTypeDef, any> {
return z.object({
name: z.string().min(1, 'Name is required'),
email: z.string().email('Valid email is required'),
})
}
}
// Se dados inválidos, ZodErrorsFilter captura e retorna 400
const validated = new CreateUserValidator(req).validate()Fluxo de Tratamento de Erros
Handler retorna failure(error)
└─ Controller verifica isFailure()
└─ throws error
└─ DomainErrorsFilter captura
└─ Retorna resposta HTTP com statusCode apropriadoTodos os erros são tratados de forma centralizada e segura!