Valibot
Generate Valibot schemas from OpenAPI
Generate Valibot schemas from your OpenAPI specification for runtime validation.
Configuration
Set the client option to valibot:
import { defineConfig } from 'orval';
export default defineConfig({
petstore: {
output: {
client: 'valibot',
mode: 'single',
target: './src/api/schemas.ts',
},
input: {
target: './petstore.yaml',
},
},
});Generated Output
Orval generates a Valibot schema for the params, query, headers, body and response of each operation. The body and response schemas come from JSON, multipart/form-data or application/x-www-form-urlencoded content, and the response schema from the first of 200, 2XX/2xx and the other 2xx responses (except 204 and 205) that has such content. Other media types, such as text/plain, get no schema:
import * as v from 'valibot';
export const CreatePetsBody = v.object({
id: v.pipe(v.number(), v.integer()),
name: v.string(),
tag: v.optional(v.string()),
});Options
Options live under override.valibot:
strict- per location (param,query,header,body,response), emitv.strictObjectinstead ofv.object. Allfalseby default.generate- per location, choose which schemas are generated. Alltrueby default.exactOptional- usev.exactOptionalfor optional properties, for projects withexactOptionalPropertyTypes.falseby default.
Usage
Parsing Data
import * as v from 'valibot';
import { CreatePetsBody } from './src/api/schemas';
const pet = v.parse(CreatePetsBody, { id: 1, name: 'Buddy', tag: 'dog' });
// => { id: 1, name: "Buddy", tag: "dog" }Type Inference
import * as v from 'valibot';
import { CreatePetsBody } from './src/api/schemas';
type Pet = v.InferOutput<typeof CreatePetsBody>;
const pet: Pet = { id: 1, name: 'Buddy', tag: 'dog' };Safe Parsing
import * as v from 'valibot';
import { CreatePetsBody } from './src/api/schemas';
const result = v.safeParse(CreatePetsBody, unknownData);
if (result.success) {
console.log(result.output);
} else {
console.error(result.issues);
}Mapping
oneOfandanyOfbecomev.union, orv.variantwhen adiscriminatoris set.allOfbecomesv.intersect.- Objects strip unknown keys. The
strictoption emitsv.strictObject, andadditionalPropertiesemitsv.looseObjectorv.record. dateanddate-timestrings are validated as ISO dates. Withoverride.useDatesthey are converted toDate.- Binary fields (
format: binary) becomev.file(), including file parts inmultipart/form-databodies. readOnlyproperties are left out of request bodies, andwriteOnlyproperties out of responses.- A
defaultthat does not fit its schema is left out, with a warning.
Limitations
- Recursive schemas (circular
$ref) are validated asunknown, with a warning. prefixItemstuples are validated asunknown[], with a warning.- Every
$refis inlined, so components are not emitted as reusable constants and shared schemas can make the output large. oneOfdoes not check that exactly one alternative matches.- Inside an
allOfintersection,strictobjects are emitted asv.object, so extra keys are stripped instead of rejected. An open member (additionalProperties: true) next to an object member is left out, so extra keys are stripped too. - Valibot schemas are not wired into the HTTP clients yet:
schemas: { type: 'valibot' }and runtime validation of responses are not available.
Combining with HTTP Clients
The valibot client generates schemas only. To use it with another client, generate that client in a separate output and parse responses yourself:
import * as v from 'valibot';
import { showPetById } from './src/api/endpoints';
import { ShowPetByIdResponse } from './src/api/schemas';
const response = await showPetById('1');
const pet = v.parse(ShowPetByIdResponse, response.data);