Communitygithub.com

Padrões GraphQL Yoga

Servidor GraphQL Yoga v5, plugins Envelop, subscriptions, mascaramento de erros

O que é Padrões GraphQL Yoga?

Este skill fornece padrões e práticas recomendadas para construir servidores GraphQL usando GraphQL Yoga v5, um servidor GraphQL compatível com a API Fetch que funciona em qualquer runtime JavaScript (Node.js, Bun, Deno, Cloudflare Workers). Ele cobre a configuração do servidor com `createYoga` e `createSchema`, o sistema de plugins Envelop (com ênfase em plugins específicos do Yoga para otimizações na camada HTTP), subscriptions usando SSE por padrão ou WebSocket, mascaramento de erros (com `GraphQLError` do pacote `graphql`), upload de arquivos e práticas de produção como CORS, prevenção de CSRF e cache de resposta. O skill é útil para desenvolvedores que precisam de um servidor GraphQL flexível, performático e pronto para produção, com suporte a subscriptions e extensibilidade via plugins. Ele inclui frameworks de decisão para escolher entre abordagens schema-first vs code-first, transporte de subscriptions SSE vs WebSocket, e seleção de plugins (Yoga-specific vs Envelop), além de bandeiras vermelhas críticas para evitar erros comuns.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/agents-inc/skills/tree/HEAD/src/skills/api-graphql-yoga

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que Padrões GraphQL Yoga faz?

Guia Rápido: Use createYoga + createSchema para um servidor GraphQL compatível com Fetch API que roda em qualquer runtime JS. Yoga v5 usa Envelop para composição de plugins, SSE para subscriptions por padrão, mascaramento de erros integrado e CORS pronto para uso. Importe GraphQLError de graphql (não de graphql-yoga) para erros intencionais visíveis ao cliente. Prefira plugins específicos do Yoga em vez de equivalentes do Envelop para otimizações na camada HTTP.


<critical_requirements>

CRÍTICO: Antes de Usar Este Skill

Todo código deve seguir as convenções do projeto em CLAUDE.md (kebab-case, exportações nomeadas, ordenação de imports, import type, constantes nomeadas)

(Você DEVE importar GraphQLError de 'graphql', NÃO de 'graphql-yoga' -- é a exportação padrão do graphql-js)

(Você DEVE preferir plugins específicos do Yoga em vez de equivalentes do Envelop -- plugins do Yoga operam na camada HTTP e podem pular a execução do GraphQL completamente para resultados em cache/persistidos)

(Você DEVE usar createSchema de 'graphql-yoga' para schema-first -- passar objetos typeDefs/resolvers diretamente para createYoga não é suportado na v5)

(Você DEVE usar constantes nomeadas para todos os valores numéricos -- timeouts, TTLs, números de porta, limites)

</critical_requirements>


Auto-detecção: GraphQL Yoga, graphql-yoga, createYoga, createSchema, createPubSub, Envelop, useResponseCache, useCSRFPrevention, usePersistedOperations, GraphQL subscriptions SSE, mascaramento de erros, maskedErrors, graphql-ws, hooks de plugins do Yoga, onRequest, onParams

Quando usar:

  • Construindo um servidor GraphQL que precisa rodar em Node.js, Bun, Deno ou Cloudflare Workers
  • APIs que exigem subscriptions via SSE (padrão) ou WebSocket
  • Estendendo a execução do GraphQL com plugins Envelop (cache, autenticação, logging)
  • Upload de arquivos usando a especificação GraphQL Multipart Request
  • APIs de produção que precisam de mascaramento de erros, CORS e proteção CSRF

Quando NÃO usar:

  • APIs somente REST sem necessidade de GraphQL
  • CRUD simples onde os manipuladores de rota integrados de um framework são suficientes
  • Quando você precisa de um gateway federado (considere uma solução de gateway dedicada)

