import type { Context, MiddlewareHandler, Env, ValidationTargets, TypedResponse } from 'hono' import { validator } from 'hono/validator' import type { IValidation } from 'typia' export type Hook = ( result: IValidation.ISuccess | { success: false; errors: IValidation.IError[]; data: T }, c: Context ) => Response | Promise | void | Promise | TypedResponse // eslint-disable-next-line @typescript-eslint/no-explicit-any export type Validation = (input: unknown) => IValidation export type OutputType = T extends Validation ? O : never export const typiaValidator = < T extends Validation, O extends OutputType, Target extends keyof ValidationTargets, E extends Env, P extends string, V extends { in: { [K in Target]: O } out: { [K in Target]: O } } = { in: { [K in Target]: O } out: { [K in Target]: O } }, >( target: Target, validate: T, hook?: Hook ): MiddlewareHandler => // @ts-expect-error not typed well validator(target, async (value, c) => { const result = validate(value) if (hook) { const hookResult = await hook({ ...result, data: value }, c) if (hookResult) { if (hookResult instanceof Response || hookResult instanceof Promise) { return hookResult } if ('response' in hookResult) { return hookResult.response } } } if (!result.success) { return c.json({ success: false, error: result.errors }, 400) } return result.data })