feat(zod-openapi): support `enum` (#837)

* feat(zod-openapi): support `enum`

* add changeset

* add changeset
pull/838/head
Yusuke Wada 2024-11-19 10:53:55 +09:00 committed by GitHub
parent 672ff939bc
commit ebd70a0e03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 50 additions and 34 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/zod-openapi': minor
---
feat: support `enum`

View File

@ -42,7 +42,7 @@
}, },
"devDependencies": { "devDependencies": {
"@cloudflare/workers-types": "^4.20240117.0", "@cloudflare/workers-types": "^4.20240117.0",
"hono": "^4.5.4", "hono": "^4.6.10",
"jest": "^29.7.0", "jest": "^29.7.0",
"tsup": "^8.0.1", "tsup": "^8.0.1",
"typescript": "^5.4.4", "typescript": "^5.4.4",
@ -52,7 +52,7 @@
}, },
"dependencies": { "dependencies": {
"@asteasolutions/zod-to-openapi": "^7.1.0", "@asteasolutions/zod-to-openapi": "^7.1.0",
"@hono/zod-validator": "0.3.0" "@hono/zod-validator": "^0.4.1"
}, },
"engines": { "engines": {
"node": ">=16.0.0" "node": ">=16.0.0"

View File

@ -85,10 +85,10 @@ type InputTypeBase<
in: { in: {
[K in Type]: HasUndefined<ValidationTargets[K]> extends true [K in Type]: HasUndefined<ValidationTargets[K]> extends true
? { ? {
[K2 in keyof z.input<RequestPart<R, Part>>]?: ValidationTargets[K][K2] [K2 in keyof z.input<RequestPart<R, Part>>]?: z.input<RequestPart<R, Part>>[K2]
} }
: { : {
[K2 in keyof z.input<RequestPart<R, Part>>]: ValidationTargets[K][K2] [K2 in keyof z.input<RequestPart<R, Part>>]: z.input<RequestPart<R, Part>>[K2]
} }
} }
out: { [K in Type]: z.output<RequestPart<R, Part>> } out: { [K in Type]: z.output<RequestPart<R, Part>> }

View File

@ -1,5 +1,4 @@
import type { Env, Hono, ToSchema } from 'hono' import { assertType, describe, it } from 'vitest'
import { assertType, describe, expectTypeOf, it } from 'vitest'
import { MiddlewareToHandlerType, OfHandlerType, OpenAPIHono, createRoute, z } from '../src/index' import { MiddlewareToHandlerType, OfHandlerType, OpenAPIHono, createRoute, z } from '../src/index'
import { createMiddleware } from 'hono/factory' import { createMiddleware } from 'hono/factory'
import type { ExtractSchema } from 'hono/types' import type { ExtractSchema } from 'hono/types'
@ -18,10 +17,13 @@ describe('Types', () => {
}) })
.openapi('Post') .openapi('Post')
const QuerySchema = z.object({ order: z.enum(['asc', 'desc']) })
const route = createRoute({ const route = createRoute({
method: 'post', method: 'post',
path: '/posts', path: '/posts',
request: { request: {
query: QuerySchema,
body: { body: {
content: { content: {
'application/json': { 'application/json': {
@ -47,32 +49,41 @@ describe('Types', () => {
const appRoutes = app.openapi(route, (c) => { const appRoutes = app.openapi(route, (c) => {
const data = c.req.valid('json') const data = c.req.valid('json')
assertType<number>(data.id) assertType<number>(data.id)
const order = c.req.valid('query')
assertType<{ order: 'asc' | 'desc' }>(order)
return c.json({ return c.json({
id: data.id, id: data.id,
message: 'Success', message: 'Success',
order,
}) })
}) })
it('Should return correct types', () => { it('Should return correct types', () => {
type H = Hono< type Expected = {
Env, '/posts': {
ToSchema< $post: {
'post', input: {
'/posts', query: {
{ order: 'asc' | 'desc'
json: { }
title: string } & {
id: number json: {
title: string
id: number
}
} }
}, output: {
{ id: number
id: number message: string
message: string }
outputFormat: 'json' | 'text'
status: 200
} }
>, }
'/' }
>
expectTypeOf(appRoutes).toMatchTypeOf<H>() type Actual = ExtractSchema<typeof appRoutes>
type verify = Expect<Equal<Expected, Actual>>
}) })
}) })
@ -229,7 +240,7 @@ describe('coerce', () => {
type Actual = ExtractSchema<typeof routes>['/api/users/:id']['$get']['input'] type Actual = ExtractSchema<typeof routes>['/api/users/:id']['$get']['input']
type Expected = { type Expected = {
param: { param: {
id: string id: number
} }
} }
type verify = Expect<Equal<Expected, Actual>> type verify = Expect<Equal<Expected, Actual>>

View File

@ -593,8 +593,8 @@ __metadata:
dependencies: dependencies:
"@asteasolutions/zod-to-openapi": "npm:^7.1.0" "@asteasolutions/zod-to-openapi": "npm:^7.1.0"
"@cloudflare/workers-types": "npm:^4.20240117.0" "@cloudflare/workers-types": "npm:^4.20240117.0"
"@hono/zod-validator": "npm:0.3.0" "@hono/zod-validator": "npm:^0.4.1"
hono: "npm:^4.5.4" hono: "npm:^4.6.10"
jest: "npm:^29.7.0" jest: "npm:^29.7.0"
tsup: "npm:^8.0.1" tsup: "npm:^8.0.1"
typescript: "npm:^5.4.4" typescript: "npm:^5.4.4"
@ -607,13 +607,13 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@hono/zod-validator@npm:0.3.0": "@hono/zod-validator@npm:^0.4.1":
version: 0.3.0 version: 0.4.1
resolution: "@hono/zod-validator@npm:0.3.0" resolution: "@hono/zod-validator@npm:0.4.1"
peerDependencies: peerDependencies:
hono: ">=3.9.0" hono: ">=3.9.0"
zod: ^3.19.1 zod: ^3.19.1
checksum: 0c33f99bec89aa5bf042e1d490b894044b60db98d9d7b1d9586ee2d4855a72b216a0101c4549118e7c7643acf12237c716a27c1849f07276dccb8e0be362a63e checksum: 30c23d247806f5775e85b42f3ae6634edcadf9e17f62ef085812c6710f57f2e856fe23b14b1cff686f442a3d298024551b5c2affd28301a08f9c8bfea966c073
languageName: node languageName: node
linkType: hard linkType: hard
@ -2379,10 +2379,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"hono@npm:^4.5.4": "hono@npm:^4.6.10":
version: 4.5.4 version: 4.6.10
resolution: "hono@npm:4.5.4" resolution: "hono@npm:4.6.10"
checksum: 980accb9567fe5ba4533c1378d175a95a0eef0a1fa8a03ceb1f9296d88d4ee8ff0e1447f5e69eb56150a8b6cc66f4a663ec9d1c1135f005f44f61353b58e276f checksum: e1a56e82059197607fbdebb5ad4a4962aa44ae239753a9be067ac61824f953bf7baf6415e03adc05986136b53cfa15b6e6d2d89d463cc3d4fc2fe93862425bab
languageName: node languageName: node
linkType: hard linkType: hard