Skip to content

MarlonUTF/bolaoCopaDW3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Node.js Fastify PostgreSQL Neon DB

Node.js Fastify PostgreSQL Neon DB Swagger
License


đź“– Sobre o Projeto

O Bolão da Copa 2026 é uma API RESTful para criação e gerenciamento de bolões de palpites da Copa do Mundo FIFA 2026. O projeto foi desenvolvido como trabalho prático da disciplina de Desenvolvimento Web 3, aplicando Vertical Slice, Orientação a Objetos, Injeção de Dependência e modelagem relacional em PostgreSQL, além de documentação automática com Swagger/OpenAPI.

Um script auxiliar importa dados reais da Copa (seleções, grupos, calendário e resultados) a partir da API pública da ESPN.


📚 Sumário


🗄️ Banco de Dados

Modelado em PostgreSQL, com 8 tabelas:

Tabela Descrição
grupos Grupos da Copa do Mundo (A a L).
paises Seleções participantes, com bandeira, sigla FIFA e grupo.
jogos Partidas da competição, incluindo fase, estádio e chaveamento.
resultados Resultados oficiais dos jogos.
perfis Participantes do bolĂŁo.
boloes Bolões criados por um perfil.
participantes_bolao Tabela pivô entre perfis e bolões, com pontuação acumulada.
palpites Palpites registrados por participantes para cada jogo de um bolĂŁo.

Relacionamentos exigidos pela atividade

  • 1:1 — resultados ↔ jogos (UNIQUE em jogo_id + FK).
  • 1:N — grupos → paises; perfis → boloes (criador); paises → jogos (casa/fora).
  • N:N — participantes_bolao (tabela associativa entre perfis e boloes, com atributos extras como pontuacao_total). palpites tambĂ©m representa uma relação N:N "resolvida" entre perfis/boloes e jogos.

O arquivo database.sql, na raiz do projeto, contém todos os CREATE TABLE com PKs, FKs e constraints necessárias para recriar o banco do zero.


🏗️ Arquitetura

O backend usa Fastify, seguindo rigorosamente Vertical Slice, OOP e Injeção de Dependência.

bolaoCopaDW3/
├── database.sql
├── package.json
├── .env
├── scripts/
│   ├── importarCopa.js      # busca dados reais da Copa na API da ESPN
│   └── runImport.js         # roda a importação e encerra o processo
└── src/
    ├── server.js            # Fastify, CORS, Swagger e registro das rotas
    ├── database/
    │   └── pool.js           # única fonte de conexão com o pg
    ├── shared/
    │   ├── AppError.js       # classe de erro customizada
    │   ├── errorHandler.js   # Error Handler Global
    │   └── errorSchema.js    # schema de erro reutilizável no Swagger
    └── features/
        ├── perfis/
        │   ├── controller.js
        │   ├── service.js
        │   ├── repository.js
        │   └── route.js
        ├── paises/      (mesma estrutura)
        ├── boloes/      (mesma estrutura)
        ├── jogos/       (mesma estrutura)
        ├── resultados/  (mesma estrutura)
        └── palpites/    (mesma estrutura)

Cada feature segue exatamente as mesmas camadas, implementadas como Classes:

  • Controller — sĂł recebe req/reply, extrai dados e devolve a resposta. NĂŁo contĂ©m lĂłgica de negĂłcio.
  • Service — regras de negĂłcio e validações. Lança throw new AppError(mensagem, statusCode) quando algo Ă© inválido. Nunca importa pg nem conhece req/reply.
  • Repository — Ăşnica camada autorizada a importar pg (via Pool) e rodar SQL.
  • route.js — monta as instâncias com new e injeta as dependĂŞncias via construtor (new Service(repository), new Controller(service)). É o Ăşnico lugar onde new aparece fora do Repository.

Regras de negĂłcio implementadas

  1. Não é possível cadastrar um resultado para um jogo que já possui resultado.
  2. Não é possível excluir um jogo já encerrado.
  3. Não é possível criar, atualizar ou remover um palpite de um jogo já encerrado.
  4. Um perfil nĂŁo pode participar do mesmo bolĂŁo duas vezes.
  5. Um perfil nĂŁo pode registrar dois palpites para o mesmo jogo dentro do mesmo bolĂŁo.
  6. Um palpite sĂł pode ser criado se o perfil for participante do bolĂŁo informado.
  7. Ao cadastrar um bolĂŁo, o criador_perfil_id precisa corresponder a um perfil existente.
  8. Ao cadastrar/atualizar um resultado com vencedor_id, o time vencedor Ă© propagado automaticamente para os jogos seguintes do chaveamento (ex: um jogo de oitavas que depende do "vencedor do jogo 49").

Tratamento de erros

Toda exceção de negócio é lançada como AppError e capturada pelo Error Handler Global (src/shared/errorHandler.js), registrado via server.setErrorHandler(...). Ele também traduz erros nativos do driver pg (violação de UNIQUE, FOREIGN KEY e CHECK) para o mesmo formato de resposta, sem nenhum if/else de tratamento de erro nos Controllers:

{ "status": "error", "message": "Descrição do erro" }

⚡ Funcionalidades e Regras de Negócio

