Skip to content

imdouglasoliveira/api-node

Repository files navigation

Desafio Node.js – Primeira API (aulas)

API simples em Node.js + TypeScript usando Fastify, Drizzle ORM (SQLite) e Zod. Inclui documentação Swagger/Scalar em ambiente de desenvolvimento.

Requisitos

  • Node.js 20.12.2+ (recomendado usar .nvmrc)
  • npm (ou outro gerenciador, mas o projeto usa package-lock.json)

Tecnologias

  • Fastify 5 - Framework web rápido e eficiente
  • TypeScript - Superset do JavaScript com tipagem estática
  • Drizzle ORM + SQLite - ORM moderno e type-safe com banco embarcado
  • Zod - Validação de dados
  • Swagger/OpenAPI + Scalar API Reference (em /docs quando NODE_ENV=development)
  • tsx - Executor TypeScript para desenvolvimento
  • pino-pretty - Logger formatado para desenvolvimento

Configuração

  1. Clone o repositório e acesse a pasta do projeto.
  2. Instale as dependências:
npm install
  1. Crie um arquivo .env na raiz com:
# Ativa docs em /docs
NODE_ENV=development
  1. Configure o banco de dados SQLite:
# Opção 1: Setup completo (gerar + aplicar migrações)
npm run db:setup

# Opção 2: Passo a passo
npm run migrate:generate  # Gera arquivo SQL de migração
npm run migrate          # Aplica migrações no banco
  1. (Opcional) Popular banco de dados com dados de exemplo:
# Seed completo (usuários + cursos + matrículas)
# Padrão: 5 usuários, 20 cursos, 3 matrículas por usuário
npm run db:seed

# Seed completo com quantidades customizadas
npm run db:seed -- --users=10 --courses=8 --enrollments=4

# Seeds individuais (caso prefira popular separadamente)
npm run db:seed-users       # Padrão: 2 usuários
npm run db:seed-users 10    # Criar 10 usuários
npm run db:seed-courses     # Padrão: todos os 20 cursos
npm run db:seed-courses 5   # Criar apenas 5 cursos
  1. (Opcional) Para inspecionar o schema/estado com o Drizzle Studio:
npm run drizzle:studio

Executando o servidor

npm run dev
  • Porta padrão: http://localhost:3333
  • Logs legíveis habilitados
  • Documentação da API (em dev): http://localhost:3333/docs

Endpoints

Base URL: http://localhost:3333

Courses (Cursos)

  • POST /courses

    • Cria um curso único ou múltiplos cursos
    • Body (JSON):
      { "title": "Curso de Docker", "description": "Aprenda Docker" }
      ou array para múltiplos:
      [
        { "title": "Curso A", "description": "Desc A" },
        { "title": "Curso B" }
      ]
    • Respostas: 201 (sucesso), 500 (erro)
  • GET /courses

    • Lista todos os cursos com paginação, busca e ordenação
    • Query params: page, limit, search, orderBy
    • 200: { "courses": [...], "currentPage": 1, "perPage": 10, "totalItems": 20, "totalPages": 2 }
  • GET /courses/:id

    • Busca um curso pelo ID
    • Respostas: 200 (encontrado), 404 (não encontrado)

Users (Usuários)

  • POST /users

    • Cria um usuário único ou múltiplos usuários
    • Body (JSON):
      { "first_name": "João", "last_name": "Silva", "email": "joao@email.com" }
      ou array para múltiplos usuários
    • Respostas: 201 (sucesso), 500 (erro)
  • GET /users

    • Lista todos os usuários com paginação, busca e ordenação
    • Query params: page, limit, search, orderBy
    • 200: { "users": [...], "currentPage": 1, "perPage": 10, "totalItems": 5, "totalPages": 1 }
  • GET /users/:id

    • Busca um usuário pelo ID
    • Respostas: 200 (encontrado), 404 (não encontrado)

Enrollments (Matrículas)

  • POST /enrollments

    • Cria uma matrícula única ou múltiplas matrículas
    • Body (JSON):
      { "user_id": 1, "course_id": 1 }
      ou array para múltiplas matrículas
    • Respostas: 201 (sucesso), 500 (erro)
  • GET /enrollments

    • Lista todas as matrículas com paginação e filtros
    • Query params: page, limit, user_id, course_id
    • 200: { "enrollments": [...], "currentPage": 1, "perPage": 10, "totalItems": 15, "totalPages": 2 }
    • Retorna dados enriquecidos com nome do usuário e título do curso
  • GET /enrollments/:user_id/:course_id

    • Busca uma matrícula específica por user_id e course_id
    • Respostas: 200 (encontrado), 404 (não encontrado)

