manicanldes-backend/src/common/errors/classify-error.ts

43 lines
1.5 KiB
TypeScript

import { HttpException } from '@nestjs/common';
import { Prisma } from '../../generated/prisma/client';
import { AppError } from './app-error';
import type { ErrorCode } from './error-catalog';
export function classifyError(error: unknown): AppError {
if (error instanceof AppError) return error;
if (error instanceof Prisma.PrismaClientKnownRequestError) {
const codes: Record<string, ErrorCode> = {
P2002: 'RECORD_CONFLICT',
P2003: 'REFERENCE_INVALID',
P2004: 'DATA_CONSTRAINT',
P2025: 'RECORD_NOT_FOUND',
P2024: 'DATABASE_BUSY',
P2028: 'DATABASE_BUSY',
P2034: 'TRANSACTION_CONFLICT',
};
return new AppError(codes[error.code] ?? 'INTERNAL_FAILURE', error.code);
}
if (error instanceof Prisma.PrismaClientInitializationError)
return new AppError('DATABASE_BUSY');
if (error instanceof HttpException) {
const codes: Record<number, ErrorCode> = {
400: 'REQUEST_MALFORMED',
401: 'AUTH_REQUIRED',
403: 'ACCESS_DENIED',
404: 'ROUTE_NOT_FOUND',
413: 'REQUEST_TOO_LARGE',
429: 'RATE_LIMITED',
503: 'DATABASE_BUSY',
};
return new AppError(codes[error.getStatus()] ?? 'INTERNAL_FAILURE');
}
// Express parser errors are not Nest HttpExceptions.
if (typeof error === 'object' && error !== null && 'type' in error) {
if (error.type === 'entity.too.large')
return new AppError('REQUEST_TOO_LARGE');
if (error.type === 'entity.parse.failed')
return new AppError('REQUEST_MALFORMED');
}
return new AppError('INTERNAL_FAILURE');
}