fix(zod-openapi): relax types to support `.refine()` for an object (#574)

* fix(zod-openapi): relax types to support `.refine()` for an object

* add a chengeset
pull/575/head
Yusuke Wada 2024-06-14 18:58:40 +09:00 committed by GitHub
parent 5a0488a254
commit ef9f45ab69
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 59 additions and 53 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/zod-openapi': patch
---
fix: relax types to support `.refine()` for an object

View File

@ -63,4 +63,4 @@
"typescript": "^5.2.2" "typescript": "^5.2.2"
}, },
"packageManager": "yarn@4.0.2" "packageManager": "yarn@4.0.2"
} }

View File

@ -30,4 +30,4 @@
"hono": "4.5.0-rc.1", "hono": "4.5.0-rc.1",
"tsup": "^8.0.1" "tsup": "^8.0.1"
} }
} }

View File

@ -44,7 +44,6 @@
"@cloudflare/workers-types": "^4.20240117.0", "@cloudflare/workers-types": "^4.20240117.0",
"hono": "^4.3.6", "hono": "^4.3.6",
"jest": "^29.7.0", "jest": "^29.7.0",
"openapi3-ts": "^4.1.2",
"tsup": "^8.0.1", "tsup": "^8.0.1",
"typescript": "^5.4.4", "typescript": "^5.4.4",
"vitest": "^1.4.0", "vitest": "^1.4.0",

View File

