Filtros de Excepción
Filtros de Excepción
Sección titulada «Filtros de Excepción»Los filtros de excepción te dan un único lugar para traducir cualquier error lanzado a una respuesta HTTP consistente — sin try/catch en cada handler.
El problema que resuelven
Sección titulada «El problema que resuelven»Sin filtros, distintos plugins lanzan distintos tipos de error con distintas formas. Los handlers acaban con bloques try/catch dispersos que producen respuestas inconsistentes.
// Sin filtros — manejo disperso@Get('/users/:id')async getUser(@Param('id') id: string) { try { return await db.findUser(id); } catch (err) { if (err instanceof DrizzleError) return c.json({ error: '...' }, 500); throw err; }}Con filtros de excepción, defines la traducción una vez y todas las rutas se benefician.
Crear un filtro
Sección titulada «Crear un filtro»Implementa la interfaz ExceptionFilter<T> y decora con @Catch:
import { ExceptionFilter, Catch } from 'veloce-ts';import type { Context } from 'hono';
@Catch(DrizzleError)class DatabaseExceptionFilter implements ExceptionFilter<DrizzleError> { catch(error: DrizzleError, c: Context): Response { return c.json( { error: 'Error de base de datos', code: error.code }, 500 ); }}@Catch acepta una o más clases de error. El filtro se aplica cuando cualquier comprobación instanceof coincide.
Registro global
Sección titulada «Registro global»const app = new Veloce();app.useFilter(new DatabaseExceptionFilter());app.useFilter(new ValidationExceptionFilter());await app.compile();Los filtros se comprueban en orden de registro. El primero que coincide gana — los siguientes se omiten.
Múltiples tipos de error en un filtro
Sección titulada «Múltiples tipos de error en un filtro»@Catch(TypeError, RangeError)class JavaScriptErrorFilter implements ExceptionFilter { catch(error: Error, c: Context): Response { return c.json({ error: error.message }, 500); }}Ejemplo de filtro para ZodError
Sección titulada «Ejemplo de filtro para ZodError»import { ExceptionFilter, Catch } from 'veloce-ts';import { ZodError } from 'zod';import type { Context } from 'hono';
@Catch(ZodError)class ValidationExceptionFilter implements ExceptionFilter<ZodError> { catch(error: ZodError, c: Context): Response { return c.json( { error: 'Validación fallida', details: error.issues.map(i => ({ field: i.path.join('.'), message: i.message, })), }, 422 ); }}Errores de dominio personalizados
Sección titulada «Errores de dominio personalizados»class UserNotFoundError extends Error { constructor(public readonly userId: string) { super(`Usuario ${userId} no encontrado`); }}
@Catch(UserNotFoundError)class UserNotFoundFilter implements ExceptionFilter<UserNotFoundError> { catch(error: UserNotFoundError, c: Context): Response { return c.json({ error: 'Usuario no encontrado', userId: error.userId }, 404); }}
// En tu servicio — solo lanza, el filtro se encarga del restoasync getUser(id: string) { const user = await db.findUser(id); if (!user) throw new UserNotFoundError(id); return user;}Orden de ejecución de los filtros
Sección titulada «Orden de ejecución de los filtros»Petición → Handler de ruta (lanza) → FilterManager → Filtro 1: comprobación instanceof → omitir si no coincide → Filtro 2: comprobación instanceof → COINCIDE → devolver Response → (sin coincidencia) → manejador de errores por defecto del frameworkFilterManager — uso avanzado
Sección titulada «FilterManager — uso avanzado»FilterManager está exportado para integraciones que necesitan activar filtros fuera del router (p. ej. manejo de errores de WebSocket):
import { FilterManager } from 'veloce-ts';
const manager = app.getFilterManager();const response = manager.handle(error, c);if (response) return response;Buenas prácticas
Sección titulada «Buenas prácticas»- Un filtro por dominio de error — mantén los filtros pequeños y enfocados.
- Registra en orden de especificidad — primero las clases de error más específicas; el filtro genérico
Erroral final. - Nunca silencies errores — siempre devuelve una
Responseo relanza.
// Filtros específicos primeroapp.useFilter(new UserNotFoundFilter());app.useFilter(new DatabaseExceptionFilter());app.useFilter(new ValidationExceptionFilter());// Genérico al finalapp.useFilter(new GenericErrorFilter());