Validacao Zod
Schemas de validacao com Zod, pipes e middlewares.
Visao geral
Zod e usado para validar e tipar dados de entrada (body, query, params) em todas as rotas da API. O PlazerCLI gera schemas de exemplo e a infraestrutura de validacao especifica para cada framework.
Schemas de exemplo
Gerados em apps/api/src/common/validation/schemas/example.schema.ts:
import { z } from 'zod';
// Criar usuario
export const CreateUserSchema = z.object({
name: z.string().min(2).max(100),
email: z.string().email('Email invalido'),
password: z.string()
.min(8, 'Senha deve ter pelo menos 8 caracteres')
.regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
'Deve conter minuscula, maiuscula e numero'),
});
export type CreateUserDto = z.infer<typeof CreateUserSchema>;
// Login
export const LoginSchema = z.object({
email: z.string().email(),
password: z.string().min(1),
});
export type LoginDto = z.infer<typeof LoginSchema>;
// Paginacao
export const PaginationSchema = z.object({
page: z.coerce.number().int().min(1).default(1),
limit: z.coerce.number().int().min(1).max(100).default(20),
});
export type PaginationDto = z.infer<typeof PaginationSchema>;
// ID param
export const IdParamSchema = z.object({
id: z.string().uuid('ID deve ser um UUID valido'),
});
export type IdParamDto = z.infer<typeof IdParamSchema>;
NestJS — ZodValidationPipe
O PlazerCLI gera um PipeTransform customizado para NestJS:
@Injectable()
export class ZodValidationPipe implements PipeTransform {
constructor(private schema: ZodSchema) {}
transform(value: unknown) {
const result = this.schema.safeParse(value);
if (!result.success) {
throw new BadRequestException({
message: 'Erro de validacao',
errors: this.formatErrors(result.error),
});
}
return result.data;
}
}
// Uso no controller:
@Post()
create(@Body(new ZodValidationPipe(CreateUserSchema)) dto: CreateUserDto) {
return this.usersService.create(dto);
}
Express — Middleware validate()
Para Express, tres middlewares sao gerados:
import { validate, validateQuery, validateParams } from '../common/validation/validate.js';
import { CreateUserSchema, PaginationSchema, IdParamSchema } from '../common/validation/schemas/example.schema.js';
// Validar body
router.post('/users', validate(CreateUserSchema), (req, res) => {
// req.body ja esta validado e tipado
res.json(req.body);
});
// Validar query params
router.get('/users', validateQuery(PaginationSchema), (req, res) => {
const { page, limit } = req.validatedQuery;
});
// Validar route params
router.get('/users/:id', validateParams(IdParamSchema), (req, res) => {
const { id } = req.params;
});
Fastify — preHandler validate()
Para Fastify, os mesmos tres helpers sao gerados como preHandler hooks:
import { validate, validateQuery, validateParams } from '../common/validation/validate.js';
import { CreateUserSchema } from '../common/validation/schemas/example.schema.js';
app.post('/users', {
preHandler: validate(CreateUserSchema)
}, async (request) => {
// request.body ja esta validado
return request.body;
});
Resposta de erro
Quando a validacao falha, o erro retornado segue este formato:
// HTTP 400 Bad Request
{
"message": "Erro de validacao",
"errors": {
"email": ["Email invalido"],
"password": [
"Senha deve ter pelo menos 8 caracteres",
"Deve conter minuscula, maiuscula e numero"
]
}
}