Qué es Spraxium
Spraxium es un framework de TypeScript que se sitúa sobre Discord.js y aporta la capa de arquitectura que Discord.js intencionalmente no incluye. Discord.js maneja la comunicación de bajo nivel con el gateway, incluyendo conexiones WebSocket, llamadas REST, eventos crudos y modelos de datos. Spraxium toma el control desde ahí y te ofrece módulos, inyección de dependencias, pipeline de guards, hooks de ciclo de vida y una secuencia de arranque determinista que garantiza que tu bot inicie igual en cada ejecución.
Cada funcionalidad vive en su propio módulo con límites claros y dependencias explícitas. El contenedor de DI resuelve e inyecta todo automáticamente; tú declaras qué necesita cada clase y el framework se encarga del wiring.
Prerrequisitos
Necesitas tres cosas antes de empezar:
- Node.js 20 o superior. Spraxium está orientado a las versiones LTS actuales. Puedes verificar tu versión instalada ejecutando
node -ven tu terminal, y tanto LTS 20 como LTS 22 son totalmente compatibles. - Un token de bot de Discord. Crea una aplicación nueva en Discord Developer Portal, añade un Bot y copia el token. Ese token es lo que permite que tu bot se autentique con el gateway de Discord.
- Proyecto TypeScript. El scaffold del CLI configura automáticamente tsconfig.json con experimentalDecorators y emitDecoratorMetadata habilitados, necesarios para el sistema de inyección de dependencias basado en decorators del que depende Spraxium.
Nunca expongas el token de tu bot
El token actúa como la contraseña de tu bot; cualquiera que lo tenga puede tomar control total del bot. Guárdalo siempre en .env y asegúrate de que .env esté incluido en .gitignore. El scaffold de Spraxium agrega esa regla al .gitignore generado automáticamente.
Usa un servidor de pruebas
Durante el desarrollo, apunta siempre tu bot a un servidor privado de Discord que controles. Así podrás registrar slash commands al instante con registro por guild y probar interacciones sin afectar a usuarios reales. Mantenlo separado de cualquier servidor de producción para evitar conflictos accidentales de comandos o problemas de rate limit.
Genera el proyecto
Ejecuta el comando de creación para generar un proyecto con la estructura de carpetas correcta, configuración TypeScript y todas las dependencias preinstaladas. El CLI solicita una plantilla, package manager y si deseas inicializar un repositorio Git.
npx @spraxium/cli@latest new my-botEstructura inicial
Cada archivo tiene un rol arquitectónico específico:
- main.ts: solo bootstrap; valida env y arranca el framework
- app.env.ts: schema de env tipado, validado antes de conectar a Discord
- app.module.ts: raíz de composición, importa módulos de funcionalidades, sin lógica de negocio
- modules/: una carpeta por dominio funcional
Bootstrap
main.ts es el único archivo que toca la factory del framework. Valida variables de entorno, crea la aplicación, carga el grafo de módulos y abre la conexión con Discord.
import { IntentPreset, SpraxiumFactory } from '@spraxium/core';
import { EnvValidator } from '@spraxium/env';
import { AppEnv } from './app.env';
import { AppModule } from './app.module';
async function main(): Promise<void> {
const env = EnvValidator.validate(AppEnv);
const app = await SpraxiumFactory.create({ token: env.token });
app.useModule(AppModule);
app.intents(IntentPreset.Standard);
await app.listen();
}
main();EnvValidator.validate lee .env y valida cada campo contra AppEnv; valores ausentes o malformados lanzan error de inmediato, antes de que Discord conecte. app.listen() resuelve el grafo de DI, instancia providers, enlaza listeners y hace login.
Módulo raíz
AppModule es la raíz de composición: importa módulos de funcionalidades, pero no contiene providers ni listeners. Agregar funcionalidades significa agregar imports de módulos aquí.
import { Module } from '@spraxium/common';
import { DefaultModule } from './modules/default/default.module';
@Module({
imports: [DefaultModule],
})
export class AppModule {}Reglas arquitectónicas principales
Tres reglas que sustentan cómo opera el framework:
- Un módulo por dominio funcional. Cada dominio de tu bot, ya sea moderación, comandos, eventos o integraciones externas, obtiene su propia carpeta de módulo dedicada con sus archivos de servicio, listener y módulo. Las dependencias entre funcionalidades pasan por imports y exports explícitos en lugar de estado global compartido, lo que facilita entender exactamente de qué depende cada módulo.
- Inyección de dependencias para todo. Nunca deberías instanciar servicios manualmente con la palabra clave new. En su lugar, declara dependencias como parámetros del constructor y deja que el contenedor de DI las resuelva automáticamente. Esto mantiene el acoplamiento explícito, hace que las pruebas con mocks sean directas y garantiza que el framework controle el ciclo de vida de cada servicio.
- Validación de arranque antes de Discord. Todo el grafo de DI se resuelve y todos los providers se instancian antes del login de Discord. Si cualquier servicio tiene configuración inválida o una dependencia faltante, el error aparece en el arranque con un mensaje claro en lugar de aparecer tras desplegar, cuando un usuario dispara el comando afectado.