/** * Swagger documentation UI for declarative `HttpApi` contracts. * * This module mounts a browser-based Swagger UI route on an `HttpRouter`. The * page renders the OpenAPI document derived from the supplied `HttpApi`, so a * running application can expose interactive API documentation without writing a * separate OpenAPI file. * * @stability unstable * @since 4.0.0 */ import * as Effect from "../Effect.ts" import * as Function from "../Function.ts" import * as HttpRouter from "../http/HttpRouter.ts" import * as HttpServerResponse from "../http/HttpServerResponse.ts" import type * as Layer from "../Layer.ts" import type * as HttpApi from "./HttpApi.ts" import type * as HttpApiGroup from "./HttpApiGroup.ts" import * as Html from "./internal/html.ts" import * as OpenApi from "./OpenApi.ts" const makeHandler = (options: { readonly api: HttpApi.HttpApi readonly javascript: string readonly css: string }) => { const makeResponse = Function.memoize((api: HttpApi.HttpApi) => { const spec = OpenApi.fromApi(api) return HttpServerResponse.html(` ${Html.escape(spec.info.title)} Documentation
`) }) return Effect.sync(() => makeResponse(options.api)) } /** * Mounts Swagger UI for an `HttpApi` at the configured path, defaulting to * `/docs`, using the OpenAPI specification generated from the API. * * **Details** * * The bundled Swagger UI assets are loaded when the layer is built, not when * this module is imported. * * @stability unstable * @category layers * @since 4.0.0 */ export const layer = ( api: HttpApi.HttpApi, options?: { readonly path?: `/${string}` | undefined } ): Layer.Layer => HttpRouter.use(Effect.fnUntraced(function*(router) { const { css, javascript } = yield* Effect.promise(() => import("./internal/httpApiSwagger.ts")) const handler = makeHandler({ api, javascript, css }) yield* router.add("GET", options?.path ?? "/docs", handler) }))