Skip to content

silvamaarcus/finance-app

Repository files navigation

Finance App API

API RESTful para gerenciamento de finanças pessoais. Permite que usuários criem contas, autentiquem-se com JWT e registrem suas transações financeiras (receitas, despesas e investimentos).


Sumário


Visão Geral

A Finance App API é um backend Node.js que oferece:

  • Cadastro, login e gerenciamento de usuários
  • Autenticação via JWT com access token (15 min) e refresh token (30 dias)
  • CRUD completo de transações financeiras por usuário
  • Cálculo de saldo por período com breakdown de receitas, despesas e investimentos
  • Documentação interativa com Swagger UI

Tecnologias e Bibliotecas

Runtime e Framework

Tecnologia Versão Uso
Node.js 20+ Runtime JavaScript no servidor
Express 5.x Framework HTTP para criação das rotas e middlewares

Banco de Dados

Tecnologia Versão Uso
PostgreSQL latest Banco de dados relacional principal
Prisma ORM 6.x ORM para comunicação com o banco, migrações e tipagem

Autenticação e Segurança

Biblioteca Versão Uso
jsonwebtoken 9.x Geração e verificação de tokens JWT
bcrypt 6.x Hash seguro de senhas (custo 10)
bcryptjs 3.x Alternativa JS pura do bcrypt

Validação de Dados

Biblioteca Versão Uso
Zod 3.x Validação e tipagem de schemas nos controllers
validator 13.x Validação de formatos (moeda, email, etc.)

Utilitários

Biblioteca Versão Uso
uuid 13.x Geração de IDs únicos (UUID v4)
dayjs 1.x Manipulação e formatação de datas
dotenv 17.x Carregamento de variáveis de ambiente do .env
dotenv-cli 11.x Injeção de .env em scripts npm
swagger-ui-express 5.x Documentação interativa da API

Infraestrutura

Tecnologia Uso
Docker Containerização do PostgreSQL (desenvolvimento e testes)
Docker Compose Orquestração dos containers

Ferramentas de Desenvolvimento

Ferramenta Versão Uso
Jest 29.x Framework de testes unitários e de integração
Supertest 7.x Testes de requisições HTTP (E2E)
@faker-js/faker 9.x Geração de dados falsos para testes
ESLint 9.x Linter para padronização e qualidade do código
Prettier 3.x Formatação automática do código
Husky 9.x Git hooks (pre-commit e commit-msg)
lint-staged 16.x Executa linter/prettier apenas nos arquivos alterados antes do commit
git-commit-msg-linter 5.x Valida a mensagem de commit no padrão Conventional Commits

Arquitetura do Projeto

O projeto segue uma arquitetura em camadas inspirada nos princípios de Clean Architecture e SOLID. Cada camada tem uma responsabilidade bem definida e se comunica apenas com a camada imediatamente abaixo.

HTTP Request
     │
     ▼
┌──────────────┐
│  Routes      │  Define os endpoints e chama os controllers via Factory
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  Middleware  │  Autenticação JWT (extrai userId do token)
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  Controller  │  Valida input (Zod), chama Use Case, formata resposta HTTP
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  Use Case    │  Contém toda a regra de negócio da aplicação
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  Repository  │  Acessa o banco de dados via Prisma ORM
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  PostgreSQL  │  Banco de dados relacional
└──────────────┘

Padrões e Técnicas Aplicados

Padrão Descrição
Factory Pattern Cada controller é criado por uma função make*Controller() que instancia e injeta todas as dependências
Dependency Injection (DI) Use Cases e Repositories são injetados via construtor, nunca instanciados internamente
Repository Pattern Toda comunicação com o banco é abstraída em classes de Repository
Adapter Pattern Serviços externos (bcrypt, uuid, jwt) são encapsulados em Adapters para fácil substituição
ESM Modules O projeto usa "type": "module" — todos os imports/exports são sintaxe ES Module (import/export)

