Skip to content

eriksonwilliam/graphql-blog-api

Repository files navigation

graphql-blog-api

API GraphQL em Node.js + TypeScript (GraphQL Yoga) para um blog — autores, posts e comentários — com o foco no que o GraphQL tem de melhor e no seu maior perigo: resolver relações aninhadas sem cair no problema N+1, usando DataLoader. Arquitetura hexagonal e cobertura de testes 100%.

{
  authors {
    name
    posts {           # 1 busca em lote, não 1 por autor
      title
      comments { text }  # 1 busca em lote, não 1 por post
    }
  }
}

Destaques

  • GraphQL de verdade — schema-first (SDL), queries e mutations, tipos relacionados (Author → Post → Comment) resolvidos por field resolvers.
  • N+1 resolvido com DataLoader — cada relação (posts de um autor, autor de um post, comentários de um post) é resolvida em uma busca em lote por nível, não uma por item. Um DataLoader novo por requisição (o cache não vaza entre requisições).
  • Arquitetura hexagonal — domínio (entidades + validação) → aplicação (BlogService + ports de repositório) → infraestrutura (repos em memória, camada GraphQL). O domínio não conhece o GraphQL.
  • Cobertura 100% — verificada na CI, incluindo os caminhos de erro (validação e "não encontrado"). Os resolvers são testados executando operações reais contra o servidor.
  • GraphiQL embutido — explorador interativo em /graphql (como o Swagger de uma REST).

Stack

  • Linguagem: TypeScript · Runtime: Node.js 22
  • Servidor: GraphQL Yoga · Batching: DataLoader
  • Testes/cobertura: Vitest (gate de 100% via v8)

Arquitetura

src/
├── domain/                 # entidades (Author, Post, Comment) + validação
├── application/            # BlogService (casos de uso) + ports (repositórios)
└── infrastructure/
    ├── memory/             # repositórios em memória
    └── graphql/            # schema (SDL), resolvers, DataLoaders, context

O problema N+1 (o ponto do projeto)

Ao pedir 10 autores e os posts de cada um, a implementação ingênua faz 1 query para os autores + 10 para os posts (uma por autor). Com o DataLoader, os 10 pedidos de "posts do autor X" são agrupados no mesmo tick e resolvidos numa única busca em lote — 2 idas ao repositório, não 11. É a diferença entre uma API GraphQL que escala e uma que derruba o banco.

Como rodar

npm install
npm start          # http://localhost:4000/graphql  (abra no navegador: GraphiQL)

Exemplo (a partir da carga inicial):

curl -X POST localhost:4000/graphql -H "content-type: application/json" \
  -d '{"query":"{ authors { name posts { title comments { text } } } }"}'

Mutations:

mutation {
  createAuthor(input: { name: "Grace Hopper" }) { id name }
}

Docker

docker compose up --build

Schema (resumo)

Tipo Campos
Query authors, author(id), posts, post(id)
Mutation createAuthor, createPost, addComment
Author id, name, posts
Post id, title, body, author, comments
Comment id, text

Testes e cobertura

npm test           # Vitest com gate de 100% (lines/branches/functions/statements)
npm run typecheck  # tsc --noEmit

Licença

MIT.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors