Apollo Server Core provides utilities for GraphQL schema processing, query parsing, template tag support, and GraphQL execution configuration.
Template tag for GraphQL queries providing syntax highlighting and consistency between client and server.
/**
* GraphQL template tag for creating DocumentNode from GraphQL strings
* @param template - Template strings array or string containing GraphQL
* @param substitutions - Values to substitute in template
* @returns Parsed GraphQL DocumentNode
*/
const gql: (
template: TemplateStringsArray | string,
...substitutions: any[]
) => DocumentNode;Usage Examples:
import { gql } from "apollo-server-core";
// Basic type definitions
const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
}
type Query {
users: [User!]!
user(id: ID!): User
}
`;
// With template substitution
const userFields = gql`
fragment UserFields on User {
id
name
email
}
`;
const query = gql`
query GetUsers {
users {
...UserFields
}
}
${userFields}
`;
// Multiple type definitions
const baseTypes = gql`
scalar DateTime
interface Node {
id: ID!
}
`;
const userTypes = gql`
type User implements Node {
id: ID!
name: String!
email: String!
createdAt: DateTime!
}
`;
const typeDefs = gql`
${baseTypes}
${userTypes}
type Query {
user(id: ID!): User
}
`;Functions for resolving and processing GraphQL execution options.
/**
* Resolve GraphQL execution options from configuration
* @param options - GraphQL options or function that returns options
* @param args - Arguments to pass to options function
* @returns Promise resolving to GraphQL options
*/
function resolveGraphqlOptions(
options: GraphQLOptions | ((...args: Array<any>) => ValueOrPromise<GraphQLOptions>),
...args: Array<any>
): Promise<GraphQLOptions>;
interface GraphQLOptions<TContext = Record<string, any>, TRootValue = any> {
/** GraphQL schema for execution */
schema: GraphQLSchema;
/** Schema hash (deprecated) */
schemaHash: SchemaHash;
/** Logger instance */
logger?: Logger;
/** Error formatting function */
formatError?: (error: GraphQLError) => GraphQLFormattedError;
/** Root value for execution */
rootValue?: ((parsedQuery: DocumentNode) => TRootValue) | TRootValue;
/** Context value for resolvers */
context?: TContext | (() => never);
/** Additional validation rules */
validationRules?: Array<(context: ValidationContext) => any>;
/** Custom GraphQL executor */
executor?: GraphQLExecutor;
/** Response formatting function */
formatResponse?: (
response: GraphQLResponse,
requestContext: GraphQLRequestContext<TContext>
) => GraphQLResponse | null;
/** Custom field resolver */
fieldResolver?: GraphQLFieldResolver<any, TContext>;
/** Enable debug mode */
debug?: boolean;
/** Data sources factory */
dataSources?: () => DataSources<TContext>;
/** Cache implementation */
cache?: KeyValueCache;
/** Persisted queries configuration */
persistedQueries?: PersistedQueryOptions;
/** Server plugins */
plugins?: ApolloServerPlugin[];
/** Document store for caching parsed queries */
documentStore?: DocumentStore | null;
/** Disable validation (dangerous) */
dangerouslyDisableValidation?: boolean;
/** GraphQL parsing options */
parseOptions?: ParseOptions;
/** Node environment */
nodeEnv?: string;
/** Allow batched HTTP requests */
allowBatchedHttpRequests?: boolean;
}Options Resolution Example:
import { resolveGraphqlOptions } from "apollo-server-core";
// Dynamic options based on request
const dynamicOptions = (req) => ({
schema: getSchemaForTenant(req.headers['x-tenant-id']),
context: {
user: req.user,
tenant: req.headers['x-tenant-id'],
},
debug: process.env.NODE_ENV !== 'production',
});
// Resolve options for a specific request
const options = await resolveGraphqlOptions(dynamicOptions, req);Types and interfaces for GraphQL schema processing and management.
interface DocumentStore {
/** Get cached parsed document */
get(key: string): Promise<DocumentNode | undefined>;
/** Cache parsed document */
set(key: string, value: DocumentNode, options?: { ttl?: number }): Promise<void>;
/** Delete cached document */
delete(key: string): Promise<boolean>;
}
type SchemaHash = string;
interface GraphQLSchemaModule {
/** SDL type definitions */
typeDefs: DocumentNode;
/** Resolver implementations */
resolvers?: IResolvers;
}
interface GraphQLExecutor {
(requestContext: {
request: GraphQLRequest;
schema: GraphQLSchema;
schemaHash: SchemaHash;
context: any;
cache: KeyValueCache;
logger: Logger;
}): ValueOrPromise<GraphQLExecutionResult>;
}
interface GraphQLExecutionResult {
data?: Record<string, any> | null;
errors?: readonly GraphQLError[];
extensions?: Record<string, any>;
}Core types used throughout the GraphQL request processing pipeline.
interface GraphQLRequest {
/** GraphQL query string */
query: string;
/** Operation name for multiple operations */
operationName?: string;
/** Variable values */
variables?: VariableValues;
/** Request extensions */
extensions?: Record<string, any>;
/** HTTP-specific information */
http?: Pick<Request, 'url' | 'method' | 'headers' | 'body'>;
}
interface GraphQLResponse {
/** Query execution result */
data?: Record<string, any> | null;
/** Execution errors */
errors?: readonly GraphQLFormattedError[];
/** Response extensions */
extensions?: Record<string, any>;
/** HTTP-specific response data */
http?: Pick<Response, 'body' | 'headers' | 'status'>;
}
type VariableValues = { readonly [variable: string]: unknown };
interface GraphQLRequestMetrics {
/** High-resolution start time */
startHrTime: [number, number];
/** Query planning phase metrics */
queryPlanningPhase?: ExecutionPhaseMetrics;
/** Validation phase metrics */
validationPhase?: ExecutionPhaseMetrics;
/** Execution phase metrics */
executionPhase?: ExecutionPhaseMetrics;
}
interface ExecutionPhaseMetrics {
/** Start offset from request start */
startOffset: number;
/** Phase duration in nanoseconds */
duration: number;
}Types for GraphQL validation rules and parsing configuration.
type ValidationRule = (context: ValidationContext) => any;
interface ParseOptions {
/** Maximum number of tokens to parse */
maxTokens?: number;
/** Allow legacy SDL syntax */
allowLegacySDLEmptyFields?: boolean;
/** Allow legacy SDL implements syntax */
allowLegacySDLImplementsInterfaces?: boolean;
/** Experimental features to enable */
experimentalFragmentVariables?: boolean;
}Custom Validation Example:
import { GraphQLError, ValidationContext } from 'graphql';
// Custom validation rule to limit query depth
const depthLimit = (maxDepth: number) => (context: ValidationContext) => {
let currentDepth = 0;
return {
Field: {
enter() {
currentDepth++;
if (currentDepth > maxDepth) {
context.reportError(
new GraphQLError(
`Query depth of ${currentDepth} exceeds maximum depth of ${maxDepth}`,
[context.getDocument()]
)
);
}
},
leave() {
currentDepth--;
},
},
};
};
// Use custom validation rule
const server = new ApolloServerBase({
typeDefs,
resolvers,
validationRules: [depthLimit(10)],
});Types for integrating with caching systems.
interface KeyValueCache<V = string> {
/** Get value by key */
get(key: string): Promise<V | undefined>;
/** Set value with optional TTL */
set(key: string, value: V, options?: { ttl?: number }): Promise<void>;
/** Delete value by key */
delete(key: string): Promise<boolean>;
}
interface DataSource<TContext = any> {
/** Initialize data source with cache and context */
initialize?(config: {
context: TContext;
cache: KeyValueCache;
}): void;
}Custom Data Source Example:
import { DataSource } from 'apollo-datasource';
class UserAPI extends DataSource {
constructor(private baseURL: string) {
super();
}
async getUser(id: string) {
// Use built-in caching
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;
}
}
// Use in server configuration
const server = new ApolloServerBase({
typeDefs,
resolvers,
dataSources: () => ({
userAPI: new UserAPI('https://api.example.com'),
}),
});Advanced utilities for schema introspection and management.
interface SchemaDerivedData {
/** Processed GraphQL schema */
schema: GraphQLSchema;
/** Hash of the schema for caching */
schemaHash: SchemaHash;
/** Document store for parsed operations */
documentStore: DocumentStore | null;
}
type SchemaChangeCallback = (schema: GraphQLSchema) => void;
type Unsubscriber = () => void;Schema Management Example:
// Dynamic schema loading
const server = new ApolloServerBase({
typeDefs: gql`
type Query {
_schema: String
}
`,
resolvers: {
Query: {
_schema: () => 'dynamic',
},
},
plugins: [
{
serverWillStart() {
// Subscribe to schema changes
const unsubscribe = schemaManager.onSchemaChange((newSchema) => {
console.log('Schema updated:', newSchema);
});
return {
serverWillStop() {
unsubscribe();
},
};
},
},
],
});