UNPKG

@faivform/zod

Version:

Adapter to use Zod with @tuentyfaiv/svelte-form

79 lines (78 loc) 2.32 kB
import { Adapter } from "@tuentyfaiv/svelte-form"; import { ZodError, ZodObject } from "zod"; class ZodAdapter extends Adapter { #schema; #resolveDeep; constructor(config) { super(); this.#schema = config.schema; this.#resolveDeep = config.resolveDeep; Object.freeze(this); } #setError = async (field, errros, error) => { let message = null; if (error instanceof ZodError) { message = error.issues.reduce((_, issue) => issue.message, ""); } await errros.update((prev) => ({ ...prev, [field]: message })); }; initial = () => { const start = Object.entries(this.#schema.shape).reduce((acc, [key, three]) => ({ fields: { ...acc.fields, [key]: this.#resolveDeep(three), }, errors: { ...acc.errors, [key]: null, }, }), { fields: {}, errors: {}, }); return start; }; validate = async (data) => { await this.#schema.parse(data); }; field = async (field, value, errors) => { try { this.#schema.shape[field].parse(value); await this.#setError(field, errors); } catch (error) { await this.#setError(field, errors, error); } }; errors = async (error, errors, handle) => { await handle?.(error); if (error instanceof ZodError) { const messages = error.issues.reduce((acc, issue) => ({ ...acc, [issue.path.join(".")]: issue.message, }), {}); await errors.update((prev) => ({ ...prev, ...messages, })); } }; } export function adapter(schema) { const resolveDeep = (three) => { if (three instanceof ZodObject) { return Object.entries(three.shape).reduce((acc, [key, value]) => ({ ...acc, [key]: resolveDeep(value), }), {}); } if (three.isNullable()) { return null; } if (three.isOptional()) { return undefined; } return null; }; return new ZodAdapter({ schema, resolveDeep }); }