Controle da configuração em primeiro lugar
A decisão arquitetural mais importante é onde os metadados vivem. O HttpServer lê os metadados de HttpClientModule a partir da classe referenciada em defineHttp({ module }), então essa classe se torna a dona única de toda declaração de controller, service, guard e middleware da superfície HTTP. Usar AppModule como essa classe deixa o controle explícito e evita desvio silencioso de configuração quando a equipe refatora módulos.
Não é preciso um módulo wrapper local para HTTP
Evite criar um AppHttpModule separado apenas para hospedar os metadados de HttpClientModule. Mantenha HttpClientModule no AppModule, importe HttpModule no AppModule e referencie AppModule em defineHttp. Um segundo módulo com seu próprio HttpClientModule é ignorado silenciosamente pelo servidor, porque só a referência raiz é resolvida.
Esse modelo elimina ambiguidade de controle. Ciclo de vida do servidor, guards, middleware e registro de rotas apontam todos para uma única classe raiz e uma única entrada de plugin. Quando você adiciona um novo controller ou altera a pilha de guards, a mudança fica visível em um só lugar e passa a valer em toda a superfície da API sem mexer nos arquivos de configuração.
HttpConfig contract
HttpConfig é a interface que defineHttp() aceita e que ConfigStore entrega ao HttpServer no boot. Cada campo se mapeia para um comportamento específico de runtime, então entender esse contrato evita surpresas na implantação.
Subestrutura de SecurityConfig
O campo security aceita um objeto SecurityConfig com quatro subcampos opcionais. Cada subcampo controla uma camada da pilha de hardening e pode ser definido como false para desativá-la por completo. Quando um subcampo é omitido, o pacote aplica SECURITY_DEFAULTS automaticamente.
Separação de integração recomendada
Mantenha a chamada de defineHttp em um arquivo de configuração dedicado para que decisões de rede e segurança fiquem visíveis sem precisar percorrer decorators de módulo. O arquivo de configuração importa AppModule, e spraxium.config.ts importa esse arquivo. Esse padrão de três arquivos dá um lugar estável para cada responsabilidade: o arquivo de configuração controla a infraestrutura, o módulo controla os metadados e a configuração raiz controla o registro do plugin.
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,
});Estrutura dos metadados de HttpClientModule
@HttpClientModule é um decorator de classe que armazena metadados consumidos por HttpServer durante o registro de rotas. Cada campo controla uma fase diferente do pipeline de inicialização.
A separação entre middleware e middlewareProviders deixa claro o limite entre política global de pipeline e declarações em nível de rota. Middleware global roda em toda requisição sem condição. Middleware de rota roda apenas em endpoints decorados com @HttpUseMiddleware e é resolvido sob demanda a partir do mapa de providers, então classes de middleware não referenciadas nunca são executadas.
Sequência de setup
Extraia a configuração do plugin para um arquivo dedicado
Mantenha a chamada de defineHttp em config/http.config.ts para que bind
de rede, política de segurança e modo sharded fiquem visíveis em um só lugar.
Isso também mantém spraxium.config.ts focado no registro do plugin, e não
em detalhes de implementação. Variáveis de ambiente para host, porta e API
key devem ser lidas aqui.
Aponte o módulo para sua composição raiz real
Defina module: AppModule em defineHttp para que HttpServer leia os
metadados da mesma classe que controla o grafo de módulos. Criar um
HttpAppModule separado leva a desvio, porque mudanças no AppModule não se
propagam automaticamente para a fonte de metadados HTTP.
Importe HttpModule uma vez no AppModule
HttpModule é global e deve aparecer uma vez nas importações do módulo raiz. Isso garante um único responsável pelo ciclo de vida da inicialização e do desligamento gracioso do servidor. Importá-lo em vários módulos não causa erro, mas também não traz benefício.
Registre guards e middleware em HttpClientModule
Declare classes de guard customizadas no array @HttpClientModule() para proteção global. O framework resolve cada classe de guard por DI na inicialização. Instâncias de middleware vão em middleware e rodam depois da pilha de segurança. Middleware em nível de rota vai em middlewareProviders e é ativado por endpoint com @HttpUseMiddleware.
Registre uma única entrada de plugin HTTP em defineConfig
Mantenha uma única entrada de plugin HTTP dentro de defineConfig({plugins}).
Entradas múltiplas levam a controle ambíguo e registro instável de rotas,
porque ConfigStore devolve apenas uma configuração para a chave
defineHttp.
Comportamento de inicialização por modo
| Modo | Quando inicia | Exigência de client | Implementação de bridge |
|---|---|---|---|
| Direto, com sharding: false | Durante o hook de ciclo de vida onBoot, depois que o Client do Discord estiver pronto. | Obrigatório. Se faltar, o servidor registra erro e pula a inicialização. | DirectBotBridge: acessa o cache de guilds e a API do Discord diretamente pela instância do client. |
| Sharded, com sharding: true | Via ParentHookRegistry quando o processo pai cria o ShardingManager. | Não é obrigatório. O ShardingManager substitui o client nas interações com o bot. | ShardedBotBridge: usa |
No modo direto, o servidor tem acesso imediato ao Client do Discord e pode injetá-lo no mapa de DI ao lado de BotBridge. Controllers que precisarem do client diretamente, em recursos não cobertos pelo bridge, podem declará-lo como parâmetro de construtor. No modo sharded, o client não está disponível no processo HTTP, então os controllers precisam usar BotBridge de forma exclusiva nas interações com o Discord.