fix(zod-openapi): fix path param format `:id` to `{id}` (#132)

* fix(zod-openapi): fix path param format `:id` to `{id}`

* changeset
pull/133/head
Yusuke Wada 2023-08-23 11:43:59 +09:00 committed by GitHub
parent c65b09edff
commit 2dbc823b29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 12 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/zod-openapi': patch
---
fix path param format `:id` to `{id}`

View File

@ -129,6 +129,10 @@ type Hook<T, E extends Env, P extends string, O> = (
c: Context<E, P> c: Context<E, P>
) => TypedResponse<O> | Promise<TypedResponse<T>> | void ) => TypedResponse<O> | Promise<TypedResponse<T>> | void
type ConvertPathType<T extends string> = T extends `${infer _}/{${infer Param}}${infer _}`
? `/:${Param}`
: T
export class OpenAPIHono<E extends Env = Env, S = {}, BasePath extends string = '/'> extends Hono< export class OpenAPIHono<E extends Env = Env, S = {}, BasePath extends string = '/'> extends Hono<
E, E,
S, S,
@ -143,12 +147,13 @@ export class OpenAPIHono<E extends Env = Env, S = {}, BasePath extends string =
openapi = < openapi = <
R extends RouteConfig, R extends RouteConfig,
I extends Input = InputTypeParam<R> & InputTypeQuery<R> & InputTypeForm<R> & InputTypeJson<R> I extends Input = InputTypeParam<R> & InputTypeQuery<R> & InputTypeForm<R> & InputTypeJson<R>,
P extends string = ConvertPathType<R['path']>
>( >(
route: R, route: R,
handler: Handler<E, R['path'], I, OutputType<R>>, handler: Handler<E, P, I, OutputType<R>>,
hook?: Hook<I, E, R['path'], OutputType<R>> hook?: Hook<I, E, P, OutputType<R>>
): Hono<E, Schema<R['method'], R['path'], I['in'], OutputType<R>>, BasePath> => { ): Hono<E, Schema<R['method'], P, I['in'], OutputType<R>>, BasePath> => {
this.#registry.registerPath(route) this.#registry.registerPath(route)
const validators: MiddlewareHandler[] = [] const validators: MiddlewareHandler[] = []
@ -187,7 +192,7 @@ export class OpenAPIHono<E extends Env = Env, S = {}, BasePath extends string =
} }
} }
this.on([route.method], route.path, ...validators, handler) this.on([route.method], route.path.replace(/\/{(.+)}/, '/:$1'), ...validators, handler)
return this return this
} }

View File

@ -22,8 +22,8 @@ describe('Basic - params', () => {
const UserSchema = z const UserSchema = z
.object({ .object({
id: z.number().openapi({ id: z.string().openapi({
example: 123, example: '123',
}), }),
name: z.string().openapi({ name: z.string().openapi({
example: 'John Doe', example: 'John Doe',
@ -44,7 +44,7 @@ describe('Basic - params', () => {
const route = createRoute({ const route = createRoute({
method: 'get', method: 'get',
path: '/users/:id', path: '/users/{id}',
request: { request: {
params: ParamsSchema, params: ParamsSchema,
}, },
@ -75,7 +75,7 @@ describe('Basic - params', () => {
(c) => { (c) => {
const { id } = c.req.valid('param') const { id } = c.req.valid('param')
return c.jsonT({ return c.jsonT({
id: Number(id), id,
age: 20, age: 20,
name: 'Ultra-man', name: 'Ultra-man',
}) })
@ -105,7 +105,7 @@ describe('Basic - params', () => {
const res = await app.request('/users/123') const res = await app.request('/users/123')
expect(res.status).toBe(200) expect(res.status).toBe(200)
expect(await res.json()).toEqual({ expect(await res.json()).toEqual({
id: 123, id: '123',
age: 20, age: 20,
name: 'Ultra-man', name: 'Ultra-man',
}) })
@ -128,7 +128,7 @@ describe('Basic - params', () => {
User: { User: {
type: 'object', type: 'object',
properties: { properties: {
id: { type: 'number', example: 123 }, id: { type: 'string', example: '123' },
name: { type: 'string', example: 'John Doe' }, name: { type: 'string', example: 'John Doe' },
age: { type: 'number', example: 42 }, age: { type: 'number', example: 42 },
}, },
@ -143,7 +143,7 @@ describe('Basic - params', () => {
parameters: {}, parameters: {},
}, },
paths: { paths: {
'/users/:id': { '/users/{id}': {
get: { get: {
parameters: [ parameters: [
{ {