Skip to content

GabrielOliveiraDeveloper/API-Supplement-Store

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

26 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ’Š API da Loja de Suplementos

Uma API RESTful para uma loja online de suplementos, construΓ­da com Node.js, TypeScript e Express. Possui autenticaΓ§Γ£o de usuΓ‘rios, gerenciamento de produtos, processamento de pagamentos via Pix com Woovi, hospedagem de imagens via ImgBB, cache com Redis e observabilidade completa com logs estruturados e mΓ©tricas Prometheus.


πŸ“‹ SumΓ‘rio


VisΓ£o Geral

A API da Loja de Suplementos permite que clientes naveguem e comprem suplementos via pagamentos Pix, enquanto administradores gerenciam o catΓ‘logo de produtos. O status do pagamento Γ© atualizado automaticamente via webhooks da Woovi. O sistema utiliza Redis para cachear respostas paginadas de produtos e pedidos, reduzindo a carga no banco de dados.


Arquitetura

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Cliente                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚ HTTP
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Servidor Express                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ Rate Limiter β”‚  β”‚  Helmet   β”‚  β”‚  logs pino-http   β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                     Rotas                         β”‚  β”‚
β”‚  β”‚  /api/auth   /api/supplements   /api/payment      β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                     β”‚                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚               Middlewares                         β”‚  β”‚
β”‚  β”‚   AuthMiddleware Β· RoleMiddleware Β· Validate(Zod) β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                     β”‚                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                  Controllers                      β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                     β”‚                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                  Services                         β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚         β”‚                        β”‚                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”               β”‚
β”‚  β”‚   MongoDB   β”‚         β”‚  Redis Cache β”‚               β”‚
β”‚  β”‚  (Mongoose) β”‚         β”‚  (Upstash)   β”‚               β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                        β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  ImgBB (imagens)β”‚      β”‚  Woovi (Pix)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Fluxo de RequisiΓ§Γ£o

  1. A requisiΓ§Γ£o passa pelo rate limiter global e pelos middlewares de seguranΓ§a (Helmet, CORS)
  2. Middlewares especΓ­ficos de rota sΓ£o aplicados: autenticaΓ§Γ£o JWT, verificaΓ§Γ£o de papel (role) e validaΓ§Γ£o com Zod
  3. O controller delega ao serviΓ§o correspondente
  4. Os serviΓ§os interagem com MongoDB, cache Redis e APIs externas (ImgBB, Woovi)
  5. Erros sobem atΓ© o handler global de erros, que responde com JSON estruturado usando AppError

