feat(zod-openapi): Make context accessible in the doc route (#272)

* feat(zod-openapi): Make context accessible in the doc route

* docs(zod-openapi): Fix typo

* docs(zod-openapi): Add a tips to the README.md on how to access the context in app.doc
pull/278/head
Karibash 2023-11-28 14:41:14 +09:00 committed by GitHub
parent b0adaab247
commit d4aa8ec5ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 4 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/zod-openapi': minor
---
Make context accessible in the doc route

View File

@ -231,7 +231,7 @@ You can generate OpenAPI v3.1 spec using the following methods:
```ts
app.doc31('/docs', {openapi: '3.1.0'}) // new endpoint
app.getOpenAPI31Document(, {openapi: '3.1.0'}) // raw json
app.getOpenAPI31Document({openapi: '3.1.0'}) // raw json
```
### The Registry
@ -312,7 +312,7 @@ app.openAPIRegistry.registerComponent('securitySchema', {
type: 'http',
scheme: 'bearer',
},
}
})
```
And setup the security scheme for specific routes:
@ -328,6 +328,26 @@ const route = createRoute({
})
```
### How to access context in app.doc
You can access the context in `app.doc` as follows:
```ts
app.doc('/doc', c => ({
openapi: '3.0.0',
info: {
version: '1.0.0',
title: 'My API',
},
servers: [
{
url: new URL(c.req.url).hostname,
description: 'Current environment',
},
],
}))
```
## Limitations
### Combining with `Hono`

View File

@ -185,6 +185,10 @@ export type RouteHook<
P extends string = ConvertPathType<R['path']>
> = Hook<I, E, P, OutputType<R>>
export type OpenAPIObjectConfigure<E extends Env, P extends string> =
OpenAPIObjectConfig |
((context: Context<E, P>) => OpenAPIObjectConfig)
export class OpenAPIHono<
E extends Env = Env,
S extends Schema = {},
@ -279,9 +283,10 @@ export class OpenAPIHono<
doc = <P extends string>(
path: P,
config: OpenAPIObjectConfig
configure: OpenAPIObjectConfigure<E, P>
): OpenAPIHono<E, S & ToSchema<'get', P, {}, {}>, BasePath> => {
return this.get(path, (c) => {
const config = typeof configure === 'function' ? configure(c) : configure
const document = this.getOpenAPIDocument(config)
return c.json(document)
}) as any
@ -289,9 +294,10 @@ export class OpenAPIHono<
doc31 = <P extends string>(
path: P,
config: OpenAPIObjectConfig
configure: OpenAPIObjectConfigure<E, P>
): OpenAPIHono<E, S & ToSchema<'get', P, {}, {}>, BasePath> => {
return this.get(path, (c) => {
const config = typeof configure === 'function' ? configure(c) : configure
const document = this.getOpenAPI31Document(config)
return c.json(document)
}) as any

View File

@ -1121,3 +1121,57 @@ describe('Path normalization', () => {
})
})
})
describe('Context can be accessible in the doc route', () => {
const app = new OpenAPIHono<{ Bindings: { TITLE: string } }>()
app.openapi(
createRoute({
method: 'get',
path: '/no-content',
responses: {
204: {
description: 'No Content',
},
},
}),
(c) => {
return c.body(null, 204)
}
)
app.doc('/doc', context => ({
openapi: '3.0.0',
info: {
version: '1.0.0',
title: context.env.TITLE,
},
}))
it('Should return with the title set as specified in env', async () => {
const res = await app.request('/doc', null, { TITLE: 'My API' })
expect(res.status).toBe(200)
expect(await res.json()).toEqual({
openapi: '3.0.0',
info: {
version: '1.0.0',
title: 'My API',
},
components: {
schemas: {},
parameters: {},
},
paths: {
'/no-content': {
get: {
responses: {
204: {
description: 'No Content',
},
},
},
},
},
})
})
})