fix(zod-openapi): Strict type checking of return values (#287)

* changeset

* fix(zod-openapi): Strict type checking of return values

* bump hono `v3.11.1`

* remove changeset

* add changeset
pull/288/head
Yusuke Wada 2023-12-04 22:23:15 +09:00 committed by GitHub
parent d8300e5cc7
commit 1568b920de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 13 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/zod-openapi': patch
---
fix: Strict type checking of return values

View File

@ -38,12 +38,12 @@
},
"homepage": "https://github.com/honojs/middleware",
"peerDependencies": {
"hono": ">=3.9.0",
"hono": ">=3.11.1",
"zod": "3.*"
},
"devDependencies": {
"@hono/zod-validator": "^0.1.11",
"hono": "^3.9.1",
"hono": "^3.11.1",
"zod": "^3.22.1"
},
"dependencies": {

View File

@ -4,6 +4,7 @@ import type {
ResponseConfig,
RouteConfig,
ZodContentObject,
ZodMediaTypeObject,
ZodRequestBody,
} from '@asteasolutions/zod-to-openapi'
import {
@ -150,11 +151,12 @@ type ConvertPathType<T extends string> = T extends `${infer Start}/{${infer Para
? `${Start}/:${Param}${ConvertPathType<Rest>}`
: T
type HandlerResponse<O> =
| TypedResponse<O>
| Promise<TypedResponse<O>>
type HandlerTypedResponse<O> = TypedResponse<O> | Promise<TypedResponse<O>>
type HandlerAllResponse<O> =
| Response
| Promise<Response>
| TypedResponse<O>
| Promise<TypedResponse<O>>
export type OpenAPIHonoOptions<E extends Env> = {
defaultHook?: Hook<any, E, any, any>
@ -171,7 +173,23 @@ export type RouteHandler<
InputTypeForm<R> &
InputTypeJson<R>,
P extends string = ConvertPathType<R['path']>
> = Handler<E, P, I, HandlerResponse<OutputType<R>>>
> = Handler<
E,
P,
I,
// If response type is defined, only TypedResponse is allowed.
R extends {
responses: {
[statusCode: string]: {
content: {
[mediaType: string]: ZodMediaTypeObject
}
}
}
}
? HandlerTypedResponse<OutputType<R>>
: HandlerAllResponse<OutputType<R>>
>
export type RouteHook<
R extends RouteConfig,
@ -186,8 +204,8 @@ export type RouteHook<
> = Hook<I, E, P, OutputType<R>>
export type OpenAPIObjectConfigure<E extends Env, P extends string> =
OpenAPIObjectConfig |
((context: Context<E, P>) => OpenAPIObjectConfig)
| OpenAPIObjectConfig
| ((context: Context<E, P>) => OpenAPIObjectConfig)
export class OpenAPIHono<
E extends Env = Env,
@ -214,7 +232,23 @@ export class OpenAPIHono<
P extends string = ConvertPathType<R['path']>
>(
route: R,
handler: Handler<E, P, I, HandlerResponse<OutputType<R>>>,
handler: Handler<
E,
P,
I,
// If response type is defined, only TypedResponse is allowed.
R extends {
responses: {
[statusCode: string]: {
content: {
[mediaType: string]: ZodMediaTypeObject
}
}
}
}
? HandlerTypedResponse<OutputType<R>>
: HandlerAllResponse<OutputType<R>>
>,
hook: Hook<I, E, P, OutputType<R>> | undefined = this.defaultHook
): OpenAPIHono<E, S & ToSchema<R['method'], P, I['in'], OutputType<R>>, BasePath> => {
this.openAPIRegistry.registerPath(route)

View File

@ -622,6 +622,14 @@ describe('Types', () => {
>
expectTypeOf(appRoutes).toMatchTypeOf<H>
})
// @ts-expect-error it should throw an error if the types are wrong
app.openapi(route, (c) => {
return c.jsonT({
id: '123', // should be number
message: 'Success',
})
})
})
describe('Routers', () => {
@ -1140,7 +1148,7 @@ describe('Context can be accessible in the doc route', () => {
}
)
app.doc('/doc', context => ({
app.doc('/doc', (context) => ({
openapi: '3.0.0',
info: {
version: '1.0.0',
@ -1149,7 +1157,7 @@ describe('Context can be accessible in the doc route', () => {
}))
it('Should return with the title set as specified in env', async () => {
const res = await app.request('/doc', null, { TITLE: 'My API' })
const res = await app.request('/doc', {}, { TITLE: 'My API' })
expect(res.status).toBe(200)
expect(await res.json()).toEqual({
openapi: '3.0.0',

View File

@ -6935,11 +6935,16 @@ heap-js@^2.2.0:
resolved "https://registry.yarnpkg.com/heap-js/-/heap-js-2.3.0.tgz#8eed2cede31ec312aa696eef1d4df0565841f183"
integrity sha512-E5303mzwQ+4j/n2J0rDvEPBN7GKjhis10oHiYOgjxsmxYgqG++hz9NyLLOXttzH8as/DyiBHYpUrJTZWYaMo8Q==
hono@^3.0.0, hono@^3.1.0, hono@^3.1.2, hono@^3.1.5, hono@^3.5.1, hono@^3.5.2, hono@^3.5.8, hono@^3.7.2, hono@^3.7.3, hono@^3.9.1, hono@^3.9.2:
hono@^3.0.0, hono@^3.1.0, hono@^3.1.2, hono@^3.1.5, hono@^3.5.1, hono@^3.5.2, hono@^3.5.8, hono@^3.7.2, hono@^3.7.3, hono@^3.9.2:
version "3.9.2"
resolved "https://registry.yarnpkg.com/hono/-/hono-3.9.2.tgz#db31a6ce733131ee16bce0c9bd031a0708ebe052"
integrity sha512-180NOiMadqU3lGmN6ajPDZvZPWus3a9mtVaAUR9uG0SImngBwRLA8vbnV0oUfUAgFT4nX55sGV9dVA06OuikHA==
hono@^3.11.1:
version "3.11.1"
resolved "https://registry.yarnpkg.com/hono/-/hono-3.11.1.tgz#2f5893ae02baf55e1c5ad1e5b3a75936e3942c88"
integrity sha512-8FNUh8p/dkw8qYFxy8IJA500iW9NSeuvuwRfLw0FGkE/blCxtqWqxWTB+NaLSK3qGpaudzKur6s40Q0kpO0E+w==
hosted-git-info@^2.1.4:
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"