87 lines
2.1 KiB
TypeScript
87 lines
2.1 KiB
TypeScript
// Common validation schemas reusable across modules
|
|
import { z } from 'zod';
|
|
|
|
/**
|
|
* Email validation schema
|
|
*/
|
|
export const emailSchema = z.string().email('Email inválido');
|
|
|
|
/**
|
|
* Password validation schema
|
|
* - Minimum 8 characters
|
|
* - At least one uppercase letter
|
|
* - At least one lowercase letter
|
|
* - At least one number
|
|
*/
|
|
export const passwordSchema = z
|
|
.string()
|
|
.min(8, 'La contraseña debe tener al menos 8 caracteres')
|
|
.regex(/[A-Z]/, 'Debe contener al menos una mayúscula')
|
|
.regex(/[a-z]/, 'Debe contener al menos una minúscula')
|
|
.regex(/[0-9]/, 'Debe contener al menos un número');
|
|
|
|
/**
|
|
* Phone number validation schema
|
|
* Supports international format with optional +
|
|
*/
|
|
export const phoneSchema = z
|
|
.string()
|
|
.regex(/^\+?[1-9]\d{1,14}$/, 'Número de teléfono inválido')
|
|
.optional();
|
|
|
|
/**
|
|
* URL validation schema
|
|
*/
|
|
export const urlSchema = z.string().url('URL inválida');
|
|
|
|
/**
|
|
* Date validation schema with coercion
|
|
*/
|
|
export const dateSchema = z.coerce.date();
|
|
|
|
/**
|
|
* Date range validation schema
|
|
* Ensures end date is after start date
|
|
*/
|
|
export const dateRangeSchema = z
|
|
.object({
|
|
start: z.coerce.date(),
|
|
end: z.coerce.date(),
|
|
})
|
|
.refine((data) => data.end > data.start, {
|
|
message: 'La fecha de fin debe ser posterior a la fecha de inicio',
|
|
path: ['end'],
|
|
});
|
|
|
|
/**
|
|
* Positive number schema
|
|
*/
|
|
export const positiveNumberSchema = z.number().positive('El valor debe ser mayor a 0');
|
|
|
|
/**
|
|
* Non-empty string schema
|
|
*/
|
|
export const nonEmptyStringSchema = z.string().min(1, 'Este campo es requerido');
|
|
|
|
/**
|
|
* Image file validation schema
|
|
* - Max size: 5MB
|
|
* - Allowed types: JPEG, PNG, WebP
|
|
*/
|
|
export const imageFileSchema = z
|
|
.instanceof(File)
|
|
.refine((file) => file.size <= 5 * 1024 * 1024, 'El archivo debe ser menor a 5MB')
|
|
.refine(
|
|
(file) => ['image/jpeg', 'image/png', 'image/webp'].includes(file.type),
|
|
'Solo se permiten imágenes JPEG, PNG o WebP'
|
|
);
|
|
|
|
/**
|
|
* Multiple image files schema
|
|
*/
|
|
export const imageFilesSchema = z
|
|
.array(imageFileSchema)
|
|
.min(1, 'Al menos una imagen es requerida')
|
|
.max(10, 'Máximo 10 imágenes');
|
|
|