Aplicação fullstack de gerenciamento de tarefas construída para demonstrar arquitetura desacoplada, regras de negócio testáveis e fluxo HTTP consistente.
- Visão geral
- O que está funcionando
- Stack
- Arquitetura (Hexagonal)
- Estrutura de pastas
- Como clonar o projeto
- Pré-requisitos
- Setup rápido (Docker)
- Setup local (Node + MySQL)
- Variáveis de ambiente
- Como executar
- API (contratos e exemplos)
- Frontend (fluxo funcional)
- Banco de dados
- Testes
- Scripts disponíveis
- Troubleshooting
- Checklist de entrega
O projeto segue o modelo de Ports and Adapters (Hexagonal) no backend:
- Entrada HTTP (Express)
- Middlewares (JWT + sanitização)
- Controller (Zod + mapeamento para DTO)
- UseCase (regra de negócio)
- Repository (Prisma + MySQL)
- Saída padronizada + Global Error Handler
- Autenticação JWT via
POST /api/auth/logincomuserId. - Middleware de autenticação para proteger rotas de tarefas.
- Middleware de sanitização básica (
trim, remoção de<e>). - CRUD de tarefas completo:
- Criar em lote (até 1000 registros)
- Listar tarefas do usuário autenticado
- Buscar por id
- Atualizar (
title,description,status) - Excluir
- Regra de segurança: apenas o dono pode acessar/editar/excluir a própria task.
- Tratamento global de erros com mapeamento de erros de domínio para HTTP.
- Login por
userIdpara obtenção de JWT. - Criação em lote (uma task por linha).
- Listagem de tarefas do usuário logado.
- Atualização de status (
PENDING/DONE) com toggle. - Edição inline de título (Salvar/Cancelar).
- Exclusão de tarefa.
- TypeScript em modo estrito.
- Testes unitários no backend (camada de comunicação + use cases).
- Build de backend e frontend funcionando.
- Docker Compose para MySQL + backend.
- Linguagem: TypeScript (strict)
- Backend: Express, Zod, JWT
- ORM/Banco: Prisma + MySQL
- Frontend: React + Vite
- Testes: Jest
- Domain: entidades e erros de domínio
- Application: use cases + ports (interfaces)
- Adapters (Input/Output): controllers/middlewares/routes + repository Prisma
- Infrastructure/Main: wiring de dependências, client Prisma, bootstrap do app
- Use cases dependem de interfaces, não de Prisma/Express.
- Controllers validam schema com Zod e apenas orquestram entrada/saída.
- Regras de autorização por dono ficam protegidas na camada de aplicação.
- Erros de domínio são traduzidos para status HTTP no handler global.
Documento auxiliar de arquitetura: apps/backend/ARCHITECTURE.md.
apps/
backend/
prisma/
src/
domain/
application/
adapters/
infrastructure/
main/
frontend/
src/
docker-compose.yml
git clone https://github.com/GabrielaMoura25/Task-Manager-.git
cd Task-Manager-git clone git@github.com:GabrielaMoura25/Task-Manager-.git
cd Task-Manager-- Node.js 20+
- npm 10+
- Docker + Docker Compose (recomendado)
Sobe MySQL e backend de uma vez:
docker compose up -d --buildO docker-compose.yml lê as variáveis do arquivo apps/backend/.env via env_file, evitando hardcode de credenciais no YAML.
Serviços:
- API:
http://localhost:3000 - MySQL para cliente externo:
127.0.0.1:3310 - MySQL interno (containers):
mysql:3306
Parar tudo:
docker compose down- Instale dependências:
npm install- Configure
.env:
cp apps/backend/.env.example apps/backend/.env
cp apps/frontend/.env.example apps/frontend/.env- Ajuste
DATABASE_URLemapps/backend/.envconforme seu cenário:
# MySQL instalado localmente
DATABASE_URL="mysql://root:root@localhost:3306/medcof_tasks"
# MySQL vindo do docker-compose (porta publicada 3310)
DATABASE_URL="mysql://root:root@localhost:3310/medcof_tasks"
MYSQL_ROOT_PASSWORD="root"
MYSQL_DATABASE="medcof_tasks"
MYSQL_USER="root"- Gere o Prisma Client e sincronize o banco:
npm run prisma:generate --workspace @medcof/backend
npm run prisma:push --workspace @medcof/backendDATABASE_URL="mysql://root:root@localhost:3306/medcof_tasks"
JWT_SECRET="change-me"
PORT=3000
MYSQL_ROOT_PASSWORD="root"
MYSQL_DATABASE="medcof_tasks"
MYSQL_USER="root"VITE_API_BASE_URL="http://localhost:3000/api"npm run dev:backendnpm run dev:frontendnpm run buildBase URL: http://localhost:3000/api
POST /auth/login
Body:
{
"userId": "user-a"
}Resposta (200):
{
"success": true,
"data": {
"token": "<JWT>"
}
}POST /tasks
Headers:
Authorization: Bearer <JWT>
Body:
{
"tasks": [
{ "title": "Task 1" },
{ "title": "Task 2", "description": "Descrição opcional" }
]
}Resposta (201):
{
"success": true,
"data": {
"createdCount": 2
}
}GET /tasks
Resposta (200):
{
"success": true,
"data": [
{
"id": "...",
"ownerId": "user-a",
"title": "Task 1",
"description": null,
"status": "PENDING",
"createdAt": "...",
"updatedAt": "..."
}
]
}GET /tasks/:id
PATCH /tasks/:id
Body (exemplo):
{
"title": "Novo título",
"status": "DONE"
}DELETE /tasks/:id
Resposta (200):
{
"success": true,
"data": {
"deleted": true
}
}400 REQUEST_VALIDATION_ERROR400 BULK_LIMIT_EXCEEDED401 UNAUTHORIZED403 FORBIDDEN_TASK_ACCESS404 TASK_NOT_FOUND500 INTERNAL_SERVER_ERROR
- Informar
userIde gerar JWT. - Criar tasks em lote (uma por linha).
- Atualizar lista.
- Editar título inline.
- Alternar status e excluir.
Schema Prisma atual (Task):
id(cuid)ownerIdtitledescription(nullable)status(PENDING|DONE)createdAtupdatedAt- índice em
ownerId
Executar testes do backend:
npm testEscopo atual coberto:
- Use case de criação em lote (limites e sucesso com mock de repositório)
- Use case de acesso por id (not found, forbidden, sucesso)
- Controller (validação e mapeamento para DTO)
- Middleware JWT
- Global Error Handler
npm run dev:backendnpm run dev:frontendnpm run buildnpm test
npm run dev --workspace @medcof/backendnpm run build --workspace @medcof/backendnpm run test --workspace @medcof/backendnpm run prisma:generate --workspace @medcof/backendnpm run prisma:migrate --workspace @medcof/backendnpm run prisma:migrate:deploy --workspace @medcof/backendnpm run prisma:push --workspace @medcof/backend
npm run dev --workspace @medcof/frontendnpm run build --workspace @medcof/frontendnpm run preview --workspace @medcof/frontend
No driver MySQL, configure:
allowPublicKeyRetrieval=trueuseSSL=false
Ou use URL:
jdbc:mysql://127.0.0.1:3310/medcof_tasks?allowPublicKeyRetrieval=true&useSSL=false
- Verifique se o compose está no ar:
docker compose ps - Confirme porta
3310publicada para MySQL - Host correto:
127.0.0.1(nãomysql)
Se necessário, sincronize manualmente:
docker compose exec backend npm run prisma:push- TypeScript strict no backend/frontend
- Backend em Express
- Frontend em React
- Prisma + MySQL
- Arquitetura hexagonal no backend
- JWT + sanitização em middleware
- Validação com Zod em controllers
- Use cases desacoplados por interfaces (ports)
- Global Error Handler
- Segurança de ownership por task
- Criação em lote até 1000 registros
- Testes unitários (comunicação + use cases)
- README com setup/execução/testes