Recurso Rotas Descrição
PaĂ­ses GET /paises
GET /paises/:id
Consulta das seleções e seus grupos (JOIN com grupos).
Perfis GET /perfis
POST /perfis
PATCH /perfis/:id
DELETE /perfis/:id
CRUD completo dos participantes.
Bolões GET /boloes
GET /boloes/:id
POST /boloes
PATCH /boloes/:id
DELETE /boloes/:id
GET /boloes/:id/participantes
POST /boloes/:id/participantes
CRUD de bolões (JOIN com perfis para trazer o nome do criador) e gestão de participantes.
Jogos GET /jogos
GET /jogos/:id
POST /jogos
PATCH /jogos/:id
DELETE /jogos/:id
CRUD de partidas. GET faz LEFT JOIN com paises (times da casa/fora) e resultados, trazendo nomes e placares — não apenas IDs.
Resultados GET /resultados
GET /resultados/:id
POST /resultados
PATCH /resultados/:id
DELETE /resultados/:id
Registro de placares com propagação automática do chaveamento.
Palpites GET /palpites
GET /palpites/:id
POST /palpites
PATCH /palpites/:id
DELETE /palpites/:id
CRUD de palpites, com JOIN trazendo nome do perfil, do bolĂŁo e dos paĂ­ses do confronto.
Documentação /docs Interface interativa do Swagger/OpenAPI.

🚀 Como Executar Localmente

Pré-requisitos

  • Node.js 18 ou superior
  • Um banco PostgreSQL acessĂ­vel (local ou serviço como Neon)

1. Clone o repositĂłrio e instale as dependĂŞncias

git clone https://github.com/MarlonUTF/bolaoCopaDW3.git
cd bolaoCopaDW3
npm install

2. Configure as variáveis de ambiente

Recomendação: utilize o Neon DB para hospedar o PostgreSQL. Este foi o banco utilizado durante o desenvolvimento do projeto, sendo totalmente compatível com a configuração apresentada abaixo.

Crie um arquivo .env na raiz do projeto (use .env.example como base):

DATABASE_URL="postgresql://usuario:senha@host:5432/nome_do_banco?sslmode=require"
PORT=3333

3. Carregue as variáveis de ambiente

Importante: o projeto utiliza dotenv para carregar as variáveis durante a execução da aplicação. Entretanto, o terminal não lê o arquivo .env automaticamente. Para utilizar o psql, carregue as variáveis na sessão atual do terminal:

set -a
source .env
set +a

4. Verifique se a variável foi carregada corretamente

echo $DATABASE_URL

Se o comando retornar a URL do banco do Neon DB, as variáveis foram carregadas corretamente.

Caso não retorne nada, confira se você está na pasta correta do projeto e se o arquivo .env existe:

pwd
ls -la

Você também pode confirmar se o arquivo possui a variável:

cat .env

5. Crie as tabelas do banco

psql "$DATABASE_URL" -f database.sql

Se tudo estiver correto, o script criará automaticamente todas as tabelas no banco hospedado no Neon DB.

6. (Opcional) Importe os dados reais da Copa

npm run importar

Busca seleções, calendário e placares na API pública da ESPN e preenche grupos, paises, jogos e resultados. Pode ser executado novamente a qualquer momento para atualizar os dados — o script usa ON CONFLICT para não duplicar registros.

Como a Copa ainda não aconteceu, jogos com confronto ainda não definido (TBD vs TBD) ficam com pais_casa_id/pais_fora_id nulos até serem definidos pela ESPN.

7. Inicie o servidor

npm start

A API estará em http://localhost:3333 e a documentação Swagger em http://localhost:3333/docs.

Para desenvolvimento com recarregamento automático:

npm run dev

📡 Documentação da API

Com o servidor rodando, acesse http://localhost:3333/docs.

A documentação Swagger cobre, para cada endpoint:

  • MĂ©todo HTTP (GET, POST, PATCH, DELETE);
  • Parâmetros de rota (ex: /jogos/:id);
  • Formato do corpo (body) esperado em POST/PATCH;
  • Ao menos uma resposta de sucesso (200/201) e uma de erro (400/404) no formato padronizado do Error Handler Global.

📌 Script de Importação

scripts/importarCopa.js exporta a função importarDadosESPN(), responsável por:

  • Criar os 12 grupos (A–L) e importar as 48 seleções via API da ESPN;
  • Importar o calendário oficial de jogos (fase de grupos e mata-mata);
  • Resolver automaticamente as origens do chaveamento (ex: converter "Winner 49" no ID real do jogo 49);
  • Registrar os placares dos jogos já encerrados.

scripts/runImport.js apenas chama essa função e encerra o processo — é o que roda quando você executa npm run importar.


🙏 Créditos dos Dados

Os dados de seleções, grupos, calendário e resultados são obtidos da API pública da ESPN, com base na documentação mantida pela comunidade em pseudo-r/Public-ESPN-API (projeto independente, sem afiliação oficial com a ESPN).


📄 Licença

Este projeto está licenciado sob a Licença MIT — veja o arquivo LICENSE para mais detalhes.

Feito com âš˝ e Node.js
API Bolão da Copa 2026 — Trabalho Prático de Arquitetura de Software

About

🏆⚽🎰 API RESTful para criação e gerenciamento de bolões de palpites da Copa do Mundo FIFA 2026.

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors