fix(zod-openapi): handle nested app base paths in openapi registration (#955)
* feat: handle nested app base paths in openapi registration * test: add test for nested base paths in OpenAPI schema * test(zod-openapi): add route without base path * chore: add changeset * chore: formatpull/957/head
parent
deae708dde
commit
70a564e268
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@hono/zod-openapi': patch
|
||||
---
|
||||
|
||||
fix: use nested app base paths in openapi schema
|
|
@ -632,13 +632,23 @@ export class OpenAPIHono<
|
|||
case 'route':
|
||||
return this.openAPIRegistry.registerPath({
|
||||
...def.route,
|
||||
path: mergePath(pathForOpenAPI, def.route.path),
|
||||
path: mergePath(
|
||||
pathForOpenAPI,
|
||||
// @ts-expect-error _basePath is private
|
||||
app._basePath,
|
||||
def.route.path
|
||||
),
|
||||
})
|
||||
|
||||
case 'webhook':
|
||||
return this.openAPIRegistry.registerWebhook({
|
||||
...def.webhook,
|
||||
path: mergePath(pathForOpenAPI, def.webhook.path),
|
||||
path: mergePath(
|
||||
pathForOpenAPI,
|
||||
// @ts-expect-error _basePath is private
|
||||
app._basePath,
|
||||
def.webhook.path
|
||||
),
|
||||
})
|
||||
|
||||
case 'schema':
|
||||
|
|
|
@ -1156,6 +1156,89 @@ describe('basePath()', () => {
|
|||
const data = (await res.json()) as any
|
||||
expect(Object.keys(data.paths)[0]).toBe('/api/message')
|
||||
})
|
||||
|
||||
it('Should add nested base paths to openapi schema', async () => {
|
||||
const app = new OpenAPIHono()
|
||||
|
||||
const v1 = new OpenAPIHono().basePath('/api/v1')
|
||||
v1.openapi(
|
||||
{
|
||||
method: 'get',
|
||||
path: '/message1',
|
||||
responses: {
|
||||
200: {
|
||||
description: 'Get message',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: z.object({ message: z.string() }),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
(c) => c.json({ message: 'Hello' })
|
||||
)
|
||||
|
||||
const v2 = new OpenAPIHono().basePath('/api/v2')
|
||||
v2.openapi(
|
||||
{
|
||||
method: 'get',
|
||||
path: '/message2',
|
||||
responses: {
|
||||
200: {
|
||||
description: 'Get message',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: z.object({ message: z.string() }),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
(c) => c.json({ message: 'Hello' })
|
||||
)
|
||||
|
||||
app.route('/', v1)
|
||||
app.route('/', v2)
|
||||
|
||||
app.openapi(
|
||||
{
|
||||
method: 'get',
|
||||
path: '/hello',
|
||||
responses: {
|
||||
200: {
|
||||
description: 'Get message',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: z.object({ message: z.string() }),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
(c) => c.json({ message: 'Hello' })
|
||||
)
|
||||
|
||||
const res1 = await app.request('/api/v1/message1')
|
||||
expect(res1.status).toBe(200)
|
||||
|
||||
const res2 = await app.request('/api/v2/message2')
|
||||
expect(res2.status).toBe(200)
|
||||
|
||||
const json = app.getOpenAPIDocument({
|
||||
openapi: '3.0.0',
|
||||
info: {
|
||||
version: '1.0.0',
|
||||
title: 'My API',
|
||||
},
|
||||
})
|
||||
|
||||
const paths = Object.keys(json.paths)
|
||||
|
||||
expect(paths).toStrictEqual(['/api/v1/message1', '/api/v2/message2', '/hello'])
|
||||
|
||||
expect(paths).not.toStrictEqual(['/message1', '/message2', '/hello'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('With hc', () => {
|
||||
|
|
Loading…
Reference in New Issue