fix(zod-openapi): support default response (#855)
* fix(zod-openapi): support default response * chore: changesetpull/858/head
parent
b1fdf7202f
commit
3f63c46fa6
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@hono/zod-openapi': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: support default response
|
|
@ -194,16 +194,26 @@ type RouteConfigStatusCode = keyof StatusCodeRangeDefinitions | StatusCode
|
||||||
type ExtractStatusCode<T extends RouteConfigStatusCode> = T extends keyof StatusCodeRangeDefinitions
|
type ExtractStatusCode<T extends RouteConfigStatusCode> = T extends keyof StatusCodeRangeDefinitions
|
||||||
? StatusCodeRangeDefinitions[T]
|
? StatusCodeRangeDefinitions[T]
|
||||||
: T
|
: T
|
||||||
export type RouteConfigToTypedResponse<R extends RouteConfig> = {
|
type DefinedStatusCodes<R extends RouteConfig> = keyof R['responses'] & RouteConfigStatusCode
|
||||||
[Status in keyof R['responses'] &
|
export type RouteConfigToTypedResponse<R extends RouteConfig> =
|
||||||
RouteConfigStatusCode]: undefined extends R['responses'][Status]['content']
|
| {
|
||||||
|
[Status in DefinedStatusCodes<R>]: undefined extends R['responses'][Status]['content']
|
||||||
? TypedResponse<{}, ExtractStatusCode<Status>, string>
|
? TypedResponse<{}, ExtractStatusCode<Status>, string>
|
||||||
: ReturnJsonOrTextOrResponse<
|
: ReturnJsonOrTextOrResponse<
|
||||||
keyof R['responses'][Status]['content'],
|
keyof R['responses'][Status]['content'],
|
||||||
ExtractContent<R['responses'][Status]['content']>,
|
ExtractContent<R['responses'][Status]['content']>,
|
||||||
Status
|
Status
|
||||||
>
|
>
|
||||||
}[keyof R['responses'] & RouteConfigStatusCode]
|
}[DefinedStatusCodes<R>]
|
||||||
|
| ('default' extends keyof R['responses']
|
||||||
|
? undefined extends R['responses']['default']['content']
|
||||||
|
? TypedResponse<{}, Exclude<StatusCode, ExtractStatusCode<DefinedStatusCodes<R>>>, string>
|
||||||
|
: ReturnJsonOrTextOrResponse<
|
||||||
|
keyof R['responses']['default']['content'],
|
||||||
|
ExtractContent<R['responses']['default']['content']>,
|
||||||
|
Exclude<StatusCode, ExtractStatusCode<DefinedStatusCodes<R>>>
|
||||||
|
>
|
||||||
|
: never)
|
||||||
|
|
||||||
export type Hook<T, E extends Env, P extends string, R> = (
|
export type Hook<T, E extends Env, P extends string, R> = (
|
||||||
result: { target: keyof ValidationTargets } & (
|
result: { target: keyof ValidationTargets } & (
|
||||||
|
|
|
@ -147,4 +147,86 @@ describe('supports async handler', () => {
|
||||||
const hono = new OpenAPIHono()
|
const hono = new OpenAPIHono()
|
||||||
hono.openapi(route, handler)
|
hono.openapi(route, handler)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('handler should support default response for unspecified status codes', () => {
|
||||||
|
const routeWithDefault = createRoute({
|
||||||
|
method: 'get',
|
||||||
|
path: '/users',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: z.object({ id: z.string() }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Success response',
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: z.object({ error: z.string() }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Error response',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const errorHandler: RouteHandler<typeof routeWithDefault> = (c) => {
|
||||||
|
return c.json({ error: 'Server Error' }, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hono = new OpenAPIHono()
|
||||||
|
hono.openapi(routeWithDefault, errorHandler)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('handler should respect explicitly defined status codes with default fallback', () => {
|
||||||
|
const routeWithDefault = createRoute({
|
||||||
|
method: 'get',
|
||||||
|
path: '/users',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: z.object({ id: z.string() }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Success response',
|
||||||
|
},
|
||||||
|
404: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: z.object({ message: z.string() }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Not found response',
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: z.object({ error: z.string() }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Error response',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const successHandler: RouteHandler<typeof routeWithDefault> = (c) => {
|
||||||
|
return c.json({ id: '123' }, 200)
|
||||||
|
}
|
||||||
|
|
||||||
|
const notFoundHandler: RouteHandler<typeof routeWithDefault> = (c) => {
|
||||||
|
return c.json({ message: 'Not Found' }, 404)
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorHandler: RouteHandler<typeof routeWithDefault> = (c) => {
|
||||||
|
return c.json({ error: 'Server Error' }, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hono = new OpenAPIHono()
|
||||||
|
hono.openapi(routeWithDefault, successHandler)
|
||||||
|
hono.openapi(routeWithDefault, notFoundHandler)
|
||||||
|
hono.openapi(routeWithDefault, errorHandler)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue