Getting started
Vovk.ts as a back-end framework supports a wide range of validation libraries, including Standard Schema. The validation models are emitted as JSON Schemas in order to be used for validation on the client side (but also for code generation, OpenAPI spec and LLM Tools, etc). The server-side and the client-side validation are two different features, the second one is outlined in the client validation page. This page will explain how to use the validation in the server-side code.
Every validation library uses an internal withValidationLibrary
function that is used to wrap the controller handler, providing unified list of options and extending the handler with extra features. Each library is named as with[name]
where the name
is the name of the library, e.g. 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({ /* ...*/ }), // in case of JSON response
// iteration: z.object({ /* ...*/ }), // in case of JSONLines response
// validateEachIteration: true, // for JSONLines 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
The body
, query
and params
options are used to specify input validation schemas. These schemas are used to validate the incoming request data before it reaches the controller handler.
output
and iteration
The output
and iteration
options are used to specify the output validation schemas, where output
is used for regular JSON responses and iteration
is used for JSONLines responses. Both are optional and they donβt affect the generated RPC modules typing, but recommended for enabling crutial features such as OpenAPI spec generation, Function Calling and Codegen for Python, Rust and other further clients. The output
and iteration
arenβt used for the client-side validation.
isForm
The isForm
option is used to specify whether the request body is a form data. This is useful for handling file uploads and other form-related data. Setting it to true
also changes the RPC module typing to accept FormData
on the client side as body
option.
handle
The handle
is the controller handler function that will be executed after the validation is successful. It is the main function that processes the request and returns a response. It provides a type-flavoured NextRequest
, represented as VovkRequest<TBody, TQuery, TParams>
type as the first argument, and params
value as the second argument.
disableServerSideValidation
The disableServerSideValidation
option is used to disable the server-side validation for the specified validation library. It can be a boolean value that indicates whether to disable validation on the server-side completely, or an array of validation types (body
, query
, params
, output
, iteration
). This is useful when you want to skip the server-side validation for certain requests. This option does not affect type inference in the generated RPC modules.
skipSchemaEmission
The skipSchemaEmission
option is used to skip the emission of the JSON Schemas for the handler, allowing to hide implementation details from the client-side code. It can be a boolean value that disables schema emission completely, or an array of validation types to skip schema emission for specific validation types (body
, query
, params
, output
, iteration
). This option does not affect type inference in the generated RPC modules.
validateEachIteration
The validateEachIteration
option is used exclusively for the iteration
validation schema. It indicates whether to validate each item in the iteration response, where by default it validates only the first iteration item.
Features
A handler created with withValidationLibrary
function gets some extra features that enhance its capabilities.
fn
The fn
property alllows to call the handler function directly, at the current context, without making an HTTP request. It follows similar signature as the generated RPC handler and accepts the same parameters.
const result = await UserController.updateUser.fn({
body: { /* ... */ },
query: { /* ... */ },
params: { /* ... */ },
meta: { /* ... */ },
disableClientSideValidation: false, // default
});
// same as
UserRPC.updateUser({
body: { /* ... */ },
query: { /* ... */ },
params: { /* ... */ },
meta: { /* ... */ },
disableClientSideValidation: false, // default
});
For more information about the fn
property, see the callable handlers page. Also see the meta documentation, since itβs handled differently in the fn
property and the RPC module.
schema
const schema = UserController.updateUser.schema;
// same as UserRPC.updateUser.schema
The schema
property provides the method schema for the handler, similar to the RPC method schema. Itβs used in tendem with the fn
property to build Function Calling tools to call the handler directly from the AI tools, without making an HTTP request.
models
const bodyModel = UserController.updateUser.models.body;
The models
property is exclusive to the server-side methods. It allows to access the original validation models used in the handler.