Fully-featured GraphQL Server with focus on easy setup, performance & great developer experience
GraphQL Yoga is a comprehensive GraphQL server library built on top of Envelop, providing a fully-featured GraphQL server with focus on easy setup, performance, and great developer experience. It offers built-in support for GraphQL subscriptions using Server-Sent Events, includes GraphiQL interface, supports file uploads, automatic persisted queries, and built-in parsing/validation caching. The library is built on top of the WHATWG Fetch API making it deployable across various environments including serverless platforms, workers, Deno, Bun, Cloudflare Workers, and AWS Lambda.
npm install graphql-yogaimport { createYoga } from "graphql-yoga";For CommonJS:
const { createYoga } = require("graphql-yoga");import { createYoga, createSchema } from "graphql-yoga";
// Create GraphQL schema
const schema = createSchema({
typeDefs: `
type Query {
hello: String
}
`,
resolvers: {
Query: {
hello: () => "Hello from GraphQL Yoga!"
}
}
});
// Create Yoga server
const yoga = createYoga({
schema,
graphqlEndpoint: '/graphql',
cors: {
origin: ['http://localhost:3000'],
credentials: true
}
});
// Use with Node.js HTTP server
import { createServer } from 'node:http';
const server = createServer(yoga);
server.listen(4000, () => {
console.log('Server is running on http://localhost:4000/graphql');
});GraphQL Yoga is built around several key components:
YogaServer class that handles HTTP requests and GraphQL executionCore server factory function and configuration options for creating GraphQL Yoga servers with comprehensive customization.
function createYoga<
TServerContext extends Record<string, any> = {},
TUserContext extends Record<string, any> = {}
>(options: YogaServerOptions<TServerContext, TUserContext>): YogaServerInstance<TServerContext, TUserContext>;
interface YogaServerOptions<TServerContext, TUserContext> {
logging?: boolean | YogaLogger | LogLevel;
maskedErrors?: boolean | Partial<YogaMaskedErrorOpts>;
context?: ((initialContext: YogaInitialContext & TServerContext) => Promise<TUserContext> | TUserContext) | Promise<TUserContext> | TUserContext;
cors?: CORSOptions;
graphqlEndpoint?: string;
healthCheckEndpoint?: string;
landingPage?: boolean;
graphiql?: GraphiQLOptionsOrFactory<TServerContext>;
schema?: YogaSchemaDefinition<TServerContext, TUserContext>;
plugins?: Array<Plugin<TUserContext & TServerContext & YogaInitialContext> | Plugin | {}>;
parserAndValidationCache?: boolean | ParserAndValidationCacheOptions;
fetchAPI?: Partial<FetchAPI>;
multipart?: boolean;
batching?: BatchingOptions;
}GraphQL schema creation and integration utilities with proper context typing and flexible schema definitions.
function createSchema<TContext = {}>(
opts: IExecutableSchemaDefinition<TContext & YogaInitialContext>
): GraphQLSchemaWithContext<TContext & YogaInitialContext>;
function useSchema<TServerContext = {}, TUserContext = {}>(
schemaDef?: YogaSchemaDefinition<TServerContext, TUserContext>
): Plugin<YogaInitialContext & TServerContext>;
type YogaSchemaDefinition<TServerContext, TUserContext> =
| PromiseOrValue<GraphQLSchemaWithContext<TServerContext & YogaInitialContext & TUserContext>>
| ((context: TServerContext & { request: YogaInitialContext['request'] }) => PromiseOrValue<GraphQLSchemaWithContext<TServerContext & YogaInitialContext & TUserContext>>);Comprehensive plugin system extending Envelop with Yoga-specific hooks for request processing, result handling, and server lifecycle management.
interface Plugin<
PluginContext extends Record<string, any> = {},
TServerContext extends Record<string, any> = {},
TUserContext = {}
> extends EnvelopPlugin<YogaInitialContext & PluginContext>, ServerAdapterPlugin<TServerContext> {
onYogaInit?: OnYogaInitHook<TServerContext>;
onRequestParse?: OnRequestParseHook<TServerContext>;
onParams?: OnParamsHook;
onResultProcess?: OnResultProcess;
onExecute?: OnExecuteHook<YogaInitialContext & PluginContext & TUserContext>;
onSubscribe?: OnSubscribeHook<YogaInitialContext & PluginContext & TUserContext>;
}Ready-to-use plugins for GraphiQL interface, health checks, request parsing, result processing, and development tools.
function useGraphiQL(options: { graphqlEndpoint: string; options?: GraphiQLOptionsOrFactory; render?: (options?: GraphiQLOptions) => PromiseOrValue<BodyInit>; logger: YogaLogger }): Plugin;
function useReadinessCheck(options: ReadinessCheckPluginOptions): Plugin;
function useParserAndValidationCache(options?: ParserAndValidationCacheOptions): Plugin;
interface GraphiQLOptions {
defaultQuery?: string;
headers?: string;
credentials?: RequestCredentials;
title?: string;
subscriptionsProtocol?: 'SSE' | 'GRAPHQL_SSE' | 'WS' | 'LEGACY_WS';
additionalHeaders?: Record<string, string>;
}Comprehensive error handling system with masking, GraphQL error creation, and production-ready error processing.
function createGraphQLError(message: string, options?: { nodes?: readonly ASTNode[]; source?: Source; positions?: readonly number[]; path?: readonly (string | number)[]; originalError?: Error; extensions?: GraphQLErrorExtensions }): GraphQLError;
function maskError(error: unknown, message: string, isDev?: boolean): Error;
function handleError(error: unknown, maskedErrorsOpts: YogaMaskedErrorOpts | null, logger: YogaLogger): GraphQLError[];
interface YogaMaskedErrorOpts {
maskError: MaskError;
errorMessage: string;
isDev?: boolean;
}
type MaskError = (error: unknown, message: string, isDev?: boolean) => Error;Server-Sent Events (SSE) support for GraphQL subscriptions with streaming capabilities and real-time data delivery.
function getSSEProcessor(): ResultProcessor;
type ResultProcessor = (
result: ResultProcessorInput,
fetchAPI: FetchAPI,
acceptedMediaType: string
) => PromiseOrValue<Response>;
type ResultProcessorInput = MaybeArray<ExecutionResultWithSerializer> | AsyncIterable<ExecutionResultWithSerializer<any, { http?: GraphQLHTTPExtensions }>>;Helper functions for caching, GraphiQL rendering, and common server operations.
function createLRUCache<T extends {}>(options?: LRUCacheOptions): LRUCache<T>;
function renderGraphiQL(opts: GraphiQLRendererOptions): string;
function shouldRenderGraphiQL(request: Request): boolean;
interface LRUCacheOptions {
max?: number;
ttl?: number;
}
interface GraphiQLRendererOptions {
endpoint?: string;
defaultQuery?: string;
headers?: string;
credentials?: RequestCredentials;
title?: string;
subscriptionsProtocol?: 'SSE' | 'GRAPHQL_SSE' | 'WS' | 'LEGACY_WS';
additionalHeaders?: Record<string, string>;
}Re-exported functions and utilities from Envelop core for advanced GraphQL execution customization.
function envelop(options: { plugins: Plugin[] }): GetEnvelopedFn;
function useEnvelop(enveloped: GetEnvelopedFn): Plugin;
function useErrorHandler(handler: (error: unknown) => void): Plugin;
function useExtendContext<T>(contextFactory: (context: any) => T): Plugin;
function useLogger(logger?: YogaLogger): Plugin;
function usePayloadFormatter(formatter: (payload: any) => any): Plugin;
function makeExecute(schema: GraphQLSchema): ExecuteFn;
function makeSubscribe(schema: GraphQLSchema): SubscribeFn;
function isAsyncIterable<T>(value: any): value is AsyncIterable<T>;
function mapAsyncIterator<T, U>(iterator: AsyncIterator<T>, mapper: (value: T) => U): AsyncIterator<U>;
function handleStreamOrSingleExecutionResult(result: any): any;
function errorAsyncIterator(error: Error): AsyncIterator<never>;
function finalAsyncIterator<T>(iterator: AsyncIterator<T>): AsyncIterator<T>;
function isIntrospectionOperationString(operation: string): boolean;
type Maybe<T> = T | null | undefined;
type Optional<T> = T | undefined;
type PromiseOrValue<T> = T | Promise<T>;
type Spread<T1, T2> = T1 & T2;All re-exported from @envelop/core for advanced GraphQL execution pipeline customization.
interface YogaInitialContext {
params: GraphQLParams;
request: Request;
}
interface GraphQLParams<TVariables = Record<string, any>, TExtensions = Record<string, any>> {
operationName?: string;
query?: string;
variables?: TVariables;
extensions?: TExtensions;
}
type YogaServerInstance<
TServerContext extends Record<string, any>,
TUserContext extends Record<string, any>
> = ServerAdapter<TServerContext, YogaServer<TServerContext, TUserContext>>;
class YogaServer<
TServerContext extends Record<string, any>,
TUserContext extends Record<string, any>
> {
constructor(options?: YogaServerOptions<TServerContext, TUserContext>);
readonly getEnveloped: GetEnvelopedFn<TUserContext & TServerContext & YogaInitialContext>;
logger: YogaLogger;
readonly graphqlEndpoint: string;
fetchAPI: FetchAPI;
handle: ServerAdapterRequestHandler<TServerContext>;
}type CORSOptions = {
origin?: string[] | string;
methods?: string[];
allowedHeaders?: string[];
exposedHeaders?: string[];
credentials?: boolean;
maxAge?: number;
} | false;
type BatchingOptions = boolean | {
limit?: number;
};
interface GraphQLSchemaWithContext<TContext> extends GraphQLSchema {
_context?: TContext;
}
type FetchAPI = {
fetch: typeof fetch;
Request: typeof Request;
Response: typeof Response;
URL: typeof URL;
URLPattern: typeof URLPattern;
TextEncoder: typeof TextEncoder;
ReadableStream: typeof ReadableStream;
};type MaybeArray<T> = T | T[];
type PromiseOrValue<T> = T | Promise<T>;
interface GraphQLHTTPExtensions {
spec?: boolean;
status?: number;
headers?: Record<string, string>;
}
type LRUCache<T extends {}> = LRU<string, T>;type GetEnvelopedFn<TContext = any> = (context?: TContext) => EnvelopedFn<TContext>;
interface EnvelopedFn<TContext> {
execute: (args: ExecutionArgs) => Promise<ExecutionResult>;
subscribe: (args: ExecutionArgs) => Promise<ExecutionResult | AsyncIterable<ExecutionResult>>;
schema: GraphQLSchema;
contextFactory: (context?: TContext) => TContext;
parse: (source: string | Source) => DocumentNode;
validate: (schema: GraphQLSchema, document: DocumentNode) => readonly GraphQLError[];
}
interface IExecutableSchemaDefinition<TContext = any> {
typeDefs: string | DocumentNode | Array<string | DocumentNode>;
resolvers?: any;
logger?: any;
allowUndefinedInResolve?: boolean;
resolverValidationOptions?: any;
directiveResolvers?: any;
schemaDirectives?: any;
parseOptions?: any;
inheritResolversFromInterfaces?: boolean;
}
interface EnvelopPlugin<TContext = any> {
onPluginInit?: (context: PluginInitContext) => void;
onParse?: (context: ParseContext<TContext>) => void;
onValidate?: (context: ValidateContext<TContext>) => void;
onExecute?: (context: ExecuteContext<TContext>) => void;
onSubscribe?: (context: SubscribeContext<TContext>) => void;
}
interface ServerAdapterPlugin<TServerContext = any> {
onRequest?: (context: RequestContext<TServerContext>) => void;
onResponse?: (context: ResponseContext<TServerContext>) => void;
}
interface ServerAdapter<TServerContext, TServerInstance> {
handle: (request: Request, serverContext?: TServerContext) => Promise<Response>;
fetch: (request: Request, serverContext?: TServerContext) => Promise<Response>;
}
type ServerAdapterRequestHandler<TServerContext> = (
request: Request,
serverContext?: TServerContext
) => Promise<Response>;
interface ExecutionArgs {
schema: GraphQLSchema;
document: DocumentNode;
rootValue?: any;
contextValue?: any;
variableValues?: any;
operationName?: string;
fieldResolver?: any;
typeResolver?: any;
}tessl i tessl/npm-graphql-yoga@4.0.0