2.3 KiB
endpoints/ui-proxy — /graphql/ui proxy
Purpose
endpoints/ui-proxy mounts the /graphql/ui endpoint. The Apollo
engine never embeds Apollo's landing page — UI is opt-in via a
separate package (GraphiQL, Altair, …), identical to Yoga's stance.
When no UI plugin is wired the endpoint returns 404 with a short
text body explaining the policy; when a plugin is wired the endpoint
forwards its render() output verbatim.
This module is deliberately framework-agnostic: it accepts a
@suaveplan/api-router Router and a UI plugin descriptor with a
render() method. The host wires whichever GraphiQL / Altair package
it prefers without the engine becoming aware of the choice.
Features
- 404 by default — no Apollo landing page leakage.
- Custom mime type — UI plugins that ship binary (e.g. WASM) bodies
can override the default
text/html. - Driven by
ApolloGraphqlOptions.uiEndpoint— operator can rename the path. - Returns a teardown handle reserved for future hot reload.
Usage: Basic
import { Router } from "@suaveplan/api-router";
import { mountGraphqlUiProxy } from "@suaveplan/api-graphql-apollo/endpoints";
import { parseApolloGraphqlOptions } from "@suaveplan/api-graphql-apollo/options";
const router = new Router();
mountGraphqlUiProxy({
router,
options: parseApolloGraphqlOptions(),
ui: null,
});
// GET /graphql/ui → 404
Usage: Advanced
Wire a GraphiQL-style UI plugin so the same router serves the
playground at /graphql/ui:
mountGraphqlUiProxy({
router,
options,
ui: {
render: () =>
`<!doctype html>
<html><body>
<div id="root"></div>
<script>/* GraphiQL bundle */</script>
</body></html>`,
},
});
API Reference
GraphqlUiPlugin—{ render(): string; contentType?: string }.UiProxyResponse—{ status: 200 | 404; body: string; contentType: string }.mountGraphqlUiProxy(args): () → void.
Implementation Notes
The UI plugin contract is intentionally minimal — render() returns
a string and the proxy serves it. Future evolution (CSP nonces,
per-tenant configuration) lives in the UI plugin itself, not in this
module. The 404 response body is text/plain so curl users see a
human-readable explanation rather than an empty page.