# `handler` — `createRedocUiHandler` _(no submodules)_ ## Purpose This module exposes `createRedocUiHandler`, the factory the api-host calls to obtain the HTTP handler serving the ReDoc HTML shell. The returned handler is a zero-argument function the host invokes per request. It is intentionally router-agnostic — adapters in the api-host layer translate the returned `RedocHttpResponse` into Hono / api-router envelopes — so the package can be wired into any HTTP surface without dragging a router peer dependency through every consumer. ## Features - Validates options at construction; invalid input raises `OPENAPI_UI_REDOC_INVALID_OPTIONS` before any handler runs. - Resolves the runtime asset URL up-front; missing bundled / inline payloads raise `OPENAPI_UI_REDOC_ASSETS_MISSING` at construction, not at request time. - Pre-renders the HTML shell once at construction — every subsequent request is a constant-time return of the frozen response object. - The response carries `Content-Type: text/html; charset=utf-8`, `Cache-Control: no-cache`, and `X-Content-Type-Options: nosniff`. - The handler is idempotent — the same call always returns the same frozen object, so adapters can safely cache it. ## Usage: Basic ```ts import { createRedocUiHandler } from "@suaveplan/api-openapi-ui-redoc/handler"; const handler = createRedocUiHandler({ openapiUrl: "/openapi.json" }); const res = handler(); // res.body is the rendered HTML shell. ``` ## Usage: Advanced Wire the bundled-asset strategy into a Hono app, including the cache-busted asset route: ```ts import { Hono } from "hono"; import { createRedocUiHandler, defineRedocAsset, } from "@suaveplan/api-openapi-ui-redoc"; const asset = defineRedocAsset( "redoc.standalone.js", "application/javascript; charset=utf-8", runtimeBody ); const handler = createRedocUiHandler({ openapiUrl: "/openapi.json", uiAssets: "bundled", bundledAsset: asset, title: "Acme API", expandResponses: "200,201", theme: "dark", }); const app = new Hono(); app.get("/docs/ui/redoc", (c) => { const r = handler(); Object.entries(r.headers).forEach(([k, v]) => c.header(k, v)); return c.body(r.body, r.status); }); app.get(`/docs/ui/redoc/assets/${asset.hash}/${asset.name}`, (c) => { c.header("Content-Type", asset.contentType); c.header("Cache-Control", "public, max-age=31536000, immutable"); return c.body(asset.body as string); }); ``` ## API Reference | Symbol | Kind | Description | | --------------------------- | ---- | ----------- | | `RedocHttpResponse` | type | `{ status, headers, body }` — router-agnostic response | | `RedocHttpHandler` | type | `() => RedocHttpResponse` | | `CreateRedocUiHandlerInput` | type | `RedocUiOptionsInput & { bundledAsset?, inlineAsset? }` | | `createRedocUiHandler` | fn | Build the handler; pre-renders the shell | ## Implementation Notes The handler pre-renders the HTML once at construction. This keeps the per-request hot path a constant-time return of a frozen object — the same shape the api-router would otherwise have to allocate per call. Pre-rendering also means every option-level fault surfaces at host start-up, not at the first request, which is the failure mode operators want for misconfigured deploys.