43 lines
1.5 KiB
TypeScript
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');
|
|
}
|