generateOpenApi
Generate an OpenAPI 3.1.0 document from a ts-kizuna contract.
Generate an OpenAPI 3.1.0 document from a contract. Returns a renderer you call with 'json' or 'yaml'.
pnpm add @ts-kizuna/openapibun add @ts-kizuna/openapinpm install @ts-kizuna/openapiimport { generateOpenApi } from '@ts-kizuna/openapi/server';Parameters
generateOpenApi(contract: Contract, overrides?: Partial<GenerateOpenApiOptions>): OpenApiRenderer| Parameter | Type | Description |
|---|---|---|
contract | Contract | The contract from k.contract |
overrides | Partial<GenerateOpenApiOptions> | Merged over the contract's options, for what only a build knows |
It lives on @ts-kizuna/openapi/server because it reads your deprecations file from disk. The contract-facing entry, @ts-kizuna/openapi, holds openApiPlugin and the document types.
Options
Options are declared on openApiPlugin in k.ts, and generateOpenApi reads them off the contract, so a build step cannot write a document that differs from the one your server serves. Pass overrides for what only a build step knows, such as the public servers list.
| Option | Type | Default | Description |
|---|---|---|---|
info | { title, version, description? } | required | OpenAPI info object |
openApiVersion | '3.1.0' | '3.1.0' | OpenAPI specification version for the generated document |
servers | { url, description? }[] | none | Server URLs |
setOperationId | boolean | 'concatenated-path' | false | Set operationId from the route key. Use 'concatenated-path' to include parent keys. |
tags | OpenApiTag[] | none | Top-level tag definitions |
operationMapper | (operation, route, id) => operation | none | Callback to transform each operation before it is added to the spec |
There are no security options, because security is emitted from the contract automatically, so the spec can't drift from what the server enforces. See below.
Returns
An OpenApiRenderer function:
renderer('json'); // OpenApiDocument object
renderer('yaml'); // YAML stringExample
import { Kizuna } from '@ts-kizuna/core';
import { openApiPlugin } from '@ts-kizuna/openapi';
export const k = new Kizuna({
plugins: {
openApi: openApiPlugin({
info: {
title: 'My API',
version: '1.0.0',
},
servers: [
{
url: 'https://api.example.com',
description: 'Production',
},
],
setOperationId: true,
}),
},
});import { generateOpenApi } from '@ts-kizuna/openapi/server';
import { contract } from './contract';
const spec = generateOpenApi(contract);
app.get('/openapi.json', (_req, res) => {
res.json(spec('json'));
});Security emission
Security is generated from the contract, not configured on the generator. Every identity registered on new Kizuna() is emitted under components.securitySchemes, and every route the auth map secures references those names in its security, with OAuth scopes where the map declares them. Public routes (false) get none.
With the user (bearer) and member (API key) identities and workspace: 'member' in the auth map, the document contains:
components:
securitySchemes:
user:
type: http
scheme: bearer
member:
type: apiKey
name: x-workspace-token
in: header
paths:
/workspace:
get:
security:
- member: []A custom identity is the exception: OpenAPI can't describe its credential, so it emits no securityScheme and no security. Its routes instead carry an x-kizuna-guarded extension, keeping a protected-out-of-band route distinct from a public one.
Because the spec and the runtime guards both derive from the auth map, documented security is enforced security, and there is nothing to keep in sync.
See the OpenAPI guide for Scalar integration, writing specs to disk, and breaking change detection.