Por que esse padrão?

  • Testabilidade: Como as dependências são injetadas, é possível substituir por mocks nos testes sem modificar o código de produção.
  • Manutenibilidade: Cada arquivo tem uma responsabilidade única (Single Responsibility Principle).
  • Desacoplamento: Trocar o banco de dados ou a lib de hash de senha não exige alterar Use Cases ou Controllers.

Estrutura de Pastas

finance-app-api/
├── .github/
│   └── workflows/
│       └── main.yml          # Pipeline CI/CD (GitHub Actions)
├── .husky/                   # Git hooks configurados pelo Husky
├── docs/
│   └── swagger.json          # Documentação OpenAPI (Swagger)
├── prisma/
│   ├── prisma.js             # Instância singleton do PrismaClient
│   ├── schema.prisma         # Definição dos modelos do banco de dados
│   └── migrations/           # Histórico de migrações do banco
├── src/
│   ├── app.js                # Configuração do Express (middlewares e rotas)
│   ├── adapters/             # Adaptadores para serviços externos
│   │   ├── id-generator.js       # Gera UUIDs (uuid v4)
│   │   ├── password-hasher.js    # Hash de senha (bcrypt)
│   │   ├── password-comparator.js # Compara senha com hash
│   │   ├── tokens-generator.js   # Gera access + refresh token (JWT)
│   │   └── token-verifier.js     # Verifica e decodifica JWT
│   ├── controllers/          # Recebem a requisição, validam e respondem
│   │   ├── helpers/
│   │   │   └── http.js           # Helpers de resposta (ok, created, badRequest, etc.)
│   │   ├── user/                 # Controllers de usuário
│   │   └── transaction/          # Controllers de transação
│   ├── errors/               # Classes de erros customizados
│   │   ├── users.js              # EmailAlreadyInUseError, UserNotFoundError, etc.
│   │   └── transactions.js       # TransactionNotFoundError, etc.
│   ├── factories/
│   │   └── controllers/
│   │       ├── user.js           # Factories que montam e injetam dependências dos controllers de usuário
│   │       └── transaction.js    # Factories dos controllers de transação
│   ├── middlewares/
│   │   └── auth.js           # Middleware JWT: extrai e valida o Bearer Token
│   ├── repositories/
│   │   └── postgres/         # Implementações do Repository para PostgreSQL
│   │       ├── user/             # Operações CRUD de usuários via Prisma
│   │       └── transaction/      # Operações CRUD de transações via Prisma
│   ├── routes/
│   │   ├── users.js              # Rotas de usuário (/api/users)
│   │   ├── transactions.js       # Rotas de transação (/api/transactions)
│   │   ├── users.e2e.test.js     # Testes E2E das rotas de usuário
│   │   └── transactions.e2e.test.js # Testes E2E das rotas de transação
│   ├── schemas/              # Schemas de validação com Zod
│   │   ├── user.js               # createUserSchema, updateUserSchema, loginSchema
│   │   └── transaction.js        # createTransactionSchema, updateTransactionSchema
│   ├── tests/
│   │   └── fixtures/         # Dados fixos reutilizáveis nos testes
│   └── use-cases/            # Regras de negócio da aplicação
│       ├── user/                 # create, delete, get-by-id, get-balance, login, refresh-token, update
│       └── transaction/          # create, delete, get-by-user-id, update
├── index.js                  # Entry point — inicia o servidor Express
├── docker-compose.yml        # Containers do PostgreSQL (dev e test)
├── jest.config.js            # Configuração do Jest
├── jest.global-setup.js      # Sobe o container de teste e aplica migrações antes dos testes
├── jest.setup-after-env.js   # Limpa o banco de testes antes de cada teste
├── eslint.config.js          # Configuração do ESLint
├── .prettierrc.json          # Configuração do Prettier
├── .env.example              # Exemplo do arquivo .env (desenvolvimento)
└── .env.test.example         # Exemplo do arquivo .env.test (testes)

Pré-requisitos

