Ownership de configuración primero
La decisión de arquitectura más importante es dónde viven los metadatos. HttpServer lee metadatos HttpClientModule desde la clase referenciada en defineHttp({ module }), por lo que esa clase se convierte en el único owner de cada declaración de controlador, servicio, guard y middleware en la superficie HTTP. Usar AppModule como esa clase mantiene explícito el ownership y evita drift silencioso de configuración cuando los equipos refactorizan módulos.
No necesitas un módulo wrapper HTTP local
Evita crear un AppHttpModule separado solo para alojar metadatos HttpClientModule. Mantén HttpClientModule en AppModule, importa HttpModule en AppModule y referencia AppModule en defineHttp. Un segundo módulo con su propio HttpClientModule será ignorado silenciosamente por el servidor porque solo se resuelve la referencia raíz.
Este modelo elimina ambigüedad de ownership. Ciclo de vida del servidor, guards, middleware y registro de rutas apuntan a una sola clase raíz y una sola entrada de plugin. Cuando agregas un nuevo controlador o cambias el stack de guards, el cambio se ve en un solo lugar y toma efecto en toda la superficie API sin tocar archivos de configuración.
Contrato HttpConfig
HttpConfig es la interfaz que acepta defineHttp() y que ConfigStore entrega a HttpServer en tiempo de boot. Cada campo se mapea a un comportamiento runtime específico, así que entender el contrato evita sorpresas en despliegue.
Subestructura de SecurityConfig
El campo security acepta un objeto SecurityConfig con cuatro subcampos opcionales. Cada subcampo controla una capa del stack de hardening y puede establecerse en false para desactivarla por completo. Cuando un subcampo se omite, el paquete aplica SECURITY_DEFAULTS automáticamente.
División de integración recomendada
Mantén la llamada a defineHttp en un archivo de config dedicado para que decisiones de red y seguridad sean visibles sin desplazarte por decoradores de módulo. El archivo de config importa AppModule, y spraxium.config.ts importa ese archivo de config. Este patrón de tres archivos da un hogar estable a cada responsabilidad: el archivo de config controla infraestructura, el módulo controla metadatos y la config raíz controla registro de plugins.
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,
headers: {
frameOptions: 'DENY',
contentSecurityPolicy: "default-src 'none'",
referrerPolicy: 'no-referrer',
},
cors: {
origins: ['https://admin.example.com'],
methods: ['GET', 'POST', 'PATCH'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Api-Key'],
credentials: true,
},
bodyLimit: { maxSize: 256_000 },
},
module: AppModule,
});Forma de metadatos de HttpClientModule
@HttpClientModule es un decorador de clase que almacena metadatos consumidos por HttpServer durante el registro de rutas. Cada campo controla una fase distinta del pipeline de startup.
La separación entre middleware y middlewareProviders da ownership claro entre política global de pipeline y declaraciones de nivel ruta. El middleware global corre en todas las requests sin condición. El middleware de ruta corre solo en endpoints decorados con @HttpUseMiddleware y se resuelve de forma perezosa desde el mapa de providers, por lo que clases middleware no referenciadas nunca se ejecutan.
Secuencia de setup
Extrae configuración de plugin a un archivo dedicado
Mantén la llamada defineHttp en config/http.config.ts para que el enlace
de red, la política de seguridad y el modo sharding sean visibles en un
único lugar. Esto también mantiene spraxium.config.ts enfocado en registro
de plugins en lugar de detalles de implementación. Variables de entorno para
host, puerto y API key deberían leerse aquí.
Apunta module a tu composición real raíz
Establece module: AppModule en defineHttp para que HttpServer lea
metadatos desde la misma clase que controla el grafo de módulos. Crear un
HttpAppModule separado produce drift porque cambios en AppModule no se
propagan automáticamente a la fuente de metadatos HTTP.
Importa HttpModule una sola vez en AppModule
HttpModule es global y debería aparecer una vez en imports del módulo raíz. Eso asegura un único owner de ciclo de vida para inicio del servidor y apagado ordenado. Importarlo en múltiples módulos no causa errores, pero no aporta beneficios.
Registra guards y middleware en HttpClientModule
Declara clases guard personalizadas en el arreglo @HttpClientModule() para protección global. El framework resuelve cada clase guard vía DI en startup. Las instancias middleware van en middleware y corren después del stack de seguridad. El middleware por ruta va en middlewareProviders y se activa por endpoint con @HttpUseMiddleware.
Registra una sola entrada HTTP plugin en defineConfig
Mantén una sola entrada de plugin HTTP dentro de defineConfig({plugins}).
Múltiples entradas llevan a ownership ambiguo y registro de rutas inestable
porque ConfigStore devuelve una sola config para la clave defineHttp.
Comportamiento de inicio por modo
| Modo | Cuándo inicia | Requisito de client | Implementación de bridge |
|---|---|---|---|
| Directo, con sharding: false | Durante el hook de ciclo de vida onBoot, después de que el Client de Discord está listo. | Requerido. Si falta, el servidor registra error en logs y omite el startup. | DirectBotBridge: accede a caché de guilds y API de Discord a través de la instancia client directamente. |
| Sharded, con sharding: true | Vía ParentHookRegistry cuando el proceso padre crea el ShardingManager. | No requerido. El ShardingManager reemplaza al client para interacciones con el bot. | ShardedBotBridge: usa |
En modo directo, el servidor tiene acceso inmediato al Client de Discord y puede inyectarlo en el mapa DI junto con BotBridge. Los controladores que necesiten el client de forma directa (para funciones no cubiertas por bridge) pueden declararlo como parámetro de constructor. En modo sharded, el client no está disponible en el proceso HTTP, así que los controladores deben usar BotBridge exclusivamente para interactuar con Discord.