Skip to Content
OpenAPI Specification

OpenAPI Specification with @operation Decorator

Vovk.ts automatically generates an OpenAPI specification from controller methods, using validation models to populate operation objects with parameters, requestBody, and responses. The @operation decorator lets you enrich operation objects with metadata such as summary, description, tags, and more. It accepts a VovkOperationObject, which extends the standard OpenAPI OperationObject type from openapi3-ts/oas31  and supports x-tool-* properties related to AI capabilities, as described in the Function Calling documentation.

src/modules/user/UserController.ts
import { put, prefix, operation } from "vovk"; import { z } from "zod"; import { withZod } from "vovk-zod"; @prefix("users") export default class UserController { @operation({ summary: "Update User", description: "Update user information", }) @put("{id}") static updateUser = withZod({ isForm: true, params: z.object({ id: z.uuid(), }), body: z.object({ /* ... */ }), query: z.object({ /* ... */ }), output: z.object({ /* ... */ }), // ... }) }

The validation models are converted to OpenAPI operation objects according to the following mapping:

  • paramsparameters with in: "path"
  • queryparameters with in: "query"
  • bodyrequestBody with the application/json content type (isForm changes it to multipart/form-data)
  • outputresponses with status 200 and application/json content type
  • iterationresponses with status 200 and application/jsonl content type

Utilizing the Generated OpenAPI Specification

The generated RPC client exports an openapi object that contains the full back-end specification for the composed client. When using the segmented client, each segment also exports its own specification.

import { UserRPC, openapi } from 'vovk-client'; // composed client
import { UserRPC, openapi } from '@/client/admin/index.ts'; // segmented client

You can alternatively import the openapi object from vovk-client/openapi or @/client/admin/openapi to access the specification independently of the RPC modules.

This object is a fully compliant OpenAPI 3.x specification and works with any tool that supports OpenAPI 3 or later.

You can use the specification directly as a variable or expose it via a static segment with a simple controller that serves it as a JSON endpoint.

npx vovk new segment --static static
npx vovk new controller static/openApi --empty
src/modules/static/openapi/OpenApiController.ts
import { get, operation } from "vovk"; import { openapi } from "vovk-client/openapi"; export default class OpenApiController { @operation({ // operation object definition is optional summary: "OpenAPI Specification", description: 'Retrieve the OpenAPI specification for the API', }) @get("openapi.json") static getSpec = () => openapi; }

On the client side, you can use any OpenAPI documentation generator. We recommend Scalar  because Vovk.ts generates code snippets that integrate directly into your codebase.

import { ApiReferenceReact } from "@scalar/api-reference-react"; import "@scalar/api-reference-react/style.css"; async function App() { return ( <ApiReferenceReact configuration={{ url: "/api/static/openapi.json", servers: [ { url: "http://localhost:3000", description: "Localhost", }, { url: "https://example.com", description: "Production", }, ], }} /> ); } export default App;

For a live demonstration, see the “Hello World” application . Additional details are available on the “Hello World” page.

Last updated on