Uma API RESTful robusta para gerenciamento de cursos, construída com Fastify, TypeScript, Drizzle ORM e PostgreSQL.
Esta aplicação fornece endpoints para criar, ler, atualizar e deletar cursos. Inclui validação de dados com Zod, integração com banco de dados PostgreSQL e documentação automática com Swagger/OpenAPI.
flowchart TD
A[Cliente/Navegador] -->|HTTP Request| B[Fastify Server]
B -->|Valida com Zod| C{Dados Válidos?}
C -->|Não| D[Retorna 400 Bad Request]
C -->|Sim| E{Operação?}
E -->|POST /courses| F[Cria Novo Curso]
E -->|GET /courses| G[Lista Todos os Cursos]
E -->|GET /courses/:id| H[Busca Curso por ID]
E -->|PUT /courses/:id| I[Atualiza Curso]
E -->|DELETE /courses/:id| J[Deleta Curso]
F -->|Insert| K[(PostgreSQL)]
G -->|Select| K
H -->|Select WHERE| K
I -->|Update WHERE| K
J -->|Delete WHERE| K
K -->|Retorna Dados| L[Drizzle ORM]
L -->|Transforma| M[Serializa Resposta]
M -->|JSON| N[Cliente Recebe Resposta]
D --> N
F -->|Sucesso 201| N
G -->|Sucesso 200| N
H -->|Sucesso 200| N
I -->|Sucesso 200| N
J -->|Sucesso 200| N
K -.->|Erro| O[Retorna 500 Error]
O --> N
Fluxo Principal:
- Cliente envia requisição HTTP para o servidor Fastify
- Zod valida os dados da requisição
- Se inválido, retorna erro 400
- Se válido, executa a operação correspondente (CRUD)
- Drizzle ORM interage com o PostgreSQL
- Resultado é serializado e retornado ao cliente
- Em caso de erro no banco, retorna 500
- Fastify - Framework web rápido e eficiente
- TypeScript - Tipagem estática para JavaScript
- Drizzle ORM - ORM type-safe para TypeScript
- PostgreSQL - Banco de dados relacional
- Zod - Validação de schemas
- Docker - Containerização
- Pino - Logger estruturado
- Node.js v18+ instalado
- Docker e Docker Compose instalados
- npm ou yarn
git clone https://github.com/carlosribeiro25/Api-nodejs_fastify.git
cd API-nodeJSnpm installCrie um arquivo .env na raiz do projeto:
DATABASE_URL=postgresql://user:password@localhost:5432/courses_db
NODE_ENV=developmentdocker compose up -dnpm run db:pushnpm run devO servidor estará disponível em http://localhost:3333
npm run dev # Inicia o servidor em modo desenvolvimento
npm run build # Compila o TypeScript
npm run start # Inicia o servidor em produção
npm run db:studio # Abre o Drizzle Studio para gerenciar o banco
npm run db:generate # Gera novas migrações
npm run db:push # Aplica as migrações ao bancoGET /coursesResposta (200):
{
"courses": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Introdução ao Node.js",
"description": "Aprenda os fundamentos do Node.js"
}
]
}GET /courses/:idParâmetros:
id(UUID) - ID do curso
Resposta (200):
{
"course": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Introdução ao Node.js",
"description": "Aprenda os fundamentos do Node.js"
}
}Resposta (404):
{
"error": "Curso não encontrado"
}POST /courses
Content-Type: application/json
{
"title": "Introdução ao Node.js",
"description": "Aprenda os fundamentos do Node.js e crie aplicações de back-end"
}Validações:
title: mínimo 5 caracteresdescription: mínimo 10 caracteres
Resposta (201):
{
"courseId": "550e8400-e29b-41d4-a716-446655440000"
}Resposta (500):
{
"error": "Falha ao criar o curso"
}PUT /courses/:id
Content-Type: application/json
{
"title": "Node.js Avançado",
"description": "Aprenda tópicos avançados do Node.js e desenvolvimento de APIs"
}Parâmetros:
id(UUID) - ID do curso
Validações:
title: mínimo 5 caracteresdescription: mínimo 10 caracteres
Resposta (200):
{
"message": "Curso atualizado com sucesso",
"course": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Node.js Avançado",
"description": "Aprenda tópicos avançados do Node.js e desenvolvimento de APIs"
}
}Resposta (404):
{
"error": "Curso não encontrado"
}DELETE /courses/:idParâmetros:
id(UUID) - ID do curso
Resposta (200):
{
"courseId": "550e8400-e29b-41d4-a716-446655440000"
}Resposta (404):
{
"error": "Curso não encontrado"
}| Coluna | Tipo | Restrições |
|---|---|---|
| id | UUID | PRIMARY KEY, DEFAULT (random) |
| title | TEXT | NOT NULL, UNIQUE, LENGTH >= 5 |
| description | TEXT | LENGTH >= 10 |
| Coluna | Tipo | Restrições |
|---|---|---|
| id | UUID | PRIMARY KEY, DEFAULT (random) |
| name | TEXT | NOT NULL |
| TEXT | NOT NULL, UNIQUE |
# Criar um curso
curl -X POST http://localhost:3333/courses \
-H "Content-Type: application/json" \
-d '{"title":"Meu Curso","description":"Descrição do meu curso"}'
# Listar todos os cursos
curl http://localhost:3333/courses
# Obter um curso específico
curl http://localhost:3333/courses/550e8400-e29b-41d4-a716-446655440000
# Atualizar um curso
curl -X PUT http://localhost:3333/courses/550e8400-e29b-41d4-a716-446655440000 \
-H "Content-Type: application/json" \
-d '{"title":"Curso Atualizado","description":"Nova descrição"}'
# Deletar um curso
curl -X DELETE http://localhost:3333/courses/550e8400-e29b-41d4-a716-446655440000Importe os exemplos de requisições do arquivo requisicoes.http
API-nodeJS/
├── src/
│ ├── database/
│ │ ├── cliente.ts # Configuração do cliente Drizzle
│ │ ├── schema.ts # Definição das tabelas
│ │ └── routes/ # Rotas organizadas por funcionalidade
│ │ ├── create-courses.ts
│ │ ├── get-courses.ts
│ │ ├── get-coursesById.ts
│ │ ├── update-courses.ts
│ │ └── delete-courses.ts
├── drizzle/ # Migrações do banco de dados
├── server.ts # Configuração principal do Fastify
├── tsconfig.json # Configuração do TypeScript
├── drizzle.config.ts # Configuração do Drizzle ORM
├── docker-compose.yml # Configuração do Docker
├── package.json
└── README.md
| Variável | Descrição | Exemplo |
|---|---|---|
DATABASE_URL |
URL de conexão com PostgreSQL | postgresql://user:pass@localhost:5432/db |
NODE_ENV |
Ambiente de execução | development ou production |
A API utiliza Zod para validar todos os inputs:
- Título: string com mínimo 5 caracteres
- Descrição: string com mínimo 10 caracteres
- ID: UUID válido
Erros de validação retornam status 400 com mensagens descritivas.
A API retorna os seguintes status HTTP:
200 OK- Requisição bem-sucedida201 Created- Recurso criado com sucesso400 Bad Request- Dados inválidos404 Not Found- Recurso não encontrado500 Internal Server Error- Erro no servidor
A aplicação utiliza Pino para logging estruturado. Os logs incluem:
- Requisições HTTP
- Erros de banco de dados
- Eventos de aplicação
Configure o nível de log em server.ts:
const server = fastify({
logger: {
level: 'info', // 'debug', 'info', 'warn', 'error'
transport: {
target: 'pino-pretty',
options: {
translateTime: 'HH:MM:ss Z',
ignore: 'pid,hostname',
},
},
},
})docker build -t api-courses .
docker run -p 3333:3333 --env-file .env api-coursesnpm run build
npm run startPara dúvidas ou problemas, abra uma issue no repositório.
Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.
Carlos Ribeiro
GitHub: @carlosribeiro25
Desenvolvido com ❤️ usando Fastify e TypeScript