const config = require('../config'); const { log } = require('./logger'); // Централизованная обработка ошибок const errorHandler = (err, req, res, next) => { // Логирование ошибки log('error', 'Ошибка обработчика', { message: err.message, stack: config.isDevelopment() ? err.stack : undefined, path: req.path, method: req.method, ip: req.ip, user: req.user?.id || 'anonymous' }); // Определение типа ошибки и статус кода let statusCode = err.statusCode || err.status || 500; let message = err.message || 'Внутренняя ошибка сервера'; // Обработка специфических ошибок if (err.name === 'ValidationError') { statusCode = 400; message = 'Ошибка валидации данных'; } else if (err.name === 'CastError') { statusCode = 400; message = 'Неверный формат данных'; } else if (err.name === 'MongoError' && err.code === 11000) { statusCode = 409; message = 'Дубликат записи'; } else if (err.name === 'MulterError') { statusCode = 400; if (err.code === 'LIMIT_FILE_SIZE') { message = 'Файл слишком большой'; } else if (err.code === 'LIMIT_FILE_COUNT') { message = 'Слишком много файлов'; } else { message = 'Ошибка загрузки файла'; } } else if (err.name === 'AxiosError') { statusCode = 502; message = 'Ошибка внешнего сервиса'; } // Отправка ответа res.status(statusCode).json({ success: false, error: message, ...(config.isDevelopment() && { stack: err.stack }) }); }; // Обработка 404 const notFoundHandler = (req, res, next) => { res.status(404).json({ success: false, error: 'Маршрут не найден' }); }; // Обработка необработанных промисов process.on('unhandledRejection', (reason, promise) => { log('error', 'Unhandled Rejection', { reason: reason instanceof Error ? reason.message : reason }); // В production можно отправить уведомление }); // Обработка необработанных исключений process.on('uncaughtException', (error) => { log('error', 'Uncaught Exception', { message: error.message, stack: error.stack }); // Graceful shutdown process.exit(1); }); module.exports = { errorHandler, notFoundHandler };