fix(zod-openapi) tweak (#126)

* fix tests

* update readme
pull/128/head
Yusuke Wada 2023-08-19 16:07:59 +09:00 committed by GitHub
parent 5c22474098
commit 6d089751fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 40 deletions

View File

@ -1,17 +1,19 @@
# Zod OpenAPI Hono
**Zod OpenAPI Hono** is extending Hono to support OpenAPI.
With it, you can validate values and types using [**Zod**](https://zod.dev/) and generate OpenAPI Swagger documentation.
This is based on [**Zod to OpenAPI**](https://github.com/asteasolutions/zod-to-openapi).
For details on creating schemas and defining routes, please refer to this resource.
**Zod OpenAPI Hono** is an extended Hono class that supports OpenAPI. With it, you can validate values and types using [**Zod**](https://zod.dev/) and generate OpenAPI Swagger documentation. This is based on [**Zod to OpenAPI**](https://github.com/asteasolutions/zod-to-openapi) (thanks a lot!). For details on creating schemas and defining routes, please refer to [the "Zod to OpenAPI" resource](https://github.com/asteasolutions/zod-to-openapi).
_This is not a real middleware but hosted on this monorepo._
_Note: This is not standalone middleware but is hosted on the monorepo "[github.com/honojs/middleware](https://github.com/honojs/middleware)"._
## Limitations
- Currently, it does not support validation of _headers_ and _cookies_.
- An instance of Zod OpenAPI Hono cannot be used as a "subApp" in conjunction with `rootApp.route('/api', subApp)`.
## Usage
### Installation
You can install it via the npm. Should be installed with `hono` and `zod`.
You can install it via npm. It should be installed alongside `hono` and `zod`.
```sh
npm i hono zod @hono/zod-openapi
@ -19,9 +21,9 @@ npm i hono zod @hono/zod-openapi
### Basic Usage
#### Write your application
#### Setting up your application
First, define schemas with Zod:
First, define your schemas with Zod. The `z` object should be imported from `@hono/zod-openapi`:
```ts
import { z } from '@hono/zod-openapi'
@ -54,7 +56,7 @@ const UserSchema = z
.openapi('User')
```
Next, create routes:
Next, create a route:
```ts
import { createRoute } from '@hono/zod-openapi'
@ -72,13 +74,13 @@ const route = createRoute({
schema: UserSchema,
},
},
description: 'Get the user',
description: 'Retrieve the user',
},
},
})
```
Finally, create the App:
Finally, set up the app:
```ts
import { OpenAPIHono } from '@hono/zod-openapi'
@ -94,7 +96,7 @@ app.openapi(route, (c) => {
})
})
// OpenAPI document will be served on /doc
// The OpenAPI documentation will be available at /doc
app.doc('/doc', {
openapi: '3.0.0',
info: {
@ -104,11 +106,17 @@ app.doc('/doc', {
})
```
### Handling validation errors
You can start your app just like you would with Hono. For Cloudflare Workers and Bun, use this entry point:
You can handle the validation errors the following ways.
```ts
export default app
```
Define the schema:
### Handling Validation Errors
Validation errors can be handled as follows:
First, define the error schema:
```ts
const ErrorSchema = z.object({
@ -121,7 +129,7 @@ const ErrorSchema = z.object({
})
```
Add the response:
Then, add the error response:
```ts
const route = createRoute({
@ -137,13 +145,13 @@ const route = createRoute({
schema: ErrorSchema,
},
},
description: 'Return Error!',
description: 'Returns an error',
},
},
})
```
Add the hook:
Finally, add the hook:
```ts
app.openapi(
@ -162,7 +170,7 @@ app.openapi(
return c.jsonT(
{
code: 400,
message: 'Validation Error!',
message: 'Validation Error',
},
400
)
@ -173,7 +181,7 @@ app.openapi(
### Middleware
You can use Hono's middleware as same as using Hono because Zod OpenAPI is just extending Hono.
Zod OpenAPI Hono is an extension of Hono, so you can use Hono's middleware in the same way:
```ts
import { prettyJSON } from 'hono/pretty-json'
@ -183,9 +191,9 @@ import { prettyJSON } from 'hono/pretty-json'
app.use('/doc/*', prettyJSON())
```
### RPC-mode
### RPC Mode
Zod OpenAPI Hono supports Hono's RPC-mode. You can create the types for passing Hono Client:
Zod OpenAPI Hono supports Hono's RPC mode. You can define types for the Hono Client as follows:
```ts
import { hc } from 'hono/client'

View File

@ -177,10 +177,9 @@ describe('Query', () => {
}),
})
const PostsSchema = z
const BooksSchema = z
.object({
title: z.string().openapi({}),
content: z.string().openapi({}),
titles: z.array(z.string().openapi({})),
page: z.number().openapi({}),
})
.openapi('Post')
@ -195,10 +194,10 @@ describe('Query', () => {
200: {
content: {
'application/json': {
schema: PostsSchema,
schema: BooksSchema,
},
},
description: 'Get the posts',
description: 'Get books',
},
},
})
@ -208,8 +207,7 @@ describe('Query', () => {
app.openapi(route, (c) => {
const { page } = c.req.valid('query')
return c.jsonT({
title: 'Good title',
content: 'Good content',
titles: ['Good title'],
page: Number(page),
})
})
@ -218,8 +216,7 @@ describe('Query', () => {
const res = await app.request('/books?page=123')
expect(res.status).toBe(200)
expect(await res.json()).toEqual({
title: 'Good title',
content: 'Good content',
titles: ['Good title'],
page: 123,
})
})
@ -236,7 +233,7 @@ describe('JSON', () => {
title: z.string().openapi({}),
})
const PostsSchema = z
const PostSchema = z
.object({
id: z.number().openapi({}),
title: z.string().openapi({}),
@ -259,10 +256,10 @@ describe('JSON', () => {
200: {
content: {
'application/json': {
schema: PostsSchema,
schema: PostSchema,
},
},
description: 'Get the posts',
description: 'Post a post',
},
},
})
@ -304,6 +301,7 @@ describe('JSON', () => {
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({}),
})
const res = await app.request(req)
expect(res.status).toBe(400)
@ -316,7 +314,7 @@ describe('Form', () => {
title: z.string().openapi({}),
})
const PostsSchema = z
const PostSchema = z
.object({
id: z.number().openapi({}),
title: z.string().openapi({}),
@ -339,10 +337,10 @@ describe('Form', () => {
200: {
content: {
'application/json': {
schema: PostsSchema,
schema: PostSchema,
},
},
description: 'Post the post',
description: 'Post a post',
},
},
})
@ -393,7 +391,7 @@ describe('Types', () => {
title: z.string().openapi({}),
})
const PostsSchema = z
const PostSchema = z
.object({
id: z.number().openapi({}),
message: z.string().openapi({}),
@ -416,10 +414,10 @@ describe('Types', () => {
200: {
content: {
'application/json': {
schema: PostsSchema,
schema: PostSchema,
},
},
description: 'Post the post',
description: 'Post a post',
},
},
})