Skip to content

Commit

Permalink
fix(zod-openapi): handle nested app base paths in openapi registration (
Browse files Browse the repository at this point in the history
#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: format
  • Loading branch information
luxass authored Feb 4, 2025
1 parent deae708 commit 70a564e
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/heavy-trains-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hono/zod-openapi': patch
---

fix: use nested app base paths in openapi schema
14 changes: 12 additions & 2 deletions packages/zod-openapi/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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':
Expand Down
83 changes: 83 additions & 0 deletions packages/zod-openapi/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down

0 comments on commit 70a564e

Please sign in to comment.