Client-Side Validation for RPC Methods
The schema emitted by the server-side code is primarily used to generate RPC modules. As a side effect of this implementation, it can also power client-side validation. Client-side validation is enabled by wiring a library into the RPC module template via the validateOnClient import.
/** @type {import('vovk').VovkConfig} */
const config = {
outputConfig: {
imports: {
validateOnClient: 'my-client-validation-library',
},
}
};
export default config;This configuration makes the generated RPC modules import the specified client-side validation library.
// ...existing code...
export const UserRPC = createRPC(
schema, '', 'UserRPC', import('vovk'),
{ validateOnClient: import('my-client-validation-library') }
);
// ...existing code...vovk-ajv
vovk-ajv is the primary library for client-side validation, built on top of Ajv . It’s installed and configured automatically when you run npx vovk-init. vovk-ajv supports additional configuration under config.libs.ajv in vovk.config, including Ajv options, localization, and the target JSON Schema draft.
npm install vovk-ajv@draft/** @type {import('vovk').VovkConfig} */
const config = {
outputConfig: {
imports: {
validateOnClient: 'vovk-ajv',
},
},
libs: {
/** @type {import('vovk-ajv').VovkAjvConfig} */
ajv: {
options: {
// Ajv options
strict: false,
},
localize: 'en', // language supported by "ajv-i18n"
target: 'draft-07', // auto-detected from $schema but can be configured
},
},
};
export default config;vovk-dto/validateOnClient
When using class-validator on the server, you can reuse the same DTOs to validate client-side requests. See the DTO client-side validation section for details.
Custom Client-Side Validation
You can implement a custom validateOnClient using createValidateOnClient, which accepts a validate option. The validate function receives the input data, the validation schema, and request metadata (meta) such as type, endpoint, and more. It should return validated data, or throw an error on failure. Optionally, throw an HttpException with status 0 (HttpStatus.NULL) to follow the default behavior for failed client-side validation.
import { createValidateOnClient, HttpException, HttpStatus } from 'vovk';
export const validateOnClient = createValidateOnClient({
validate: async (input, schema, meta) => {
try {
return myValidateFunction(input, schema, meta);
} catch (error) {
throw new HttpException(HttpStatus.NULL, `Custom validation failed: ${error.message}`);
}
},
});FormData
Because JSON Schema has no standard representation for FormData, each validation library must provide a way to generate an OAS-compatible schema for multipart/form-data requests.
{
"type": "object",
"properties": {
"fileField": {
"type": "string",
"format": "binary"
}
}
}Zod 4 includes a .file() schema that is converted to a valid OAS schema . For other libraries, this is addressed individually in the corresponding sections of the docs (for ArkType, use a fallback; for Valibot, use overrideSchema, etc.).
If you’re using an unlisted library and can’t produce a proper OAS file schema, the simplest workaround is to set disableClientValidation in the generated RPC call:
import { UserRPC } from 'vovk-client';
const respData = await UserRPC.updateUser({
body: formData, // FormData instance
params: { id: '...' },
disableClientValidation: true, // disable client-side validation
});This skips client-side validation while keeping server-side validation intact. The file field won’t appear in the generated OpenAPI spec, but the endpoint will still accept multipart/form-data requests.