import type { z } from "zod"; export type FormSubmitResult = | { toast?: string; close?: boolean; reset?: boolean; error?: | string | { what: string; where: string } | { what: string; where: string }[]; } | undefined; export function defineFormHandler( schema: TSchema, action: (input: z.output) => Promise, ): (form: FormData) => Promise; export function defineFormHandler< TAction extends (form: FormData) => Promise, >(action: TAction): TAction; export function defineFormHandler( schemaOrAction: z.ZodType | ((form: FormData) => Promise), action?: (input: unknown) => Promise, ): (form: FormData) => Promise { if (!action) return schemaOrAction as (form: FormData) => Promise; const schema = schemaOrAction as z.ZodType; return async (form: FormData) => { // "use server"; const raw = Object.fromEntries([...form.entries()]); const parsed = schema.safeParse(raw); if (!parsed.success) { return { error: parsed.error.issues.map((issue) => ({ what: issue.message, where: issue.path.join("."), })), }; } return action(parsed.data); }; } export function formParse( schema: TSchema, data: FormData, ): { $: z.output; error: { what: string; where: string }[] | string } { const raw = Object.fromEntries([...data.entries()]); const parsed = schema.safeParse(raw); if (!parsed.success) { if ( parsed.error.issues.length === 1 && parsed.error.issues[0].path.length === 0 ) return { error: parsed.error.issues[0].message, $: undefined as any }; return { error: parsed.error.issues.map((issue) => ({ what: issue.message, where: issue.path.join("."), })), $: undefined as any, }; } return { $: parsed.data, error: undefined as any }; }