Spraxium logoSpraxium

Fundamentos de Excepciones

La capa de excepciones convierte fallos de runtime y de dominio en un comportamiento predecible para el usuario. Construye el modelo mental de clases de excepción, layouts y políticas antes de escribir tu primer manejador de errores.

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.

shop.command.ts
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.

order-limit.exception.ts
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,
});
CampoTipoPropósito
codestring

Identificador legible por máquina para filtrado, monitoreo y consultas de logs

messagestring

Descripción legible por humanos con soporte para placeholders de doble llave

propsRecord

Datos de runtime para interpolación de placeholders y renderizado del layout

shouldReplybooleanSi se debe enviar una respuesta en Discord, por defecto true
shouldLogbooleanSi se debe registrar la excepción, por defecto false
layoutExceptionLayoutClass

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.

shop.command.ts
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.

EtapaResponsabilidadResultado esperado
Sitio de lanzamiento de la excepciónEl código de dominio señala un fallo de política o reglaEstado 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
ObservabilidadEl pipeline registra fallos manejados y no manejadosDiagnósticos operativos predecibles