Rikta provides first-class support for Zod validation. You can pass Zod schemas directly to parameter decorators to validate incoming data and infer types automatically.
Validation is performed automatically when you pass a Zod schema to decorators like @Body, @Query, @Param, or @Headers.
If validation fails, Rikta automatically throws a BadRequestException (400) with detailed error messages.
Pass a Zod schema to the @Body() decorator:
import { z } from 'zod';
import { Controller, Post, Body } from '@riktajs/core';
// Define schema
const CreateUserSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
age: z.number().min(18).optional()
});
// Infer type (optional but recommended)
type CreateUserDto = z.infer<typeof CreateUserSchema>;
@Controller('/users')
export class UserController {
@Post()
create(@Body(CreateUserSchema) data: CreateUserDto) {
// 'data' is fully typed and validated here!
console.log(data.email);
return { id: 1, ...data };
}
}Validate and transform query strings:
const SearchSchema = z.object({
q: z.string().min(1),
page: z.coerce.number().default(1), // Auto-convert string to number
limit: z.coerce.number().max(100).default(10)
});
@Get('/search')
search(@Query(SearchSchema) query: z.infer<typeof SearchSchema>) {
// query.page is a number
return this.service.search(query.q, query.page, query.limit);
}Validate path parameters (e.g., ensure IDs are numbers or UUIDs):
const IdSchema = z.object({
id: z.coerce.number().int().positive()
});
@Get('/:id')
findOne(@Param(IdSchema) params: z.infer<typeof IdSchema>) {
return this.service.findById(params.id);
}When validation fails, the client receives a 400 response with details:
{
"statusCode": 400,
"message": "Validation failed",
"error": "Bad Request",
"details": [
{
"code": "invalid_string",
"validation": "email",
"message": "Invalid email",
"path": ["email"]
}
]
}You can share schemas between frontend and backend if you are using a monorepo.
// shared/schemas.ts
export const UserSchema = z.object({
id: z.string().uuid(),
username: z.string()
});
// backend/controller.ts
@Post()
update(@Body(UserSchema) user: z.infer<typeof UserSchema>) { ... }Zod allows custom error messages which Rikta will return to the client:
const LoginSchema = z.object({
email: z.string().email("Please provide a valid email address"),
password: z.string().min(1, "Password is required")
});Use Zod's transformation features to sanitize data:
const TrimmedString = z.string().transform(val => val.trim());
const SignupSchema = z.object({
username: TrimmedString,
email: z.string().email().toLowerCase() // Auto-lowercase
});