or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

error-handling.mdhttp-integration.mdindex.mdplugins.mdserver-lifecycle.mdtypes.md
tile.json

plugins.mddocs/

Plugin System

Comprehensive plugin architecture for extending Apollo Server functionality with built-in plugins for caching, tracing, analytics, federation, and custom integrations.

Capabilities

Plugin Interface

Core plugin interface defining lifecycle hooks for server and request-level customization.

/**
 * Main plugin interface for extending Apollo Server
 * @template TContext - The GraphQL context type
 */
interface ApolloServerPlugin<TContext extends BaseContext> {
  /**
   * Called when the server starts up
   * @param service - Server context with logger, cache, schema, etc.
   * @returns Optional server listener for additional hooks
   */
  serverWillStart?(service: GraphQLServerContext): Promise<GraphQLServerListener | void>;

  /**
   * Called for each GraphQL request
   * @param requestContext - Request context with query, variables, etc.
   * @returns Optional request listener for request lifecycle hooks
   */
  requestDidStart?(requestContext: GraphQLRequestContext<TContext>): Promise<GraphQLRequestListener<TContext> | void>;

  /**
   * Called when an unexpected error occurs during request processing
   * @param requestContext - Request context when error occurred
   * @param error - The unexpected error
   */
  unexpectedErrorProcessingRequest?(requestContext: GraphQLRequestContext<TContext>, error: Error): Promise<void>;
}

/**
 * Server-level context available to plugins
 */
interface GraphQLServerContext {
  /** Logger instance */
  logger: Logger;
  /** Cache instance */
  cache: KeyValueCache<string>;
  /** GraphQL schema */
  schema: GraphQLSchema;
  /** Apollo configuration */
  apollo: ApolloConfig;
  /** Whether server started in background */
  startedInBackground: boolean;
}

/**
 * Server lifecycle listener
 */
interface GraphQLServerListener {
  /** Called when schema loads or updates */
  schemaDidLoadOrUpdate?(schemaContext: GraphQLSchemaContext): Promise<void>;
  /** Called to drain server connections */
  drainServer?(): Promise<void>;
  /** Called when server will stop */
  serverWillStop?(): Promise<void>;
  /** Called to render landing page */
  renderLandingPage?(): Promise<LandingPage>;
}

Cache Control Plugin

GraphQL cache control implementation with HTTP header generation.

/**
 * Enables GraphQL cache control via @cacheControl directive
 * @param options - Cache control configuration
 * @returns Apollo Server plugin
 */
function ApolloServerPluginCacheControl(
  options?: ApolloServerPluginCacheControlOptions
): ApolloServerPlugin;

/**
 * Cache control plugin options
 */
interface ApolloServerPluginCacheControlOptions {
  /** Default max age for fields in seconds (default: 0) */
  defaultMaxAge?: number;
  /** Whether to calculate and set HTTP Cache-Control headers */
  calculateHttpHeaders?: boolean | 'if-cacheable';
  /** Testing-only cache hints override */
  __testing__cacheHints?: Map<string, CacheHint>;
}

/**
 * Cache annotation interface
 */
interface CacheAnnotation extends CacheHint {
  /** Whether to inherit max age from parent field */
  inheritMaxAge?: true;
}

Usage Reporting Plugin

Comprehensive analytics plugin for reporting operation metrics and traces to Apollo Studio.

/**
 * Reports operation metrics and traces to Apollo Studio
 * @param options - Usage reporting configuration
 * @returns Apollo Server plugin
 */
function ApolloServerPluginUsageReporting<TContext>(
  options?: ApolloServerPluginUsageReportingOptions<TContext>
): ApolloServerPlugin<TContext>;

/**
 * Usage reporting plugin options
 */
interface ApolloServerPluginUsageReportingOptions<TContext> {
  /** Include individual execution traces (default: true) */
  sendTraces?: boolean;
  /** Variable value reporting policy */
  sendVariableValues?: VariableValueOptions;
  /** Header reporting policy */
  sendHeaders?: SendValuesBaseOptions;
  /** Error reporting policy */
  sendErrors?: SendErrorsOptions;
  /** Include parse/validation failures */
  sendUnexecutableOperationDocuments?: boolean;
  
  /** Field-level execution tracking configuration */
  fieldLevelInstrumentation?: number | ((request: GraphQLRequestContext<TContext>) => number);
  /** Request filtering predicate */
  includeRequest?: (requestContext: GraphQLRequestContext<TContext>) => Promise<boolean>;
  /** Client information extraction function */
  generateClientInfo?: GenerateClientInfo<TContext>;
  
  /** Send reports immediately after each request */
  sendReportsImmediately?: boolean;
  /** Batch reporting interval in milliseconds */
  reportIntervalMs?: number;
  /** Size threshold for sending reports (default: 4MB) */
  maxUncompressedReportSize?: number;
  /** Custom Apollo Studio endpoint URL */
  endpointUrl?: string;
  /** Custom fetch implementation */
  fetcher?: Fetcher;
  /** Logger for plugin messages */
  logger?: Logger;
}