Principais padrões abordados:

  • Configuração do servidor com createYoga e createSchema (schema-first)
  • Contexto type-safe com genéricos em createYoga<ServerContext>
  • Sistema de plugins Envelop: hooks de ciclo de vida, plugins personalizados, plugins específicos do Yoga
  • Subscriptions: SSE (padrão), WebSocket via graphql-ws, PubSub integrado
  • Mascaramento de erros e exposição intencional de GraphQLError
  • Upload de arquivos com escalar File do WHATWG
  • Fortalecimento de produção: CORS, prevenção CSRF, GraphQL Armor, logging
  • Implantação em múltiplos runtimes: Node.js, Bun, Deno, Cloudflare Workers

Recursos Detalhados:


Filosofia

GraphQL Yoga é um servidor GraphQL repleto de funcionalidades e compatível com a API Fetch. Seu núcleo é construído sobre a API Fetch do WHATWG (Request/Response), tornando-o independente de runtime -- o mesmo código do servidor implanta em Node.js, Bun, Deno e runtimes de borda. O sistema de plugins Envelop fornece middleware componível tanto na camada HTTP quanto na de execução do GraphQL.

Abordagem de schema: Yoga é agnóstico em relação à biblioteca de schema. Use createSchema (SDL schema-first), Pothos (code-first) ou graphql-js vanilla -- qualquer coisa que produza um GraphQLSchema funciona.

Prioridade de plugins: Quando existem tanto um plugin Envelop quanto um plugin específico do Yoga para a mesma funcionalidade (cache, operações persistidas, defer/stream), sempre escolha a variante do Yoga. Os plugins do Yoga se conectam à camada HTTP e podem interromper antes do início da execução do GraphQL, pulando completamente a análise e validação para resultados em cache ou persistidos.

Filosofia de erros: Todos os erros inesperados são mascarados por padrão em produção. Erros intencionais são lançados como GraphQLError do pacote graphql -- estes ignoram o mascaramento e chegam ao cliente com sua mensagem e extensões intactas.


Padrões Principais

Padrão 1: Configuração do Servidor com createYoga

Crie uma instância do Yoga com createSchema para schemas baseados em SDL. A instância do Yoga É um manipulador da API Fetch -- passe-o diretamente para o servidor HTTP de qualquer runtime.

import { createYoga, createSchema } from "graphql-yoga";
import { createServer } from "node:http";

const PORT = 4000;

const yoga = createYoga({
  schema: createSchema({
    typeDefs: /* GraphQL */ `
      type Query {
        greeting(name: String!): String!
      }
    `,
    resolvers: {
      Query: {
        greeting: (_, { name }) => `Hello, ${name}!`,
      },
    },
  }),
});

const server = createServer(yoga);
server.listen(PORT, () => {
  console.info(`Server running on http://localhost:${PORT}/graphql`);
});

Por que é bom: createSchema envolve makeExecutableSchema, a instância do yoga é um manipulador Fetch padrão, funciona em qualquer runtime

Veja examples/core.md para configuração completa, implantação em múltiplos runtimes e contexto type-safe.


Padrão 2: Contexto Type-Safe

Passe um genérico para createYoga para tipagem de contexto específica do servidor. A factory context recebe YogaInitialContext (contendo request e params) e retorna seu contexto personalizado.

import { createYoga, type YogaInitialContext } from "graphql-yoga";

interface ServerContext {
  req: IncomingMessage;
  res: ServerResponse;
}

const yoga = createYoga<ServerContext>({
  schema,
  context: async ({ request }: YogaInitialContext) => {
    const token = request.headers.get("authorization");
    return { user: token ? await verifyToken(token) : null };
  },
});

Por que é bom: tipos genéricos fluem para o parâmetro de contexto do resolver, request usa API Fetch padrão (não req/res específicos do framework)

Veja examples/core.md para padrões de contexto completos.


Padrão 3: Sistema de Plugins Envelop

Os plugins são passados no array plugins. Use plugins específicos do Yoga quando disponíveis -- eles operam na camada HTTP e podem pular completamente a execução do GraphQL.

import { createYoga } from "graphql-yoga";
import { useResponseCache } from "@graphql-yoga/plugin-response-cache";

const CACHE_TTL_MS = 2_000;

const yoga = createYoga({
  schema,
  plugins: [
    useResponseCache({
      session: () => null,
      ttl: CACHE_TTL_MS,
    }),
  ],
});

Por que é bom: O cache de resposta do Yoga pula a análise/validação para resultados em cache (o equivalente do Envelop não consegue), os plugins compõem sem conflitos

Veja examples/plugins.md para plugins personalizados, hooks de ciclo de vida e todos os plugins específicos do Yoga.


Padrão 4: Subscriptions com SSE (Padrão)

Yoga usa Server-Sent Events por padrão para subscriptions -- nenhuma configuração de WebSocket é necessária. Use sintaxe AsyncGenerator em resolvers de subscription.

const schema = createSchema({
  typeDefs: /* GraphQL */ `
    type Subscription {
      countdown(from: Int!): Int!
    }
  `,
  resolvers: {
    Subscription: {
      countdown: {
        subscribe: async function* (_, { from }) {
          for (let i = from; i >= 0; i--) {
            await new Promise((resolve) => setTimeout(resolve, 1_000));
            yield { countdown: i };
          }
        },
      },
    },
  },
});

Por que é bom: nenhuma infraestrutura de WebSocket necessária, funciona através de proxies HTTP e balanceadores de carga, biblioteca graphql-sse para clientes

Veja examples/subscriptions.md para PubSub, configuração de WebSocket e filtragem.


Padrão 5: Mascaramento de Erros e GraphQLError

Yoga mascara todos os erros inesperados por padrão. Lance GraphQLError (de graphql) para erros intencionais visíveis ao cliente -- estes ignoram o mascaramento.

import { GraphQLError } from "graphql";

const NOT_FOUND_CODE = "USER_NOT_FOUND";

throw new GraphQLError("User not found", {
  extensions: { code: NOT_FOUND_CODE },
});

Por que é bom: erros inesperados nunca vazam detalhes internos (detalhes de banco de dados, stack traces), erros intencionais passam com mensagem + extensões

Veja examples/error-handling.md para mascaramento personalizado, desativação do mascaramento e modo de desenvolvimento.


Padrão 6: Upload de Arquivos

Yoga suporta a especificação GraphQL Multipart Request. Adicione um escalar File e receba objetos File do WHATWG nos resolvers.

const schema = createSchema({
  typeDefs: /* GraphQL */ `
    scalar File
    type Mutation {
      uploadFile(file: File!): Boolean!
    }
  `,
  resolvers: {
    Mutation: {
      uploadFile: async (_, { file }: { file: File }) => {
        const content = await file.arrayBuffer();
        // Process file content
        return true;
      },
    },
  },
});

Por que é bom: usa a API File padrão do WHATWG (mesma do navegador), nenhum pacote extra necessário, desative com multipart: false

Veja examples/core.md para padrões completos de upload de arquivos.


<decision_framework>

Framework de Decisão

Abordagem de Schema

Precisa de tipos gerados automaticamente a partir do SDL?
+-- SIM --> createSchema (schema-first com typeDefs + resolvers)
+-- NÃO  --> Quer inferência completa de TypeScript na definição do schema?
    +-- SIM --> Biblioteca code-first (ex: Pothos) -- passe o GraphQLSchema resultante para o Yoga
    +-- NÃO  --> GraphQLSchema vanilla do graphql-js

Transporte de Subscription

Precisa de subscriptions?
+-- SIM --> Os clientes precisam de comunicação bidirecional?
|   +-- SIM --> WebSocket via graphql-ws (adicione pacotes ws + graphql-ws)
|   +-- NÃO  --> SSE (padrão, configuração zero, funciona através de proxies)
+-- NÃO  --> Nenhuma configuração de subscription necessária

Seleção de Plugin

Funcionalidade disponível como plugin específico do Yoga?
+-- SIM --> Use plugin do Yoga (hooks de nível HTTP, pode pular execução)
+-- NÃO  --> Use plugin Envelop (hooks de nível de execução do GraphQL)

