Criando API REST com Jumentix
Responsabilidade no escopo
- Responsável por: Adapter HTTP + use-cases de aplicação para REST
- Usado com: sdk-rest-client, pacotes de persistência, hub do app backend-template
- Não responsável por: Realtime WebSocket/gRPC (guia realtime) ou IndexedDB offline (Cana)
O que é
Este guia mostra como inicializar, executar e validar um serviço REST usando o template de backend Jumentix. Você vai ligar lógica de domínio a um adaptador HTTP (Express por padrão) e chamar a API por um client tipado.
Por que existe
Times júnior costumam editar controllers e esperar que rotas permaneçam alinhadas à documentação. O Jumentix inverte isso: OpenAPI é o contrato, o código de domínio fica no centro e o framework HTTP é um adaptador substituível. Este guia oferece um caminho repetível de perfil de env → servidor rodando → testes verdes.
Pré-requisitos
| Item | Obrigatório | Notas |
|---|---|---|
| Bun 1.3.13+ | Sim | Veja Começando |
| Getting-started concluído | Recomendado | Modelo mental + playground Cana |
| Scaffold backend-template | Sim | Use o monorepo apps/backend-template ou o fluxo interno de bootstrap |
| Service Management (opcional) | Times design-first | Domain Designer gera entidades alinhadas ao OpenAPI |
Arquivo de ambiente: apps/backend-template/src/config/.env.dev (ou equivalente do seu scaffold).
Glossário
| Termo | Significado nesta página |
|---|---|
| REST | API HTTP com verbos (GET, POST, …) e payloads JSON. |
| OpenAPI | Spec em spec/1.0.0.yml descrevendo paths, schemas e operationIds. |
| Perfil de runtime | Variáveis de env (JUMENTIX_HTTP_FRAMEWORK, JUMENTIX_REALTIME_API) que selecionam adaptadores. |
| Controller | Classe da camada de interface mapeando requests HTTP para casos de uso. |
| Caso de uso | Serviço de aplicação implementando uma operação de negócio. |
| Porta de repositório | Interface de persistência; implementada por adaptador de banco. |
| Adaptador HTTP | Módulo Express/Fastify/etc. montando rotas a partir de operationIds OpenAPI. |
| oas:check-routes | Script que verifica se todo path OpenAPI resolve para um handler registrado. |
Passos numerados
Passo 1 — Selecionar perfil REST (< 5 minutos)
- Abra seu arquivo de env (padrão:
apps/backend-template/src/config/.env.dev). - Configure modo só REST:
JUMENTIX_HTTP_FRAMEWORK=express
JUMENTIX_REALTIME_API=noFrameworks HTTP suportados estão em Adaptadores HTTP.
- Inicie o servidor dev na raiz do monorepo:
bun run dev:httpOu de dentro de apps/backend-template:
bun run dev:restVerificação de sucesso: PM2 reporta jumentix-dev-http online; curl ou browser
acessa /health (ou rota de health do scaffold) com HTTP 200.
Passo 2 — Modelar domínio e contratos (< 15 minutos)
- Design-first (recomendado): abra Service Management → Domain Designer. Defina entidades, relacionamentos e contextos limitados.
- Spec-first: edite OpenAPI em
spec/1.0.0.yml— adicione paths, schemas eoperationIdestáveis. - Mantenha DTOs de request/response alinhados às entradas/saídas do controller.
- Packages de contrato compartilhado (
@jumentix/shared-contracts) devem espelhar as mesmas formas; veja /docs/pt-BR/jumentix/packages/shared-contracts.
Verificação de sucesso: bun run oas:check-routes passa sem rotas não resolvidas.
Passo 3 — Implementar fluxo de domínio (< 30 minutos por feature)
Siga as camadas do backend template — de baixo para cima:
- Domínio — entidades, value objects, eventos em
src/domain/. - Portas — interfaces de repositório e gateway dos casos de uso.
- Casos de uso — serviços de aplicação orquestrando regras de domínio.
- Controllers — traduzem DTOs HTTP ↔ entradas/saídas do caso de uso.
- Handlers — bindings de rota específicos do framework (módulos Express).
Regra: domínio e casos de uso não importam Express/Fastify. Só adaptadores importam.
Verificação de sucesso: testes unitários do caso de uso passam sem subir HTTP.
Passo 4 — Vincular ao adaptador HTTP (< 10 minutos)
- Confirme que
JUMENTIX_HTTP_FRAMEWORKcorresponde ao adaptador ligado. - O startup REST carrega
start-rest-api.ts(ou entry do scaffold) registrando handlers das interfaces de módulo. - Cada
operationIdOpenAPI mapeia para um método de controller via registro do adaptador.
Troque adaptadores só mudando env — código de domínio intacto:
JUMENTIX_HTTP_FRAMEWORK=fastify # exemplo; confirme suporte na página de adaptadoresVerificação de sucesso: request manual a um endpoint novo retorna JSON no formato do contrato.
Passo 5 — Validar portões de qualidade (< 10 minutos)
Execute na raiz do monorepo (ou bun --cwd ../.. a partir de backend-template):
bun run lint
bun run test:unit
bun run oas:check-routes
bun run test:integration:expressSmoke opcional antes do push:
cd apps/backend-template && bun run test:integration:smokeVerificação de sucesso: os quatro comandos saem com código 0; teste de integração bate HTTP real contra o perfil rodando.
Passo 6 — Chamar a API de um client (caminho júnior)
No Node ou no playground de docs do browser, injete o documento OpenAPI em vez
de carregar do disco com fs:
const client = api.createMockClient();
const result = await client.request({ method: 'GET', path: '/health' });
console.log(result.status, result.body);Para clients de produção, use @jumentix/sdk-rest-client com a mesma spec injetada
em bundles de browser.
Exemplos
Client mock estático
const client = api.createMockClient();
const result = await client.request({ method: 'GET', path: '/health' });
console.log(result.status, result.body);Playground interativo REST client
Experimente o client REST mockado — Run deve retornar /health com sucesso:
Cliente REST com fetch mock
Chame operações OpenAPI de Task com um cliente mock seguro para browser.
### Cliente REST com fetch mock
```ts
const client = api.createMockClient();
const created = await client.request({
operationId: 'createTask',
method: 'POST',
path: '/tasks',
body: {
id: 'task-1',
title: 'Generate REST SDK example',
categoryId: 'work',
completed: false
}
});
const listed = await client.request({
operationId: 'listTasks',
method: 'GET',
path: '/tasks?categoryId=work'
});
return {
created,
listed
};
```const client = api.createMockClient();
const created = await client.request({
operationId: 'createTask',
method: 'POST',
path: '/tasks',
body: {
id: 'task-1',
title: 'Generate REST SDK example',
categoryId: 'work',
completed: false
}
});
const listed = await client.request({
operationId: 'listTasks',
method: 'GET',
path: '/tasks?categoryId=work'
});
return {
created,
listed
};Erros comuns
| Sintoma | Causa provável | Correção | Verificar sucesso |
|---|---|---|---|
| Processo PM2 sai imediatamente | Caminho de env inválido ou secret ausente | Confirme --env-file=./apps/backend-template/src/config/.env.dev | bun run dev:http permanece online |
oas:check-routes falha | Path OpenAPI sem handler | Adicione handler + método de controller; rode de novo | Script sai com 0 |
| 404 em rota documentada | Adaptador HTTP errado carregado | Alinhe JUMENTIX_HTTP_FRAMEWORK ao módulo ligado | curl retorna 200 |
| Timeout em teste de integração | Servidor parado ou porta errada | Suba perfil dev antes da suite | test:integration:express verde |
| Client browser não carrega YAML | fs.readFile no bundle | Injete objeto OpenAPI parseado (padrão do playground) | Mock client funciona no browser |
| Domínio importa Express | Violação de camada | Mova código HTTP para adaptador/handler | arch:check-boundaries passa |
Checklist júnior (“Eu consigo …”)
- Definir
JUMENTIX_HTTP_FRAMEWORKeJUMENTIX_REALTIME_API=noe iniciarbun run dev:http. - Localizar
spec/1.0.0.ymle explicar o que é umoperationId. - Adicionar ou rastrear um path: OpenAPI → controller → caso de uso → porta de repositório.
- Rodar
bun run oas:check-routesebun run test:integration:expresscom sucesso. - Chamar
/healthvia playground sdk-rest-client (Run verde). - Citar um adaptador HTTP alternativo sem alterar código de domínio.
Próximo passo
Quando precisar de push ou atualizações ao vivo, continue em Criar API em tempo real. Para referência de adaptadores, veja Adaptadores HTTP e Erros e respostas.