/**
 * Client information interface
 */
interface ClientInfo {
  /** Client name */
  clientName?: string;
  /** Client version */
  clientVersion?: string;
}

/**
 * Generate client info function type
 */
type GenerateClientInfo<TContext> = (
  requestContext: GraphQLRequestContext<TContext>
) => ClientInfo;

Landing Page Plugins

Customizable GraphQL landing pages with Apollo Studio integration.

/**
 * Local development landing page with embedded Sandbox
 * @param options - Local landing page configuration
 * @returns Apollo Server plugin
 */
function ApolloServerPluginLandingPageLocalDefault(
  options?: ApolloServerPluginLandingPageLocalDefaultOptions
): ApolloServerPlugin;

/**
 * Production landing page with embedded Explorer
 * @param options - Production landing page configuration
 * @returns Apollo Server plugin
 */
function ApolloServerPluginLandingPageProductionDefault(
  options?: ApolloServerPluginLandingPageProductionDefaultOptions
): ApolloServerPlugin;

/**
 * Local landing page options
 */
interface ApolloServerPluginLandingPageLocalDefaultOptions {
  /** Embed Apollo Studio Sandbox */
  embed?: true | EmbeddableSandboxOptions;
  /** Landing page version */
  version?: string;
  /** Show/hide Apollo footer */
  footer?: boolean;
  /** Include cookies in Sandbox requests */
  includeCookies?: boolean;
  /** Initial document to display */
  document?: string;
  /** Initial variables to display */
  variables?: Record<string, any>;
  /** Initial headers to display */
  headers?: Record<string, string>;
}

/**
 * Production landing page options
 */
interface ApolloServerPluginLandingPageProductionDefaultOptions 
  extends ApolloServerPluginLandingPageLocalDefaultOptions {
  /** Apollo Studio graph reference (required for embedded mode) */
  graphRef?: string;
}

/** Default embedded Explorer version */
const DEFAULT_EMBEDDED_EXPLORER_VERSION = 'v3';
/** Default embedded Sandbox version */
const DEFAULT_EMBEDDED_SANDBOX_VERSION = 'v2';
/** Default Apollo Server landing page version */
const DEFAULT_APOLLO_SERVER_LANDING_PAGE_VERSION = '_latest';

Federation and Tracing Plugins

Plugins for Apollo Federation and distributed tracing.

/**
 * Generates federation traces for subgraphs
 * @param options - Inline trace configuration
 * @returns Apollo Server plugin
 */
function ApolloServerPluginInlineTrace(
  options?: ApolloServerPluginInlineTraceOptions
): ApolloServerPlugin;

/**
 * Inline trace plugin options
 */
interface ApolloServerPluginInlineTraceOptions {
  /** How to handle errors in traces */
  includeErrors?: SendErrorsOptions;
  /** Internal option for conditional activation */
  __onlyIfSchemaIsSubgraph?: boolean;
}

/**
 * Reports schema changes to Apollo Studio
 * @param options - Schema reporting configuration
 * @returns Apollo Server plugin
 */
function ApolloServerPluginSchemaReporting(
  options?: ApolloServerPluginSchemaReportingOptions
): ApolloServerPlugin;

/**
 * Schema reporting plugin options
 */
interface ApolloServerPluginSchemaReportingOptions {
  /** Maximum initial delay for reporting in milliseconds */
  initialDelayMaxMs?: number;
  /** Override schema SDL to report */
  overrideReportedSchema?: string;
  /** Custom reporting endpoint URL */
  endpointUrl?: string;
  /** Custom fetch implementation */
  fetcher?: Fetcher;
}

Infrastructure Plugins

Plugins for server infrastructure and lifecycle management.

/**
 * Gracefully drains HTTP server connections on shutdown
 * @param options - Drain HTTP server configuration
 * @returns Apollo Server plugin
 */
function ApolloServerPluginDrainHttpServer(
  options: ApolloServerPluginDrainHttpServerOptions
): ApolloServerPlugin;

/**
 * Drain HTTP server plugin options
 */
interface ApolloServerPluginDrainHttpServerOptions {
  /** HTTP server instance to drain */
  httpServer: http.Server;
  /** Grace period before force close in milliseconds */
  stopGracePeriodMillis?: number;
}

/**
 * Implements callback-based subscriptions for Apollo Router
 * @param options - Subscription callback configuration
 * @returns Apollo Server plugin
 */
function ApolloServerPluginSubscriptionCallback(
  options?: ApolloServerPluginSubscriptionCallbackOptions
): ApolloServerPlugin;

/**
 * Subscription callback plugin options
 */
interface ApolloServerPluginSubscriptionCallbackOptions {
  /** Maximum consecutive heartbeat failures before termination */
  maxConsecutiveHeartbeatFailures?: number;
  /** Logger for plugin messages */
  logger?: Logger;
  /** Retry configuration for requests */
  retry?: retry.Options;
  /** Custom fetch implementation */
  fetcher?: Fetcher;
}

Utility Plugins

