feat: Add `getRoutingPath` to the return value of `createRoute`. (#161)
* feat(zod-openapi): add getRoutingPath * feat(zod-openapi): add docs * feat(zod-openapi): add versioning docpull/162/head
parent
928f84a226
commit
05b8e9a751
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@hono/zod-openapi': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add getRoutingPath to the return value of createRoute.
|
|
@ -203,6 +203,18 @@ import { prettyJSON } from 'hono/pretty-json'
|
||||||
app.use('/doc/*', prettyJSON())
|
app.use('/doc/*', prettyJSON())
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Configure middleware for each endpoint
|
||||||
|
|
||||||
|
You can configure middleware for each endpoint from a route created by `createRoute` as follows.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { prettyJSON } from 'hono/pretty-json'
|
||||||
|
import { cache } from 'honoc/cache'
|
||||||
|
|
||||||
|
app.use(route.getRoutingPath(), prettyJSON(), cache({ cacheName: "my-cache" }))
|
||||||
|
app.openapi(route, handler)
|
||||||
|
```
|
||||||
|
|
||||||
### RPC Mode
|
### RPC Mode
|
||||||
|
|
||||||
Zod OpenAPI Hono supports Hono's RPC mode. You can define types for the Hono Client as follows:
|
Zod OpenAPI Hono supports Hono's RPC mode. You can define types for the Hono Client as follows:
|
||||||
|
|
|
@ -323,9 +323,18 @@ export class OpenAPIHono<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RoutingPath<P extends string> = P extends `${infer Head}/{${infer Param}}${infer Tail}` ? `${Head}/:${Param}${RoutingPath<Tail>}` : P
|
||||||
|
|
||||||
export const createRoute = <P extends string, R extends Omit<RouteConfig, 'path'> & { path: P }>(
|
export const createRoute = <P extends string, R extends Omit<RouteConfig, 'path'> & { path: P }>(
|
||||||
routeConfig: R
|
routeConfig: R
|
||||||
) => routeConfig
|
) => {
|
||||||
|
return {
|
||||||
|
...routeConfig,
|
||||||
|
getRoutingPath(): RoutingPath<R['path']> {
|
||||||
|
return routeConfig.path.replaceAll(/\/{(.+?)}/g, '/:$1') as RoutingPath<P>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extendZodWithOpenApi(z)
|
extendZodWithOpenApi(z)
|
||||||
export { z }
|
export { z }
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* eslint-disable node/no-extraneous-import */
|
||||||
|
import { describe, it, expect, expectTypeOf } from 'vitest'
|
||||||
|
import { createRoute, z } from '../src'
|
||||||
|
|
||||||
|
describe('createRoute', () => {
|
||||||
|
it.each([
|
||||||
|
{ path: '/users', expected: '/users' },
|
||||||
|
{ path: '/users/{id}', expected: '/users/:id' },
|
||||||
|
{ path: '/users/{uid}/posts/{postId}', expected: '/users/:uid/posts/:postId' },
|
||||||
|
])('createRoute(%j)', ({ path, expected }) => {
|
||||||
|
const ParamsSchema = z.object({
|
||||||
|
id: z
|
||||||
|
.string()
|
||||||
|
.min(3)
|
||||||
|
.openapi({
|
||||||
|
param: {
|
||||||
|
name: 'id',
|
||||||
|
in: 'path',
|
||||||
|
},
|
||||||
|
example: '1212121',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const UserSchema = z.object({
|
||||||
|
id: z.string().openapi({
|
||||||
|
example: '123',
|
||||||
|
}),
|
||||||
|
name: z.string().openapi({
|
||||||
|
example: 'John Doe',
|
||||||
|
}),
|
||||||
|
age: z.number().openapi({
|
||||||
|
example: 42,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
method: 'get',
|
||||||
|
path,
|
||||||
|
request: {
|
||||||
|
params: ParamsSchema,
|
||||||
|
},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: UserSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Retrieve the user',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const
|
||||||
|
const route = createRoute(config)
|
||||||
|
|
||||||
|
expect(route).toEqual({
|
||||||
|
...config,
|
||||||
|
getRoutingPath: expect.any(Function),
|
||||||
|
})
|
||||||
|
expect(route.getRoutingPath()).toBe(expected)
|
||||||
|
expectTypeOf(route.getRoutingPath()).toEqualTypeOf<typeof expected>()
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue