O que Padrões GraphQL Yoga faz?
Guia Rápido: Use
createYoga+createSchemapara 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. ImporteGraphQLErrordegraphql(não degraphql-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
createYogaecreateSchema(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
Filedo 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:
- examples/core.md - Configuração do servidor, schema, contexto, resolvers, implantação em múltiplos runtimes
- examples/plugins.md - Plugins Envelop, plugins personalizados, hooks de ciclo de vida
- examples/subscriptions.md - SSE, WebSocket, PubSub, filtragem
- examples/error-handling.md - Mascaramento de erros, GraphQLError, mascaramento personalizado
- examples/production.md - CORS, CSRF, cache de resposta, operações persistidas, logging
- reference.md - Frameworks de decisão, referência de plugins, checklist de produção
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)
| Plugin | Package | Por que específico do Yoga |
|---|---|---|
| Cache de Resposta | @graphql-yoga/plugin-response-cache | Pula a execução para consultas em cache |
| Operações Persistidas | @graphql-yoga/plugin-persisted-operations | Rejeita operações desconhecidas na camada HTTP |
| Defer/Stream | @graphql-yoga/plugin-defer-stream | Stream via codificação chunked HTTP |
| Prevenção CSRF | @graphql-yoga/plugin-csrf-prevention | Exige cabeçalho personalizado antes de analisar |
| GraphQL SSE | @graphql-yoga/plugin-graphql-sse | Modo SSE de conexão única |
</decision_framework>
<red_flags>
BANDEIRAS VERMELHAS
Alta Prioridade:
- Importar
GraphQLErrordegraphql-yogaem vez degraphql-- pacote errado, irá falhar - Passar objetos
typeDefs/resolversdiretamente paracreateYogasemcreateSchema-- 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
Errorsimples 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
createRedisEventTargetcom Redis) - Falta da dependência
graphqlcomo peer --graphql-yogarequergraphqlcomo peer, instale ambos - Chamar
createSchemasem schema algum -- Yoga requer um schema; ele não infere um
Pegadinhas e Casos de Borda:
YogaInitialContext.requesté umRequestda API Fetch, não umIncomingMessagedo Node.js -- userequest.headers.get(), nãoreq.headers- A ordem de execução dos plugins mudou na v5 -- plugins adicionados via
addPluginemonPluginInitagora executam imediatamente após o plugin adicionador, não por último - O callback
sessiondouseResponseCachedeve retornar uma string (ID do usuário) para escopo PRIVADO ounullpara público -- retornarundefinedquebra o cache - Subscriptions SSE passam por HTTP (text/event-stream) -- alguns proxies podem armazenar eventos em buffer; defina
X-Accel-Buffering: nopara Nginx - O escalar
Fileem uploads fornece um objetoFiledo WHATWG -- use métodos.text(),.arrayBuffer()ou.stream()(nãoBufferdo Node.js diretamente) - O GraphiQL integrado do Yoga está habilitado por padrão -- desative com
graphiql: falseem produção maskedErrorsdefinido comofalsedesativa TODO o mascaramento, incluindo stack traces -- use a função personalizadamaskErrorpara exposição seletiva- CORS
credentials: truecomorigin: '*'é 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>