Há arquivos .http na pasta src/requests/ com exemplos prontos (compatível com extensões de REST Client):

  • src/requests/courses/courses.http - Requisições de cursos
  • src/requests/users/users.http - Requisições de usuários
  • src/requests/enrollments/enrollments.http - Requisições de matrículas

Estrutura do Projeto

api-node/
├── docs/                 # Documentação técnica (local)
│   ├── README.md         # Visão geral da documentação
│   ├── instrucoes.md     # Instruções de setup
│   ├── migracoes-drizzle.md  # Guia de migrações
│   └── drizzle-studio-setup.md  # Configuração do Studio
├── drizzle/              # Migrações do banco de dados
├── src/
│   ├── database/         # Schema e cliente do banco
│   │   ├── schema.ts     # Definição das tabelas
│   │   ├── client.ts     # Cliente SQLite
│   │   ├── dev.db        # Arquivo do banco SQLite
│   │   └── seeds/        # Scripts para popular o banco
│   │       ├── index.ts           # Seed completo (users + courses + enrollments)
│   │       ├── seed-users.ts      # Seed apenas de usuários
│   │       └── seed-courses.ts    # Seed apenas de cursos
│   ├── requests/         # Arquivos de requisições HTTP (REST Client)
│   │   ├── courses/
│   │   │   └── courses.http      # Exemplos de requisições de cursos
│   │   ├── users/
│   │   │   └── users.http        # Exemplos de requisições de usuários
│   │   └── enrollments/
│   │       └── enrollments.http  # Exemplos de requisições de matrículas
│   ├── routes/           # Rotas da API
│   │   ├── courses/      # Rotas de cursos (get, create, get-by-id)
│   │   ├── users/        # Rotas de usuários (get, create, get-by-id)
│   │   └── enrollments/  # Rotas de matrículas (get, create, get-by-ids)
│   └── scripts/          # Scripts utilitários
│       ├── database/     # Scripts de gerenciamento do banco
│       │   ├── index.js          # Exportações
│       │   ├── apply-migration.js # Aplicar migrações
│       │   ├── check-db.js       # Verificar status do banco
│       │   └── reset-table.js    # Resetar tabelas específicas
│       ├── git/          # Scripts de automação Git
│       │   ├── index.js          # Exportações
│       │   ├── cleanup.js        # Limpar processos
│       │   ├── deploy.js         # Deploy automatizado
│       │   ├── push-dev.js       # Push para dev
│       │   └── status.js         # Git status formatado
│       └── README.md     # Documentação dos scripts
├── .claude/              # Configurações Claude (local)
├── server.ts            # Servidor principal
├── CLAUDE.md            # Documentação Claude (local)
├── package.json         # Configurações e dependências
├── tsconfig.json        # Configuração TypeScript
├── drizzle.config.ts    # Configuração Drizzle Kit
└── README.md           # Este arquivo

Nota: Os diretórios docs/, .claude/ e o arquivo CLAUDE.md são locais e não são versionados no Git.

Modelos (schema)

Tabelas principais definidas em src/database/schema.ts:

  • courses
    • id (integer, pk, auto-increment)
    • title (text, único, obrigatório)
    • description (text, opcional)
    • created_at (timestamp, obrigatório)
    • updated_at (timestamp, obrigatório)
  • users
    • id (integer, pk, auto-increment)
    • first_name (text, obrigatório)
    • last_name (text, obrigatório)
    • email (text, único, obrigatório)
    • created_at (timestamp, obrigatório)
    • updated_at (timestamp, obrigatório)
  • enrollments
    • user_id (integer, fk → users.id, obrigatório)
    • course_id (integer, fk → courses.id, obrigatório)
    • created_at (timestamp, obrigatório)
    • updated_at (timestamp, obrigatório)

Scripts

Desenvolvimento

  • npm run dev: inicia o servidor com reload e carrega variáveis de .env
  • npm run drizzle:studio: abre o Drizzle Studio

Migrações

  • npm run migrate:generate: gera artefatos do Drizzle a partir do schema
  • npm run migrate: aplica migrações no banco
  • npm run db:setup: configura o banco de dados (gera e aplica migrações)
  • npm run db:reset: DELETA o banco SQLite e recria do zero
  • npm run db:check: verifica o status do banco SQLite