Plugins Específicos do Yoga (Prefira em vez do Envelop)

PluginPackagePor que específico do Yoga
Cache de Resposta@graphql-yoga/plugin-response-cachePula a execução para consultas em cache
Operações Persistidas@graphql-yoga/plugin-persisted-operationsRejeita operações desconhecidas na camada HTTP
Defer/Stream@graphql-yoga/plugin-defer-streamStream via codificação chunked HTTP
Prevenção CSRF@graphql-yoga/plugin-csrf-preventionExige cabeçalho personalizado antes de analisar
GraphQL SSE@graphql-yoga/plugin-graphql-sseModo SSE de conexão única

</decision_framework>


<red_flags>

BANDEIRAS VERMELHAS

Alta Prioridade:

  • Importar GraphQLError de graphql-yoga em vez de graphql -- pacote errado, irá falhar
  • Passar objetos typeDefs/resolvers diretamente para createYoga sem createSchema -- não suportado na v5
  • Usar um plugin Envelop quando existe um equivalente específico do Yoga -- perde otimizações de nível HTTP (o cache de resposta do Yoga pula a análise completamente; o equivalente do Envelop não consegue)
  • Lançar Error simples em resolvers esperando que os clientes vejam a mensagem -- mascarado para "Erro inesperado." em produção

Média Prioridade:

  • Não configurar origens CORS para produção -- o padrão é *, que deve ser restringido
  • Usar PubSub em memória em múltiplas instâncias do servidor -- eventos não serão propagados (use createRedisEventTarget com Redis)
  • Falta da dependência graphql como peer -- graphql-yoga requer graphql como peer, instale ambos
  • Chamar createSchema sem schema algum -- Yoga requer um schema; ele não infere um

Pegadinhas e Casos de Borda:

  • YogaInitialContext.request é um Request da API Fetch, não um IncomingMessage do Node.js -- use request.headers.get(), não req.headers
  • A ordem de execução dos plugins mudou na v5 -- plugins adicionados via addPlugin em onPluginInit agora executam imediatamente após o plugin adicionador, não por último
  • O callback session do useResponseCache deve retornar uma string (ID do usuário) para escopo PRIVADO ou null para público -- retornar undefined quebra o cache
  • Subscriptions SSE passam por HTTP (text/event-stream) -- alguns proxies podem armazenar eventos em buffer; defina X-Accel-Buffering: no para Nginx
  • O escalar File em uploads fornece um objeto File do WHATWG -- use métodos .text(), .arrayBuffer() ou .stream() (não Buffer do Node.js diretamente)
  • O GraphiQL integrado do Yoga está habilitado por padrão -- desative com graphiql: false em produção
  • maskedErrors definido como false desativa TODO o mascaramento, incluindo stack traces -- use a função personalizada maskError para exposição seletiva
  • CORS credentials: true com origin: '*' é rejeitado por navegadores de acordo com a especificação Fetch -- especifique origens exatas

</red_flags>


<critical_reminders>

LEMBRETES CRÍTICOS

Todo código deve seguir as convenções do projeto em CLAUDE.md

(Você DEVE importar GraphQLError de 'graphql', NÃO de 'graphql-yoga' -- é a exportação padrão do graphql-js)

(Você DEVE preferir plugins específicos do Yoga em vez de equivalentes do Envelop -- plugins do Yoga operam na camada HTTP e podem pular a execução do GraphQL completamente para resultados em cache/persistidos)

(Você DEVE usar createSchema de 'graphql-yoga' para schema-first -- passar objetos typeDefs/resolvers diretamente para createYoga não é suportado na v5)

(Você DEVE usar constantes nomeadas para todos os valores numéricos -- timeouts, TTLs, números de porta, limites)

A falha em seguir estas regras causará erros de importação, comportamento de cache incorreto, erros de configuração e a API expondo detalhes internos do servidor.

</critical_reminders>

Individual skills in this repo

This repo contains 11 individual skills — each has its own dedicated page.

Habilidades Relacionadas