import type { Context, Env, Input as HonoInput, MiddlewareHandler, ValidationTargets } from 'hono' import { validator } from 'hono/validator' import type { GenericSchema, GenericSchemaAsync, InferInput, InferOutput, SafeParseResult } from 'valibot' import { safeParseAsync } from 'valibot' type Hook = ( result: SafeParseResult, c: Context ) => Response | Promise | void | Promise type HasUndefined = undefined extends T ? true : false export const vValidator = < T extends GenericSchema | GenericSchemaAsync, Target extends keyof ValidationTargets, E extends Env, P extends string, In = InferInput, Out = InferOutput, I extends HonoInput = { in: HasUndefined extends true ? { [K in Target]?: K extends 'json' ? In : HasUndefined extends true ? { [K2 in keyof In]?: ValidationTargets[K][K2] } : { [K2 in keyof In]: ValidationTargets[K][K2] } } : { [K in Target]: K extends 'json' ? In : HasUndefined extends true ? { [K2 in keyof In]?: ValidationTargets[K][K2] } : { [K2 in keyof In]: ValidationTargets[K][K2] } } out: { [K in Target]: Out } }, V extends I = I >( target: Target, schema: T, hook?: Hook ): MiddlewareHandler => // @ts-expect-error not typed well validator(target, async (value, c) => { const result = await safeParseAsync(schema, value) if (hook) { const hookResult = hook(result, c) if (hookResult instanceof Response || hookResult instanceof Promise) { return hookResult } } if (!result.success) { return c.json(result, 400) } const data = result.output as InferOutput return data })