@henriquecosta/chaos-api
v1.0.5
Published
Middleware pra simular falhas de producao (delay, erros, timeout, indisponibilidade, respostas malformadas/obsoletas) em APIs Express/Fastify/NestJS/Koa durante desenvolvimento.
Readme
@henriquecosta/chaos-api
Middleware pra simular falhas de produção — delay, erros, timeout, indisponibilidade, respostas malformadas/obsoletas — em APIs Express/Fastify/NestJS/Koa durante desenvolvimento.
Vem com control API + dashboard UI pra ligar/desligar cenários em tempo real, e um wrapper de fetch outbound pra injetar caos em chamadas que sua aplicação faz pra APIs de terceiros.
Instalação
npm install @henriquecosta/chaos-apiInício rápido (Express)
import express from "express";
import { chaos } from "@henriquecosta/chaos-api";
const app = express();
app.use(chaos());
app.get("/orders/:id", (req, res) => {
res.json({ id: req.params.id });
});
app.listen(3000);Abra http://localhost:3000/dashboard — o dashboard UI e a control API já vêm montados na própria porta da sua app, sem processo separado nem porta pra configurar. É a control API de verdade, ligada ao StateStore real do middleware, e funciona igual em dev e em prod (o guardrail de NODE_ENV=production bloqueia a execução de cenários, não as rotas do dashboard — veja "Guardrail de produção" abaixo).
Também dá pra registrar um cenário direto no store exposto pelo middleware, sem passar pela UI:
chaosMiddleware.store.register({
type: "delay",
scope: { pattern: "/orders/*" },
rate: 0.5, // aplica em 50% das requisições que casam com o scope
options: { minMs: 300, maxMs: 1500 },
});Pra desligar o dashboard embutido (ex: não quer expor essas rotas no processo da app) passe chaos({ dashboard: false }). Pra rodar a UI num processo à parte (útil sem uma app real por perto), veja "CLI do dashboard" mais abaixo.
Adapters de framework
Fastify
import Fastify from "fastify";
import { chaosFastifyPlugin } from "@henriquecosta/chaos-api";
const fastify = Fastify();
await fastify.register(chaosFastifyPlugin());NestJS
// main.ts
import { createChaosNestMiddleware } from "@henriquecosta/chaos-api";
app.use(createChaosNestMiddleware());Ou registre por módulo via NestModule.configure():
consumer.apply(createChaosNestMiddleware()).forRoutes("*");Koa
import Koa from "koa";
import { chaosKoaMiddleware } from "@henriquecosta/chaos-api";
const app = new Koa();
app.use(chaosKoaMiddleware());Os quatro adapters aceitam as mesmas opções (ChaosOptions), incluindo dashboard e, pra quem prefere isolar a control API numa porta própria em vez de embutida, controlPort (avançado — veja o JSDoc de ChaosOptions).
Tipos de cenário
Seis primitivos, casados por caminho da requisição (scope) e probabilidade (rate):
| type | efeito |
| -------------------- | ----------------------------------------------------------------- |
| delay | Adiciona latência antes de continuar a requisição (minMs/maxMs). |
| error-response | Interrompe com status/body (statusCodes, body, headers, methods). |
| connection-reset | Derruba a conexão — nenhuma resposta é escrita. |
| unavailable | Retorna um status fixo de indisponibilidade (statusCode, padrão 503). |
| malformed-response | Retorna um body de resposta estruturalmente quebrado. |
| stale-response | Retorna um body de resposta em cache/desatualizado. |
chaosMiddleware.store.register({
type: "error-response",
scope: { pattern: "/payments/*" },
direction: "inbound", // padrão; "outbound" escopa pelo host de destino em vez do path
rate: 0.2,
options: { statusCodes: [500, 502], body: { error: "payment provider unavailable" } },
});Use scope: "global" (padrão) pra aplicar um cenário em todas as rotas.
Presets
Catálogo com ~85 itens de cenários nomeados e pré-configurados (queda de auth, timeout de terceiros, erro de config etc.) mapeados sobre os seis primitivos acima:
import { applyPreset, listPresets } from "@henriquecosta/chaos-api";
listPresets("dependencias-externas"); // navega por categoria
applyPreset(chaosMiddleware.store, "third-party-rate-limit", {
scope: { pattern: "/checkout/*" },
rate: 0.3,
});Caos outbound (chamadas que sua aplicação faz)
Envolva o fetch pra que cenários registrados com direction: "outbound" intercepetem chamadas pra um host de destino:
import { createChaosFetch } from "@henriquecosta/chaos-api";
const chaosFetch = createChaosFetch(chaosMiddleware.store);
chaosMiddleware.store.register({
type: "connection-reset",
direction: "outbound",
scope: { pattern: "api.stripe.com" },
rate: 0.1,
});
await chaosFetch("https://api.stripe.com/v1/charges"); // pode lançar uma falha de rede simuladaGuardrail de produção
Cenários são desabilitados automaticamente quando NODE_ENV=production, pra evitar que um cenário ativo vaze pro tráfego real. Override (não recomendado) com:
chaos({ allowInProduction: true });CLI do dashboard
npx chaos-api dashboard [--port <n>] [--host <addr>] [--cors-origin <origin>] [--no-control-api]Sobe um processo à parte servindo a UI do dashboard (padrão http://localhost:4000/dashboard), com uma control API demo montada na mesma porta (StateStore isolado, não ligado a uma app real — só pra exercitar a UI). Útil pra explorar o dashboard sem escrever uma app. Se sua app já roda chaos() (que serve seu próprio dashboard embutido, veja "Início rápido"), você não precisa desse comando — mas se quiser mesmo assim usar essa UI standalone apontando pra control API real da sua app, passe --no-control-api e digite a origem da sua app (ex: http://localhost:3000) no campo "control API" da página.
Licença
MIT
