From 845e336ff41d29fa74ec3cf84afc16f5ac0c2c77 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 18 Jul 2025 16:40:21 +0900 Subject: [PATCH] feat(zod-openapi): support Zod v4 (#1223) * feat(zod-openapi): support Zod v4 * update `peerDependencies` * add changeset * fixed type error * update dependencies --- .changeset/young-cats-shop.md | 9 +++++++++ packages/zod-openapi/package.json | 6 +++--- packages/zod-openapi/src/index.test-d.ts | 2 +- packages/zod-openapi/src/index.ts | 18 +++++++++++------- yarn.lock | 18 +++++++++--------- 5 files changed, 33 insertions(+), 20 deletions(-) create mode 100644 .changeset/young-cats-shop.md diff --git a/.changeset/young-cats-shop.md b/.changeset/young-cats-shop.md new file mode 100644 index 00000000..42186511 --- /dev/null +++ b/.changeset/young-cats-shop.md @@ -0,0 +1,9 @@ +--- +'@hono/zod-openapi': major +--- + +feat: support Zod v4 + +Zod OpenAPI has been migrated the Zod version from v3 to v4. As a result, the `zod` in `peerDependencies` has been updated to 4.0.0 or higher. + +Although this is not a breaking change, it is a major change, so it is considered a major version upgrade. diff --git a/packages/zod-openapi/package.json b/packages/zod-openapi/package.json index 3846b8a4..ed0e8a32 100644 --- a/packages/zod-openapi/package.json +++ b/packages/zod-openapi/package.json @@ -41,7 +41,7 @@ "homepage": "https://github.com/honojs/middleware", "peerDependencies": { "hono": ">=4.3.6", - "zod": ">=3.0.0" + "zod": "^4.0.0" }, "devDependencies": { "@arethetypeswrong/cli": "^0.17.4", @@ -51,10 +51,10 @@ "typescript": "^5.8.2", "vitest": "^3.2.4", "yaml": "^2.4.3", - "zod": "^3.22.1" + "zod": "^4.0.5" }, "dependencies": { - "@asteasolutions/zod-to-openapi": "^7.3.0", + "@asteasolutions/zod-to-openapi": "^8.0.0", "@hono/zod-validator": "workspace:^", "openapi3-ts": "^4.5.0" }, diff --git a/packages/zod-openapi/src/index.test-d.ts b/packages/zod-openapi/src/index.test-d.ts index e0127e9c..6e77c759 100644 --- a/packages/zod-openapi/src/index.test-d.ts +++ b/packages/zod-openapi/src/index.test-d.ts @@ -240,7 +240,7 @@ describe('coerce', () => { type Actual = ExtractSchema['/api/users/:id']['$get']['input'] type Expected = { param: { - id: number + id: unknown } } type verify = Expect> diff --git a/packages/zod-openapi/src/index.ts b/packages/zod-openapi/src/index.ts index b156405d..687d5ea2 100644 --- a/packages/zod-openapi/src/index.ts +++ b/packages/zod-openapi/src/index.ts @@ -11,6 +11,7 @@ import { OpenApiGeneratorV3, OpenApiGeneratorV31, extendZodWithOpenApi, + getOpenApiMetadata, } from '@asteasolutions/zod-to-openapi' import { zValidator } from '@hono/zod-validator' import { Hono } from 'hono' @@ -38,8 +39,8 @@ import type { JSONParsed, JSONValue, RemoveBlankRecord, SimplifyDeepArray } from import { mergePath } from 'hono/utils/url' import type { OpenAPIObject } from 'openapi3-ts/oas30' import type { OpenAPIObject as OpenAPIV31bject } from 'openapi3-ts/oas31' -import type { ZodError, ZodSchema } from 'zod' -import { ZodType, z } from 'zod' +import { ZodType, z } from 'zod/v4' +import type { ZodError } from 'zod/v4' type MaybePromise = Promise | T @@ -128,7 +129,7 @@ type InputTypeJson = R['request'] extends RequestTypes ? {} : R['request']['body']['content'][keyof R['request']['body']['content']] extends Record< 'schema', - ZodSchema + ZodType > ? { in: { @@ -154,7 +155,7 @@ type InputTypeForm = R['request'] extends RequestTypes ? {} : R['request']['body']['content'][keyof R['request']['body']['content']] extends Record< 'schema', - ZodSchema + ZodType > ? { in: { @@ -181,7 +182,7 @@ type InputTypeCookie = InputTypeBase = T extends { [K in keyof T]: infer A } - ? A extends Record<'schema', ZodSchema> + ? A extends Record<'schema', ZodType> ? z.infer : never : never @@ -659,11 +660,14 @@ export class OpenAPIHono< } case 'schema': - return this.openAPIRegistry.register(def.schema._def.openapi._internal.refId, def.schema) + return this.openAPIRegistry.register( + getOpenApiMetadata(def.schema)._internal?.refId, + def.schema + ) case 'parameter': return this.openAPIRegistry.registerParameter( - def.schema._def.openapi._internal.refId, + getOpenApiMetadata(def.schema)._internal?.refId, def.schema ) diff --git a/yarn.lock b/yarn.lock index 5809abca..a9e15b66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -99,14 +99,14 @@ __metadata: languageName: node linkType: hard -"@asteasolutions/zod-to-openapi@npm:^7.3.0": - version: 7.3.0 - resolution: "@asteasolutions/zod-to-openapi@npm:7.3.0" +"@asteasolutions/zod-to-openapi@npm:^8.0.0": + version: 8.0.0 + resolution: "@asteasolutions/zod-to-openapi@npm:8.0.0" dependencies: openapi3-ts: "npm:^4.1.2" peerDependencies: - zod: ^3.20.2 - checksum: 10c0/f0a68a89929cdeaa3e21d2027489689f982824d676a9332c680e119f60881dd39b571324b24ad4837fda49bf6fe7c3e2af2199268b281bf1aec923d7a7cbfc40 + zod: ^4.0.0 + checksum: 10c0/b522d074832fb137dca724c8bd4bb134c7b4d4cad12c247ed3c864f993923b3475fc06580e6e1cbc4fd8641cd361679bbe1dd87c9bb42e142bc056d96d59fbc8 languageName: node linkType: hard @@ -2734,7 +2734,7 @@ __metadata: resolution: "@hono/zod-openapi@workspace:packages/zod-openapi" dependencies: "@arethetypeswrong/cli": "npm:^0.17.4" - "@asteasolutions/zod-to-openapi": "npm:^7.3.0" + "@asteasolutions/zod-to-openapi": "npm:^8.0.0" "@hono/zod-validator": "workspace:^" hono: "npm:^4.8.4" openapi3-ts: "npm:^4.5.0" @@ -2743,10 +2743,10 @@ __metadata: typescript: "npm:^5.8.2" vitest: "npm:^3.2.4" yaml: "npm:^2.4.3" - zod: "npm:^3.22.1" + zod: "npm:^4.0.5" peerDependencies: hono: ">=4.3.6" - zod: ">=3.0.0" + zod: ^4.0.0 languageName: unknown linkType: soft @@ -16830,7 +16830,7 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.20.2, zod@npm:^3.22.1, zod@npm:^3.22.3": +"zod@npm:^3.20.2, zod@npm:^3.22.3": version: 3.24.2 resolution: "zod@npm:3.24.2" checksum: 10c0/c638c7220150847f13ad90635b3e7d0321b36cce36f3fc6050ed960689594c949c326dfe2c6fa87c14b126ee5d370ccdebd6efb304f41ef5557a4aaca2824565