Uma base escalável e modular para o desenvolvimento de APIs backend utilizando Fastify, Prisma e PostgreSQL. Ideal para kickstart de projetos robustos que necessitam de autenticação JWT, testes automatizados e integração com ferramentas modernas (Docker, Vercel, Redis e AWS).
- Fastify Starter API Template
- Configuração para deploy na Vercel
- Configuração:
- Servidor e API com Fastify: Gerenciamento eficiente de requisições HTTP e definição de rotas.
- Banco de Dados com PostgreSQL e Prisma: Operações CRUD com Prisma Client e migrações via Prisma Migrate.
- Autenticação JWT: Segurança para endpoints protegidos.
- Sistema de Ranking: Listagem paginada, filtrada e ordenada dos jogadores.
- Endpoints de Gameplay: Caça ao monstro com lógica de progressão (XP, ouro e níveis).
- Middleware Personalizado: Autenticação e tratamento centralizado de erros.
- Testes Automatizados: Cobertura de endpoints críticos com Jest e supertest.
- Integração com Redis e AWS: Configurações para caching e serviços em nuvem.
- Deploy Pronto para Docker e Vercel: Facilita o escalonamento e a implantação em ambientes serverless.
As principais mudanças na camada de dados foram:
- ORM anterior removido (entities/migrations/repository antigos deixaram de existir).
- Prisma introduzido:
- Schema em
prisma/schema.prisma - Migrations em
prisma/migrations/* - Prisma Client singleton (serverless-safe) em
src/config/db.config.ts
- Schema em
- Camada de dados com ports/adapters (para trocar banco com impacto mínimo):
- Ports (interfaces):
src/repositories/ports/* - Adapters:
src/repositories/prisma/*(PostgreSQL) esrc/repositories/memory/*(test) - O restante do app importa apenas
src/repositories/player.repository.ts
- Ports (interfaces):
- Testes sem banco: em
NODE_ENV=test, o repositório usa o adapter in-memory.
- Fastify – Framework web de alta performance.
- Prisma – ORM/Toolkit (Client + Migrate) para TypeScript.
- PostgreSQL – Banco de dados relacional.
- JWT – Autenticação via JSON Web Tokens.
- @sinclair/typebox – Definição e validação de schemas para Fastify. Utilizado para criar definições de tipos e realizar a validação automática dos dados de entrada e saída dos endpoints.
- Jest – Framework para testes.
- Docker – Containerização.
- Vercel – Plataforma de deploy serverless.
- Redis – Armazenamento em cache e gerenciamento de sessões.
A estrutura do projeto segue uma abordagem modular, separando as responsabilidades em:
- Controllers: Lógica de processamento e respostas HTTP.
- Services: Regras de negócio e manipulação de dados.
- Data layer (ports/adapters): Acesso a dados via interfaces (ports) + implementações (adapters), hoje com Prisma.
- Routes: Definição dos endpoints e integração com os controllers.
- Schemas: Validação de entrada e saída utilizando @sinclair/typebox. Essa abordagem permite que o Fastify valide automaticamente os dados das requisições, eliminando a necessidade de validação manual dentro dos controllers.
- Plugins: Configurações personalizadas (ex.: autenticação, tratamento de erros).
- Config: Arquivos de configuração para banco de dados, AWS, Redis, etc.
- Tests: Scripts para testes automatizados, garantindo a integridade dos endpoints.
A seguir, a estrutura de pastas do projeto:
├── prisma/
├── schema.prisma
├── migrations/
├── seed.ts
└── scripts/
└── prisma.cjs
├── __tests__/
├── monster.test.ts
└── ranking.test.ts
├── src/
├── api/
│ └── index.ts
├── config/
│ ├── aws.config.ts
│ ├── db.config.ts
│ ├── index.ts
│ └── redis.config.ts
├── controllers/
│ ├── auth.controller.ts
│ ├── healthcheck.controller.ts
│ ├── monster.controller.ts
│ ├── player.controller.ts
│ └── ranking.controller.ts
├── docs/
│ ├── auth.doc.ts
│ ├── healthcheck.doc.ts
│ ├── monster.doc.ts
│ ├── player.doc.ts
│ └── ranking.doc.ts
├── entities/
│ └── Player.entity.ts
├── plugins/
│ ├── auth.ts
│ └── errorHandler.ts
├── repositories/
│ ├── player.repository.ts
│ ├── ports/
│ │ └── player.repository.port.ts
│ ├── prisma/
│ │ └── player.prisma.repository.ts
│ └── memory/
│ └── player.memory.repository.ts
├── routes/
│ ├── auth.routes.ts
│ ├── healthcheck.routes.ts
│ ├── index.ts
│ ├── monster.routes.ts
│ ├── player.routes.ts
│ └── ranking.routes.ts
├── schemas/
│ ├── auth.schema.ts
│ ├── healthcheck.schema.ts
│ ├── monster.schema.ts
│ ├── player.schema.ts
│ └── ranking.schema.ts
├── services/
│ ├── monster.service.ts
│ ├── player.service.ts
│ └── ranking.service.ts
├── types/
│ ├── fastify-jwt.d.ts
│ └── fastify.d.ts
├── local.ts
└── server.ts
├── .editorconfig
├── .prettierrc
├── debug.log
├── Dockerfile
├── errors.log
├── jest.config.js
├── package-lock.json
├── package.json
├── README.md
├── tsconfig.json
└── vercel.json-
Clone o repositório:
git clone <URL_DO_REPOSITORIO> cd fastify-starter-api-template
-
Instale as dependências:
npm install
Este template usa Husky para executar checagens automaticamente via Git hooks:
pre-commit: rodalint-staged(lint + format apenas nos arquivos staged)- O que roda no
lint-staged(ver.lintstagedrc.cjs):*.{ts,tsx,js,jsx}→eslint --fix+prettier --write*.{json,yml,yaml}→prettier --write(Markdown é ignorado no hook)
pre-push: rodanpm test- Para pular os testes no push, defina
SKIP_TESTS=1(ex.: PowerShell:$env:SKIP_TESTS=1; git push)
- Para pular os testes no push, defina
Observações:
- O Husky é instalado via
npm install(scriptprepare). Se precisar reinstalar manualmente:npm run prepare. - Para bypass pontual:
git commit --no-verify/git push --no-verify(ouHUSKY=0).
Comandos disponíveis:
npm run lint
npm run lint:fixPara formatar o projeto:
npm run format# Configurações do Servidor
PORT = 5000
NODE_ENV = development|production|homolog|test|local
# Banco de Dados - Opção 1: URLs completas (recomendado)
DATABASE_URL_WRITE = postgres://user:password@host:port/database
# opcional (read replica)
DATABASE_URL_READ = postgres://user:password@host:port/database
# Prisma CLI usa DATABASE_URL.
# Se você não setar DATABASE_URL, os scripts db:* fazem fallback automático para DATABASE_URL_WRITE.
# (opcional, mas recomendado para ferramentas externas)
DATABASE_URL = postgres://user:password@host:port/database
# Banco de Dados - Opção 2: Variáveis individuais
DB_HOST = localhost
DB_PORT = 5432
DB_USER = root
DB_PASSWORD = your_password
DB_NAME = your_database
DB_SSL = true|false
DB_MAX_CONNECTION = 10
# Redis e Cache
CACHE_PROVIDER = none|redis|upstash
REDIS_URL = redis://localhost:6379
# opcional (força TLS quando CACHE_PROVIDER=redis; se REDIS_URL começar com rediss://, TLS já é ativado)
REDIS_TLS = true|false
UPSTASH_REDIS_REST_URL =
UPSTASH_REDIS_REST_TOKEN =
# AWS Services (Opcional)
AWS_REGION =
AWS_ACCESS_KEY_ID =
AWS_SECRET_ACCESS_KEY =
# JWT & API Security
JWT_SECRET = your-super-secret-jwt-key-here-make-it-long-and-random
API_SECRET_KEY = your-api-secret-key-for-additional-security
# Rate Limiting
RATE_LIMIT_REDIS_URL = redis://localhost:6379
# Logging
LOG_LEVEL = info
APP_NAME = your_app_name
# CORS
CORS_ORIGIN = http://localhost:3000,https://yourdomain.comO carregamento/validação do .env é centralizado em src/config/env.ts (com Zod):
- Se existir um arquivo
.envna raiz, ele é carregado automaticamente. - Em seguida, as variáveis são validadas e o app falha cedo (com mensagem detalhada) se algo essencial estiver errado.
- Para validar sem subir o servidor, use:
npm run env:checkRegras importantes:
NODE_ENV=test: relaxa algumas exigências (ex.: JWT/DB) para facilitar testes.- JWT: em ambientes não-test,
JWT_SECRETé obrigatório. - Banco: em ambientes não-test, é obrigatório configurar
DATABASE_URL_WRITEou as variáveisDB_*. - CORS:
CORS_ORIGINaceita múltiplas origens separadas por vírgula (URLs completas).
O logger é configurado em src/config/logger.ts usando Pino:
- Em
development/local: saída “pretty” (viapino-pretty). - Em
production/homolog: logs estruturados (JSON). - Campos sensíveis comuns (token/password/authorization/cookies/etc.) são redigidos automaticamente.
Variáveis:
LOG_LEVEL:fatal|error|warn|info|debug|trace|silent(default:infoem prod-like,debugem dev/local)APP_NAME: nome do serviço aplicado nos logs (default:api)
O cache é opcional e você deve escolher exatamente um provider via CACHE_PROVIDER:
none(padrão): sem cache (nenhuma conexão é aberta).redis: usa Redis viaREDIS_URL(opcionalmente com TLS).upstash: usa Upstash viaUPSTASH_REDIS_REST_URL+UPSTASH_REDIS_REST_TOKEN.
Se CACHE_PROVIDER estiver ausente ou inválido, o fallback é none.
CACHE_PROVIDER:none | redis | upstash(default:none).REDIS_URL: usado quandoCACHE_PROVIDER=redis(ex.:redis://localhost:6379ourediss://...).REDIS_TLS(opcional):true|false. Quandotrue, força TLS paraCACHE_PROVIDER=redis. SeREDIS_URLcomeçar comrediss://, TLS já é ativado automaticamente.UPSTASH_REDIS_REST_URL+UPSTASH_REDIS_REST_TOKEN: usados quandoCACHE_PROVIDER=upstash.
1) Sem cache (default):
CACHE_PROVIDER=none2) Redis (local):
CACHE_PROVIDER=redis
REDIS_URL=redis://localhost:6379
# opcional (default: false)
# REDIS_TLS=true3) Redis (TLS / cloud):
CACHE_PROVIDER=redis
REDIS_URL=rediss://:password@your-host:6379
# opcional (já fica true com rediss://)
# REDIS_TLS=true4) Upstash (REST):
CACHE_PROVIDER=upstash
UPSTASH_REDIS_REST_URL=https://YOUR-DB.upstash.io
UPSTASH_REDIS_REST_TOKEN=YOUR_TOKEN- TTL: o
ttldoCacheServiceé em segundos. - Fail-safe: se
CACHE_PROVIDERestiver configurado mas as variáveis necessárias estiverem faltando/erradas, o cache é desativado e o app não quebra (loga e segue). - No-op quando desativado:
set/get/del/flushnão quebram a aplicação quandoCACHE_PROVIDER=none(ou quando o cache é desativado por falha de configuração/conexão).
O @fastify/rate-limit funciona de forma segura mesmo sem Redis:
- Se
RATE_LIMIT_REDIS_URLnão estiver configurado, o plugin usa store em memória (por processo). - Com
skipOnError: true, qualquer erro no Redis não bloqueia as requisições. - Em ambientes Vercel/serverless,
RATE_LIMIT_REDIS_URLapontando paralocalhosté ignorado (fallback para memória) para evitar travar requests.
Exemplo com Redis dedicado para rate limit:
RATE_LIMIT_REDIS_URL=rediss://:password@your-redis-host:6379npm run db:generatenpm run db:migrate:devnpm run db:migratenpm run db:seednpm run db:reset
npm run db:seednpm run db:studioPara iniciar o servidor em modo de desenvolvimento com hot-reloading:
npm run db:generate
npm run db:migrate:dev
npm run db:seed
npm run devPara construir e iniciar o projeto utilizando Vercel:
npm run build
npm run startOs testes automatizados foram desenvolvidos com Jest e supertest. Para executá-los, use:
npm testOs testes estão localizados na pasta tests/ e cobrem os endpoints de monster-hunt e ranking, garantindo o comportamento esperado.
Observação: em NODE_ENV=test, a camada de dados usa um adapter in-memory (não precisa Postgres).
A documentação interativa da API está disponível via Swagger:
Por padrão, a UI está na raiz (/).
Acesse: http://localhost:5000/ (ou a porta definida em PORT)
Nesta interface, você pode visualizar todos os endpoints, modelos de dados, parâmetros e exemplos de resposta.
O projeto inclui um Dockerfile para containerização. Para construir e rodar o container:
docker build -t fastify-starter-api-template .
docker run -p 5000:5000 fastify-starter-api-templateA configuração para deploy em Vercel está pronta no arquivo vercel.json. Basta conectar o repositório ao Vercel para que o deploy seja efetuado automaticamente.
Este projeto está licenciado sob a MIT License.