diff --git a/.changeset/plenty-tables-beg.md b/.changeset/plenty-tables-beg.md new file mode 100644 index 00000000..0e115423 --- /dev/null +++ b/.changeset/plenty-tables-beg.md @@ -0,0 +1,5 @@ +--- +'@hono/zod-openapi': minor +--- + +extract range definitions to StatusCode diff --git a/packages/zod-openapi/src/index.ts b/packages/zod-openapi/src/index.ts index 786964af..96f670c2 100644 --- a/packages/zod-openapi/src/index.ts +++ b/packages/zod-openapi/src/index.ts @@ -27,7 +27,14 @@ import type { TypedResponse, } from 'hono' import type { MergePath, MergeSchemaPath } from 'hono/types' -import type { StatusCode } from 'hono/utils/http-status' +import type { + ClientErrorStatusCode, + InfoStatusCode, + RedirectStatusCode, + ServerErrorStatusCode, + StatusCode, + SuccessStatusCode, +} from 'hono/utils/http-status' import type { Prettify, RemoveBlankRecord } from 'hono/utils/types' import { mergePath } from 'hono/utils/url' import type { AnyZodObject, ZodSchema, ZodError } from 'zod' @@ -143,13 +150,28 @@ type ExtractContent = T extends { : never : never +type StatusCodeRangeDefinitions = { + '1XX': InfoStatusCode + '2XX': SuccessStatusCode + '3XX': RedirectStatusCode + '4XX': ClientErrorStatusCode + '5XX': ServerErrorStatusCode +} +type RouteConfigStatusCode = keyof StatusCodeRangeDefinitions | StatusCode +type ExtractStatusCode = T extends keyof StatusCodeRangeDefinitions + ? StatusCodeRangeDefinitions[T] + : T export type RouteConfigToTypedResponse = { - [Status in keyof R['responses'] & StatusCode]: IsJson< + [Status in keyof R['responses'] & RouteConfigStatusCode]: IsJson< keyof R['responses'][Status]['content'] > extends never - ? TypedResponse<{}, Status, string> - : TypedResponse, Status, 'json'> -}[keyof R['responses'] & StatusCode] + ? TypedResponse<{}, ExtractStatusCode, string> + : TypedResponse< + ExtractContent, + ExtractStatusCode, + 'json' + > +}[keyof R['responses'] & RouteConfigStatusCode] export type Hook = ( result: diff --git a/packages/zod-openapi/test/index.test.ts b/packages/zod-openapi/test/index.test.ts index 40efe279..e3286846 100644 --- a/packages/zod-openapi/test/index.test.ts +++ b/packages/zod-openapi/test/index.test.ts @@ -4,6 +4,7 @@ import { hc } from 'hono/client' import { describe, it, expect, expectTypeOf } from 'vitest' import { OpenAPIHono, createRoute, z, RouteConfigToTypedResponse } from '../src/index' import { Expect, Equal } from 'hono/utils/types' +import { ServerErrorStatusCode } from 'hono/utils/http-status' describe('Constructor', () => { it('Should not require init object', () => { @@ -200,11 +201,19 @@ describe('Basic - params', () => { responses: { '200': { description: 'Get the user', - content: { 'application/json': { schema: { $ref: '#/components/schemas/User' } } }, + content: { + 'application/json': { + schema: { $ref: '#/components/schemas/User' }, + }, + }, }, '400': { description: 'Error!', - content: { 'application/json': { schema: { $ref: '#/components/schemas/Error' } } }, + content: { + 'application/json': { + schema: { $ref: '#/components/schemas/Error' }, + }, + }, }, }, }, @@ -1465,6 +1474,14 @@ describe('RouteConfigToTypedResponse', () => { }, description: 'Error!', }, + '5XX': { + content: { + 'application/json': { + schema: ErrorSchema, + }, + }, + description: 'Server Error!', + }, }, } @@ -1486,6 +1503,13 @@ describe('RouteConfigToTypedResponse', () => { 400, 'json' > + | TypedResponse< + { + ok: boolean + }, + ServerErrorStatusCode, + 'json' + > type verify = Expect> }) })