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.docpull/278/head
parent
b0adaab247
commit
d4aa8ec5ad
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@hono/zod-openapi': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Make context accessible in the doc route
|
|
@ -231,7 +231,7 @@ You can generate OpenAPI v3.1 spec using the following methods:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
app.doc31('/docs', {openapi: '3.1.0'}) // new endpoint
|
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
|
### The Registry
|
||||||
|
@ -312,7 +312,7 @@ app.openAPIRegistry.registerComponent('securitySchema', {
|
||||||
type: 'http',
|
type: 'http',
|
||||||
scheme: 'bearer',
|
scheme: 'bearer',
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
And setup the security scheme for specific routes:
|
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
|
## Limitations
|
||||||
|
|
||||||
### Combining with `Hono`
|
### Combining with `Hono`
|
||||||
|
|
|
@ -185,6 +185,10 @@ export type RouteHook<
|
||||||
P extends string = ConvertPathType<R['path']>
|
P extends string = ConvertPathType<R['path']>
|
||||||
> = Hook<I, E, P, OutputType<R>>
|
> = Hook<I, E, P, OutputType<R>>
|
||||||
|
|
||||||
|
export type OpenAPIObjectConfigure<E extends Env, P extends string> =
|
||||||
|
OpenAPIObjectConfig |
|
||||||
|
((context: Context<E, P>) => OpenAPIObjectConfig)
|
||||||
|
|
||||||
export class OpenAPIHono<
|
export class OpenAPIHono<
|
||||||
E extends Env = Env,
|
E extends Env = Env,
|
||||||
S extends Schema = {},
|
S extends Schema = {},
|
||||||
|
@ -279,9 +283,10 @@ export class OpenAPIHono<
|
||||||
|
|
||||||
doc = <P extends string>(
|
doc = <P extends string>(
|
||||||
path: P,
|
path: P,
|
||||||
config: OpenAPIObjectConfig
|
configure: OpenAPIObjectConfigure<E, P>
|
||||||
): OpenAPIHono<E, S & ToSchema<'get', P, {}, {}>, BasePath> => {
|
): OpenAPIHono<E, S & ToSchema<'get', P, {}, {}>, BasePath> => {
|
||||||
return this.get(path, (c) => {
|
return this.get(path, (c) => {
|
||||||
|
const config = typeof configure === 'function' ? configure(c) : configure
|
||||||
const document = this.getOpenAPIDocument(config)
|
const document = this.getOpenAPIDocument(config)
|
||||||
return c.json(document)
|
return c.json(document)
|
||||||
}) as any
|
}) as any
|
||||||
|
@ -289,9 +294,10 @@ export class OpenAPIHono<
|
||||||
|
|
||||||
doc31 = <P extends string>(
|
doc31 = <P extends string>(
|
||||||
path: P,
|
path: P,
|
||||||
config: OpenAPIObjectConfig
|
configure: OpenAPIObjectConfigure<E, P>
|
||||||
): OpenAPIHono<E, S & ToSchema<'get', P, {}, {}>, BasePath> => {
|
): OpenAPIHono<E, S & ToSchema<'get', P, {}, {}>, BasePath> => {
|
||||||
return this.get(path, (c) => {
|
return this.get(path, (c) => {
|
||||||
|
const config = typeof configure === 'function' ? configure(c) : configure
|
||||||
const document = this.getOpenAPI31Document(config)
|
const document = this.getOpenAPI31Document(config)
|
||||||
return c.json(document)
|
return c.json(document)
|
||||||
}) as any
|
}) as any
|
||||||
|
|
|
@ -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',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in New Issue