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

2.9 KiB

endpoints/http — POST /graphql + GET /graphql/sdl

Purpose

endpoints/http mounts the two HTTP endpoints every GraphQL adapter must expose: POST /graphql for operation dispatch and GET /graphql/sdl for schema introspection by external tooling. The paths are driven by ApolloGraphqlOptions so operators can rename them — useful for shops that namespace internal APIs under /internal/.

The module is framework-agnostic in that it takes a Router from @suaveplan/api-router and registers handlers via the router's verb methods. Concrete router adapters (api-router-hono, api-router-in-memory) consume the same Router interface.

Features

  • Mount paths driven by ApolloGraphqlOptions.endpoint / sdlEndpoint.
  • executeQuery handler accepts a { body, headers, context } envelope — the host's request pipeline decodes the HTTP frame into this shape before dispatch.
  • sdl handler returns the merged SDL synchronously.
  • Returns a teardown function (currently no-op; reserved for hot reload).
  • Empty headers default — handlers that the host invokes without an explicit map see {} rather than undefined.

Usage: Basic

import { Router } from "@suaveplan/api-router";
import { mountGraphqlHttpEndpoints } from "@suaveplan/api-graphql-apollo/endpoints";
import { parseApolloGraphqlOptions } from "@suaveplan/api-graphql-apollo/options";

const router = new Router();
mountGraphqlHttpEndpoints({
    router,
    options: parseApolloGraphqlOptions(),
    executeQuery: async (r) => ({ data: { ok: true } }),
    sdl: () => "type Query { ok: Boolean! }",
});

Usage: Advanced

Drive the executeQuery handler through the engine instead of a stub so the router calls into Apollo Server's lifecycle on every POST:

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

const engine = createApolloGraphqlEngine();
engine.buildSchema(registry);
mountGraphqlHttpEndpoints({
    router,
    options,
    executeQuery: async ({ body, context }) => {
        const req = body as { query: string; variables?: Record<string, unknown> };
        return await engine.executeQuery(req, context as RequestContext);
    },
    sdl: () => engine.sdl() ?? "",
});

API Reference

  • GraphqlHttpHandler — (req: { body, headers, context }) → Promise<unknown>.
  • GraphqlSdlHandler — () → string.
  • MountHttpEndpointsArgs — { router, options, executeQuery, sdl }.
  • mountGraphqlHttpEndpoints(args): () → void — returns teardown.

Implementation Notes

The handler returns a free-form Record<string, unknown> because the host's transport adapter serialises the response to wire form. The SDL handler is synchronous on purpose; SDL is computed once at buildSchema time and held in memory thereafter. The teardown closure is a no-op today but exists so callers do not need to rewrite their host-wiring code when hot reload lands.