Getting Started
Vovk.ts, as a backend framework, supports a wide range of validation libraries. Validation models are emitted as JSON Schema for client-side validation and for use in code generation, the OpenAPI spec, LLM tools, and more.
Every validation library integrates through an internal withValidationLibrary function that wraps the controller handler, providing a unified set of options and extending the handler with extra features. Each library follows the with[name] naming, where name is the library (for example, withZod).
Options
import { z } from 'zod';
import { withZod } from 'vovk-zod';
import { prefix, post } from 'vovk';
@prefix('users')
export default class UserController {
@post('{id}')
static updateUser = withZod({
body: z.object({ /* ... */ }),
params: z.object({ /* ... */ }),
query: z.object({ /* ... */ }),
output: z.object({ /* ... */ }), // for JSON response
// iteration: z.object({ /* ... */ }), // for JSON Lines response
// validateEachIteration: true, // for JSON Lines response only
disableServerSideValidation: ['body', 'query'], // disable server-side validation for body and query
skipSchemaEmission: ['output'], // skip schema emission for output
isForm: false, // default
async handle(req, params) {
// ...
},
});
}body, query, and params
Use body, query, and params to provide input validation schemas. These validate incoming request data before it reaches the controller handler.
output and iteration
Use output and iteration to provide output validation schemas. output is for regular JSON responses, while iteration is for JSON Lines. Both are optional and don’t affect generated RPC typings, but they enable key features like OpenAPI, function calling, and codegen for Python, Rust, and future clients. These schemas are not used for client-side validation.
isForm
isForm specifies that the request body is form data (useful for file uploads and similar cases). Setting it to true changes RPC method typing to accept FormData on the client as the body option and adds x-isForm to the emitted JSON Schema for the body.
handle
handle is the controller function executed after validation succeeds. It receives a type-enhanced NextRequest as VovkRequest<TBody, TQuery, TParams> and the params: TParams value as the second argument.
disableServerSideValidation
Disables server-side validation for the specified library. Provide a boolean to disable it entirely, or an array of validation types (body, query, params, output, iteration). This does not affect generated RPC typings or client-side validation.
skipSchemaEmission
Skips emitting JSON Schema for the handler. Provide a boolean to skip entirely, or an array of validation types (body, query, params, output, iteration). This does not change RPC typings but disables features that depend on emitted schemas, including client-side validation.
validateEachIteration
Applies only to iteration. Controls whether to validate each item in the streamed response. By default, only the first iteration item is validated.
operation
Optionally provide an operation object to specify OAS details when the @operation decorator is not applicable—useful with fn on a regular function instead of a class method.
preferTransformed = true
By default, Vovk.ts transforms incoming data into the validation result shape. If you need raw I/O without transformations, set preferTransformed to false. This causes all features that rely on validation models (body, query, params, output, iteration) to return the original data format instead of the transformed one.
Features
Handlers created with withValidationLibrary gain extra capabilities.
fn
The fn property lets you call the handler directly without making an HTTP request. It mirrors the generated RPC handler signature and accepts the same parameters.
const result = await UserController.updateUser.fn({
body: { /* ... */ },
query: { /* ... */ },
params: { /* ... */ },
meta: { /* ... */ },
disableClientValidation: false, // default
});
// same as
const result = await UserRPC.updateUser({
body: { /* ... */ },
query: { /* ... */ },
params: { /* ... */ },
meta: { /* ... */ },
disableClientValidation: false, // default
});See callable handlers for details. Also review the meta documentation, as it behaves differently for fn and RPC modules.
schema
const schema = UserController.updateUser.schema;
// same as UserRPC.updateUser.schemaThe schema property exposes the method schema, mirroring the RPC method schema. It’s typically used with fn to build function calling tools that invoke handlers without HTTP.
models
const bodyModel = UserController.updateUser.models.body;The models property is available only on server-side methods, but not on the RPC methods. It lets you access the original validation models used by the handler.