diff --git a/.changeset/smooth-grapes-pay.md b/.changeset/smooth-grapes-pay.md new file mode 100644 index 00000000..30657045 --- /dev/null +++ b/.changeset/smooth-grapes-pay.md @@ -0,0 +1,5 @@ +--- +'@hono/zod-openapi': patch +--- + +fix(zod-openapi): correctly handle path parameters in basePath diff --git a/packages/zod-openapi/src/index.ts b/packages/zod-openapi/src/index.ts index 59b905b6..e9e90c1f 100644 --- a/packages/zod-openapi/src/index.ts +++ b/packages/zod-openapi/src/index.ts @@ -638,7 +638,7 @@ export class OpenAPIHono< path: mergePath( pathForOpenAPI, // @ts-expect-error _basePath is private - app._basePath, + app._basePath.replaceAll(/:([^\/]+)/g, '{$1}'), def.route.path ), }) @@ -649,7 +649,7 @@ export class OpenAPIHono< path: mergePath( pathForOpenAPI, // @ts-expect-error _basePath is private - app._basePath, + app._basePath.replaceAll(/:([^\/]+)/g, '{$1}'), def.webhook.path ), }) diff --git a/packages/zod-openapi/test/index.test.ts b/packages/zod-openapi/test/index.test.ts index 8d29402a..3d056832 100644 --- a/packages/zod-openapi/test/index.test.ts +++ b/packages/zod-openapi/test/index.test.ts @@ -1274,6 +1274,53 @@ describe('basePath()', () => { expect(res.status).toBe(200) expect(await res.json()).toEqual({ path: 'abc' }) }) + + it('Should correctly handle path parameters in nested basePath', async () => { + const app = new OpenAPIHono() + const nested = new OpenAPIHono().basePath('/:param2') + + nested.openapi( + createRoute({ + method: 'get', + path: '/{param3}', + responses: { + 200: { + description: 'Get message', + }, + }, + }), + (c) => { + return c.json({ + param1: c.req.param('param1'), + param2: c.req.param('param2'), + param3: c.req.param('param3') + }) + } + ) + + app.route('/:param1', nested) + + 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(['/{param1}/{param2}/{param3}']) + expect(paths).not.toStrictEqual(['/{param1}/:param2/{param3}']) + + const res = await app.request('/foo/bar/baz') + expect(res.status).toBe(200) + expect(await res.json()).toEqual({ + param1: 'foo', + param2: 'bar', + param3: 'baz' + }) + }) }) describe('With hc', () => {