| import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'; |
| import { Prisma } from '@prisma/client'; |
| import { logger } from '../logger'; |
|
|
| export interface ApiErrorResponse { |
| error: string; |
| message: string; |
| code?: string; |
| details?: any; |
| } |
|
|
| export const setupErrorHandler = (server: FastifyInstance) => { |
| server.setErrorHandler((error: any, request: FastifyRequest, reply: FastifyReply) => { |
| |
| logger.error({ |
| err: error, |
| path: request.url, |
| method: request.method, |
| requestId: request.id |
| }, 'API Error detected'); |
|
|
| |
| if (error instanceof Prisma.PrismaClientKnownRequestError) { |
| |
| if (error.code === 'P2002') { |
| return reply.code(409).send({ |
| error: 'Conflict', |
| message: `A record with this ${error.meta?.target} already exists.`, |
| code: 'PRISMA_P2002' |
| }); |
| } |
| |
| if (error.code === 'P2025') { |
| return reply.code(404).send({ |
| error: 'Not Found', |
| message: 'The requested record does not exist.', |
| code: 'PRISMA_P2025' |
| }); |
| } |
| } |
|
|
| |
| if (error.validation) { |
| return reply.code(400).send({ |
| error: 'Bad Request', |
| message: 'Validation failed', |
| details: error.validation, |
| code: 'VALIDATION_ERROR' |
| }); |
| } |
|
|
| |
| if (error.statusCode === 401 || error.code === 'FST_JWT_NO_AUTHORIZATION_TOKEN') { |
| return reply.code(401).send({ |
| error: 'Unauthorized', |
| message: error.message || 'Authentication required', |
| code: 'AUTH_ERROR' |
| }); |
| } |
|
|
| |
| const statusCode = error.statusCode || 500; |
| return reply.code(statusCode).send({ |
| error: statusCode === 500 ? 'Internal Server Error' : error.name || 'Error', |
| message: statusCode === 500 ? 'An unexpected error occurred' : error.message, |
| code: error.code || 'GENERIC_ERROR' |
| }); |
| }); |
| }; |
|
|