Antes de começar, certifique-se de ter instalado na sua máquina:

  • Node.js — versão 20 ou superior
    node -v   # deve exibir v20.x.x ou superior
  • npm — vem junto com o Node.js
    npm -v
  • Docker e Docker Compose — para rodar o PostgreSQL
    docker -v
    docker compose version
  • Git — para clonar o repositório
    git --version

Como Clonar o Repositório

# Clone o repositório
git clone https://github.com/silvamaarcus/finance-app-api.git

# Acesse a pasta do projeto
cd finance-app-api

Configuração do Ambiente

1. Instale as dependências

npm install

O comando postinstall roda automaticamente husky (configura os git hooks) e prisma generate (gera o Prisma Client).

2. Configure as variáveis de ambiente

Copie os arquivos de exemplo e preencha com seus valores:

# Para desenvolvimento
cp .env.example .env

# Para testes
cp .env.test.example .env.test

Edite o arquivo .env com as informações do seu banco:

PORT=8080
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DATABASE=finance-app
DATABASE_URL=postgresql://postgres:password@localhost:5432/finance-app

JWT_ACCESS_TOKEN_SECRET=sua_chave_secreta_de_access_token_aqui
JWT_REFRESH_TOKEN_SECRET=sua_chave_secreta_de_refresh_token_aqui

Edite o arquivo .env.test com as informações do banco de testes (porta 5433):

DATABASE_URL=postgresql://postgres:password@localhost:5433/finance-app

JWT_ACCESS_TOKEN_SECRET=sua_chave_secreta_de_access_token_aqui
JWT_REFRESH_TOKEN_SECRET=sua_chave_secreta_de_refresh_token_aqui

Por que duas portas? O docker-compose.yml sobe dois containers: um na porta 5432 (desenvolvimento) e outro na porta 5433 (testes). Assim os testes nunca afetam o banco de desenvolvimento.


Como Rodar o Projeto

1. Suba o banco de dados com Docker

# Sobe o container do PostgreSQL para desenvolvimento em segundo plano
docker compose up -d postgres

2. Execute as migrações do banco

# Aplica todas as migrações e cria as tabelas no banco de dados
npx prisma migrate deploy

3. Inicie o servidor

# Modo desenvolvimento (reinicia automaticamente ao salvar arquivos)
npm run start:dev

# Modo produção
npm start

O servidor estará disponível em: http://localhost:8080

A documentação Swagger estará em: http://localhost:8080/docs


Banco de Dados e Migrações

O projeto usa Prisma ORM com PostgreSQL. Os modelos são:

User (Usuário)

Campo Tipo Descrição
id String (UUID) Identificador único
first_name String Primeiro nome (max 50 chars)
last_name String Último nome (max 50 chars)
email String (único) E-mail do usuário (max 100 chars)
password String Senha hasheada com bcrypt (max 100 chars)

Transaction (Transação)

Campo Tipo Descrição
id String (UUID) Identificador único
user_id String Referência ao usuário dono da transação
name String Nome/descrição da transação (max 50 chars)
date DateTime Data da transação
amount Decimal Valor (10 dígitos, 2 casas decimais)
type Enum EARNING | EXPENSE | INVESTMENT

Cascade Delete: ao deletar um usuário, todas as suas transações são deletadas automaticamente.

Comandos úteis do Prisma

# Criar uma nova migração após alterar o schema.prisma
npx prisma migrate dev --name nome_da_migracao

# Aplicar migrações em produção
npx prisma migrate deploy

# Abrir o Prisma Studio (interface visual do banco)
npx prisma studio

# Regenerar o Prisma Client (necessário após alterar o schema)
npx prisma generate

Rotas da API

A URL base é: http://localhost:8080

A documentação completa e interativa está disponível em: http://localhost:8080/docs

Usuários — /api/users