Plugins for disabling features and modifying behavior.

/**
 * Removes GraphQL validation error suggestions
 * @returns Apollo Server plugin
 */
function ApolloServerPluginDisableSuggestions(): ApolloServerPlugin;

/**
 * Disables built-in cache control plugin
 * @returns Apollo Server plugin
 */
function ApolloServerPluginCacheControlDisabled(): ApolloServerPlugin<BaseContext>;

/**
 * Disables built-in inline trace plugin
 * @returns Apollo Server plugin
 */
function ApolloServerPluginInlineTraceDisabled(): ApolloServerPlugin<BaseContext>;

/**
 * Disables built-in landing page plugin
 * @returns Apollo Server plugin
 */
function ApolloServerPluginLandingPageDisabled(): ApolloServerPlugin<BaseContext>;

/**
 * Disables built-in schema reporting plugin
 * @returns Apollo Server plugin
 */
function ApolloServerPluginSchemaReportingDisabled(): ApolloServerPlugin<BaseContext>;

/**
 * Disables built-in usage reporting plugin
 * @returns Apollo Server plugin
 */
function ApolloServerPluginUsageReportingDisabled(): ApolloServerPlugin<BaseContext>;

Usage Examples

Basic Plugin Usage

import { ApolloServer } from "@apollo/server";
import { 
  ApolloServerPluginCacheControl,
  ApolloServerPluginLandingPageLocalDefault 
} from "@apollo/server/plugin/cacheControl";
import { ApolloServerPluginLandingPageLocalDefault } from "@apollo/server/plugin/landingPage/default";

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    // Enable cache control with custom settings
    ApolloServerPluginCacheControl({
      defaultMaxAge: 300, // 5 minutes
      calculateHttpHeaders: 'if-cacheable',
    }),
    
    // Custom landing page
    ApolloServerPluginLandingPageLocalDefault({
      embed: {
        initialState: {
          document: `query GetBooks { books { title author } }`,
          variables: {},
          headers: { authorization: 'Bearer token' },
        },
      },
    }),
  ],
});

Custom Plugin Development

import type { ApolloServerPlugin, GraphQLRequestListener } from "@apollo/server";

// Simple logging plugin
const loggingPlugin: ApolloServerPlugin = {
  requestDidStart() {
    return Promise.resolve({
      didResolveOperation(requestContext) {
        console.log(`Operation: ${requestContext.operationName || 'Anonymous'}`);
        return Promise.resolve();
      },
      
      didEncounterErrors(requestContext) {
        console.error('GraphQL errors:', requestContext.errors);
        return Promise.resolve();
      },
      
      willSendResponse(requestContext) {
        console.log('Response sent');
        return Promise.resolve();
      },
    } as GraphQLRequestListener);
  },
};

// Authentication plugin
interface AuthContext {
  user?: User;
}

const authPlugin: ApolloServerPlugin<AuthContext> = {
  requestDidStart() {
    return Promise.resolve({
      didResolveOperation(requestContext) {
        const { user } = requestContext.contextValue;
        if (!user && requiresAuth(requestContext.operationName)) {
          throw new Error('Authentication required');
        }
        return Promise.resolve();
      },
    });
  },
};

const server = new ApolloServer<AuthContext>({
  typeDefs,
  resolvers,
  plugins: [loggingPlugin, authPlugin],
});

Production Usage Reporting

import { ApolloServerPluginUsageReporting } from "@apollo/server/plugin/usageReporting";

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    ApolloServerPluginUsageReporting({
      // Send detailed traces for better insights
      sendTraces: true,
      
      // Include variable values (excluding sensitive ones)
      sendVariableValues: {
        transform: ({ variables, operationString }) => {
          // Remove sensitive variables
          const sanitized = { ...variables };
          delete sanitized.password;
          delete sanitized.token;
          return sanitized;
        },
      },
      
      // Include relevant headers
      sendHeaders: {
        onlyNames: ['user-agent', 'referer'],
      },
      
      // Extract client information
      generateClientInfo: ({ request }) => ({
        clientName: request.http?.headers.get('x-client-name'),
        clientVersion: request.http?.headers.get('x-client-version'),
      }),
      
      // Filter out health checks
      includeRequest: async (requestContext) => {
        return requestContext.operationName !== 'HealthCheck';
      },
    }),
  ],
});

HTTP Server Integration

import http from 'http';
import { ApolloServer } from "@apollo/server";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";

// Create HTTP server
const httpServer = http.createServer();

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    // Enable graceful shutdown
    ApolloServerPluginDrainHttpServer({ 
      httpServer,
      stopGracePeriodMillis: 5000, // 5 second grace period
    }),
  ],
});

await server.start();

// Set up GraphQL endpoint
httpServer.on('request', async (req, res) => {
  // Handle GraphQL requests...
});

// Graceful shutdown
process.on('SIGTERM', async () => {
  console.log('SIGTERM received, shutting down gracefully');
  httpServer.close(() => {
    console.log('HTTP server closed');
  });
  await server.stop();
});

httpServer.listen(4000);