diff --git a/.changeset/itchy-spiders-explain.md b/.changeset/itchy-spiders-explain.md new file mode 100644 index 00000000..d687e25e --- /dev/null +++ b/.changeset/itchy-spiders-explain.md @@ -0,0 +1,5 @@ +--- +'@hono/typebox-validator': patch +--- + +Fix fail case not returning error array in hook diff --git a/packages/typebox-validator/src/index.ts b/packages/typebox-validator/src/index.ts index 81c12521..2f52ee83 100644 --- a/packages/typebox-validator/src/index.ts +++ b/packages/typebox-validator/src/index.ts @@ -72,6 +72,15 @@ export function tbValidator< } return data } - return c.json({ success: false, errors: [...Value.Errors(schema, data)] }, 400) + + const errors = Array.from(Value.Errors(schema, data)); + if (hook) { + const hookResult = hook({ success: false, errors }, c); + if (hookResult instanceof Response || hookResult instanceof Promise) { + return hookResult; + } + } + + return c.json({ success: false, errors }, 400); }) } diff --git a/packages/typebox-validator/test/index.test.ts b/packages/typebox-validator/test/index.test.ts index 6699f795..1d808477 100644 --- a/packages/typebox-validator/test/index.test.ts +++ b/packages/typebox-validator/test/index.test.ts @@ -1,7 +1,8 @@ -import { Type as T } from '@sinclair/typebox' +import { Type as T, TypeBoxError } from '@sinclair/typebox'; import { Hono } from 'hono' import type { Equal, Expect } from 'hono/utils/types' import { tbValidator } from '../src' +import { ValueError } from '@sinclair/typebox/value'; // eslint-disable-next-line @typescript-eslint/no-unused-vars type ExtractSchema = T extends Hono ? S : never @@ -106,6 +107,18 @@ describe('With Hook', () => { message: `${data.id} is ${data.title}`, }) } + ).post( + '/errorTest', + tbValidator('json', schema, (result, c) => { + return c.json(result, 400) + }), + (c) => { + const data = c.req.valid('json') + return c.json({ + success: true, + message: `${data.id} is ${data.title}`, + }) + } ) it('Should return 200 response', async () => { @@ -140,4 +153,39 @@ describe('With Hook', () => { expect(res).not.toBeNull() expect(res.status).toBe(400) }) + + it('Should return 400 response and error array', async () => { + const req = new Request('http://localhost/errorTest', { + body: JSON.stringify({ + id: 123, + }), + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }) + const res = await app.request(req) + expect(res).not.toBeNull() + expect(res.status).toBe(400) + + const {errors, success} = (await res.json()) as { success: boolean; errors: any[] } + expect(success).toBe(false) + expect(Array.isArray(errors)).toBe(true) + expect(errors.map((e: ValueError) => ({ + 'type': e?.schema?.type, + path: e?.path, + message: e?.message + }))).toEqual([ + { + "type": "string", + "path": "/title", + "message": "Required property" + }, + { + "type": "string", + "path": "/title", + "message": "Expected string" + } + ]) + }) })