fix(valibot-validator): make validation input optional when schema is optional (#384)

* chore(valibot-validator): Replace `jsonT` in tests

* fix(valibot-validator): Handle optional schema

* test(valibot-validator): Update tests

* chore(valibot-validator): Add changeset

* chore(valibot-validator): Fix formatting
pull/392/head
Andrew 2024-02-14 21:38:43 +01:00 committed by GitHub
parent df8d403182
commit 9b57c3bb30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 11 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/valibot-validator': patch
---
fix(valibot-validator): make validation input optional when schema is optional

View File

@ -8,16 +8,22 @@ type Hook<T extends BaseSchema, E extends Env, P extends string> = (
c: Context<E, P>
) => Response | Promise<Response> | void | Promise<Response | void>
type HasUndefined<T> = undefined extends T ? true : false
export const vValidator = <
T extends BaseSchema,
Target extends keyof ValidationTargets,
E extends Env,
P extends string,
V extends {
in: { [K in Target]: Input<T> }
in: HasUndefined<Input<T>> extends true
? { [K in Target]?: Input<T> }
: { [K in Target]: Input<T> }
out: { [K in Target]: Output<T> }
} = {
in: { [K in Target]: Input<T> }
in: HasUndefined<Input<T>> extends true
? { [K in Target]?: Input<T> }
: { [K in Target]: Input<T> }
out: { [K in Target]: Output<T> }
}
>(

View File

@ -1,6 +1,6 @@
import { Hono } from 'hono'
import type { Equal, Expect } from 'hono/utils/types'
import { number, object, string } from 'valibot'
import { number, object, string, optional } from 'valibot'
import { vValidator } from '../src'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@ -14,13 +14,26 @@ describe('Basic', () => {
age: number(),
})
const route = app.post('/author', vValidator('json', schema), (c) => {
const data = c.req.valid('json')
return c.jsonT({
success: true,
message: `${data.name} is ${data.age}`,
const querySchema = optional(
object({
search: optional(string()),
})
})
)
const route = app.post(
'/author',
vValidator('json', schema),
vValidator('query', querySchema),
(c) => {
const data = c.req.valid('json')
const query = c.req.valid('query')
return c.json({
success: true,
message: `${data.name} is ${data.age}, search is ${query?.search}`,
})
}
)
type Actual = ExtractSchema<typeof route>
type Expected = {
@ -31,6 +44,12 @@ describe('Basic', () => {
name: string
age: number
}
} & {
query?:
| {
search?: string | undefined
}
| undefined
}
output: {
success: boolean
@ -44,7 +63,7 @@ describe('Basic', () => {
type verify = Expect<Equal<Expected, Actual>>
it('Should return 200 response', async () => {
const req = new Request('http://localhost/author', {
const req = new Request('http://localhost/author?search=hello', {
body: JSON.stringify({
name: 'Superman',
age: 20,
@ -59,7 +78,7 @@ describe('Basic', () => {
expect(res.status).toBe(200)
expect(await res.json()).toEqual({
success: true,
message: 'Superman is 20',
message: 'Superman is 20, search is hello',
})
})