81 lines
2.9 KiB
Markdown
81 lines
2.9 KiB
Markdown
# `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
|
|
|
|
```ts
|
|
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:
|
|
|
|
```ts
|
|
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.
|