API RESTful para gerenciamento de categorias e produtos da loja "Mundo Geek", especializada em produtos colecionáveis, jogos de tabuleiro e itens de cultura pop.
A API foi desenvolvida com as melhores práticas de arquitetura de software, incluindo:
- Linguagem: TypeScript
- Framework Web: Express.js
- ORM: TypeORM
- Banco de Dados: PostgreSQL
- Validação: Zod
- Padrão Arquitetural: MVC com Serviços
- Node.js (v16 ou superior)
- npm ou yarn
- PostgreSQL (v12 ou superior)
- Instale as dependências do projeto:
npm install- Configure as variáveis de ambiente:
Edite o arquivo .env na raiz do projeto com suas credenciais do PostgreSQL:
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=sua_senha_aqui
DB_DATABASE=mundo_geek
NODE_ENV=development
PORT=3000- Crie o banco de dados PostgreSQL:
CREATE DATABASE mundo_geek;- Inicie o servidor em modo desenvolvimento:
npm run devO servidor rodará em http://localhost:3000
npm run dev # Inicia servidor em modo desenvolvimento com hot-reload
npm run build # Compila TypeScript para JavaScript
npm start # Inicia servidor em produçãosrc/
├── server.ts # Ponto de entrada da aplicação
├── config/
│ └── index.ts # Configurações e variáveis de ambiente
├── database/
│ └── data-source.ts # Conexão e configuração TypeORM
├── entities/
│ ├── Categoria.ts # Entidade Categoria
│ └── Produto.ts # Entidade Produto
├── services/
│ ├── CategoriaService.ts # Lógica de negócio - Categorias
│ └── ProdutoService.ts # Lógica de negócio - Produtos
├── controllers/
│ ├── CategoriaController.ts # Manipulação de requisições - Categorias
│ └── ProdutoController.ts # Manipulação de requisições - Produtos
├── routes/
│ ├── categoriaRoutes.ts # Rotas de Categorias
│ └── produtoRoutes.ts # Rotas de Produtos
├── middlewares/
│ └── errorHandler.ts # Tratamento centralizado de erros
└── validates/
├── CategoriaValidation.ts # Schemas Zod para Categorias
└── ProdutoValidation.ts # Schemas Zod para Produtos
Representa uma categoria de produtos na loja.
{
id: string (UUID); // Identificador único
nome: string; // Nome da categoria (único, obrigatório)
descricao?: string; // Descrição opcional
dataCriacao: Date; // Data de criação (automática)
dataAtualizacao: Date; // Data da última atualização (automática)
produtos?: Produto[]; // Lista de produtos da categoria
}Representa um item disponível na loja.
{
id: string (UUID); // Identificador único
nome: string; // Nome do produto (obrigatório)
descricao?: string; // Descrição opcional
preco: number; // Preço do produto (> 0)
estoque: number; // Quantidade em estoque (>= 0)
dataCriacao: Date; // Data de criação (automática)
dataAtualizacao: Date; // Data da última atualização (automática)
categoria: Categoria; // Relacionamento com Categoria (1:N)
categoriaId: string; // Chave estrangeira para Categoria
}Categoria 1:N Produto
- Uma categoria pode ter muitos produtos
- Um produto pertence a apenas uma categoria
- Ao deletar uma categoria, seus produtos são deletados em cascata (ON DELETE CASCADE)
http://localhost:3000/api
POST /categorias
Content-Type: application/json
{
"nome": "Jogos de Tabuleiro",
"descricao": "Jogos estratégicos e educacionais"
}Resposta (201 Created):
{
"success": true,
"message": "Categoria criada com sucesso",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"nome": "Jogos de Tabuleiro",
"descricao": "Jogos estratégicos e educacionais",
"dataCriacao": "2024-02-02T10:30:00Z",
"dataAtualizacao": "2024-02-02T10:30:00Z"
}
}GET /categoriasResposta (200 OK):
{
"success": true,
"message": "Categorias encontradas",
"total": 2,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"nome": "Jogos de Tabuleiro",
"descricao": "Jogos estratégicos e educacionais",
"dataCriacao": "2024-02-02T10:30:00Z",
"dataAtualizacao": "2024-02-02T10:30:00Z",
"produtos": []
}
]
}GET /categorias/{id}Resposta (200 OK):
{
"success": true,
"message": "Categoria encontrada",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"nome": "Jogos de Tabuleiro",
"descricao": "Jogos estratégicos e educacionais",
"dataCriacao": "2024-02-02T10:30:00Z",
"dataAtualizacao": "2024-02-02T10:30:00Z",
"produtos": []
}
}PUT /categorias/{id}
Content-Type: application/json
{
"nome": "Jogos Modernos",
"descricao": "Jogos estratégicos atualizados"
}Resposta (200 OK):
{
"success": true,
"message": "Categoria atualizada com sucesso",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"nome": "Jogos Modernos",
"descricao": "Jogos estratégicos atualizados",
"dataCriacao": "2024-02-02T10:30:00Z",
"dataAtualizacao": "2024-02-02T11:00:00Z"
}
}DELETE /categorias/{id}Resposta (204 No Content): Sem corpo
POST /produtos
Content-Type: application/json
{
"nome": "Catan",
"descricao": "Jogo clássico de estratégia",
"preco": 89.90,
"estoque": 15,
"categoriaId": "550e8400-e29b-41d4-a716-446655440000"
}Resposta (201 Created):
{
"success": true,
"message": "Produto criado com sucesso",
"data": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"nome": "Catan",
"descricao": "Jogo clássico de estratégia",
"preco": 89.90,
"estoque": 15,
"dataCriacao": "2024-02-02T10:30:00Z",
"dataAtualizacao": "2024-02-02T10:30:00Z",
"categoria": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"nome": "Jogos de Tabuleiro"
},
"categoriaId": "550e8400-e29b-41d4-a716-446655440000"
}
}GET /produtosResposta (200 OK):
{
"success": true,
"message": "Produtos encontrados",
"total": 1,
"data": [
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"nome": "Catan",
"descricao": "Jogo clássico de estratégia",
"preco": 89.90,
"estoque": 15,
"dataCriacao": "2024-02-02T10:30:00Z",
"dataAtualizacao": "2024-02-02T10:30:00Z",
"categoria": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"nome": "Jogos de Tabuleiro"
},
"categoriaId": "550e8400-e29b-41d4-a716-446655440000"
}
]
}GET /produtos/{id}Resposta (200 OK): Similar ao endpoint anterior
GET /produtos/categoria/{categoriaId}Resposta (200 OK): Lista de produtos da categoria
PUT /produtos/{id}
Content-Type: application/json
{
"preco": 99.90,
"estoque": 20
}Resposta (200 OK): Dados do produto atualizado
DELETE /produtos/{id}Resposta (204 No Content): Sem corpo
// nome: obrigatório, 3-255 caracteres
// descricao: opcional, até 1000 caracteres
// nome deve ser únicoErro de Validação (400 Bad Request):
{
"success": false,
"message": "Erro de validação",
"errors": {
"nome": ["O nome da categoria deve ter no mínimo 3 caracteres"]
}
}// nome: obrigatório, 3-255 caracteres
// descricao: opcional, até 1000 caracteres
// preco: obrigatório, > 0, até 2 casas decimais
// estoque: obrigatório, >= 0, inteiro
// categoriaId: obrigatório (criação), UUID válidoA API retorna erros estruturados com mensagens claras:
{
"success": false,
"message": "Erro de validação",
"errors": { "campo": ["mensagem de erro"] }
}{
"success": false,
"message": "Categoria com ID xxx não encontrada"
}{
"success": false,
"message": "Uma categoria com este nome já existe"
}{
"success": false,
"message": "Erro interno do servidor"
}- Controllers: Manipulam requisições/respostas HTTP
- Services: Contêm a lógica de negócio
- Entities: Definem a estrutura de dados
- Routes: Mapeiam endpoints para controladores
- Validadores: Garantem integridade de dados
- Validação centralizada com Zod
- Tratamento de erros único e reutilizável
- Esquemas de validação bem organizados
- Single Responsibility: Cada classe/função tem um propósito único
- Dependency Injection: Services usam repositórios injetados
- Liskov Substitution: Padrões consistentes em toda a API
- Interface Segregation: Schemas Zod definem contatos claros
- Dependency Inversion: Services não dependem de implementações específicas
- Nomes descritivos e convenções padronizadas
- Funções pequenas e focadas
- Comentários onde necessário
- Código TypeScript com tipos explícitos
# Criar categoria
curl -X POST http://localhost:3000/api/categorias \
-H "Content-Type: application/json" \
-d '{
"nome": "Action Figures",
"descricao": "Miniaturas colecionáveis"
}'
# Listar categorias
curl http://localhost:3000/api/categorias
# Obter categoria específica
curl http://localhost:3000/api/categorias/550e8400-e29b-41d4-a716-446655440000
# Criar produto
curl -X POST http://localhost:3000/api/produtos \
-H "Content-Type: application/json" \
-d '{
"nome": "Batman Figure",
"preco": 59.90,
"estoque": 10,
"categoriaId": "550e8400-e29b-41d4-a716-446655440000"
}'- Importe a coleção fornecida em
postman-collection.json - Configure a variável
base_urlcomohttp://localhost:3000/api - Teste todos os endpoints
- Synchronize: Habilitado para desenvolvimento automático de schema
- Logging: Desabilitado em produção
- Relations: Configuradas com
eager: truepara Produtos (carrega categoria automaticamente)
- Todas as validações usam Zod
- Schemas separados para CREATE e UPDATE
- Validação de UUID para IDs
- Validação de unicidade de nome para categorias no serviço
- Cascade Delete: Deletar categoria deleta automaticamente seus produtos
- Auto-increment: IDs são UUIDs gerados automaticamente
- Timestamps:
dataCriacaoedataAtualizacaosão automáticos
-
Autenticação e Autorização
- Implementar JWT
- Adicionar roles de usuário
-
Paginação
- Adicionar parâmetros
limiteoffset - Implementar cursor-based pagination
- Adicionar parâmetros
-
Filtros e Busca
- Busca por nome
- Filtros por preço
- Filtros por estoque
-
Logging
- Implementar logger (Winston, Morgan)
- Registrar todas as operações
-
Testes
- Testes unitários com Jest
- Testes de integração
- Cobertura de 80%+
-
Deploy
- Docker e Docker Compose
- CI/CD com GitHub Actions
- Migrations com TypeORM CLI
-
Performance
- Implementar cache (Redis)
- Índices de banco de dados
- Rate limiting
Para dúvidas ou problemas, verifique:
- Configuração das variáveis de ambiente
- Conexão com PostgreSQL
- Logs da aplicação em
NODE_ENV=development
Desenvolvido para a disciplina de Programação Web - Arquitetura e Banco de Dados