Método Rota Autenticação Descrição
POST /api/users Não Cria um novo usuário
GET /api/users/me Sim Retorna os dados do usuário autenticado
PATCH /api/users/me Sim Atualiza os dados do usuário autenticado
DELETE /api/users/me Sim Deleta o usuário autenticado
GET /api/users/me/balance Sim Retorna o saldo financeiro por período
POST /api/users/login Não Autentica o usuário e retorna os tokens JWT
POST /api/users/refresh-token Não Gera um novo par de tokens usando o refresh token

Exemplo: Criar usuário (POST /api/users)

// Body da requisição
{
  "first_name": "João",
  "last_name": "Silva",
  "email": "joao@email.com",
  "password": "senha123"
}

// Resposta 201 Created
{
  "id": "uuid-gerado",
  "first_name": "João",
  "last_name": "Silva",
  "email": "joao@email.com",
  "tokens": {
    "accessToken": "eyJhbGci...",
    "refreshToken": "eyJhbGci..."
  }
}

Exemplo: Saldo do usuário (GET /api/users/me/balance?from=2024-01-01&to=2024-12-31)

// Resposta 200 OK
{
    "earnings": { "amount": 5000, "percentage": 62 },
    "expenses": { "amount": 2000, "percentage": 25 },
    "investments": { "amount": 1000, "percentage": 13 },
    "balance": 2000
}

Transações — /api/transactions

Todas as rotas de transação exigem autenticação (Bearer Token).

Método Rota Descrição
GET /api/transactions/me Lista as transações do usuário autenticado
POST /api/transactions/me Cria uma nova transação
PATCH /api/transactions/me/:transactionId Atualiza uma transação existente
DELETE /api/transactions/me/:transactionId Deleta uma transação

Exemplo: Criar transação (POST /api/transactions/me)

// Body da requisição
{
  "name": "Salário",
  "date": "2024-01-05T00:00:00.000Z",
  "amount": 5000,
  "type": "EARNING"
}

// Resposta 201 Created
{
  "id": "uuid-gerado",
  "user_id": "uuid-do-usuario",
  "name": "Salário",
  "date": "2024-01-05T00:00:00.000Z",
  "amount": "5000.00",
  "type": "EARNING"
}

Autenticação

A API usa JWT (JSON Web Token) com dois tokens:

Token Duração Uso
accessToken 15 minutos Enviado no header de cada requisição protegida
refreshToken 30 dias Usado para gerar um novo par de tokens quando o accessToken expirar

Como usar o accessToken

Inclua o token no header Authorization de todas as requisições protegidas:

Authorization: Bearer SEU_ACCESS_TOKEN_AQUI

Fluxo de Autenticação

1. POST /api/users/login  →  recebe { accessToken, refreshToken }
2. Usa o accessToken nas requisições (válido por 15 min)
3. Quando expirar: POST /api/users/refresh-token  →  recebe novos tokens

Testes

O projeto possui três tipos de testes:

Tipo Localização Descrição
Unitários src/use-cases/**/*.test.js Testam a lógica de negócio isolada (com mocks)
Integração src/repositories/**/*.test.js Testam a comunicação real com o banco de dados
E2E src/routes/**/*.e2e.test.js Testam o fluxo completo da requisição HTTP ao banco

Configuração dos testes

Antes de rodar os testes, o Jest automaticamente:

  1. Sobe o container postgres-test via Docker Compose (porta 5433)
  2. Aplica as migrações no banco de teste com prisma db push
  3. Limpa todas as tabelas do banco antes de cada teste para garantir isolamento

Comandos de teste

# Roda todos os testes uma vez
npm test

# Roda em modo watch (re-executa ao salvar arquivos)
npm run test:watch

# Roda os testes e gera relatório de cobertura
npm run test:coverage

O relatório de cobertura é gerado na pasta coverage/. Abra coverage/lcov-report/index.html no navegador para ver o resultado visual.

Exemplo de saída dos testes

✓ CreateUserUseCase — should create user successfully
✓ CreateUserUseCase — should throw EmailAlreadyInUseError if email is already in use
✓ POST /api/users — should return 201 when user is created
✓ POST /api/users/login — should return 200 and tokens on valid credentials
...

Qualidade de Código

