UNPKG

svelte-simple-form

Version:

A lightweight, **type-safe**, and **reactive** form state management hook for **Svelte 5**, featuring:

75 lines (74 loc) 2.43 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ import { getByPath } from '../helper.js'; import { z } from 'zod'; function flattenZodErrors(obj, path = '', result = {}) { for (const key in obj) { if (key === '_errors') { if (obj[key].length > 0 && path) { result[path] = obj[key]; } continue; } const newPath = path ? `${path}.${key}` : key; if (typeof obj[key] === 'object' && obj[key] !== null) { flattenZodErrors(obj[key], newPath, result); } } return result; } function unwrapEffects(schema) { while (schema instanceof z.ZodEffects) { schema = schema._def.schema; } return schema; } function getSchemaByPath(schema, path) { const keys = path.split('.'); let current = unwrapEffects(schema); for (const key of keys) { if (current instanceof z.ZodObject) { current = unwrapEffects(current.shape[key]); } else if (current instanceof z.ZodArray) { const index = Number(key); if (isNaN(index)) return null; current = unwrapEffects(current._def.type); } else { return null; } } return current; } export function zodValidator(schema, formData, field) { const errors = {}; if (!field) { const result = schema.safeParse(formData); if (!result.success) { return flattenZodErrors(result.error.format()); } return {}; // no errors } const fields = Array.isArray(field) ? field : [field]; // Validate full form once (to catch cross-field refine errors) const fullResult = schema.safeParse(formData); const fullFlat = fullResult.success ? {} : flattenZodErrors(fullResult.error.format()); for (const f of fields) { const fieldSchema = getSchemaByPath(schema, f); if (fieldSchema) { const value = getByPath(formData, f); const result = fieldSchema.safeParse(value); if (!result.success) { const flat = flattenZodErrors(result.error.format()); if (flat[f]) errors[f] = flat[f]; } } // Merge any errors from full schema (refine/cross-field) if (fullFlat[f]) { errors[f] = fullFlat[f]; } } return errors; }