import type { Context, MiddlewareHandler, Env, ValidationTargets, TypedResponse } from 'hono' import { validator } from 'hono/validator' import type { z, ZodSchema, ZodError } from 'zod' export type Hook = ( result: { success: true; data: T } | { success: false; error: ZodError; data: T }, c: Context ) => | Response | Promise | void | Promise | TypedResponse | Promise> | Promise | void> export const zValidator = < T extends ZodSchema, Target extends keyof ValidationTargets, E extends Env, P extends string, V extends { in: { [K in Target]: z.input } out: { [K in Target]: z.output } } = { in: { [K in Target]: z.input } out: { [K in Target]: z.output } } >( target: Target, schema: T, hook?: Hook, E, P> ): MiddlewareHandler => validator(target, (value, c) => { const result = schema.safeParse(value) if (hook) { const hookResult = hook({ data: value, ...result }, c) if ( hookResult && (hookResult instanceof Response || hookResult instanceof Promise || 'response' in hookResult) ) { return hookResult } } if (!result.success) { return c.json(result, 400) } const data = result.data as z.infer return data })