Seeds (Popular dados)

  • npm run db:seed: executa seed completo (usuários + cursos + matrículas)
    • Padrão: 5 usuários, 20 cursos, 3 matrículas/usuário
    • Com parâmetros: npm run db:seed -- --users=10 --courses=8 --enrollments=4
    • Algoritmo de matrículas: Cada usuário é matriculado em N cursos aleatórios sem repetição
      • Exemplo: 3 usuários, 5 cursos, 2 matrículas/usuário = 6 matrículas totais
      • User 1 → sorteados: Course A, Course D
      • User 2 → sorteados: Course B, Course E
      • User 3 → sorteados: Course C, Course A
  • npm run db:seed-users [quantidade]: cria apenas usuários (padrão: 2)
  • npm run db:seed-courses [limite]: cria apenas cursos (padrão: todos os 20)

Resetar Tabelas (limpa dados, mantém estrutura, reseta IDs)

Importante: Estes comandos apagam todos os registros da tabela e resetam os IDs autoincrementais para 1.

  • npm run db:reset-table [nome]: reseta tabela específica (users, courses ou enrollments)
  • npm run db:reset-users: limpa apenas a tabela users
  • npm run db:reset-courses: limpa apenas a tabela courses
  • npm run db:reset-enrollments: limpa apenas a tabela enrollments
  • npm run db:reset-all-tables: limpa TODAS as tabelas (mantém estrutura do banco)

Exemplo de uso:

# Cenário: Você tem cursos com IDs 5, 6, 7 e quer recomeçar do ID 1
npm run db:reset-courses    # Limpa tabela courses
npm run db:seed-courses 3   # Cria 3 cursos com IDs 1, 2, 3

Fluxo principal (Mermaid)

sequenceDiagram
  participant C as Client
  participant S as Fastify Server
  participant V as Zod Validator
  participant DB as Drizzle + SQLite

  C->>S: POST /courses {title}
  S->>V: Validar body
  V-->>S: OK ou Erro 400
  alt válido
    S->>DB: INSERT INTO courses (title)
    DB-->>S: {id}
    S-->>C: 201 {courseId}
  else inválido
    S-->>C: 400
  end

  C->>S: GET /courses
  S->>DB: SELECT id,title FROM courses
  DB-->>S: lista
  S-->>C: 200 {result: [...]} 

  C->>S: GET /courses/:id
  S->>V: Validar param id (number)
  V-->>S: OK ou Erro 400
  alt encontrado
    S->>DB: SELECT * FROM courses WHERE id=...
    DB-->>S: course
    S-->>C: 200 {course}
  else não encontrado
    S-->>C: 404
  end
Loading

Dicas e solução de problemas

Problema: Banco de dados não criado ou vazio

Solução:

# 1. Verificar status do banco
npm run db:check

# 2. Se o banco estiver vazio ou corrompido, execute:
npm run db:reset

# 3. Popular com dados de exemplo
npm run db:seed -- --users=5 --courses=10 --enrollments=3

Problema: Migrações ausentes (pasta drizzle/ vazia)

Solução:

# 1. Regenerar migrações
npm run migrate:generate

# 2. Aplicar migrações
npm run migrate

# 3. Verificar se funcionou
npm run db:check

Problema: Preciso limpar dados de teste mas manter a estrutura

Solução:

# Resetar uma tabela específica (apaga dados e reseta IDs)
npm run db:reset-courses
npm run db:reset-users

# Resetar TODAS as tabelas (mantém estrutura do banco)
npm run db:reset-all-tables

# Popular novamente com dados limpos
npm run db:seed -- --users=5 --courses=10 --enrollments=3

Diferença entre comandos de reset

  • npm run db:reset: DELETA o arquivo do banco e recria tudo do zero (estrutura + dados)
  • npm run db:reset-table [nome]: Limpa apenas UMA tabela, mantém estrutura e reseta IDs para começar do 1
  • npm run db:reset-all-tables: Limpa TODAS as tabelas, mas mantém a estrutura do banco

Outros problemas comuns

  • Arquivo SQLite não encontrado: confirme que npm run db:setup foi executado e que o arquivo src/database/dev.db existe.
  • Variável NODE_ENV ausente: verifique seu .env. A documentação em /docs só aparece quando NODE_ENV=development.
  • Docs não aparecem em /docs: garanta NODE_ENV=development no .env e reinicie o servidor.
  • Banco corrompido: execute npm run db:reset para resetar o banco SQLite.
  • Erro ao popular dados: certifique-se de que as migrações foram aplicadas antes de rodar os seeds.

Licença

ISC (ver package.json).

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published