fix(zod-validator): validator support async hook (#552)

* fix(zod-validator): validator support async hook

* fix

* changeset

* refactor

* chore: format (includes other middleware)

* fix

* revert

* Revert "chore: format (includes other middleware)"

This reverts commit 16b4462014.

* changeset

* revert
pull/554/head
Ame_x 2024-06-01 11:35:21 +09:00 committed by GitHub
parent 63898bbdab
commit aa05549497
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 67 additions and 11 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/zod-validator': patch
---
fix: support async hook

View File

@ -5,7 +5,7 @@ import type { z, ZodSchema, ZodError } from 'zod'
export type Hook<T, E extends Env, P extends string, O = {}> = ( export type Hook<T, E extends Env, P extends string, O = {}> = (
result: { success: true; data: T } | { success: false; error: ZodError; data: T }, result: { success: true; data: T } | { success: false; error: ZodError; data: T },
c: Context<E, P> c: Context<E, P>
) => Response | Promise<Response> | void | Promise<Response | void> | TypedResponse<O> ) => Response | void | TypedResponse<O> | Promise<Response | void | TypedResponse<O>>
type HasUndefined<T> = undefined extends T ? true : false type HasUndefined<T> = undefined extends T ? true : false
@ -45,11 +45,12 @@ export const zValidator = <
const result = await schema.safeParseAsync(value) const result = await schema.safeParseAsync(value)
if (hook) { if (hook) {
const hookResult = hook({ data: value, ...result }, c) const hookResult = await hook({ data: value, ...result }, c)
if (hookResult) { if (hookResult) {
if (hookResult instanceof Response || hookResult instanceof Promise) { if (hookResult instanceof Response) {
return hookResult return hookResult
} }
if ('response' in hookResult) { if ('response' in hookResult) {
return hookResult.response return hookResult.response
} }
@ -60,6 +61,5 @@ export const zValidator = <
return c.json(result, 400) return c.json(result, 400)
} }
const data = result.data as z.infer<T> return result.data as z.infer<T>
return data
}) })

View File

@ -159,15 +159,66 @@ describe('With Hook', () => {
if (!result.success) { if (!result.success) {
return c.text(`${result.data.id} is invalid!`, 400) return c.text(`${result.data.id} is invalid!`, 400)
} }
const data = result.data
return c.text(`${data.id} is valid!`)
}), }),
(c) => { (c) => {
const data = c.req.valid('json') const data = c.req.valid('json')
return c.json({ return c.text(`${data.id} is valid!`)
success: true, }
message: `${data.id} is ${data.title}`, )
})
it('Should return 200 response', async () => {
const req = new Request('http://localhost/post', {
body: JSON.stringify({
id: 123,
title: 'Hello',
}),
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
})
const res = await app.request(req)
expect(res).not.toBeNull()
expect(res.status).toBe(200)
expect(await res.text()).toBe('123 is valid!')
})
it('Should return 400 response', async () => {
const req = new Request('http://localhost/post', {
body: JSON.stringify({
id: '123',
title: 'Hello',
}),
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
})
const res = await app.request(req)
expect(res).not.toBeNull()
expect(res.status).toBe(400)
expect(await res.text()).toBe('123 is invalid!')
})
})
describe('With Async Hook', () => {
const app = new Hono()
const schema = z.object({
id: z.number(),
title: z.string(),
})
app.post(
'/post',
zValidator('json', schema, async (result, c) => {
if (!result.success) {
return c.text(`${result.data.id} is invalid!`, 400)
}
}),
(c) => {
const data = c.req.valid('json')
return c.text(`${data.id} is valid!`)
} }
) )