@ -8,11 +8,11 @@ import type {
ZodRequestBody, ZodRequestBody,
} from '@asteasolutions/zod-to-openapi' } from '@asteasolutions/zod-to-openapi'
import { import {
OpenAPIRegistry,
OpenApiGeneratorV3, OpenApiGeneratorV3,
OpenApiGeneratorV31, OpenApiGeneratorV31,
OpenAPIRegistry, extendZodWithOpenApi,
} from '@asteasolutions/zod-to-openapi' } from '@asteasolutions/zod-to-openapi'
import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi'
import type { OpenAPIObjectConfig } from '@asteasolutions/zod-to-openapi/dist/v3.0/openapi-generator' import type { OpenAPIObjectConfig } from '@asteasolutions/zod-to-openapi/dist/v3.0/openapi-generator'
import { zValidator } from '@hono/zod-validator' import { zValidator } from '@hono/zod-validator'
import { Hono } from 'hono' import { Hono } from 'hono'
@ -35,10 +35,10 @@ import type {
StatusCode, StatusCode,
SuccessStatusCode, SuccessStatusCode,
} from 'hono/utils/http-status' } from 'hono/utils/http-status'
import type { Prettify, RemoveBlankRecord } from 'hono/utils/types' import type { RemoveBlankRecord } from 'hono/utils/types'
import { mergePath } from 'hono/utils/url' import { mergePath } from 'hono/utils/url'
import type { AnyZodObject, ZodSchema, ZodError } from 'zod' import type { AnyZodObject, ZodError, ZodSchema } from 'zod'
import { z, ZodType } from 'zod' import { ZodType, z } from 'zod'
type MaybePromise<T> = Promise<T> | T type MaybePromise<T> = Promise<T> | T
@ -48,10 +48,10 @@ export type RouteConfig = RouteConfigBase & {
type RequestTypes = { type RequestTypes = {
body?: ZodRequestBody body?: ZodRequestBody
params?: AnyZodObject params?: ZodType
query?: AnyZodObject query?: ZodType
cookies?: AnyZodObject cookies?: ZodType
headers?: AnyZodObject | ZodType<unknown>[] headers?: ZodType | ZodType[]
} }
type IsJson<T> = T extends string type IsJson<T> = T extends string
@ -77,7 +77,7 @@ type InputTypeBase<
Part extends string, Part extends string,
Type extends string Type extends string
> = R['request'] extends RequestTypes > = R['request'] extends RequestTypes
? RequestPart<R, Part> extends AnyZodObject ? RequestPart<R, Part> extends ZodType
? { ? {
in: { [K in Type]: z.input<RequestPart<R, Part>> } in: { [K in Type]: z.input<RequestPart<R, Part>> }
out: { [K in Type]: z.output<RequestPart<R, Part>> } out: { [K in Type]: z.output<RequestPart<R, Part>> }
@ -299,7 +299,7 @@ export class OpenAPIHono<
InputTypeJson<R>, InputTypeJson<R>,
P extends string = ConvertPathType<R['path']> P extends string = ConvertPathType<R['path']>
>( >(
{middleware: routeMiddleware, ...route}: R, { middleware: routeMiddleware, ...route }: R,
handler: Handler< handler: Handler<
E, E,
P, P,

View File

@ -2,11 +2,12 @@ import type { RouteConfig } from '@asteasolutions/zod-to-openapi'
import type { Context, TypedResponse } from 'hono' import type { Context, TypedResponse } from 'hono'
import { bearerAuth } from 'hono/bearer-auth' import { bearerAuth } from 'hono/bearer-auth'
import { hc } from 'hono/client' import { hc } from 'hono/client'
import { describe, it, expect, expectTypeOf } from 'vitest' import { describe, expect, expectTypeOf, it } from 'vitest'
import { OpenAPIHono, createRoute, z, RouteConfigToTypedResponse } from '../src/index' import type { RouteConfigToTypedResponse } from '../src/index'
import { Expect, Equal } from 'hono/utils/types' import { OpenAPIHono, createRoute, z } from '../src/index'
import { ServerErrorStatusCode } from 'hono/utils/http-status' import type { Equal, Expect } from 'hono/utils/types'
import { stringify } from "yaml" import type { ServerErrorStatusCode } from 'hono/utils/http-status'
import { stringify } from 'yaml'
describe('Constructor', () => { describe('Constructor', () => {
it('Should not require init object', () => { it('Should not require init object', () => {
@ -1491,43 +1492,45 @@ describe('RouteConfigToTypedResponse', () => {
type Expected = type Expected =
| TypedResponse< | TypedResponse<
{ {
name: string name: string
age: number age: number
}, },
200, 200,
'json' 'json'
> >
| TypedResponse< | TypedResponse<
{ {
ok: boolean ok: boolean
}, },
400, 400,
'json' 'json'
> >
| TypedResponse< | TypedResponse<
{ {
ok: boolean ok: boolean
}, },
ServerErrorStatusCode, ServerErrorStatusCode,
'json' 'json'
> >
type verify = Expect<Equal<Expected, Actual>> type verify = Expect<Equal<Expected, Actual>>
}) })
}) })
describe("Generate YAML", () => { describe('Generate YAML', () => {
it("Should generate YAML with Middleware", async () => { it('Should generate YAML with Middleware', async () => {
const app = new OpenAPIHono() const app = new OpenAPIHono()
app.openapi( app.openapi(
createRoute({ createRoute({
method: 'get', method: 'get',
path: '/books', path: '/books',
middleware: [bearerAuth({ middleware: [
verifyToken: (_, __) => { bearerAuth({
return true; verifyToken: (_, __) => {
}, return true
})], },
}),
],
responses: { responses: {
200: { 200: {
description: 'Books', description: 'Books',
@ -1550,8 +1553,8 @@ describe("Generate YAML", () => {
info: { info: {
title: 'My API', title: 'My API',
version: '1.0.0', version: '1.0.0',
} },
}); })
expect(() => stringify(doc)).to.not.throw(); expect(() => stringify(doc)).to.not.throw()
}) })
}); })

View File

@ -596,7 +596,6 @@ __metadata:
"@hono/zod-validator": "npm:0.2.2" "@hono/zod-validator": "npm:0.2.2"
hono: "npm:^4.3.6" hono: "npm:^4.3.6"
jest: "npm:^29.7.0" jest: "npm:^29.7.0"
openapi3-ts: "npm:^4.1.2"
tsup: "npm:^8.0.1" tsup: "npm:^8.0.1"
typescript: "npm:^5.4.4" typescript: "npm:^5.4.4"
vitest: "npm:^1.4.0" vitest: "npm:^1.4.0"
@ -2381,9 +2380,9 @@ __metadata:
linkType: hard linkType: hard
"hono@npm:^4.3.6": "hono@npm:^4.3.6":
version: 4.3.6 version: 4.4.6
resolution: "hono@npm:4.3.6" resolution: "hono@npm:4.4.6"
checksum: 2e27eb1e90b392a5884af573179d29e3f717f5e803c2b90f1383488f42bc986810e8e714d5bb1205935fda1d3e9944b3262aed88e852ea44d0e13d799474fa5b checksum: 065318f3fe021320b59f3daddacf7d74bfc3303de55f415a999b6967a9f09714e136528bc86cc880a45633cd85dec5428e41e902b5e3a3809f3cd17204302668
languageName: node languageName: node
linkType: hard linkType: hard