Uma API RESTful moderna e robusta para gerenciamento de tarefas, construída com as melhores práticas de desenvolvimento e arquitetura limpa! 🚀
- 🎯 Sobre o Projeto
- 🛠 Tecnologias Utilizadas
- 🏗 Arquitetura e Organização
- 📁 Estrutura de Pastas
- 🚀 Instalação e Configuração
- 🔧 Scripts Disponíveis
- 📚 Documentação da API
- 🧪 Testes
- 🎨 Boas Práticas
- 🐛 Debug e Monitoramento
A Task Manager API é uma aplicação backend moderna que permite gerenciar tarefas de forma eficiente com sistema de autenticação completo. O projeto foi desenvolvido seguindo os princípios de Clean Architecture, SOLID e Domain-Driven Design (DDD), garantindo:
- ✅ Escalabilidade: Arquitetura modular e bem organizada
- ✅ Testabilidade: Cobertura de testes abrangente
- ✅ Maintibilidade: Código limpo e bem documentado
- ✅ Performance: Otimizações e boas práticas aplicadas
- ✅ Type Safety: TypeScript em todo o projeto
- ✅ Segurança: Sistema completo de autenticação JWT
- ✅ Autorização: Controle de acesso a recursos protegidos
- Node.js - Runtime JavaScript/TypeScript
- TypeScript - Superset tipado do JavaScript
- Fastify - Framework web rápido e eficiente
- PostgreSQL - Banco de dados relacional robusto
- Drizzle ORM - ORM type-safe moderno
- Drizzle Kit - Ferramentas CLI para migrations
- pg - Driver PostgreSQL para Node.js
- Biome - Linter e formatter ultra-rápido
- Vitest - Framework de testes moderno
- TSX - TypeScript executor para desenvolvimento
- TSUP - Build tool TypeScript zero-config
- @fastify/swagger - Geração automática de documentação OpenAPI
- @scalar/fastify-api-reference - Interface moderna para documentação da API
- @fastify/cors - Middleware CORS para Fastify
- Zod - Schema validation com inferência de tipos
- fastify-type-provider-zod - Integração Fastify + Zod
- Docker Compose - Orquestração de containers
- Bitnami PostgreSQL - Imagem PostgreSQL otimizada
- bcryptjs - Hashing de senhas com bcrypt
- jose - Geração e verificação de JWT tokens
- @fastify/cookie - Manipulação de cookies HTTP
- UUIDv7 - Geração de IDs únicos e ordenáveis
- http-status-codes - Constantes HTTP status
- dotenv - Gerenciamento de variáveis de ambiente
O projeto segue os princípios da Clean Architecture com uma abordagem hexagonal, promovendo:
┌─────────────────────────────────────┐
│ 🌐 HTTP Layer │
│ (Routes & Controllers) │
├─────────────────────────────────────┤
│ 💼 Use Cases Layer │
│ (Business Logic & Rules) │
├─────────────────────────────────────┤
│ 🏪 Repository Layer │
│ (Data Access Abstraction) │
├─────────────────────────────────────┤
│ 💾 Database Layer │
│ (PostgreSQL & Drizzle) │
└─────────────────────────────────────┘
- 🏭 Factory Pattern: Criação de instâncias de use cases
- 🔌 Dependency Injection: Inversão de dependências
- 📦 Repository Pattern: Abstração do acesso a dados
- 🎯 Use Case Pattern: Encapsulamento da lógica de negócio
- 🛡 Type Provider Pattern: Validação e tipagem automática
📦 task-manager-api/
├── 📁 src/ # Código fonte principal
│ ├── 📄 app.ts # Configuração do Fastify
│ ├── 📄 server.ts # Inicialização do servidor
│ ├── 📄 env.ts # Configuração de ambiente
│ │
│ ├── 📁 @types/ # Definições de tipos TypeScript
│ │ ├── 📄 fastify.d.ts # Extensões de tipos do Fastify
│ │ └── 📁 domain/ # Types do domínio da aplicação
│ │ ├── 📄 auth.ts # Types de autenticação
│ │ ├── 📄 task.ts # Types de tarefas
│ │ └── 📄 user.ts # Types de usuários
│ │
│ ├── 📁 db/ # Configuração do banco de dados
│ │ ├── � schema/ # Schemas das tabelas
│ │ │ ├── 📄 index.ts # Exportação dos schemas
│ │ │ ├── 📄 tasks-table.ts # Schema da tabela tasks
│ │ │ └── 📄 user-table.ts # Schema da tabela users
│ │ ├── 📁 migrations/ # Arquivos de migração
│ │ └── 📁 seed/ # Scripts de seed
│ │ ├── 📄 seed.ts # Script principal de seed
│ │ ├── 📄 tasks.ts # Seed das tarefas
│ │ └── 📄 users.ts # Seed dos usuários
│ │
│ ├── 📁 lib/ # Bibliotecas e utilitários
│ │ └── 📄 drizzle.ts # Configuração do Drizzle ORM
│ │
│ ├── 📁 middlewares/ # Middlewares da aplicação
│ │ └── 📄 check-auth.middleware.ts # Middleware de autenticação
│ │
│ ├── 📁 repositories/ # Camada de acesso a dados
│ │ ├── 📁 drizzle/ # Implementação com Drizzle
│ │ │ ├── 📄 drizzle-task.repository.ts
│ │ │ └── 📄 drizzle-user.repository.ts
│ │ ├── 📁 in-memory/ # Implementação em memória (testes)
│ │ │ ├── 📄 in-memory-task.repository.ts
│ │ │ └── 📄 in-memory-user.repository.ts
│ │ └── 📁 interfaces/ # Contratos dos repositórios
│ │ ├── 📄 task.repository.ts
│ │ └── 📄 user.repository.ts
│ │
│ ├── 📁 routes/ # Rotas HTTP da aplicação
│ │ ├── 📄 routes.schame.ts # Schemas comuns das rotas
│ │ ├── 📁 auth/ # Rotas de autenticação
│ │ │ ├── 📁 login/ # POST /auth/login
│ │ │ └── 📁 signup/ # POST /auth/signup
│ │ ├── 📁 health/ # Rotas de health check
│ │ │ └── 📁 check/ # GET /health/check
│ │ └── 📁 tasks/ # Rotas de tarefas (protegidas)
│ │ ├── 📁 create/ # POST /tasks
│ │ ├── 📁 list/ # GET /tasks
│ │ ├── 📁 load/ # GET /tasks/:id
│ │ ├── 📁 update/ # PUT /tasks/:id
│ │ ├── 📁 delete/ # DELETE /tasks/:id
│ │ └── 📁 complete/ # PATCH /tasks/:id
│ │
│ ├── 📁 services/ # Serviços da aplicação
│ │ ├── 📄 index.ts # Exportação dos serviços
│ │ ├── 📁 hash/ # Serviço de hashing
│ │ │ ├── 📄 hash.service.ts
│ │ │ ├── 📄 hash.service.interface.ts
│ │ │ └── 📄 hash.types.ts
│ │ └── 📁 token/ # Serviço de tokens JWT
│ │ ├── 📄 token.service.ts
│ │ ├── 📄 token.service.interface.ts
│ │ └── 📄 token.types.ts
│ │
│ └── 📁 use-cases/ # Lógica de negócio
│ ├── 📁 auth/ # Use cases de autenticação
│ │ ├── 📄 login.use-case.ts
│ │ └── 📄 signup.use-case.ts
│ ├── 📁 errors/ # Erros customizados
│ ├── 📁 factory/ # Factory de use cases
│ └── 📁 tasks/ # Use cases de tarefas
│
├── 📁 coverage/ # Relatórios de cobertura de testes
├── 📁 data/ # Dados persistentes do PostgreSQL
├── 📄 docker-compose.yml # Configuração do Docker
├── 📄 drizzle.config.ts # Configuração do Drizzle Kit
├── 📄 package.json # Dependências e scripts
├── 📄 tsconfig.json # Configuração do TypeScript
├── 📄 vitest.config.ts # Configuração do Vitest
├── 📄 vitest.setup.ts # Setup dos testes
└── 📄 biome.json # Configuração do Biome
Cada rota segue uma estrutura padronizada:
📁 route-name/
├── 📄 route-name.route.ts # Implementação da rota
├── 📄 route-name.schemas.ts # Schemas de validação (Zod)
├── 📄 route-name.types.ts # Tipos TypeScript
└── 📄 index.ts # Exportação da rota
- Node.js ≥ 18.0.0
- npm ou yarn ou pnpm
- Docker e Docker Compose (para o banco de dados)
- Clone o repositório:
git clone <repository-url>
cd task-manager-api- Instale as dependências:
npm install- Configure o ambiente:
# Crie um arquivo .env baseado no .env.example
cp .env.example .env
# Exemplo de configuração:
# PORT=3000
# PERSISTENCE_TYPE=database
# DATABASE_URL=postgresql://postgres:postgres@localhost:5432/task_manager
# JWT_SECRET=your-super-secret-jwt-key- Inicie o ambiente completo (recomendado):
# Sobe o banco, aplica migrações e popula com dados de exemplo
npm run environment:upOU configure manualmente:
4a. Inicie o banco de dados:
# Sobe o PostgreSQL via Docker
docker-compose up -d4b. Execute as migrações:
# Gera e aplica as migrações
npm run db:generate
npm run db:migrate4c. Popule com dados de exemplo (opcional):
npm run db:seed- Inicie o servidor de desenvolvimento:
npm run dev🎉 Pronto! A API estará rodando em http://localhost:3000
- Scalar API Docs:
http://localhost:3000/docs
Crie um arquivo .env na raiz do projeto com as seguintes variáveis:
# Porta do servidor
PORT=3000
# Tipo de persistência: 'database' ou 'in-memory'
PERSISTENCE_TYPE=database
# URL de conexão com PostgreSQL
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/task_manager
# Chave secreta para assinatura dos tokens JWT
JWT_SECRET=your-super-secret-jwt-keyTipos de Persistência:
database: Usa PostgreSQL com Drizzle ORM (recomendado para produção)in-memory: Usa repositório em memória (ideal para testes e desenvolvimento rápido)
Teste se tudo está funcionando:
curl http://localhost:3000/health/checkResposta esperada:
{
"status": "ok"
}O projeto inclui um sistema de seed que popula o banco com dados de exemplo:
👥 Usuários:
- Rick Ruiz:
[email protected](senha:123456) - Gui Ruiz:
[email protected](senha:123456)
📋 Tarefas:
- 20 tarefas de exemplo distribuídas entre os usuários
- 10 tarefas não completadas (IDs ímpares)
- 10 tarefas completadas (IDs pares)
Para popular o banco:
npm run db:seedExemplo de tarefa criada:
- Título: "Task #1", "Task #2", etc.
- Descrição: "Description Task #1", "Description Task #2", etc.
- Status: Alternado entre completo/incompleto
- Usuário: Associada aos usuários de exemplo
npm run dev # Inicia o servidor em modo desenvolvimento (watch)
npm run build # Compila o projeto para produção (usando TSUP)
npm run start # Inicia o servidor compiladonpm run db:generate # Gera migrações baseadas no schema
npm run db:migrate # Aplica migrações pendentes
npm run db:studio # Abre o Drizzle Studio (GUI do banco)
npm run db:seed # Popula o banco com dados de exemplonpm run environment:up # Sobe ambiente completo (DB + migrations + seed)
npm run environment:down # Derruba o ambiente Dockernpm run test # Executa todos os testes
npm run test:ui # Interface gráfica dos testes
npm run test:watch # Executa testes em modo watch
npm run test:coverage # Gera relatório de coberturanpm run lint # Executa o linter
npm run lint:fix # Corrige problemas de lint automaticamente
npm run format # Verifica formatação
npm run format:fix # Formata o código
npm run check # Executa lint + format
npm run check:fix # Corrige lint + formathttp://localhost:3000
- Scalar API Reference:
http://localhost:3000/docs - Swagger JSON:
http://localhost:3000/documentation/json
A documentação é gerada automaticamente usando OpenAPI 3.0 com schemas Zod integrados!
Verifica se a API está funcionando.
Response:
{
"status": "ok",
"timestamp": "2024-01-01T00:00:00.000Z"
}Registra um novo usuário no sistema.
Body:
{
"name": "João Silva",
"email": "[email protected]",
"password": "123456",
"passwordConfirmation": "123456"
}Response (201):
{
"id": "01HZ1234567890ABCDEFGHIJKL",
"name": "João Silva",
"email": "[email protected]"
}Autentica um usuário e retorna um token JWT.
Body:
{
"email": "[email protected]",
"password": "123456"
}Response (200):
Status: 200 OK
Set-Cookie: token=<JWT_TOKEN>; HttpOnly; Secure; SameSite=Strict; Max-Age=7200
🔒 Nota: O token JWT é retornado como um cookie HTTP-only para maior segurança.
Lista todas as tarefas do usuário autenticado com paginação e filtros opcionais.
Headers:
Cookie: token=<JWT_TOKEN>
Query Parameters:
title(string, opcional): Filtro por títulodescription(string, opcional): Filtro por descriçãopage(number, opcional): Página atual (padrão: 1)itemsPerPage(number, opcional): Items por página (padrão: 10)
Response:
{
"data": [
{
"id": "01HZ1234567890ABCDEFGHIJKL",
"title": "Minha tarefa",
"description": "Descrição da tarefa",
"completedAt": null
}
]
}Cria uma nova tarefa para o usuário autenticado.
Headers:
Cookie: token=<JWT_TOKEN>
Body:
{
"title": "Nova tarefa",
"description": "Descrição da nova tarefa"
}Response (201):
{
"id": "01HZ1234567890ABCDEFGHIJKL",
"title": "Nova tarefa",
"description": "Descrição da nova tarefa",
"completedAt": null
}Busca uma tarefa específica do usuário autenticado pelo ID.
Headers:
Cookie: token=<JWT_TOKEN>
Response (200):
{
"id": "01HZ1234567890ABCDEFGHIJKL",
"title": "Minha tarefa",
"description": "Descrição da tarefa",
"completedAt": null
}Response (404):
{
"error": "Task not found"
}Response (401):
Status: 401 Unauthorized
Atualiza uma tarefa existente do usuário autenticado.
Headers:
Cookie: token=<JWT_TOKEN>
Body:
{
"title": "Título atualizado",
"description": "Descrição atualizada"
}Response (204): (No Content)
Marca uma tarefa do usuário autenticado como completada.
Headers:
Cookie: token=<JWT_TOKEN>
Response (204): (No Content)
Remove uma tarefa do usuário autenticado.
Headers:
Cookie: token=<JWT_TOKEN>
Response (200):
{
"id": "01HZ1234567890ABCDEFGHIJKL",
"title": "Tarefa removida",
"description": "Descrição da tarefa removida",
"completedAt": null
}200- OK (sucesso)201- Created (recurso criado)204- No Content (sucesso sem conteúdo)400- Bad Request (dados inválidos)401- Unauthorized (não autenticado)404- Not Found (recurso não encontrado)422- Unprocessable Entity (validação falhou)500- Internal Server Error (erro interno)
A API utiliza JWT (JSON Web Tokens) para autenticação com as seguintes características:
- 🍪 Cookies HTTP-only: Tokens armazenados em cookies seguros
- ⏰ Expiração: Tokens válidos por 2 horas
- 🔒 Proteção: Rotas de tarefas protegidas por middleware de autenticação
- 🛡️ Segurança: Cookies com flags
HttpOnly,SecureeSameSite=Strict
Fluxo de Autenticação:
- Usuário faz login via
POST /auth/login - API retorna token JWT como cookie HTTP-only
- Cliente envia cookie automaticamente nas próximas requisições
- Middleware verifica e decodifica o token
- Usuário autenticado pode acessar rotas protegidas
O projeto possui uma suite de testes abrangente usando Vitest:
- Unit Tests: Testam componentes isolados (use cases, services)
- Authentication Tests: Testam fluxos de login, signup e validação de tokens
- Authorization Tests: Testam middleware de autenticação e controle de acesso
- Integration Tests: Testam a integração entre camadas
- Repository Tests: Testam implementações in-memory e database
npm run test:coverageOs relatórios são gerados em coverage/index.html e podem ser visualizados no navegador.
- In-memory repositories: Testes isolados sem dependência do PostgreSQL
- Mock services: Hash e token services mockados para testes determinísticos
- Factory pattern: Factories separadas para testes (InMemoryUseCaseFactory)
- Setup automático: Configuração automática do ambiente de teste (vitest.setup.ts)
- Path mapping: Suporte a imports absolutos com
@/nos testes - Coverage exclusions: Arquivos de configuração e interfaces excluídos da cobertura
- Authentication mocking: Simulação de contexto de usuário autenticado nos testes
- TypeScript Strict Mode: Tipagem rigorosa em todo o projeto
- Biome Linting: Linter e formatter ultra-rápido (substitui ESLint + Prettier)
- Conventional Commits: Commits padronizados e semânticos
- Path Mapping: Imports absolutos com
@/para melhor organização - Schema-First Design: Validação de dados com schemas Zod tipados
- Input Validation: Validação rigorosa com Zod e schemas tipados
- SQL Injection Protection: ORM type-safe (Drizzle) com queries preparadas
- CORS Configuration: Configuração adequada para diferentes ambientes
- UUIDv7 Validation: Validação específica de IDs usando UUIDv7
- Error Handling: Tratamento adequado de erros sem vazamento de informações
- Connection Pooling: Pool de conexões nativo do PostgreSQL
- Query Optimization: Queries otimizadas com Drizzle ORM
- Pagination: Paginação eficiente com LIMIT/OFFSET
- UUIDv7: IDs ordenáveis por timestamp para melhor performance de consultas
- Fastify Framework: Framework web de alta performance para Node.js
- Build Optimization: Build otimizado com TSUP para produção
- OpenAPI 3.0: Documentação automática gerada pelos schemas Zod
- Scalar UI: Interface moderna e interativa para testar a API
- JSDoc Comments: Comentários estruturados em pontos críticos
- Type Definitions: Tipos bem definidos e documentados
- Schema Descriptions: Descrições detalhadas em todos os campos da API
- README Detalhado: Documentação completa do projeto
- Drizzle Studio: Interface visual do banco de dados
npm run db:studio- Vitest UI: Interface gráfica dos testes
npm run test:ui- Scalar API Documentation: Documentação interativa da API
# Acesse: http://localhost:3000/docs- Logs Estruturados: Sistema de logs do Fastify com queries SQL visíveis
- Health Check Endpoint: Verificação básica de saúde da API (
/health/check) - Database Connection: Verificação da conectividade com o banco via Drizzle
- OpenAPI Documentation: Documentação completa e testável da API
- Query Logging: Logs detalhados das queries SQL executadas
- CORS Configuration: Configuração flexível para desenvolvimento e produção
- ✅ Sistema de Autenticação Completo: JWT com cookies HTTP-only seguros
- ✅ Gerenciamento de Usuários: Registro, login e autenticação
- ✅ Controle de Acesso: Middleware de autenticação para rotas protegidas
- ✅ Relacionamento de Dados: Tarefas associadas a usuários específicos
- ✅ Documentação Interativa: Interface Scalar para testar todos os endpoints
- ✅ Dual Persistence: Suporte a banco PostgreSQL e repositório em memória
- ✅ Data Seeding: Sistema automático de população com usuários e tarefas
- ✅ Environment Scripts: Scripts para gerenciar todo o ambiente de desenvolvimento
- ✅ Comprehensive Testing: Testes unitários para todos os use cases e auth
- ✅ Type Safety: Validação completa com Zod e tipagem TypeScript
- ✅ Modern Tooling: Biome para linting/formatting, Vitest para testes
- ✅ Production Ready: Build otimizado com TSUP e configurações de produção
- ✅ Security First: Hash de senhas com bcrypt, tokens JWT seguros
# Setup completo do ambiente
npm run environment:up
# Testar a API rapidamente
curl http://localhost:3000/health/check
# Registrar um novo usuário
curl -X POST http://localhost:3000/auth/signup \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"[email protected]","password":"123456","passwordConfirmation":"123456"}'
# Fazer login (salva cookie automaticamente)
curl -X POST http://localhost:3000/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"123456"}' \
-c cookies.txt
# Listar tarefas (usando cookie salvo)
curl http://localhost:3000/tasks -b cookies.txt
# Ver dados no banco
npm run db:studio
# Executar testes com interface
npm run test:ui
# Ver documentação interativa
# Abra: http://localhost:3000/docsContribuições são sempre bem-vindas!
- Faça um fork do projeto
- Crie uma branch para sua feature (
git checkout -b feature/amazing-feature) - Commit suas mudanças (
git commit -m 'Add some amazing feature') - Push para a branch (
git push origin feature/amazing-feature) - Abra um Pull Request
Este projeto está sob a licença ISC. Veja o arquivo LICENSE para mais detalhes.
Feito com ❤️ e muito ☕ por desenvolvedores apaixonados por código limpo!
🚀 Happy Coding! 🚀