Qué controla este paquete
@spraxium/http es el límite de transporte entre tu bot de Discord y clientes HTTP externos. Inicia un servidor basado en Hono, aplica middleware y guards compartidos, convierte metadatos de controladores en rutas ejecutables y expone una abstracción BotBridge para que los controladores interactúen con guilds, miembros y APIs de moderación sin depender de un modo específico de ejecución de Discord. Cada parte de este pipeline, desde la resolución de plugins hasta el apagado ordenado, está gestionada por un único servicio llamado HttpServer.
El paquete sigue un modelo de tres capas. La configuración del plugin define comportamientos como host, puerto, modo sharding y política de seguridad. Los metadatos del módulo declaran los controladores, servicios, guards y middleware que forman la superficie de la API. HttpServer lee ambas capas en el arranque y produce una aplicación Hono completamente conectada y enlazada a @hono/node-server. Esta separación permite que las decisiones de configuración vivan fuera del código, que los contratos de rutas vivan en decoradores y que el cableado en runtime quede oculto detrás de un ciclo de vida predecible.
Entender este modelo de ownership es clave para usar el paquete de forma efectiva. Todas las demás páginas de la categoría HTTP se construyen sobre esta base, así que invertir tiempo aquí evita confusiones cuando llegues más adelante a enrutamiento, seguridad o bridge.
Mapa interno del paquete
Hono como base HTTP
El paquete usa Hono como framework HTTP en lugar de Express o Fastify. Hono es un framework web liviano, compatible con edge, que corre sobre cualquier runtime estándar de JavaScript. HttpServer crea una instancia new Hono() durante el arranque, registra en ella todo el middleware y handlers de rutas, y luego pasa app.fetch a @hono/node-server mediante la función serve() con el host y puerto configurados.
Este diseño implica que controladores y middleware interactúan con los tipos Context y Next de Hono. Decoradores de parámetros como @HttpParam, @HttpQuery y @HttpHeader leen desde ctx.req, mientras que los handlers pueden devolver objetos planos (serializados automáticamente a JSON) o instancias nativas de Response para control total. Entender esta base de Hono ayuda cuando necesites acceder a funcionalidades fuera de la superficie de decoradores, como leer cuerpos de request sin procesar o establecer headers de respuesta personalizados mediante ctx.res.
Modelo global de ownership
Usa una sola ruta global de ownership HTTP
No crees un módulo wrapper local solo para HTTP. Usa tu AppModule raíz como fuente de metadatos en defineHttp() e importa HttpModule una vez dentro de AppModule. Múltiples raíces de metadatos provocan comportamiento ambiguo en guards, middleware y ciclo de vida.
El modelo de ownership único implica una entrada de plugin en spraxium.config.ts, un decorador @HttpClientModule en tu AppModule y una importación de HttpModule en el grafo de módulos. Este patrón mantiene explícito el ownership del ciclo de vida: el servidor se enlaza una vez, la política de guards se declara una vez y el orden de middleware es visible en un único sitio. Cuando los equipos reparten responsabilidades, agregan controladores y servicios a los mismos metadatos del módulo en lugar de crear árboles de módulos que compiten entre sí.
Esta restricción existe porque HttpServer lee metadatos de HttpClientModule desde la clase referenciada en defineHttp({ module }). Si creas un segundo módulo con su propio HttpClientModule, el servidor lo ignora porque solo se resuelve la referencia raíz. Mantener todo en AppModule evita drift silencioso de configuración.
Snapshot mínimo de integración
import { defineHttp } from '@spraxium/http';
import { AppModule } from '../src/app.module';
export const httpPlugin = defineHttp({
enabled: true,
host: process.env.HTTP_HOST ?? '0.0.0.0',
port: Number(process.env.HTTP_PORT ?? 3000),
apiKey: process.env.HTTP_API_KEY ?? '',
sharding: false,
security: {
hidePoweredBy: true,
cors: { origins: ['https://admin.example.com'], credentials: true },
},
module: AppModule,
});Modos de inicio: directo vs sharded
HttpServer soporta dos rutas de arranque según el flag sharding en HttpConfig. Entender la diferencia es importante porque afecta cuándo inicia el servidor, qué implementación de bridge se selecciona y si hay un Client de Discord disponible en el contenedor DI.
En modo directo (sharding: false), el servidor arranca durante onBoot y requiere un Client de Discord inyectado. Si el cliente no existe, el arranque se aborta con un error registrado en logs. BridgeFactory crea un DirectBotBridge que accede a guilds, miembros y baneos mediante la caché y los métodos API del cliente directamente.
En modo sharded (sharding: true), el servidor no arranca durante onBoot. En su lugar, un bloque estático en HttpServer registra un hook en ParentHookRegistry. Cuando el proceso padre crea shards, ese hook recibe la instancia de ShardingManager e inicia el servidor fuera del ciclo normal de boot. BridgeFactory crea un ShardedBotBridge que usa manager.broadcastEval() para alcanzar guilds en todos los shards. Este modo también guarda la referencia del manager en HttpRegistry para que sobreviva al contexto de inicialización estática.
Flujo runtime de un vistazo
Resolver configuración del plugin
HttpServer lee la entrada del plugin HTTP desde ConfigStore mediante getPluginConfig(defineHttp). Ese objeto contiene host, puerto, modo sharding, política de seguridad y la referencia a la clase de módulo. Si no se encuentra config o enabled es false, el servidor omite totalmente el arranque y registra una advertencia.
Seleccionar estrategia de inicio
En modo directo, onBoot requiere un Client de Discord inyectado. En modo sharded, un hook estático de ParentHookRegistry recibe el ShardingManager y llama server.start() fuera del ciclo de vida normal. Ambas rutas convergen en el mismo método start() que construye la aplicación Hono.
Crear BotBridge
BridgeFactory.create() verifica si hay un ShardingManager o un Client disponible y devuelve el bridge correspondiente. La instancia del bridge se agrega al mapa de dependencias DI para que controladores y servicios puedan inyectar BotBridge como parámetro de constructor.
Aplicar capa global de seguridad
El servidor registra middleware en este orden fijo: remoción de X-Powered-By, SecurityHeadersMiddleware, CorsMiddleware, BodyLimitMiddleware y luego cualquier middleware global personalizado desde los metadatos de HttpClientModule. Cada middleware se enlaza a la ruta '*' para ejecutarse antes de todos los handlers.
Ejecutar guards globales
Si HttpClientModule declara guards, GuardExecutor los envuelve en middleware Hono que corre secuencialmente. Cuando algún guard retorna false, la ejecución se detiene y el servidor responde con { ok: false, error: 'Unauthorized' } con estado 401. No se ejecuta más middleware ni handlers.
Registrar controladores y servicios
RouteRegistry resuelve primero los servicios usando orden topológico para respetar dependencias, luego instancia los controladores con el mapa resuelto. RouteBuilder lee metadatos de rutas de cada controlador y enlaza handlers en Hono con cadenas de middleware fusionadas de nivel clase y método.
Resolver parámetros y validar DTOs
Cuando una request llega a un handler, ParamResolver lee metadatos de decoradores de parámetros y extrae valores desde params, query, body, headers o el Context completo de Hono. Si un decorador @HttpBody incluye una clase DTO, ValidationPipe transforma el body crudo en una instancia tipada y lo valida con reglas de class-validator antes de ejecutar el handler.
Normalizar errores y devolver respuesta
Los handlers que devuelven objetos planos se serializan automáticamente a JSON con estado 200 (o un estado personalizado de @HttpStatus). Si un handler devuelve un Response nativo, Hono lo pasa sin cambios. El handler onError normaliza excepciones lanzadas: ValidationError devuelve 400 con detalles, cualquier HttpError devuelve su propio status code y excepciones desconocidas devuelven 500 tras registrarse en logs.
Apagado ordenado
Durante onShutdown, el servidor cierra la instancia subyacente de Server de Node.js y espera a que drenen las conexiones activas. El handler de apagado también se registra para SIGINT y SIGTERM en modo sharded para asegurar que el servidor se detenga limpiamente cuando termine el proceso padre.
Hoja de ruta de documentación
Cada página de esta categoría cubre en profundidad una capa del stack HTTP. Léalas en orden para tener una visión completa, o salta al tema específico cuando necesites una referencia puntual.
- Configuración y Setup de Módulo Único, cubre defineHttp, HttpConfig y el modelo de ownership de módulos.
- Estructura de Carpetas y Módulos HTTP, cubre la organización de archivos recomendada a medida que crece el número de endpoints.
- Pipeline de Enrutamiento y Decoradores, cubre decoradores, resolución de parámetros, validación de DTO y forma de respuestas.
- Seguridad, Guards y Middleware, cubre el stack de hardening, la interfaz de guard y la composición de middleware.
- Modos Runtime de Bot Bridge, cubre el contrato BotBridge, implementaciones directas vs sharded y serializadores.
- Excepciones y Manejo de Errores, cubre la jerarquía HttpError, detalles de ValidationError y la capa central de normalización.