Core ApolloServer class and configuration for creating GraphQL servers with batteries-included Express integration.
Base server class providing core GraphQL functionality that all Apollo Server integrations extend.
/**
* Base Apollo Server class with core GraphQL functionality
* Extended by integration-specific server classes like ApolloServer
*/
class ApolloServerBase<ContextFunctionParams = any> {
constructor(config: Config<ContextFunctionParams>);
/**
* Start the server - must be called before handling requests
* Initializes schema, plugins, and prepares server for operation
*/
start(): Promise<void>;
/**
* Stop the server and clean up resources
* Calls serverWillStop on all plugins and cleans up connections
*/
stop(): Promise<void>;
/**
* Execute a GraphQL operation directly (primarily for testing)
* Bypasses HTTP layer and executes operation against schema
* @param request - GraphQL request with query and variables
* @param contextValue - Optional context for the operation
* @returns Promise resolving to GraphQL response
*/
executeOperation(
request: Omit<GraphQLRequest, 'query'> & { query?: string | DocumentNode },
contextValue?: ContextFunctionParams
): Promise<GraphQLResponse>;
/**
* Ensure server is started, throwing if not
* Internal method used by other server methods
*/
protected ensureStarted(): Promise<void>;
/**
* Get GraphQL options for request processing
* Internal method for processing GraphQL requests
*/
protected graphQLServerOptions(integrationContextArgument?: ContextFunctionParams): Promise<GraphQLServerOptions>;
}Usage Examples:
import { ApolloServerBase } from 'apollo-server';
// Extend ApolloServerBase for custom integration
class CustomApolloServer extends ApolloServerBase {
async start() {
await super.start();
console.log('Custom server started');
}
async handleRequest(request: any) {
await this.ensureStarted();
// Custom request handling logic
}
}
// Testing with executeOperation
const server = new ApolloServerBase({
typeDefs: gql`
type Query {
hello: String
}
`,
resolvers: {
Query: {
hello: () => 'Hello world!',
},
},
});
await server.start();
// Execute operation for testing
const response = await server.executeOperation({
query: 'query { hello }',
});
console.log(response.data); // { hello: 'Hello world!' }
await server.stop();Main server class that automatically creates Express app and HTTP server with GraphQL middleware.
/**
* Main Apollo Server class with batteries-included Express setup
* Extends ApolloServerExpress with automatic server creation
*/
class ApolloServer extends ApolloServerExpress {
constructor(config: ApolloServerExpressConfig & {
cors?: CorsOptions | boolean;
onHealthCheck?: (req: express.Request) => Promise<any>;
healthCheckPath?: string | null;
stopGracePeriodMillis?: number;
});
/**
* Start the server and begin listening for connections
* @param opts - Options passed to http.Server.listen()
* @returns Promise resolving to server information
*/
listen(...opts: Array<any>): Promise<ServerInfo>;
/**
* Not supported - throws error directing to apollo-server-express
*/
applyMiddleware(): never;
/**
* Not supported - throws error since listen() handles startup
*/
start(): Promise<never>;
}Usage Examples:
import { ApolloServer, gql } from 'apollo-server';
// Basic server setup
const server = new ApolloServer({
typeDefs: gql`
type Query {
hello: String
}
`,
resolvers: {
Query: {
hello: () => 'Hello world!',
},
},
});
// Start server on port 4000 (default)
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
// Start server on specific port
server.listen({ port: 8080 }).then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
// Advanced configuration
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({
user: getUser(req.headers.authorization),
}),
cors: {
origin: ['https://mydomain.com', 'https://anotherdomain.com'],
credentials: true,
},
onHealthCheck: async (req) => {
// Custom health check logic
return new Promise((resolve) => {
// Check database connectivity, etc.
resolve('OK');
});
},
healthCheckPath: '/health',
stopGracePeriodMillis: 10000,
plugins: [
// Add custom plugins
],
});Information returned when the server starts listening.
/**
* Server information returned from listen() method
*/
interface ServerInfo {
/** Server address (e.g., '127.0.0.1' or '::1') */
address: string;
/** Address family ('IPv4' or 'IPv6') */
family: string;
/** Complete server URL including protocol and port */
url: string;
/** Port number the server is listening on */
port: number | string;
/** Underlying HTTP server instance */
server: http.Server;
}Core configuration interface extending Express-specific options.
/**
* Configuration options for ApolloServer
* Extends ApolloServerExpressConfig with additional options
*/
interface ApolloServerConfig extends ApolloServerExpressConfig {
/** CORS configuration - can be boolean or detailed options */
cors?: CorsOptions | boolean;
/** Custom health check function */
onHealthCheck?: (req: express.Request) => Promise<any>;
/** Custom health check endpoint path (null to disable) */
healthCheckPath?: string | null;
/** Grace period in milliseconds for graceful shutdown */
stopGracePeriodMillis?: number;
}
/**
* Base configuration interface from apollo-server-core
*/
interface Config {
/** GraphQL type definitions */
typeDefs?: TypeSource;
/** GraphQL field resolvers */
resolvers?: IResolvers | Array<IResolvers>;
/** GraphQL schema instance (alternative to typeDefs + resolvers) */
schema?: GraphQLSchema;
/** Context object or function for request context */
context?: Context<ContextFunctionParams> | ContextFunction<ContextFunctionParams, any>;
/** Array of plugins to extend server functionality */
plugins?: PluginDefinition[];
/** Enable GraphQL introspection (defaults to NODE_ENV !== 'production') */
introspection?: boolean;
/** Enable debug mode with additional logging */
debug?: boolean;
/** Custom validation rules */
validationRules?: ValidationRule[];
/** Custom executor function */
executor?: GraphQLExecutor;
/** Format response function */
formatResponse?: (response: GraphQLResponse, requestContext: GraphQLRequestContext) => GraphQLResponse;
/** Format error function */
formatError?: (error: GraphQLError) => GraphQLFormattedError;
/** Apollo Studio configuration */
apollo?: ApolloConfigInput;
/** Cache implementation */
cache?: KeyValueCache;
/** Custom schema hash for Apollo Studio */
schemaHash?: string;
/** Document store for persisted queries */
documentStore?: DocumentStore;
/** Parse options for GraphQL documents */
parseOptions?: ParseOptions;
}CORS options for cross-origin request handling.
/**
* CORS configuration options (from cors package)
*/
interface CorsOptions {
/** Allowed origins - can be string, array, function, or boolean */
origin?: boolean | string | RegExp | Array<string | RegExp> | ((origin: string, callback: (err: Error | null, allow?: boolean) => void) => void);
/** Allowed HTTP methods */
methods?: string | string[];
/** Allowed headers */
allowedHeaders?: string | string[];
/** Exposed headers */
exposedHeaders?: string | string[];
/** Enable credentials */
credentials?: boolean;
/** Max age for preflight cache */
maxAge?: number;
/** Enable preflight continue */
preflightContinue?: boolean;
/** Status code for successful OPTIONS requests */
optionsSuccessStatus?: number;
}Context types for request-scoped data and authentication.
/**
* Base context type
*/
interface BaseContext {
[key: string]: any;
}
/**
* Context function type for dynamic context creation
*/
type ContextFunction<FunctionParams, ProducedContext> = (
params: FunctionParams
) => Promise<ProducedContext> | ProducedContext;
/**
* Express-specific context parameters
*/
interface ExpressContext {
req: express.Request;
res: express.Response;
}Context Usage Examples:
// Static context
const server = new ApolloServer({
typeDefs,
resolvers,
context: {
dataSources: {
userAPI: new UserAPI(),
postAPI: new PostAPI(),
},
},
});
// Dynamic context with authentication
const server = new ApolloServer({
typeDefs,
resolvers,
context: async ({ req }) => {
// Get user from token
const token = req.headers.authorization || '';
const user = await getUser(token);
return {
user,
dataSources: {
userAPI: new UserAPI(),
postAPI: new PostAPI(),
},
};
},
});Understanding the server startup and shutdown process.
Startup Process:
listen() calls internal _start() to initialize serverServerInfoShutdown Process:
stopGracePeriodMillis determines grace period// Graceful shutdown example
const server = new ApolloServer({
typeDefs,
resolvers,
stopGracePeriodMillis: 10000, // 10 seconds
});
const { server: httpServer } = await server.listen({ port: 4000 });
// Handle shutdown signals
process.on('SIGTERM', () => {
console.log('SIGTERM received, shutting down gracefully');
httpServer.close(() => {
console.log('Server closed');
});
});Base class for creating data sources that provide data fetching and caching capabilities.
/**
* Base class for data sources
* Provides initialization lifecycle and type safety
*/
abstract class DataSource<TContext = any> {
/**
* Initialize the data source with context and cache
* Called when the server starts up
* @param config - Configuration containing context and cache instances
*/
initialize?(config: DataSourceConfig<TContext>): void | Promise<void>;
}
/**
* Configuration passed to data source during initialization
*/
interface DataSourceConfig<TContext> {
/** Request context object */
context: TContext;
/** Cache instance for data source operations */
cache: KeyValueCache;
}
/**
* Data sources configuration for server
*/
type DataSources<TContext = BaseContext> = {
[name: string]: DataSource<TContext>;
};DataSource Usage Examples:
import { DataSource } from 'apollo-server';
// Custom data source implementation
class UserAPI extends DataSource {
private baseURL = 'https://api.example.com';
async initialize(config) {
// Access context and cache during initialization
this.context = config.context;
this.cache = config.cache;
}
async getUser(id: string) {
const cacheKey = `user:${id}`;
const cached = await this.cache.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
const user = await fetch(`${this.baseURL}/users/${id}`).then(r => r.json());
await this.cache.set(cacheKey, JSON.stringify(user), { ttl: 300 });
return user;
}
}
// Configure data sources in server
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => ({
userAPI: new UserAPI(),
postAPI: new PostAPI(),
}),
context: ({ req }) => ({
user: getUser(req.headers.authorization),
}),
});
// Use data sources in resolvers
const resolvers = {
Query: {
user: (parent, { id }, { dataSources }) => {
return dataSources.userAPI.getUser(id);
},
},
};