Client-side validation for RPC methods
The schema emitted by the server-side code is primarily used to build the RPC modules, but as an implementation side-effect it can also be used for client-side validation. The cllient-side validation library is defined by hooking into the RPC module template via validateOnClient import.
/** @type {import('vovk').VovkConfig} */
const config = {
generatorConfig: {
imports: {
validateOnClient: 'my-client-validation-library',
},
}
};
export default config;
This will affect the generated RPC modules to import the given client-side validation library.
// ...
export const UserRPC = createRPC(
schema, '', 'UserRPC', import('vovk'),
{ validateOnClient: import('my-client-validation-library') }
);
vovk-ajv
vovk-ajv is the primary library that implements the client-side validation using Ajv . It is installed and set up automatically when npx vovk-init
is used. vovk-ajv supports additional configuration listed as config.libs.ajv
in the vovk.config file, such as Ajv options, localization and target version of the JSON schema.
npm install vovk-ajv@draft
/** @type {import('vovk').VovkConfig} */
const config = {
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 for server-side validation, you can use the same DTOs to validate client-side requests. For more information see the DTO client-side validation section.
Custom client-side validation
A custom validateOnClient
function can be implemented with createClientValidation
function that accepts validate
option, that in its turn accepts the input data, validation schema and some extra information about the request. The validate
function should return the validated input data or throw an error if the validation fails. The meta
object contains information about the request such as type
, endpoint
, etc. It can optionally throw HttpException
with 0
status as 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
As there is no standard way to describe FormData
in JSON Schema, every validation library have to provide its own way to generate OAS-compatible schema for FormData
requests.
{
"type": "object",
"properties": {
"fileField": {
"type": "string",
"format": "binary"
}
},
}
Zod 4 includes .file()
schema that is converted to the valid OAS schema but for other libraries it needs to be solved individually. It’s outlined for every library mentioned at this documentation (for arktype it’s solved by using a fallback
, for Valibot you need to use overrideSchema
etc).
In case if you use a library that isn’t mentioned here and you don’t know how to make it properly generate the OAS file schema, the easiest way to work around this problem is to use disableClientValidation
option in the generated RPC modules:
import { UserRPC } from 'vovk-client';
const respData = await UserRPC.updateUser({
body: formData, // FormData instance
params: { id: '...' },
disableClientSideValidation: true, // disable client-side validation
});
This way the client-side validation will be skipped, but the server-side validation will still be performed. The file will not appear in the generated OpenAPI specification, but the endpoint will still accept multipart/form-data
requests.