Uma API RESTful genérica construída com Node.js e Express 5, implementando operações CRUD (Create, Read, Update, Delete) com autenticação JWT, validação de dados e arquitetura modular.
- Node.js - Runtime JavaScript
- Express 5 - Framework web
- Sequelize - ORM para banco de dados
- SQLite - Banco de dados (desenvolvimento)
- PostgreSQL - Banco de dados (produção)
- JWT - Autenticação baseada em tokens
- Zod - Validação de schemas
- bcryptjs - Hash de senhas
- Helmet - Segurança HTTP
- CORS - Controle de acesso cross-origin
- express-rate-limit - Limitação de taxa de requisições
- Node.js 18+
- npm ou yarn
- SQLite (para desenvolvimento)
- PostgreSQL (para produção, opcional)
- Clone o repositório:
git clone https://github.com/IgorSasaki/generic-crud-api.git
cd generic-crud-api- Instale as dependências:
npm install
# ou
yarn install- Configure as variáveis de ambiente (opcional):
# Crie um arquivo .env na raiz do projeto
PORT=3333
JWT_SECRET=seu-secret-super-seguro-aqui
JWT_EXPIRES_IN=15m
CORS_ORIGIN=*
NODE_ENV=developmentO banco SQLite é criado automaticamente na raiz do projeto (database.sqlite) quando a aplicação é iniciada.
Para popular o banco com dados de exemplo:
npx sequelize-cli db:seed:allIsso criará:
- 2 usuários de exemplo (admin@email.com e user@email.com, senha:
senha123) - Vários reports de exemplo
npm run dev
# ou
yarn devnpm start
# ou
yarn startA API estará disponível em http://localhost:3333 (ou na porta configurada).
generic-crud-api/
├── src/
│ ├── config/ # Configurações (banco, env)
│ ├── database/ # Seeders e migrations
│ ├── middlewares/ # Middlewares (auth, validate, errorHandler)
│ ├── models/ # Modelos Sequelize (User, Report)
│ ├── modules/ # Módulos da aplicação
│ │ ├── users/ # Módulo de usuários
│ │ │ ├── user.controller.js
│ │ │ ├── user.service.js
│ │ │ ├── user.repo.sequelize.js
│ │ │ └── user.schemas.js
│ │ └── reports/ # Módulo de reports
│ │ ├── report.controller.js
│ │ ├── report.service.js
│ │ ├── report.repo.sequelize.js
│ │ └── report.schemas.js
│ ├── routes/ # Definição de rotas
│ ├── utils/ # Utilitários
│ ├── app.js # Configuração do Express
│ └── server.js # Ponto de entrada
├── database.sqlite # Banco SQLite (desenvolvimento)
├── package.json
└── README.md
A API usa JWT (JSON Web Tokens) para autenticação. Para acessar rotas protegidas, inclua o token no header:
Authorization: Bearer <seu_token>
GET /health
Resposta:
{
"ok": true
}POST /auth/register
Body:
{
"name": "João Silva",
"email": "joao@email.com",
"password": "senha123"
}Resposta (201):
{
"id": "uuid-do-usuario",
"name": "João Silva",
"email": "joao@email.com"
}POST /auth/login
Body:
{
"email": "joao@email.com",
"password": "senha123"
}Resposta (200):
{
"accessToken": "jwt-token-aqui"
}GET /auth/me
Headers:
Authorization: Bearer <token>
Resposta (200):
{
"userId": "uuid-do-usuario"
}GET /reports
Query Parameters (opcionais):
q- Busca por título (busca parcial)order- Campo para ordenação (id,title,createdAt)dir- Direção da ordenação (ASC,DESC)page- Número da página (padrão: 1)limit- Itens por página (padrão: 10, máximo: 100)
Exemplo:
GET /reports?q=lenda&order=createdAt&dir=DESC&page=1&limit=10
Resposta (200):
{
"items": [
{
"id": "uuid",
"title": "Título do Report",
"content": "Conteúdo do report",
"originLocation": "São Paulo",
"createdBy": "uuid-do-usuario",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z",
"user": {
"id": "uuid",
"name": "Nome do Usuário"
}
}
],
"page": 1,
"limit": 10,
"total": 50,
"totalPages": 5
}GET /reports/:id
Resposta (200):
{
"id": "uuid",
"title": "Título do Report",
"content": "Conteúdo do report",
"originLocation": "São Paulo",
"createdBy": "uuid-do-usuario",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}POST /reports
Headers:
Authorization: Bearer <token>
Body:
{
"title": "Título do Report",
"content": "Conteúdo do report",
"originLocation": "São Paulo - Capital"
}Resposta (201):
{
"id": "uuid",
"title": "Título do Report",
"content": "Conteúdo do report",
"originLocation": "São Paulo - Capital",
"createdBy": "uuid-do-usuario",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}PATCH /reports/:id
Headers:
Authorization: Bearer <token>
Body (todos os campos são opcionais, mas pelo menos um deve ser enviado):
{
"title": "Novo Título",
"content": "Novo Conteúdo",
"originLocation": "Nova Localização"
}Resposta (200):
{
"id": "uuid",
"title": "Novo Título",
"content": "Novo Conteúdo",
"originLocation": "Nova Localização",
"createdBy": "uuid-do-usuario",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}DELETE /reports/:id
Headers:
Authorization: Bearer <token>
Resposta (204): Sem conteúdo
- Helmet: Protege contra vulnerabilidades HTTP comuns
- CORS: Configurável via variável de ambiente
- Rate Limiting: Limita a 100 requisições por minuto por IP
- JWT: Tokens com expiração configurável
- bcryptjs: Senhas hasheadas com salt rounds
- Validação: Todos os dados de entrada são validados com Zod
name: String, obrigatório, mínimo 1 caractereemail: Email válido, obrigatório, únicopassword: String, obrigatório, mínimo 6 caracteres
title: String, obrigatório, mínimo 1 caracterecontent: String, obrigatório, mínimo 1 caractereoriginLocation: String, obrigatório, mínimo 1 caractere
id: UUID (primary key)name: String(100)email: String(255), únicopasswordHash: String(255)createdAt: TimestampupdatedAt: Timestamp
id: UUID (primary key)title: String(100)content: String(255)originLocation: String(255)createdBy: UUID (foreign key para User)createdAt: TimestampupdatedAt: Timestamp
A aplicação segue uma arquitetura em camadas:
- Routes: Define as rotas e aplica middlewares
- Controllers: Recebe requisições, valida e chama services
- Services: Lógica de negócio
- Repositories: Acesso aos dados (Sequelize)
- Models: Definição dos modelos do banco de dados
# Desenvolvimento (com watch mode)
npm run dev
# Produção
npm start
# Seeders
npx sequelize-cli db:seed:all
# Reverter seeders
npx sequelize-cli db:seed:undo:allA API retorna erros em um formato padronizado:
{
"message": "Mensagem de erro",
"code": "CODIGO_DO_ERRO",
"details": null
}Códigos de status HTTP:
200- Sucesso201- Criado com sucesso204- Sem conteúdo (delete)400- Erro de validação401- Não autorizado404- Não encontrado409- Conflito (ex: email já existe)500- Erro interno do servidor
MIT
Igor Sasaki - igor-sasaki@hotmail.com
Contribuições são bem-vindas! Sinta-se à vontade para abrir issues e pull requests.