API REST de finanças pessoais — usuários, receitas, despesas e relatórios. Backend only, construído com Express 5, MongoDB e TypeScript.
O que é? Uma API para registrar receitas e despesas, gerenciar titular e dependentes, e gerar relatórios por período. Não há frontend — o foco é o backend.
Qual problema resolve? Organizar lançamentos financeiros de uma família ou unidade doméstica com papéis distintos: o titular gerencia tudo; o dependente registra e consulta apenas o próprio.
Para quem serve? Primariamente, quem avalia o autor como engenheiro (portfólio, entrevista). No domínio, um titular de finanças domésticas via API — escopo deliberadamente pequeno: uma instância da API = um titular e seus dependentes.
| Camada | Tecnologia |
|---|---|
| Runtime | Node.js, TypeScript (ESM) |
| HTTP | Express 5 |
| Persistência | MongoDB + Mongoose |
| Auth | JWT + bcrypt |
| Contrato | OpenAPI 3 (express-openapi-validator) |
| Testes | Jest, Supertest, mongodb-memory-server |
- src/domain — Entidades, contratos de repository/service, erros (
DomainError,EErrorCode) e helpers puros. Sem Express, Mongoose ou HTTP. - src/application — Controllers HTTP (
IController+initRoutes), middlewares (JWT, ObjectId) e servidor Express. - src/infrastructure — MongoDB (schemas, models, repos, mappers), JWT/bcrypt e i18n de erros.
- src/configurations — Variáveis de ambiente e factories (composition root).
- src/contracts —
service.yaml(OpenAPI): documenta e valida requests em runtime. - src/tests — Testes unitários (
unit/) e de integração E2E (integration/). - main.ts — Conecta ao MongoDB, instancia controllers via factories e sobe o servidor.
flowchart TB
main[main.ts] --> config[configurations/factory]
config --> app[application/controllers]
config --> infra[infrastructure]
app --> domain[domain]
infra --> domain
server[application/http/server] --> contracts[contracts/service.yaml]
- Instale as dependências:
yarn install- Crie um
.enva partir do exemplo:
cp .env.example .env| Variável | Descrição |
|---|---|
MONGODB_URI |
URI de conexão com o MongoDB |
PORT |
Porta HTTP (ex.: 3000) |
JWT_SECRET |
Segredo para assinatura dos tokens JWT |
JWT_EXPIRATION |
Tempo de expiração do token (ex.: 1d) |
BCRYPT_SALT_ROUNDS |
Rounds do bcrypt para hash de senha |
É necessário ter um MongoDB acessível na URI configurada (local ou remoto).
- Desenvolvimento:
yarn dev- Build e produção:
yarn build
yarn start- Testes:
yarn test:unit # schemas e domínio (*.unit.test.ts)
yarn test:int # endpoints E2E com MongoDB em memória (*.int.test.ts)
yarn test # unit + integração| Decisão | Por quê |
|---|---|
| Clean Architecture / camadas rígidas | Domínio testável sem Express/Mongoose; trocar infra sem reescrever regras |
Dois contratos por feature (*.interface.ts + *.service.interface.ts) |
Separa persistência de casos de uso; evita DTOs de login no agregado |
| OpenAPI como fonte de verdade e validação em runtime | Documentação não diverge do comportamento real |
| Autorização no service, não só no middleware | Anti-IDOR via assertResourceAccess — titular vs dependente |
Credenciais em port (IUserCredentialsPort) |
Repository read nunca expõe senha/hash |
| Registro público só para o 1º titular | Single-tenant por instância; dependentes só via titular autenticado |
| Factories como composition root | main.ts só conecta DB e registra controllers |
| AGENTS.md + rules Cursor | Governança explícita; reduz drift arquitetural |
- Repository read/write separados por agregado
DomainError+EErrorCodeno domínio; tradução na infra (ErrorCatalog,Accept-Language)- Controllers finos: parse HTTP → service →
handleTranslatedError - Enums de entidade no
*.interface.tsdo agregado (nuncadomain/common/enums/)
| Escolha | Ganho | Custo / limite |
|---|---|---|
| MongoDB document-oriented | Agilidade; schemas alinhados ao domínio | Relatórios agregam em memória |
| Single titular por instância | Auth simples e testável | Não é multi-tenant |
| OpenAPI valida só requests | Menos acoplamento response ↔ spec | Responses não validadas automaticamente |
| Sem paginação/filtros | CRUD direto, código enxuto | Não escala para milhares de lançamentos |
Relatório via POST /api/reports |
Body tipado no OpenAPI | Recalcula a cada request |
| Backend only | Foco em API e arquitetura | Incompleto para usuário final sem client |
| Camada | O quê | Onde | Qtd. |
|---|---|---|---|
| Unit | Schemas Mongoose, helpers (date, access), ReportService |
src/__tests__/unit/ |
6 |
| Integração E2E | Register, login, CRUD income/expense, reports | src/__tests__/integration/ |
6 |
| Segurança | IDOR, papéis, registro fechado, auth | src/__tests__/integration/security/ |
3 |
Antes de merge: yarn build && yarn test:unit && yarn test:int. Endpoint novo com
:id → incluir teste de ownership em security/.
- Request body/path contra
service.yaml(additionalProperties: false) - ObjectId inválido → middleware dedicado
- Domínio: datas brasileiras (
DD/MM/AAAA), intervalos de relatório, enums de status e método de pagamento
- Domínio lança
DomainError(EErrorCode, status)— sem Express no domain - Application captura →
handleTranslatedError→ mensagem em pt-BR / en / es - Login: email inexistente e senha errada → mesmo código (
401) — anti-enumeration - Rate limit em
/api/users/logine/api/users/register
Fluxo end-to-end implementado e testado:
- Bootstrap — primeiro titular via
POST /api/users/register; tentativas seguintes retornam403. - Autenticação —
POST /api/users/loginretorna JWT; rotas protegidas exigemAuthorization: Bearer <token>. - Gestão de pessoas — titular cria dependentes (
POST /api/users), lista (GET /api/users), consulta/atualiza/remove por id (GET/PUT/DELETE /api/users/:id). - Receitas — titular cria e lista (
POST/GET /api/incomes); titular ou dono consulta/edita (GET/PUT /api/incomes/:id); titular remove (DELETE /api/incomes/:id). - Despesas — mesmo padrão em
/api/expenses. - Relatórios —
POST /api/reportscomtype:income,expenseouprofite intervalo de datas; escopo = usuário do JWT. - Health —
GET /api/health.
flowchart LR
register[Register] --> login[Login]
login --> users[Users]
users --> transactions[Incomes/Expenses]
transactions --> report[Report]
Papéis: USER (titular) e DEPENDENT (dependente). Payloads completos em
src/contracts/service.yaml.
| Método | Rota | Quem | O que faz |
|---|---|---|---|
| GET | /api/health |
— | Health check |
| POST | /api/users/register |
— | Registra o 1º titular |
| POST | /api/users/login |
— | Autentica e retorna JWT |
| POST | /api/users |
Titular | Cria dependente |
| GET | /api/users |
Titular | Lista usuários |
| GET | /api/users/:id |
Titular ou self | Consulta usuário |
| PUT | /api/users/:id |
Titular | Atualiza usuário |
| DELETE | /api/users/:id |
Titular | Remove usuário |
| POST | /api/incomes |
Titular | Cria receita (opcional userId) |
| GET | /api/incomes |
Titular | Lista receitas |
| GET | /api/incomes/:id |
Titular ou dono | Consulta receita |
| PUT | /api/incomes/:id |
Titular ou dono | Atualiza receita |
| DELETE | /api/incomes/:id |
Titular | Remove receita |
| POST | /api/expenses |
Titular | Cria despesa (opcional userId) |
| GET | /api/expenses |
Titular | Lista despesas |
| GET | /api/expenses/:id |
Titular ou dono | Consulta despesa |
| PUT | /api/expenses/:id |
Titular ou dono | Atualiza despesa |
| DELETE | /api/expenses/:id |
Titular | Remove despesa |
| POST | /api/reports |
JWT (escopo do token) | Gera relatório por período |
- Frontend ou client consumidor
- CI/CD (não há
.github/workflowshoje) - Paginação, filtros, categorias, exportação
- Multi-tenant (vários titulares na mesma instância)
- Observabilidade avançada (métricas, tracing, logs estruturados)
- Cache ou fila para relatórios pesados
- Horizontal: API stateless + MongoDB replicado; JWT sem sessão server-side
- Dados: índices em
user+ datas; paginação cursor-based; agregações MongoDB nos relatórios - Produto: multi-tenant com
tenantIdno JWT e isolamento no repository - Qualidade: CI com
build + test; contract tests de response; load test nos relatórios - Operação: health + readiness; secrets via env/vault; rate limit por IP/user
Este repositório prioriza manutenibilidade sobre escopo de produto: governança escrita (AGENTS.md), separação de concerns que facilita onboarding, testes de segurança junto com CRUD, trade-offs documentados e caminho claro para evoluir sem reescrever do zero.
- Defina entidades e interfaces em
src/domain:entity/interfaces/<feature>.interface.ts— persistência (E*,I*,IParamsCreate*)entity/interfaces/<feature>.service.interface.ts— casos de uso (I*Service, fluxos)- entidade, contratos de repository e service
- Crie implementações em
src/infrastructure(schema, model, mapper, repos). - Registre dependências em
src/configurations/factory/(service + controller). - Exponha rotas em
src/application/<feature>.controller.tscominitRoutes(). - Registre o controller em
src/main.ts. - Documente rotas e schemas em
src/contracts/service.yaml. - Escreva testes: unitário de schema (
*.unit.test.ts) e integração (*.int.test.ts).
Leia AGENTS.md — contrato de camadas, dependências, nomenclatura, enums, segurança e testes para humanos e agentes de IA.