Por qué importa la capa de excepciones
En Spraxium, las excepciones transforman tanto fallos técnicos como de dominio en un comportamiento predecible para el usuario. Sin una capa de excepciones estructurada, cada handler inventa su propio estilo de respuesta de error, lo que termina en una UX inconsistente y logs ruidosos.
Los usuarios dispararán denegaciones de permisos, límites de cooldown, argumentos inválidos y recursos no disponibles como parte normal del uso del bot. Una capa de excepciones dedicada garantiza que todo eso produzca respuestas consistentes y significativas.
El error como contrato, no como accidente
Cada fallo relevante debe tener una intención explícita: una clase de excepción dedicada que represente un escenario concreto, como permisos faltantes, violaciones de cooldown o recursos no disponibles. Esto crea un vocabulario compartido donde cualquier ingeniero puede leer el código y entender de inmediato qué falló y cómo se informa al usuario.
El objetivo es la previsibilidad. El mismo tipo de fallo siempre debe producir la misma clase de excepción, el mismo formato de respuesta y la misma señal operativa, sin importar en qué parte del código se origine el error.
La clase base SpraxiumException
Toda excepción en el ecosistema Spraxium extiende SpraxiumException, que a su vez extiende el Error nativo de JavaScript. La clase base agrega campos estructurados que el pipeline usa para resolución de layouts, decisiones de logging y renderizado de respuestas. Entender estos campos es esencial antes de crear excepciones personalizadas o trabajar con las integradas, porque cada campo controla un aspecto específico de cómo se procesa el error en runtime.
import { SpraxiumException } from '@spraxium/core';
throw new SpraxiumException({
code: 'ORDER_LIMIT_EXCEEDED',
message: 'You have exceeded the {{limit}} order limit for today.',
props: { limit: 5, userId: interaction.user.id },
shouldReply: true,
shouldLog: false,
});Para cualquier cosa más allá de un lanzamiento puntual, extiende SpraxiumException en una clase con nombre para que la excepción tenga una identidad estable que los layouts y las reglas de monitoreo puedan apuntar. El constructor acepta el mismo objeto de opciones y lo pasa a super, permitiendo que cada subclase defina su código, mensaje por defecto e interfaz de props tipada.
import { SpraxiumException } from '@spraxium/core';
interface OrderLimitProps {
limit: number;
userId: string;
}
export class OrderLimitExceededException extends SpraxiumException {
constructor(props: OrderLimitProps) {
super({
code: 'ORDER_LIMIT_EXCEEDED',
message: 'You have exceeded the {{limit}} order limit for today.',
props,
});
}
}
// Usage anywhere in domain code
throw new OrderLimitExceededException({
limit: 5,
userId: interaction.user.id,
});| Campo | Tipo | Propósito |
|---|---|---|
| code | string | Identificador legible por máquina para filtrado, monitoreo y consultas de logs |
| message | string | Descripción legible por humanos con soporte para placeholders de doble llave |
| props | Record | Datos de runtime para interpolación de placeholders y renderizado del layout |
| shouldReply | boolean | Si se debe enviar una respuesta en Discord, por defecto true |
| shouldLog | boolean | Si se debe registrar la excepción, por defecto false |
| layout | ExceptionLayoutClass | Override de layout por instancia con la prioridad de resolución más alta |
Excepciones integradas
Spraxium incluye quince clases de excepción que cubren los escenarios de fallo más comunes en bots de Discord. Cada clase extiende SpraxiumException con un code predefinido, un message por defecto con soporte para placeholders y props tipadas para el renderizado del layout. Puedes lanzar cualquiera de estas directamente sin crear clases personalizadas, y todas se importan desde @spraxium/core.
Uso de excepciones integradas
Las excepciones integradas están listas para usarse sin configuración adicional. Cada clase acepta un objeto props opcional que completa placeholders en el mensaje por defecto y aporta contexto para el renderizado del layout. El ejemplo siguiente muestra tres escenarios comunes que encontrarás en la mayoría de bots.
import {
CooldownException,
PermissionDeniedException,
MaintenanceException,
} from '@spraxium/core';
// User must wait before retrying the command
throw new CooldownException({ seconds: 10 });
// User lacks the required permission
throw new PermissionDeniedException({ permission: 'MANAGE_MESSAGES' });
// Feature is temporarily disabled
throw new MaintenanceException({ feature: 'Leaderboard', eta: '2 hours' });Dónde entran las excepciones en el flujo de ejecución
En la práctica, una excepción se lanza dentro de código de dominio como un service, guard, handler o listener, y luego se resuelve por el pipeline core que decide la estrategia de renderizado y el comportamiento de logging. Entender este flujo es esencial porque determina dónde se originan tus clases de excepción, cómo se seleccionan los layouts para presentar errores a los usuarios y qué tipo de datos operativos se registran para diagnóstico y monitoreo.
| Etapa | Responsabilidad | Resultado esperado |
|---|---|---|
| Sitio de lanzamiento de la excepción | El código de dominio señala un fallo de política o regla | Estado de fallo explícito y trazable |
| Resolución de layout | Core selecciona el layout por override, mapeo de clase o fallback | Respuesta consistente para el usuario |
| Observabilidad | El pipeline registra fallos manejados y no manejados | Diagnósticos operativos predecibles |