0
0
mirror of https://github.com/honojs/hono.git synced 2024-11-29 17:46:30 +01:00
hono/deno_dist/validator/validator.ts
Yusuke Wada 9c4197a772
feat(validator): support type transformation (#969)
* feat(validator): support type transformation

* denoify

* create `ValidationFunction` and add a test

* denoify

* rename

* denoify
2023-03-11 22:17:08 +09:00

74 lines
2.0 KiB
TypeScript

import type { Context } from '../context.ts'
import type { Env, ValidationTargets, MiddlewareHandler } from '../types.ts'
import { parseBody } from '../utils/body.ts'
type ValidationTargetKeysWithBody = 'form' | 'json'
type ValidationTargetByMethod<M> = M extends 'get' | 'head' // GET and HEAD request must not have a body content.
? Exclude<keyof ValidationTargets, ValidationTargetKeysWithBody>
: keyof ValidationTargets
export type ValidationFunction<InputType, OutputType, E extends Env = {}> = (
value: InputType,
c: Context<E>
) => OutputType | Response | Promise<Response>
export const validator = <
InputType,
P extends string,
M extends string,
U extends ValidationTargetByMethod<M>,
OutputType = ValidationTargets[U],
V extends {
in: { [K in U]: unknown extends InputType ? OutputType : InputType }
out: { [K in U]: OutputType }
} = {
in: { [K in U]: unknown extends InputType ? OutputType : InputType }
out: { [K in U]: OutputType }
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
E extends Env = any
>(
target: U,
validationFunc: ValidationFunction<InputType, OutputType, E>
): MiddlewareHandler<E, P, V> => {
return async (c, next) => {
let value = {}
switch (target) {
case 'json':
try {
value = await c.req.raw.clone().json()
} catch {
console.error('Error: Malformed JSON in request body')
return c.json(
{
success: false,
message: 'Malformed JSON in request body',
},
400
)
}
break
case 'form':
value = await parseBody(c.req.raw.clone())
break
case 'query':
value = c.req.query()
break
case 'queries':
value = c.req.queries()
break
}
const res = validationFunc(value as InputType, c)
if (res instanceof Response || res instanceof Promise) {
return res
}
c.req.addValidatedData(target, res as never)
await next()
}
}