52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import type { Router } from "@suaveplan/api-router";
|
|
import type { ApolloGraphqlOptions } from "../options/options.js";
|
|
|
|
/**
|
|
* UI plugin descriptor. The host wires a separate UI package (GraphiQL,
|
|
* Altair, …) and hands a renderer in; the Apollo engine itself never
|
|
* embeds Apollo's landing page (UI is opt-in — same stance as Yoga).
|
|
*/
|
|
export interface GraphqlUiPlugin {
|
|
/** Returns the HTML body served at `/graphql/ui`. */
|
|
render(): string;
|
|
/** MIME type — defaults to `text/html` when omitted. */
|
|
readonly contentType?: string;
|
|
}
|
|
|
|
/** Response envelope returned by the UI proxy handler. */
|
|
export interface UiProxyResponse {
|
|
readonly status: 200 | 404;
|
|
readonly body: string;
|
|
readonly contentType: string;
|
|
}
|
|
|
|
/**
|
|
* Mount the `/graphql/ui` proxy endpoint. When `ui` is `null` the
|
|
* handler responds `404` with a short note explaining the UI is opt-in;
|
|
* when supplied it returns the plugin's rendered HTML.
|
|
*/
|
|
export function mountGraphqlUiProxy(args: {
|
|
readonly router: Router;
|
|
readonly options: ApolloGraphqlOptions;
|
|
readonly ui: GraphqlUiPlugin | null;
|
|
}): () => void {
|
|
const { router, options, ui } = args;
|
|
router.get(options.uiEndpoint, (): UiProxyResponse => {
|
|
if (ui === null) {
|
|
return {
|
|
status: 404,
|
|
body: "GraphQL UI is opt-in — wire a UI plugin to enable",
|
|
contentType: "text/plain",
|
|
};
|
|
}
|
|
return {
|
|
status: 200,
|
|
body: ui.render(),
|
|
contentType: ui.contentType ?? "text/html",
|
|
};
|
|
});
|
|
return () => {
|
|
/* hot-reload teardown reserved */
|
|
};
|
|
}
|