From dadf5ce3c2c134b83420702ca8fe13d6fb8d9390 Mon Sep 17 00:00:00 2001 From: Axel Meinhardt <26243798+ameinhardt@users.noreply.github.com> Date: Sun, 25 Aug 2024 11:01:09 +0800 Subject: [PATCH] feat(zod-openapi): allow multiple mimetype (#710) * feat(zod-openapi): allow multiple mimetype Signed-off-by: Axel Meinhardt <26243798+ameinhardt@users.noreply.github.com> * simplify the test --------- Signed-off-by: Axel Meinhardt <26243798+ameinhardt@users.noreply.github.com> Co-authored-by: Yusuke Wada --- .changeset/clean-buses-shop.md | 5 ++ packages/zod-openapi/src/index.ts | 2 +- packages/zod-openapi/test/index.test.ts | 61 +++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 .changeset/clean-buses-shop.md diff --git a/.changeset/clean-buses-shop.md b/.changeset/clean-buses-shop.md new file mode 100644 index 00000000..e04fa704 --- /dev/null +++ b/.changeset/clean-buses-shop.md @@ -0,0 +1,5 @@ +--- +'@hono/zod-openapi': minor +--- + +Allow multiple mime type response diff --git a/packages/zod-openapi/src/index.ts b/packages/zod-openapi/src/index.ts index 1b3df225..b1360a57 100644 --- a/packages/zod-openapi/src/index.ts +++ b/packages/zod-openapi/src/index.ts @@ -180,7 +180,7 @@ export type RouteConfigToTypedResponse = { : TypedResponse< JSONParsed>, ExtractStatusCode, - 'json' + 'json' | 'text' > }[keyof R['responses'] & RouteConfigStatusCode] diff --git a/packages/zod-openapi/test/index.test.ts b/packages/zod-openapi/test/index.test.ts index 3c819488..396429a6 100644 --- a/packages/zod-openapi/test/index.test.ts +++ b/packages/zod-openapi/test/index.test.ts @@ -8,6 +8,7 @@ import { OpenAPIHono, createRoute, z } from '../src/index' import type { Equal, Expect } from 'hono/utils/types' import type { ServerErrorStatusCode } from 'hono/utils/http-status' import { stringify } from 'yaml' +import { accepts } from 'hono/accepts' describe('Constructor', () => { it('Should not require init object', () => { @@ -788,6 +789,60 @@ describe('JSON and Form', () => { }) }) +describe('JSON and Text response', () => { + const route = createRoute({ + method: 'get', + path: '/hello', + responses: { + 200: { + content: { + 'application/json': { + schema: z.object({}), + }, + 'text/plain': { + schema: z.string(), + }, + }, + description: 'response', + }, + }, + }) + + const app = new OpenAPIHono() + + app.openapi(route, (c) => { + const mimeTypes = ['application/json', 'text/plain'] + if ( + accepts(c, { + default: mimeTypes[0], + header: 'Accept', + supports: mimeTypes, + }) === mimeTypes[0] + ) { + return c.json({}) + } + return c.text('') + }) + + test('should respond with JSON fallback', async () => { + const res = await app.request('/hello', { + method: 'GET', + }) + expect(res.status).toBe(200) + expect(await res.json()).toEqual({}) + }) + test('should respond with Text', async () => { + const res = await app.request('/hello', { + method: 'GET', + headers: { + accept: 'text/plain', + }, + }) + expect(res.status).toBe(200) + expect(await res.text()).toEqual('') + }) +}) + describe('Input types', () => { const ParamsSchema = z.object({ id: z @@ -1724,21 +1779,21 @@ describe('RouteConfigToTypedResponse', () => { age: number }, 200, - 'json' + 'json' | 'text' > | TypedResponse< { ok: boolean }, 400, - 'json' + 'json' | 'text' > | TypedResponse< { ok: boolean }, ServerErrorStatusCode, - 'json' + 'json' | 'text' > type verify = Expect> })