dec8891506
Panel nuevo en Configuracion ("Errores del sistema", solo superadmin): errores de backend
(excepciones 500 no manejadas, con stack/ruta/metodo/usuario) y de frontend (errores JS y
promesas sin catch en el navegador del usuario, antes invisibles para cualquiera mas alla de esa
persona). Filtro por origen, boton para limpiar el historial.
Error Boundary de React: si algo rompe el render, ya no queda pantalla en blanco -- aviso simple
con boton de recargar, y el error queda reportado igual.
Nuevo error_logs (tabla, se recorta sola a 1000 filas) + GET/DELETE /api/error-logs (superadmin)
+ POST /api/error-logs (publico, rate-limited, para reportar incluso sin sesion).
Probado de punta a punta en dev: error real de backend (500) capturado con stack completo y
usuario correcto, error JS global y promesa rechazada capturados desde el navegador, panel
muestra ambos y el boton de limpiar funciona. Se encontro y corrigio un bug real en el camino: la
identificacion de usuario opcional leia jwt.payload.id en vez de .sub (como realmente lo firma
auth/service.js), asi que nunca identificaba a nadie.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
23 lines
825 B
JavaScript
23 lines
825 B
JavaScript
import { HttpError } from '../utils/http.js';
|
|
import { logBackendError } from '../modules/errorLogs/service.js';
|
|
|
|
export function notFoundHandler(req, res) {
|
|
res.status(404).json({ success: false, data: null, error: 'Ruta no encontrada' });
|
|
}
|
|
|
|
export function errorHandler(err, req, res, next) { // eslint-disable-line no-unused-vars
|
|
if (err instanceof HttpError) {
|
|
return res.status(err.status).json({ success: false, data: null, error: err.message });
|
|
}
|
|
console.error('[error]', err);
|
|
// Fire-and-forget: logBackendError nunca tira (se traga sus propios fallos), no bloquea la
|
|
// respuesta al cliente.
|
|
logBackendError(err, req);
|
|
const isProd = process.env.NODE_ENV === 'production';
|
|
res.status(500).json({
|
|
success: false,
|
|
data: null,
|
|
error: isProd ? 'Error interno' : err.message,
|
|
});
|
|
}
|