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 changesetpull/288/head
parent
d8300e5cc7
commit
1568b920de
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@hono/zod-openapi': patch
|
||||
---
|
||||
|
||||
fix: Strict type checking of return values
|
|
@ -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": {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue