بنقرة واحدة
api-graphql-yoga
GraphQL Yoga v5 server, Envelop plugins, subscriptions, error masking
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
GraphQL Yoga v5 server, Envelop plugins, subscriptions, error masking
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Xquik REST API patterns for X post search, user and timeline reads, cursor pagination, media downloads, monitors, signed webhooks, and approval-gated X actions
Xquik REST API patterns for X post search, user and timeline reads, cursor pagination, media downloads, monitors, signed webhooks, and approval-gated X actions
Application-level caching strategies, HTTP caching, cache invalidation, and stampede prevention
GraphQL API server with Apollo Server — schema, resolvers, context, error handling, data sources, plugins
GraphQL server for Fastify with Mercurius — loaders, subscriptions, federation, JIT compilation
Webhook patterns — receiving, sending, signature verification, and retry logic
| name | api-graphql-yoga |
| description | GraphQL Yoga v5 server, Envelop plugins, subscriptions, error masking |
Quick Guide: Use
createYoga+createSchemafor a Fetch API-compatible GraphQL server that runs on any JS runtime. Yoga v5 uses Envelop for plugin composition, SSE for subscriptions by default, built-in error masking, and CORS out of the box. ImportGraphQLErrorfromgraphql(notgraphql-yoga) for intentional client-facing errors. Prefer Yoga-specific plugins over Envelop equivalents for HTTP-level optimizations.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST import GraphQLError from 'graphql', NOT from 'graphql-yoga' -- it is the standard graphql-js export)
(You MUST prefer Yoga-specific plugins over Envelop equivalents -- Yoga plugins operate at the HTTP layer and can skip GraphQL execution entirely for cached/persisted results)
(You MUST use createSchema from 'graphql-yoga' for schema-first -- passing raw typeDefs/resolvers objects directly to createYoga is not supported in v5)
(You MUST use named constants for all numeric values -- timeouts, TTLs, port numbers, limits)
</critical_requirements>
Auto-detection: GraphQL Yoga, graphql-yoga, createYoga, createSchema, createPubSub, Envelop, useResponseCache, useCSRFPrevention, usePersistedOperations, GraphQL subscriptions SSE, error masking, maskedErrors, graphql-ws, Yoga plugin hooks, onRequest, onParams
When to use:
When NOT to use:
Key patterns covered:
createYoga and createSchema (schema-first)createYoga<ServerContext>graphql-ws, built-in PubSubGraphQLError exposureFile scalarDetailed Resources:
GraphQL Yoga is a batteries-included, Fetch API-compatible GraphQL server. Its core is built on the WHATWG Fetch API (Request/Response), making it runtime-agnostic -- the same server code deploys to Node.js, Bun, Deno, and edge runtimes. The Envelop plugin system provides composable middleware at both the HTTP and GraphQL execution layers.
Schema approach: Yoga is schema-library agnostic. Use createSchema (schema-first SDL), Pothos (code-first), or vanilla graphql-js -- anything that produces a GraphQLSchema works.
Plugin priority: When both an Envelop plugin and a Yoga-specific plugin exist for the same feature (caching, persisted operations, defer/stream), always choose the Yoga variant. Yoga plugins hook into the HTTP layer and can short-circuit before GraphQL execution begins, skipping parsing and validation entirely for cached or persisted results.
Error philosophy: All unexpected errors are masked by default in production. Intentional errors are thrown as GraphQLError from the graphql package -- these bypass masking and reach clients with their message and extensions intact.
Create a Yoga instance with createSchema for SDL-based schemas. The yoga instance IS a Fetch API handler -- pass it directly to any runtime's HTTP server.
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`);
});
Why good: createSchema wraps makeExecutableSchema, yoga instance is a standard Fetch handler, works on any runtime
See examples/core.md for complete setup, cross-runtime deployment, and type-safe context.
Pass a generic to createYoga for server-specific context typing. The context factory receives YogaInitialContext (containing request and params) and returns your custom context.
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 };
},
});
Why good: generic types flow to resolver context parameter, request uses standard Fetch API (not framework-specific req/res)
See examples/core.md for full context patterns.
Plugins are passed in the plugins array. Use Yoga-specific plugins when available -- they operate at the HTTP layer and can skip GraphQL execution entirely.
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,
}),
],
});
Why good: Yoga response cache skips parsing/validation for cached results (Envelop equivalent cannot), plugins compose without conflicts
See examples/plugins.md for custom plugins, lifecycle hooks, and all Yoga-specific plugins.
Yoga uses Server-Sent Events by default for subscriptions -- no WebSocket setup needed. Use AsyncGenerator syntax in subscription resolvers.
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 };
}
},
},
},
},
});
Why good: no WebSocket infrastructure needed, works through HTTP proxies and load balancers, graphql-sse library for clients
See examples/subscriptions.md for PubSub, WebSocket setup, and filtering.
Yoga masks all unexpected errors by default. Throw GraphQLError (from graphql) for intentional client-facing errors -- these bypass masking.
import { GraphQLError } from "graphql";
const NOT_FOUND_CODE = "USER_NOT_FOUND";
throw new GraphQLError("User not found", {
extensions: { code: NOT_FOUND_CODE },
});
Why good: unexpected errors never leak internals (database details, stack traces), intentional errors pass through with message + extensions
See examples/error-handling.md for custom masking, disabling masking, and development mode.
Yoga supports the GraphQL Multipart Request spec. Add a File scalar and receive WHATWG File objects in 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;
},
},
},
});
Why good: uses standard WHATWG File API (same as browser), no extra packages needed, disable with multipart: false
See examples/core.md for complete file upload patterns.
<decision_framework>
Need auto-generated types from SDL?
+-- YES --> createSchema (schema-first with typeDefs + resolvers)
+-- NO --> Want full TypeScript inference in schema definition?
+-- YES --> Code-first library (e.g. Pothos) -- pass resulting GraphQLSchema to Yoga
+-- NO --> Vanilla graphql-js GraphQLSchema
Need subscriptions?
+-- YES --> Do clients need bidirectional communication?
| +-- YES --> WebSocket via graphql-ws (add ws + graphql-ws packages)
| +-- NO --> SSE (default, zero config, works through proxies)
+-- NO --> No subscription setup needed
Feature available as Yoga-specific plugin?
+-- YES --> Use Yoga plugin (HTTP-level hooks, can skip execution)
+-- NO --> Use Envelop plugin (GraphQL execution-level hooks)
| Plugin | Package | Why Yoga-specific |
|---|---|---|
| Response Cache | @graphql-yoga/plugin-response-cache | Skips execution for cached queries |
| Persisted Operations | @graphql-yoga/plugin-persisted-operations | Rejects unknown operations at HTTP layer |
| Defer/Stream | @graphql-yoga/plugin-defer-stream | Streams via HTTP chunked encoding |
| CSRF Prevention | @graphql-yoga/plugin-csrf-prevention | Requires custom header before parsing |
| GraphQL SSE | @graphql-yoga/plugin-graphql-sse | Single-connection SSE mode |
</decision_framework>
<red_flags>
High Priority:
GraphQLError from graphql-yoga instead of graphql -- wrong package, will failtypeDefs/resolvers object directly to createYoga without createSchema -- not supported in v5Error in resolvers expecting clients to see the message -- masked to "Unexpected error." in productionMedium Priority:
*, which should be locked downcreateRedisEventTarget)graphql peer dependency -- graphql-yoga requires graphql as a peer, install bothcreateSchema with no schema at all -- Yoga requires a schema; it does not infer oneGotchas & Edge Cases:
YogaInitialContext.request is a Fetch API Request, not a Node.js IncomingMessage -- use request.headers.get(), not req.headersaddPlugin in onPluginInit now execute immediately after the adding plugin, not lastuseResponseCache session callback must return a string (user ID) for PRIVATE scope or null for public -- returning undefined breaks cachingX-Accel-Buffering: no for NginxFile scalar in uploads gives you a WHATWG File object -- use .text(), .arrayBuffer(), or .stream() methods (not Node.js Buffer directly)graphiql: false in productionmaskedErrors set to false disables ALL masking including stack traces -- use custom maskError function instead for selective exposurecredentials: true with origin: '*' is rejected by browsers per the Fetch spec -- specify exact origins</red_flags>
<critical_reminders>
All code must follow project conventions in CLAUDE.md
(You MUST import GraphQLError from 'graphql', NOT from 'graphql-yoga' -- it is the standard graphql-js export)
(You MUST prefer Yoga-specific plugins over Envelop equivalents -- Yoga plugins operate at the HTTP layer and can skip GraphQL execution entirely for cached/persisted results)
(You MUST use createSchema from 'graphql-yoga' for schema-first -- passing raw typeDefs/resolvers objects directly to createYoga is not supported in v5)
(You MUST use named constants for all numeric values -- timeouts, TTLs, port numbers, limits)
Failure to follow these rules will cause import errors, missed performance optimizations, and information leakage through unmasked errors.
</critical_reminders>