openApiPlugin
Serve your OpenAPI document and an API reference UI for it, on any adapter.
Serve a reference UI for the OpenAPI document generated from your contract, and the document itself if you want it public. Declare it on new Kizuna(), pass openApiPluginServer() to server.api, and api.mount serves the routes.
pnpm add @ts-kizuna/openapibun add @ts-kizuna/openapinpm install @ts-kizuna/openapiimport { openApiPlugin } from '@ts-kizuna/openapi';
import { openApiPluginServer } from '@ts-kizuna/openapi/server';Parameters
openApiPlugin(props: OpenApiPluginProps): PluginDeclaration
openApiPluginServer(): PluginImplementation| Parameter | Type | Required | Description |
|---|---|---|---|
props | OpenApiPluginProps | Yes | Everything generateOpenApi takes, plus the options below |
Props
OpenApiPluginProps extends GenerateOpenApiOptions, so info, servers, setOperationId and the rest work exactly as they do on generateOpenApi. On top of those:
| Option | Default | Description |
|---|---|---|
docsPath | off | The reference UI. Give it a path to serve it |
jsonPath | off | The document. A path ending in .json |
yamlPath | off | The document as YAML. A path ending in .yaml |
provider | 'scalar' | Which reference UI to render, 'scalar' or 'swagger' |
cdnUrl | the provider's CDN | Where to load the UI's assets from |
pageTitle | the document title | The page's <title> |
configuration | none | Extra config merged into the UI's initializer |
Props are pure data, because they reach the contract and the contract reaches your client. The generator lives in openApiPluginServer(), which takes nothing: declaring the plugin is where it is configured.
They are also the options generateOpenApi uses when you call it without any, so a build step and the served document cannot disagree.
Each prop serves nothing until you give it a path. The document paths carry their extension in the type, so jsonPath: '/docs' does not compile.
Example
import { Kizuna } from '@ts-kizuna/core';
import { openApiPlugin } from '@ts-kizuna/openapi';
export const k = new Kizuna({
tags,
plugins: {
openApi: openApiPlugin({
info: {
title: 'My API',
version: '1.0.0',
},
setOperationId: true,
}),
},
});import { openApiPluginServer } from '@ts-kizuna/openapi/server';
export const api = server.api({
router,
plugins: {
openApi: openApiPluginServer(),
},
});api.mount(app);Two halves
@ts-kizuna/openapi declares the paths it serves and the options the document is built from, as data on your contract. @ts-kizuna/openapi/server holds the generator that renders it. Miss the second half and server.api throws, naming the module to import. See Plugins.
Not in your client
Its routes are plugin routes, so they live outside contract.routes. Your fetch client and generated Swift and Kotlin clients never see them, and neither does the document itself.
Public by default
Nothing guards these routes. Gate them with your framework's own middleware if your document should not be public.
Air-gapped and strict CSP
cdnUrl points the page at a self-hosted copy of the UI's assets. For 'scalar' it is the script URL; for 'swagger' it is the directory holding swagger-ui.css and swagger-ui-bundle.js.
Serving it yourself
generateOpenApi is unchanged and exported, so you can skip the plugin and serve the document from your own route. Mixing works too: docsPath: false lets the plugin serve the document while you render your own UI, and leaving jsonPath unset keeps the plugin off a path you serve yourself.
See also
- OpenAPI guide
generateOpenApito write the document to disk instead- Plugins