3.1 KiB
factory/create-altair-ui — Altair UI plugin factory
(no submodules)
Purpose
factory/create-altair-ui is the package's public entry point.
createAltairUi(opts) validates the caller's options against the Zod
schema, builds the asset registry and OTel instruments, and returns a
RouterPlugin whose mount(router) method registers GET <uiEndpoint>
plus the hashed-asset routes against any Router instance. Endpoint
collisions are detected up-front via router.collidesWith and reject
the mount with a typed GRAPHQL_UI_ALTAIR.ENDPOINT_COLLISION error
before any route is written — partial mounts are impossible.
Features
- Zero-config call:
createAltairUi()works out of the box. - Returns a frozen
RouterPluginwithname,options,mount,renderHtml, andrenderAssetmembers. - HTML response always carries the strict CSP + ancillary security headers.
- Asset response carries
Cache-Control: public, max-age=31536000, immutable. - Asset misses (wrong hash, wrong name) throw
GraphqlUiAltairErrorwith codeASSET_MISSING. - Endpoint collisions throw
GraphqlUiAltairErrorwith codeENDPOINT_COLLISIONbefore any route is registered. - Injectable internals (
assetRegistry,instruments) for integration tests and operators wanting custom asset bundles.
Usage: Basic
import { createAltairUi } from "@suaveplan/api-graphql-ui-altair/factory";
import { Router } from "@suaveplan/api-router";
const router = new Router();
const altair = createAltairUi();
altair.mount(router);
// router.match("GET", "/graphql/ui") now resolves to the HTML handler.
Usage: Advanced
import { createAltairUi } from "@suaveplan/api-graphql-ui-altair/factory";
import { createAltairInstruments } from "@suaveplan/api-graphql-ui-altair/instruments";
import { MeterProvider } from "@opentelemetry/sdk-metrics";
import { Router } from "@suaveplan/api-router";
const meterProvider = new MeterProvider();
const instruments = createAltairInstruments({ meterProvider });
const router = new Router();
const altair = createAltairUi(
{
uiEndpoint: "/dev/altair",
graphqlEndpoint: "/api/graphql",
theme: "dark",
initialEnvironments: {
production: {
url: "https://api.example.com/graphql",
headers: { "x-tenant": "acme" },
},
},
},
{ instruments }
);
altair.mount(router);
API Reference
createAltairUi(input?: AltairUiOptionsInput, internals?: CreateAltairUiInternals): RouterPlugin.RouterPlugin—{ name, options, mount(router), renderHtml(), renderAsset(hash, name) }.CreateAltairUiInternals—{ assetRegistry?, instruments? }.
Implementation Notes
The factory composes five lower-level modules — options, assets, html,
headers, instruments — and exposes their behaviour behind one
ergonomic entry point. The RouterPlugin.options field is the parsed,
defaulted bundle (not the caller's raw input) so downstream code reads
the same value the renderer wrote. Frozen-everything posture means
operators cannot accidentally mutate the plugin between mount calls.