Skip to content

Commit eda3584

Browse files
authoredSep 26, 2024··
feat(zod-validator): pass target from zod-validator to a hook (#695)
* feat(zod-validator): passing target to hook * feat(zod-validator): trigger githubaction * feat(zod-validator): add changeset * feat: pass narrower type to zod validation hook
1 parent 45f5d45 commit eda3584

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed
 

‎.changeset/olive-hounds-shout.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hono/zod-validator': minor
3+
---
4+
5+
feat(zod-validator): pass target to a hook

‎packages/zod-validator/src/index.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import type { Context, MiddlewareHandler, Env, ValidationTargets, TypedResponse,
22
import { validator } from 'hono/validator'
33
import type { z, ZodSchema, ZodError } from 'zod'
44

5-
export type Hook<T, E extends Env, P extends string, O = {}> = (
6-
result: { success: true; data: T } | { success: false; error: ZodError; data: T },
7-
c: Context<E, P>
5+
export type Hook<T, E extends Env, P extends string, Target extends keyof ValidationTargets = keyof ValidationTargets, O = {}> = (
6+
result: ({ success: true; data: T} | { success: false; error: ZodError; data: T }) & {target: Target },
7+
c: Context<E, P>,
88
) => Response | void | TypedResponse<O> | Promise<Response | void | TypedResponse<O>>
99

1010
type HasUndefined<T> = undefined extends T ? true : false
@@ -38,14 +38,14 @@ export const zValidator = <
3838
>(
3939
target: Target,
4040
schema: T,
41-
hook?: Hook<z.infer<T>, E, P>
41+
hook?: Hook<z.infer<T>, E, P, Target>
4242
): MiddlewareHandler<E, P, V> =>
4343
// @ts-expect-error not typed well
4444
validator(target, async (value, c) => {
4545
const result = await schema.safeParseAsync(value)
4646

4747
if (hook) {
48-
const hookResult = await hook({ data: value, ...result }, c)
48+
const hookResult = await hook({ data: value, ...result, target, }, c)
4949
if (hookResult) {
5050
if (hookResult instanceof Response) {
5151
return hookResult

‎packages/zod-validator/test/index.test.ts

+45
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Hono } from 'hono'
22
import type { Equal, Expect } from 'hono/utils/types'
33
import { z } from 'zod'
44
import { zValidator } from '../src'
5+
import {vi} from 'vitest'
6+
57

68
// eslint-disable-next-line @typescript-eslint/no-unused-vars
79
type ExtractSchema<T> = T extends Hono<infer _, infer S> ? S : never
@@ -256,3 +258,46 @@ describe('With Async Hook', () => {
256258
expect(await res.text()).toBe('123 is invalid!')
257259
})
258260
})
261+
262+
263+
describe('With target', () => {
264+
it('should call hook for correctly validated target', async () => {
265+
const app = new Hono()
266+
267+
const schema = z.object({
268+
id: z.string(),
269+
})
270+
271+
const jsonHook = vi.fn()
272+
const paramHook = vi.fn()
273+
const queryHook = vi.fn()
274+
app.post(
275+
'/:id/post',
276+
zValidator('json', schema, jsonHook),
277+
zValidator('param', schema, paramHook),
278+
zValidator('query', schema, queryHook),
279+
(c) => {
280+
return c.text('ok')
281+
}
282+
)
283+
284+
const req = new Request('http://localhost/1/post?id=2', {
285+
body: JSON.stringify({
286+
id: '3',
287+
}),
288+
method: 'POST',
289+
headers: {
290+
'Content-Type': 'application/json',
291+
},
292+
})
293+
294+
const res = await app.request(req)
295+
expect(res).not.toBeNull()
296+
expect(res.status).toBe(200)
297+
expect(await res.text()).toBe('ok')
298+
expect(paramHook).toHaveBeenCalledWith({data: {id: '1'}, success: true, target:
299+
'param'}, expect.anything())
300+
expect(queryHook).toHaveBeenCalledWith({data: {id: '2'}, success: true, target: 'query'}, expect.anything())
301+
expect(jsonHook).toHaveBeenCalledWith({data: {id: '3'}, success: true, target: 'json'}, expect.anything())
302+
})
303+
})

0 commit comments

Comments
 (0)
Please sign in to comment.