EstratΓ©gia de Cache

  • Respostas de GET /supplements sΓ£o cacheadas por 60 segundos com a chave supplements:{page}:{limit}
  • Respostas de GET /order/* sΓ£o cacheadas por 30 segundos com as chaves orders:user:{id}:{page}:{limit} e orders:admin:{page}:{limit}
  • O cache Γ© invalidado em operaΓ§Γ΅es de escrita (criar/deletar/atualizar suplemento, novo pedido de pagamento)

Fluxo de Pagamento

POST /api/payment
       β”‚
       β–Ό
  Busca suplementos e calcula o total
       β”‚
       β–Ό
  POST para a API da Woovi β†’ obtΓ©m QR Code + brCode
       β”‚
       β–Ό
  Salva o Pedido (isPaid: false)
       β”‚
       β–Ό
  Retorna o QR Code ao cliente
       β”‚
       β–Ό (assΓ­ncrono, via webhook)
  POST /api/payment/webhook (Woovi)
       β”‚
       β–Ό
  Encontra o Pedido pelo correlationID β†’ define isPaid: true

Stack TecnolΓ³gica

Camada Tecnologia
Runtime Node.js + TypeScript
Framework Express
Banco de Dados MongoDB (Mongoose + mongoose-paginate-v2)
Cache Redis (Upstash)
AutenticaΓ§Γ£o JWT (jsonwebtoken) + bcryptjs
ValidaΓ§Γ£o Zod
Upload de Arquivos Multer + ImgBB API
Pagamentos Woovi (Open Pix)
Logging Pino + pino-pretty (dev) / pino file transport (prod)
MΓ©tricas Prometheus (prom-client)
SeguranΓ§a Helmet + CORS + express-rate-limit
Testes Jest

Estrutura do Projeto

src/
β”œβ”€β”€ controllers/
β”‚   β”œβ”€β”€ auth/
β”‚   β”‚   β”œβ”€β”€ LoginController.ts
β”‚   β”‚   └── RegisterController.ts
β”‚   β”œβ”€β”€ payments/
β”‚   β”‚   └── PaymentsController.ts
β”‚   └── supplements/
β”‚       └── SupplementsController.ts
β”‚
β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ ConvertImages.ts
β”‚   β”œβ”€β”€ CreatePaymentService.ts
β”‚   β”œβ”€β”€ CreateSupplement.ts
β”‚   β”œβ”€β”€ CreateUser.ts
β”‚   β”œβ”€β”€ DeleteSupplementService.ts
β”‚   β”œβ”€β”€ GetOrdersService.ts
β”‚   β”œβ”€β”€ GetSupplementsService.ts
β”‚   β”œβ”€β”€ UpdateSupplementService.ts
β”‚   └── ValidateUser.ts
β”‚
β”œβ”€β”€ models/
β”‚   β”œβ”€β”€ Order.ts
β”‚   β”œβ”€β”€ Supplement.ts
β”‚   └── User.ts
β”‚
β”œβ”€β”€ middlewares/
β”‚   β”œβ”€β”€ AuthMiddleware.ts
β”‚   β”œβ”€β”€ RateLimiter.ts
β”‚   β”œβ”€β”€ RoleMiddleware.ts
β”‚   └── ValidateMiddleware.ts
β”‚
β”œβ”€β”€ routes/
β”‚   β”œβ”€β”€ authRoutes.ts
β”‚   β”œβ”€β”€ paymentsRoutes.ts
β”‚   └── supplementsRoutes.ts
β”‚
β”œβ”€β”€ validators/
β”‚   β”œβ”€β”€ auth.validator.ts
β”‚   β”œβ”€β”€ payments.validator.ts
β”‚   └── supplements.validator.ts
β”‚
β”œβ”€β”€ db/
β”‚   └── connectToDB.ts
β”‚
β”œβ”€β”€ lib/
β”‚   └── cache.ts
β”‚
β”œβ”€β”€ observability/
β”‚   └── logger.ts
β”‚
β”œβ”€β”€ utils/
β”‚   └── AppError.ts
β”‚
└── server.ts

Endpoints da API

AutenticaΓ§Γ£o β€” /api

MΓ©todo Caminho Auth DescriΓ§Γ£o
POST /register β€” Registrar um novo usuΓ‘rio
POST /login β€” Fazer login e receber um token JWT

POST /register β€” Body

{
  "username": "joaosilva",
  "email": "joao@exemplo.com",
  "password": "senha123"
}

POST /login β€” Body

{
  "email": "joao@exemplo.com",
  "password": "senha123"
}

Suplementos β€” /api

MΓ©todo Caminho Auth Papel DescriΓ§Γ£o
GET /supplements β€” β€” Listar suplementos (paginado)
POST /supplements βœ… JWT admin Adicionar um novo suplemento com imagens
PATCH /supplements/:id βœ… JWT admin Atualizar um suplemento
DELETE /supplements/:id βœ… JWT admin Deletar um suplemento

GET /supplements β€” ParΓ’metros de query

?page=1&limit=10

POST /supplements β€” multipart/form-data

name        string
description string (mΓ‘x. 400 caracteres)
price       number
image       arquivo(s) (atΓ© 5)

Pagamentos β€” /api

MΓ©todo Caminho Auth Papel DescriΓ§Γ£o
POST /payment βœ… JWT customer Criar um pagamento Pix
POST /payment/webhook β€” β€” Webhook da Woovi para confirmaΓ§Γ£o de pagamento
GET /order/admin βœ… JWT admin Listar todos os pedidos (paginado)
GET /order/costumer βœ… JWT β€” Listar pedidos do usuΓ‘rio autenticado

POST /payment β€” Body

{
  "supplementsIds": ["id1", "id2"],
  "addressUser": "Rua Principal, 123"
}

Sistema

MΓ©todo Caminho DescriΓ§Γ£o
GET /health VerificaΓ§Γ£o de saΓΊde (status do DB + uptime)
GET /metrics MΓ©tricas do Prometheus

VariΓ‘veis de Ambiente

Crie um arquivo .env na raiz do projeto:

# Servidor
PORT=3000
NODE_ENV=development

# Banco de Dados
MONGODB_URI=mongodb://localhost:27017/supplements-store

# Cache
UPSTASH_REDIS_REST_URL=redis://localhost:6379

# AutenticaΓ§Γ£o
JWT_SECRET=seu_jwt_secret_aqui

# APIs Externas
IMGBB_API_KEY=sua_chave_imgbb
WOOVI_API_URL=https://api.woovi.com/api/v1/charge
WOOVI_API_KEY=sua_chave_woovi

# Logging
LOG_LEVEL=debug
VariΓ‘vel DescriΓ§Γ£o
PORT Porta em que o servidor escuta
NODE_ENV development ou production
MONGODB_URI String de conexΓ£o com o MongoDB
UPSTASH_REDIS_REST_URL URL de conexΓ£o com o Redis
JWT_SECRET Chave secreta para assinar tokens JWT
IMGBB_API_KEY Chave de API do imgbb.com
WOOVI_API_URL Endpoint de cobranΓ§a da Woovi (OpenPix)
WOOVI_API_KEY Chave de autorizaΓ§Γ£o da API da Woovi
LOG_LEVEL NΓ­vel de log do Pino (debug, info, warn, error)

Executando o Projeto

PrΓ©-requisitos

  • Node.js 18+
  • MongoDB
  • Redis

Instalar dependΓͺncias

npm install

Desenvolvimento

npm run dev

Build de produΓ§Γ£o

npm run build
npm start

Executando os Testes

Os testes utilizam Jest com mock de mΓ³dulos para todas as dependΓͺncias externas (MongoDB, Redis, axios). NΓ£o sΓ£o necessΓ‘rias conexΓ΅es reais para executar a suΓ­te de testes.

# Executar todos os testes
npm test

# Modo watch
npm run test:watch

# RelatΓ³rio de cobertura
npm run test:coverage

Cobertura de testes

Suite O que Γ© testado
ConvertImages.test.ts Upload no ImgBB, codificaΓ§Γ£o base64, tratamento de erros
CreatePayment.test.ts CΓ‘lculo de preΓ§o, chamada Γ  API da Woovi, persistΓͺncia do pedido
CreateSupplement.test.ts CriaΓ§Γ£o de suplemento, salvamento no DB, tratamento de erros
CreateUser.test.ts VerificaΓ§Γ£o de duplicatas, criaΓ§Γ£o de usuΓ‘rio, chamadas ao logger

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors