Files
skills/docs/api-stack/api/api-graphql-apollo/src/engine/apollo-engine.md
2026-05-29 08:20:56 +01:00

4.0 KiB

engine/apollo-engine — ApolloGraphqlEngine

(no submodules)

Purpose

ApolloGraphqlEngine is the concrete Apollo Server implementation of the @suaveplan/api-graphql engine contract. It owns the Apollo Server instance, the merged executable schema, the persisted-query manifest plumbing, the request-time depth and complexity guards, and the OTel instrument emission. The factory createApolloGraphqlEngine hands out fresh instances; the class is new-able for tests and power users that want subclass overrides.

Every operation pivots on three lifecycle calls: buildSchema once at boot (or on hot reload), executeQuery per request, dispose at shutdown. Schema rebuild gracefully tears down the prior Apollo instance only when its startup has completed — a half-started server is left alone, which is safe because the new server replaces the slot.

Features

  • Implements every GraphqlEngine method — buildSchema, executeQuery, executeSubscription, dispose.
  • Pluggable instruments, persistedQueries, apolloPlugins dependencies — sane defaults, full override.
  • Depth + complexity guards run BEFORE Apollo sees the document so the engine rejects pathological queries cheaply.
  • requestTimeoutMs enforced via a race against a setTimeout- driven rejection — the timer is unref'd so it never holds the event loop open.
  • attachResolvers resolves SDL-declared fields against the registry's resolver maps; unknown types and unknown fields are silently skipped so plugin authors can register superset maps without runtime breakage.
  • Introspection denial layered above Apollo's introspection: false flag so the engine raises a typed error before Apollo even validates the document.

Usage: Basic

import { createGraphqlRegistry } from "@suaveplan/api-graphql";
import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo";

const engine = createApolloGraphqlEngine();
const registry = createGraphqlRegistry();
registry.addTypes("type Query { ping: String! }");
registry.addResolvers({ Query: { ping: () => "pong" } });
engine.buildSchema(registry);
const result = await engine.executeQuery(
    { query: "{ ping }" },
    requestContext
);
await engine.dispose();

Usage: Advanced

Wire persisted queries, custom instruments, a 5-second timeout, and a custom Apollo plugin for cache control:

import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo";
import { createInstruments } from "@suaveplan/api-graphql-apollo/instruments";
import { createPersistedQueryManifest } from "@suaveplan/api-graphql-apollo/persisted-queries";

const instruments = createInstruments();
const persistedQueries = createPersistedQueryManifest([
    ["abc123", "{ ping }"],
]);
const engine = createApolloGraphqlEngine({
    instruments,
    persistedQueries,
    apolloPlugins: [cacheControlPlugin],
    options: { requestTimeoutMs: 5000, maxQueryDepth: 12 },
});

API Reference

  • class ApolloGraphqlEngine<Caps> implements GraphqlEngine<Caps>.
    • constructor(args?: CreateApolloGraphqlEngineArgs)
    • buildSchema(registry): MergedSchema
    • executeQuery(req, ctx): Promise<GraphqlResponse>
    • executeSubscription(req, ctx): AsyncIterable<GraphqlResponse>
    • dispose(): Promise<void>
    • sdl(): string | null
  • createApolloGraphqlEngine(args?): ApolloGraphqlEngine.
  • raceWithTimeout<T>(p, ms): Promise<T> — exported for unit testing.

Implementation Notes

startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests was rejected in favour of an explicit start() Promise because the former turns a startup failure into per-request rejections we cannot discriminate cleanly. The current implementation awaits the start promise inside executeQuery and again inside dispose so a failed start never leaves the engine in a half-stopped state. The raceWithTimeout helper is exported so a focused unit test can exercise both the resolve and reject branches without standing up an Apollo Server.