Concepto clave
Las validaciones y manejo de errores en Server Actions son el sistema de defensa de tu aplicación. Imagina que estás construyendo un formulario de registro: sin validaciones, los usuarios podrían enviar emails inválidos o contraseñas vacías, corrompiendo tu base de datos. Las validaciones actúan como un filtro que solo permite datos limpios y estructurados, mientras que el manejo de errores es el plan de contingencia cuando algo falla.
En SvelteKit, las Server Actions se ejecutan en el servidor, lo que significa que puedes validar datos antes de procesarlos, sin exponer lógica sensible al cliente. Esto es crucial para seguridad y consistencia. Piensa en ello como un control de calidad en una fábrica: cada producto (dato) pasa por inspección antes de ser empaquetado (almacenado).
Cómo funciona en la práctica
El flujo típico sigue estos pasos: 1) El cliente envía datos a través de un formulario, 2) La Server Action recibe los datos en el servidor, 3) Se ejecutan validaciones (ej., formato de email, longitud de contraseña), 4) Si hay errores, se devuelven al cliente con mensajes claros, 5) Si todo es válido, se procesa la acción (ej., guardar en base de datos).
Veamos un ejemplo básico: validar un formulario de contacto. Primero, definimos esquemas de validación usando librerías como Zod o validaciones manuales. Luego, en la acción, verificamos cada campo. Si falla, retornamos un objeto de errores que SvelteKit puede mostrar en el frontend. Este enfoque mantiene la lógica centralizada y evita duplicación.
Código en acción
Aquí tienes un ejemplo funcional con validaciones usando Zod:
// +page.server.js - Server Action con validaciones
import { z } from 'zod';
import { fail } from '@sveltejs/kit';
// Esquema de validación para un formulario de registro
const registerSchema = z.object({
email: z.string().email('Email inválido'),
password: z.string().min(8, 'La contraseña debe tener al menos 8 caracteres'),
name: z.string().min(2, 'El nombre debe tener al menos 2 caracteres')
});
export const actions = {
register: async ({ request }) => {
const formData = await request.formData();
const data = Object.fromEntries(formData);
// Validar datos
const result = registerSchema.safeParse(data);
if (!result.success) {
// Devolver errores de validación
const errors = result.error.errors.reduce((acc, err) => {
acc[err.path[0]] = err.message;
return acc;
}, {});
return fail(400, { errors, data });
}
// Procesar datos válidos (ej., guardar en base de datos)
console.log('Datos válidos:', result.data);
return { success: true };
}
};Y en el frontend, manejamos los errores:
<!-- +page.svelte -->
<script>
import { enhance } from '$app/forms';
import { page } from '$app/stores';
</script>
<form method="POST" action="?/register" use:enhance>
<label>Email:</label>
<input type="email" name="email" value={$page.form?.data?.email || ''} />
{#if $page.form?.errors?.email}
<p style="color: red;">{$page.form.errors.email}</p>
{/if}
<label>Contraseña:</label>
<input type="password" name="password" />
{#if $page.form?.errors?.password}
<p style="color: red;">{$page.form.errors.password}</p>
{/if}
<button type="submit">Registrarse</button>
</form>Errores comunes
- Validar solo en el cliente: Los usuarios pueden deshabilitar JavaScript o manipular requests, exponiendo tu aplicación a datos maliciosos. Solución: Siempre valida en el servidor con Server Actions, usando el cliente solo para mejor UX.
- Mensajes de error genéricos: Devolver "Error 500" o "Algo salió mal" no ayuda al usuario a corregir problemas. Solución: Proporciona mensajes específicos, como "El email ya está registrado" o "La contraseña es demasiado corta".
- No manejar excepciones de base de datos: Asumir que las operaciones de BD siempre tienen éxito puede crashear tu app. Solución: Envuelve llamadas a BD en try-catch y devuelve errores amigables.
- Olvidar limpiar datos antiguos: Al recargar una página con errores, los campos pueden mostrar valores incorrectos. Solución: Usa
$page.form?.datapara rellenar formularios y resetear después del éxito.
Checklist de dominio
- ¿Implementas validaciones tanto en cliente (para UX) como en servidor (para seguridad)?
- ¿Usas esquemas de validación (ej., Zod) para mantener consistencia y reutilización?
- ¿Devuelves mensajes de error específicos y accionables para cada campo fallido?
- ¿Manejas excepciones inesperadas (ej., fallos de BD) con try-catch en Server Actions?
- ¿Proteges contra ataques comunes como inyección SQL o XSS al validar y sanitizar datos?
- ¿Testeas validaciones con casos límite (ej., strings vacíos, caracteres especiales)?
- ¿Documentas los códigos de error y flujos de validación para tu equipo?
Implementa validaciones y manejo de errores en un formulario de tareas
En este ejercicio, mejorarás un formulario de tareas existente agregando validaciones robustas y manejo de errores. Sigue estos pasos:
- Configura el proyecto: Crea un nuevo proyecto SvelteKit o usa uno existente. Asegúrate de tener Zod instalado (
npm install zod). - Crea el esquema de validación: En
+page.server.js, define un esquema Zod para una tarea con campos: título (requerido, mínimo 3 caracteres), descripción (opcional, máximo 500 caracteres), y fecha límite (requerida, debe ser futura). - Implementa la Server Action: Modifica la acción existente o crea una nueva (
createTask) que valide los datos del formulario usando el esquema. Si hay errores, devuélvelos confail(400, { errors, data }). Si es válido, simula guardar en una variable en memoria y retorna éxito. - Actualiza el frontend: En
+page.svelte$page.form?.errors. Asegúrate de que los campos mantengan sus valores tras un error. - Agrega manejo de excepciones: Envuelve la lógica de "guardado" en un try-catch. Si ocurre un error inesperado (ej., simula lanzando un error), devuelve un mensaje general amigable.
- Prueba tu implementación: Envía el formulario con datos inválidos y verifica que los errores se muestren. Luego, con datos válidos, confirma que se procesa correctamente.
- Usa
z.date().min(new Date())en Zod para validar fechas futuras. - Recuerda que
fail()de SvelteKit es clave para devolver errores al frontend sin crashear. - Para simular un error inesperado, puedes agregar
if (Math.random() > 0.8) throw new Error('Error de BD simulado');en la acción.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.