From 31a74267686376bc2e37682dfa672780f92e7136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Ortiz?= Date: Fri, 27 Dec 2024 12:30:47 -0500 Subject: [PATCH 1/4] fix(valibot-validator): Fix query types on RPC --- packages/valibot-validator/src/index.ts | 56 +++++++++++++++---------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/packages/valibot-validator/src/index.ts b/packages/valibot-validator/src/index.ts index 75fb4a7c..989323c6 100644 --- a/packages/valibot-validator/src/index.ts +++ b/packages/valibot-validator/src/index.ts @@ -1,4 +1,4 @@ -import type { Context, Env, Input as HonoInput, MiddlewareHandler, ValidationTargets } from 'hono' +import type { Context, Env, Input, MiddlewareHandler, TypedResponse, ValidationTargets } from 'hono' import { validator } from 'hono/validator' import type { GenericSchema, @@ -7,12 +7,20 @@ import type { InferOutput, SafeParseResult, } from 'valibot' -import { safeParseAsync } from 'valibot' +import { flatten, safeParseAsync } from 'valibot' -export type Hook = ( - result: SafeParseResult, +export type Hook< + T extends GenericSchema | GenericSchemaAsync, + E extends Env, + P extends string, + Target extends keyof ValidationTargets = keyof ValidationTargets, + O = {} +> = ( + result: SafeParseResult & { + target: Target + }, c: Context -) => Response | Promise | void | Promise +) => Response | void | TypedResponse | Promise> type HasUndefined = undefined extends T ? true : false @@ -23,20 +31,16 @@ export const vValidator = < P extends string, In = InferInput, Out = InferOutput, - I extends HonoInput = { + I extends Input = { in: HasUndefined extends true ? { - [K in Target]?: K extends 'json' + [K in Target]?: In extends ValidationTargets[K] ? In - : HasUndefined extends true - ? { [K2 in keyof In]?: ValidationTargets[K][K2] } - : { [K2 in keyof In]: ValidationTargets[K][K2] } + : { [K2 in keyof In]?: ValidationTargets[K][K2] } } : { - [K in Target]: K extends 'json' + [K in Target]: In extends ValidationTargets[K] ? In - : HasUndefined extends true - ? { [K2 in keyof In]?: ValidationTargets[K][K2] } : { [K2 in keyof In]: ValidationTargets[K][K2] } } out: { [K in Target]: Out } @@ -45,23 +49,31 @@ export const vValidator = < >( target: Target, schema: T, - hook?: Hook + hook?: Hook ): MiddlewareHandler => // @ts-expect-error not typed well validator(target, async (value, c) => { - const result = await safeParseAsync(schema, value) + const parsed = await safeParseAsync(schema, value) if (hook) { - const hookResult = hook(result, c) - if (hookResult instanceof Response || hookResult instanceof Promise) { - return hookResult + const hookResult = await hook({ ...parsed, target }, c) + if (hookResult) { + if (hookResult instanceof Response) { + return hookResult + } + + if ('response' in hookResult) { + return hookResult.response + } } } - if (!result.success) { - return c.json(result, 400) + if (!parsed.success) { + return c.json({ + target, + issues: flatten(parsed.issues) + }, 400) } - const data = result.output as InferOutput - return data + return parsed.output }) From f3dcb057e890370bee1a4bd66911ac875de23005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Ortiz?= Date: Fri, 27 Dec 2024 12:48:08 -0500 Subject: [PATCH 2/4] Add changeset --- .changeset/warm-plants-thank.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/warm-plants-thank.md diff --git a/.changeset/warm-plants-thank.md b/.changeset/warm-plants-thank.md new file mode 100644 index 00000000..aa241c8e --- /dev/null +++ b/.changeset/warm-plants-thank.md @@ -0,0 +1,5 @@ +--- +'@hono/valibot-validator': patch +--- + +Fix request query types for valibot schemas From 739a8de63b82f9e2600911520373133d3d37c84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Ortiz?= Date: Tue, 7 Jan 2025 08:24:03 -0500 Subject: [PATCH 3/4] Remove valibot issue flatenning --- packages/valibot-validator/src/index.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/valibot-validator/src/index.ts b/packages/valibot-validator/src/index.ts index 989323c6..438cbc95 100644 --- a/packages/valibot-validator/src/index.ts +++ b/packages/valibot-validator/src/index.ts @@ -7,7 +7,7 @@ import type { InferOutput, SafeParseResult, } from 'valibot' -import { flatten, safeParseAsync } from 'valibot' +import { safeParseAsync } from 'valibot' export type Hook< T extends GenericSchema | GenericSchemaAsync, @@ -53,10 +53,10 @@ export const vValidator = < ): MiddlewareHandler => // @ts-expect-error not typed well validator(target, async (value, c) => { - const parsed = await safeParseAsync(schema, value) + const result = await safeParseAsync(schema, value) if (hook) { - const hookResult = await hook({ ...parsed, target }, c) + const hookResult = await hook({ ...result, target }, c) if (hookResult) { if (hookResult instanceof Response) { return hookResult @@ -68,12 +68,9 @@ export const vValidator = < } } - if (!parsed.success) { - return c.json({ - target, - issues: flatten(parsed.issues) - }, 400) + if (!result.success) { + return c.json(result, 400) } - return parsed.output + return result.output }) From 72ce1ce2ed7eaeb3990606032fa0fa7a791f8f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Ortiz?= Date: Tue, 7 Jan 2025 08:29:50 -0500 Subject: [PATCH 4/4] Add types test --- packages/valibot-validator/test/index.test.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/valibot-validator/test/index.test.ts b/packages/valibot-validator/test/index.test.ts index d50fd78e..2c16d761 100644 --- a/packages/valibot-validator/test/index.test.ts +++ b/packages/valibot-validator/test/index.test.ts @@ -324,3 +324,28 @@ describe('With Hook Async', () => { expect(res.status).toBe(400) }) }) + +describe('Test types', () => { + it('Should return correct types when validating a query', () => { + const app = new Hono() + + const routes = app.post( + '/', + vValidator( + 'query', + object({ + foo: string(), + }) + ), + (c) => { + return c.json(c.req.valid('query')) + } + ) + + type T = ExtractSchema + + type Actual = T['/']['$post']['input']['query'] + type Expected = { foo: string } + type verify = Expect> + }) +})