O projeto usa várias ferramentas para manter a qualidade e consistência do código.

ESLint

Verifica erros e padrões de código:

# Verifica os arquivos sem corrigir
npm run eslint:check

Prettier

Formata o código automaticamente:

# Verifica se o código está formatado
npm run prettier:check

# Formata todos os arquivos de src/
npm run prettier:fix

Husky + lint-staged

Os git hooks configurados pelo Husky garantem que:

  • Antes de cada commit (pre-commit): ESLint e Prettier são executados automaticamente nos arquivos alterados via lint-staged.
  • Na mensagem de commit (commit-msg): O git-commit-msg-linter valida que a mensagem segue o padrão Conventional Commits.

Conventional Commits

Todas as mensagens de commit devem seguir o padrão:

tipo: descrição curta

Exemplos:
feat: add login endpoint
fix: correct password comparison logic
refactor: extract token generator to adapter
test: add unit tests for create-user use case
docs: update README
chore: update dependencies

CI/CD

O projeto possui um pipeline de GitHub Actions em .github/workflows/main.yml que é executado a cada push na branch main.

Pipeline

push na branch main
        │
        ▼
┌───────────────────┐
│  Job: check       │
│  ─────────────    │
│  1. Checkout      │
│  2. Setup Node 20 │
│  3. npm ci        │
│  4. ESLint check  │
│  5. Prettier check│
│  6. npm test      │
└────────┬──────────┘
         │ (se tudo passar)
         ▼
┌───────────────────┐
│  Job: migrate     │
│  ─────────────    │
│  1. Checkout      │
│  2. Setup Node 20 │
│  3. npm ci        │
│  4. prisma migrate│
│     deploy        │
└───────────────────┘

Secrets necessários no GitHub

Para o pipeline de produção funcionar, configure os seguintes secrets no repositório (Settings > Secrets and variables > Actions):

Secret Descrição
DATABASE_URL URL de conexão do banco de dados de produção
JWT_ACCESS_TOKEN_SECRET Chave secreta para assinar access tokens
JWT_REFRESH_TOKEN_SECRET Chave secreta para assinar refresh tokens

Variáveis de Ambiente

.env (desenvolvimento)

Variável Exemplo Descrição
PORT 8080 Porta em que o servidor Express vai rodar
POSTGRES_USER postgres Usuário do PostgreSQL
POSTGRES_PASSWORD password Senha do PostgreSQL
POSTGRES_HOST localhost Host do banco de dados
POSTGRES_PORT 5432 Porta do banco de dados
POSTGRES_DATABASE finance-app Nome do banco de dados
DATABASE_URL postgresql://postgres:password@localhost:5432/finance-app URL completa de conexão (usada pelo Prisma)
JWT_ACCESS_TOKEN_SECRET sua_chave_secreta Chave para assinar access tokens (use uma string longa e aleatória)
JWT_REFRESH_TOKEN_SECRET outra_chave_secreta Chave para assinar refresh tokens (diferente da de access)

.env.test (testes)

Variável Exemplo Descrição
DATABASE_URL postgresql://postgres:password@localhost:5433/finance-app URL do banco de testes (porta 5433)
JWT_ACCESS_TOKEN_SECRET test_secret Chave para testes
JWT_REFRESH_TOKEN_SECRET test_secret_refresh Chave para testes

Segurança: nunca commite os arquivos .env ou .env.test com valores reais. Eles estão no .gitignore.


Erros Customizados

A API retorna erros padronizados com mensagens descritivas:

Erro HTTP Quando ocorre
EmailAlreadyInUseError 400 Email já cadastrado ao criar usuário
UserNotFoundError 404 Usuário não encontrado
InvalidPasswordError 401 Senha incorreta no login
ForbiddenError 403 Usuário sem permissão para a operação
UnauthorizedError 401 Token ausente, inválido ou expirado
TransactionNotFoundError 404 Transação não encontrada

Licença

ISC — Marcus

About

API para Dashboard Financeira

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors