Spraxium logoSpraxium

Fundamentos de erros

A camada de exceções transforma falhas de runtime e de domínio em um comportamento previsível para a pessoa usuária. Construa o modelo mental de classes de exceção, layouts e políticas antes de escrever seu primeiro handler de erro.

Por que a camada de exceções importa

No Spraxium, as exceções transformam falhas técnicas e de domínio em um comportamento previsível para a pessoa usuária. Sem uma camada de exceções estruturada, cada handler inventa seu próprio estilo de resposta a erro, o que leva a uma UX inconsistente e a logs barulhentos.

Usuários vão acionar negativas de permissão, limites de cooldown, argumentos inválidos e recursos indisponíveis como parte do uso normal do bot. Uma camada de exceções dedicada garante que tudo isso produza respostas consistentes e significativas.

Erro como contrato, não acidente

Cada falha relevante deve ter intenção explícita: uma classe de exceção dedicada representando um cenário concreto, como permissões ausentes, violação de cooldown ou recursos indisponíveis. Isso cria um vocabulário compartilhado em que qualquer pessoa de engenharia consegue ler o código e entender imediatamente o que falhou e como a pessoa usuária é informada.

O objetivo é previsibilidade. O mesmo tipo de falha deve sempre produzir a mesma classe de exceção, o mesmo formato de resposta e o mesmo sinal operacional, independentemente de onde o erro se originou no código.

A classe base SpraxiumException

Toda exceção no ecossistema do Spraxium estende SpraxiumException, que por sua vez estende o Error nativo do JavaScript. A classe base adiciona campos estruturados que o pipeline usa para resolução de layouts, decisões de logging e renderização de resposta. Entender esses campos é essencial antes de criar exceções personalizadas ou trabalhar com as embutidas, porque cada campo controla um aspecto específico de como o erro é processado em 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 qualquer coisa além de um lançamento pontual, estenda SpraxiumException em uma classe nomeada para que a exceção carregue uma identidade estável, que layouts e regras de monitoramento possam mirar. O construtor aceita o mesmo objeto de opções e o encaminha para super, permitindo que cada subclasse defina seu código, sua mensagem padrão e sua interface tipada de props.

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,
});
CampoTypeFinalidade
codestring

Identificador legível por máquina para filtros, monitoramento e buscas em logs

messagestring

Descrição legível por humanos com suporte a placeholders com chaves duplas

propsRecord

Dados de runtime para interpolação de placeholders e renderização de layout

shouldReplybooleanDefine se uma resposta será enviada no Discord; o padrão é true
shouldLogbooleanDefine se a exceção será registrada em log; o padrão é false
layoutExceptionLayoutClass

Override de layout por instância com a prioridade mais alta de resolução

Exceções embutidas

O Spraxium oferece quinze classes de exceção que cobrem os cenários de falha mais comuns em bots do Discord. Cada classe estende SpraxiumException com um code predefinido, uma message padrão com suporte a placeholders e props tipadas para renderização de layout. Você pode lançar qualquer uma delas diretamente, sem criar classes personalizadas, e todas são importadas de @spraxium/core.

Usando as exceções embutidas

As exceções embutidas estão prontas para uso sem nenhuma configuração. Toda classe aceita um objeto opcional de props que preenche placeholders na mensagem padrão e fornece contexto para renderização do layout. O exemplo abaixo mostra três cenários comuns que você encontrará na maioria dos 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' });

Onde as exceções entram no fluxo de runtime

Na prática, uma exceção é lançada dentro do código de domínio, como um service, guard, handler ou listener, e depois é resolvida pelo pipeline central, que decide a estratégia de renderização e o comportamento de logging. Entender esse fluxo é essencial porque ele determina de onde suas classes de exceção surgem, como os layouts são selecionados para apresentar erros às pessoas usuárias e que tipo de dado operacional é registrado para diagnóstico e monitoramento.

EtapaResponsabilidadeResultado esperado
Ponto de lançamento da exceçãoO código de domínio sinaliza uma falha de política ou regraEstado de falha explícito e rastreável
Resolução de layout

O core seleciona o layout por override, mapeamento de classe ou fallback

Resposta consistente para a pessoa usuária
ObservabilidadeO pipeline registra falhas tratadas e não tratadasDiagnóstico operacional previsível