Node.js y ExpressExpress.jsLección 10 de 20
Validación con Zod
Zod es una librería de validación que te permite definir exactamente qué forma deben tener tus datos. En lugar de escribir if (!body.email || !body.email.includes("@")) con decenas de condiciones manuales, defines un schema z.object({ email: z.string().email(), edad: z.number().min(18) }) y Zod valida todo automáticamente con mensajes de error claros.
// npm install zod
const { z } = require('zod');
// Definir schema de validación
const usuarioSchema = z.object({
nombre: z.string()
.min(2, 'Nombre debe tener al menos 2 caracteres')
.max(100, 'Nombre muy largo'),
email: z.string().email('Email inválido'),
password: z.string()
.min(8, 'Mínimo 8 caracteres')
.regex(/[A-Z]/, 'Debe tener al menos una mayúscula')
.regex(/[0-9]/, 'Debe tener al menos un número'),
edad: z.number().int().min(18).max(120).optional(),
rol: z.enum(['admin', 'usuario', 'moderador']).default('usuario'),
});
// Schema para actualización parcial (todos los campos opcionales)
const actualizarUsuarioSchema = usuarioSchema.partial().omit({ password: true });
// Middleware de validación genérico (reutilizable)
const validar = (schema) => (req, res, next) => {
const resultado = schema.safeParse(req.body);
if (!resultado.success) {
// Formatear errores de Zod en algo legible
const errores = resultado.error.issues.map(issue => ({
campo: issue.path.join('.'),
mensaje: issue.message,
}));
return res.status(400).json({ error: 'Datos inválidos', errores });
}
// Datos validados y parseados disponibles en req.validatedBody
req.validatedBody = resultado.data;
next();
};
// Query params con schema
const paginacionSchema = z.object({
page: z.coerce.number().int().positive().default(1),
limit: z.coerce.number().int().min(1).max(100).default(20),
q: z.string().optional(),
});
// Uso en rutas
app.post('/usuarios', validar(usuarioSchema), async (req, res) => {
const datosValidados = req.validatedBody; // ya está limpio y tipado
const usuario = await usuariosService.crear(datosValidados);
res.status(201).json(usuario);
});
app.get('/usuarios', async (req, res) => {
const { page, limit, q } = paginacionSchema.parse(req.query);
const usuarios = await usuariosService.listar({ page, limit, q });
res.json(usuarios);
});
ConsejoUsa schema.safeParse() en lugar de schema.parse() en middlewares. safeParse() devuelve { success, data } o { success: false, error } sin lanzar excepciones. parse() lanza ZodError que puede romper tu app si no la capturas.
Practica esta lección
Resuelve los ejercicios del curso de Node.js y Express en la app, gratis y con corrección automática.
Empezar a practicar