From 53db4d3b39ac21bf1742b6aafc0f3cf3bb88d84a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 16:37:12 +0000 Subject: [PATCH 1/5] chore(deps): update dependency zod to v4 --- package.json | 2 +- pnpm-lock.yaml | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4c1beb68..cec6aabf 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "typescript": "5.9.3", "valibot": "1.2.0", "vitest": "4.0.18", - "zod": "3.25.76", + "zod": "4.3.6", "zod-to-json-schema": "3.25.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c4799565..a8411d5c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,11 +100,11 @@ importers: specifier: 4.0.18 version: 4.0.18(@types/node@24.10.13)(tsx@4.21.0) zod: - specifier: 3.25.76 - version: 3.25.76 + specifier: 4.3.6 + version: 4.3.6 zod-to-json-schema: specifier: 3.25.1 - version: 3.25.1(zod@3.25.76) + version: 3.25.1(zod@4.3.6) packages: @@ -4232,6 +4232,9 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zx@8.8.5: resolution: {integrity: sha512-SNgDF5L0gfN7FwVOdEFguY3orU5AkfFZm9B5YSHog/UDHv+lvmd82ZAsOenOkQixigwH2+yyH198AwNdKhj+RA==} engines: {node: '>= 12.17.0'} @@ -8703,10 +8706,12 @@ snapshots: dependencies: zod: 3.25.76 - zod-to-json-schema@3.25.1(zod@3.25.76): + zod-to-json-schema@3.25.1(zod@4.3.6): dependencies: - zod: 3.25.76 + zod: 4.3.6 zod@3.25.76: {} + zod@4.3.6: {} + zx@8.8.5: {} From 600a40b0a14cf11ce57e92a478571082f436e757 Mon Sep 17 00:00:00 2001 From: Misha Kaletsky <15040698+mmkal@users.noreply.github.com> Date: Fri, 13 Feb 2026 06:20:59 +0000 Subject: [PATCH 2/5] fix: restore help output for zod v4 anyOf unions --- src/json-schema.ts | 61 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/json-schema.ts b/src/json-schema.ts index 1ec30def..26c99f7f 100644 --- a/src/json-schema.ts +++ b/src/json-schema.ts @@ -81,6 +81,7 @@ export const getDescription = (v: JSONSchema7, depth = 0): string => { if (k.startsWith('$')) return false // helpers props to add on to a few different external library output formats if (k === 'maximum' && vv === Number.MAX_SAFE_INTEGER) return false // zod adds this for `z.number().int().positive()` if (depth <= 1 && k === 'enum' && getEnumChoices(v)?.type === 'string_enum') return false // don't show Enum: ["a","b"], that's handled by commander's `choices` + if (depth === 0 && k === 'anyOf' && getEnumChoices(v)?.type === 'string_enum') return false return true }) .sort(([a], [b]) => { @@ -89,6 +90,21 @@ export const getDescription = (v: JSONSchema7, depth = 0): string => { }) .map(([k, vv], i) => { if (k === 'type' && Array.isArray(vv)) return `type: ${vv.join(' or ')}` + if (k === 'anyOf') { + const anyOf = (v.anyOf || []) as JSONSchema7[] + const isSimpleAnyOf = anyOf.every(subSchema => { + if (!subSchema || typeof subSchema !== 'object') return false + return Object.keys(subSchema).every(key => key === 'type' || key === 'const') + }) + + if (isSimpleAnyOf) { + const types = [...new Set(anyOf.flatMap(getSchemaTypes))] + if (types.length > 0) { + const label = depth > 0 ? 'Type' : 'type' + return `${label}: ${types.join(' or ')}` + } + } + } if (k === 'description' && i === 0) return String(vv) if (k === 'properties') return `Object (json formatted)` if (typeof vv === 'object') return `${capitaliseFromCamelCase(k)}: ${JSON.stringify(vv)}` @@ -126,6 +142,7 @@ export const getSchemaTypes = ( /** Returns a list of all allowed subschemas. If the schema is not a union, returns a list with a single item. */ export const getAllowedSchemas = (schema: JSONSchema7): JSONSchema7[] => { if (!schema) return [] + if (getEnumChoices(schema)) return [schema] if ('anyOf' in schema && Array.isArray(schema.anyOf)) return (schema.anyOf as JSONSchema7[]).flatMap(getAllowedSchemas) if ('oneOf' in schema && Array.isArray(schema.oneOf)) @@ -136,24 +153,22 @@ export const getAllowedSchemas = (schema: JSONSchema7): JSONSchema7[] => { } export const getEnumChoices = (propertyValue: JSONSchema7) => { + const isLiteralAnyOfEntry = ( + subSchema: unknown, + expectedType: 'string' | 'number', + ): subSchema is {const: string} | {const: number} => { + if (!subSchema || typeof subSchema !== 'object' || !('const' in subSchema)) return false + if (typeof subSchema.const !== expectedType) return false + if ('type' in subSchema && subSchema.type != null && ![subSchema.type].flat().includes(expectedType)) { + return false + } + return Object.keys(subSchema).every(key => key === 'const' || key === 'type') + } + if (!propertyValue) return null if (!('enum' in propertyValue && Array.isArray(propertyValue.enum))) { // arktype prefers {anyOf: [{const: 'foo'}, {const: 'bar'}]} over {enum: ['foo', 'bar']} 🤷 - if ( - 'anyOf' in propertyValue && - propertyValue.anyOf?.every(subSchema => { - if ( - subSchema && - typeof subSchema === 'object' && - 'const' in subSchema && - Object.keys(subSchema).length === 1 && - typeof subSchema.const === 'string' - ) { - return true - } - return false - }) - ) { + if ('anyOf' in propertyValue && propertyValue.anyOf?.every(subSchema => isLiteralAnyOfEntry(subSchema, 'string'))) { // all the subschemas are string literals, so we can use them as choices return { type: 'string_enum', @@ -161,21 +176,7 @@ export const getEnumChoices = (propertyValue: JSONSchema7) => { } as const } - if ( - 'anyOf' in propertyValue && - propertyValue.anyOf?.every(subSchema => { - if ( - subSchema && - typeof subSchema === 'object' && - 'const' in subSchema && - Object.keys(subSchema).length === 1 && - typeof subSchema.const === 'number' - ) { - return true - } - return false - }) - ) { + if ('anyOf' in propertyValue && propertyValue.anyOf?.every(subSchema => isLiteralAnyOfEntry(subSchema, 'number'))) { // all the subschemas are string literals, so we can use them as choices return { type: 'number_enum', From bf8e4d9001ab7a6dc821e1d67bd6e68407f98719 Mon Sep 17 00:00:00 2001 From: Misha Kaletsky <15040698+mmkal@users.noreply.github.com> Date: Mon, 16 Feb 2026 13:00:12 +0000 Subject: [PATCH 3/5] add zod3 explicitly? --- package.json | 1 + pnpm-lock.yaml | 3 +++ test/zod3.test.ts | 2 +- vite.config.ts | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cec6aabf..72748447 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "typescript": "5.9.3", "valibot": "1.2.0", "vitest": "4.0.18", + "zod3": "npm:zod@3.25.76", "zod": "4.3.6", "zod-to-json-schema": "3.25.1" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a8411d5c..64e5a131 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,6 +105,9 @@ importers: zod-to-json-schema: specifier: 3.25.1 version: 3.25.1(zod@4.3.6) + zod3: + specifier: npm:zod@3.25.76 + version: zod@3.25.76 packages: diff --git a/test/zod3.test.ts b/test/zod3.test.ts index 1c960d23..6d3e586c 100644 --- a/test/zod3.test.ts +++ b/test/zod3.test.ts @@ -1,7 +1,7 @@ import {initTRPC} from '@trpc/server' import {inspect} from 'util' import {expect, test} from 'vitest' -import {z} from 'zod/v3' // same as 'zod' but this is more explicit +import {z} from 'zod3' import {createCli, TrpcCliMeta} from '../src/index.js' import {run, snapshotSerializer} from './test-run.js' diff --git a/vite.config.ts b/vite.config.ts index 3530063a..1ddaa0ca 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,7 +2,7 @@ import {defineConfig} from 'vitest/config' export default defineConfig({ test: { - exclude: ['*ignoreme*', 'node_modules'], + exclude: ['*ignoreme*', 'node_modules', '.opencode'], setupFiles: ['./test/setup.ts'], typecheck: { enabled: true, From 0e350a059e06e828ae07e79e030fb89ea1cb015d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 09:51:58 +0000 Subject: [PATCH 4/5] Update dependency zod to v4.4.3 --- package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 78ce36c5..b6fab3a3 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "valibot": "1.2.0", "vitest": "4.0.18", "zod3": "npm:zod@3.25.76", - "zod": "4.3.6", + "zod": "4.4.3", "zod-to-json-schema": "3.25.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9187ab2d..f33e45f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,11 +100,11 @@ importers: specifier: 4.0.18 version: 4.0.18(@types/node@24.10.13)(tsx@4.21.0) zod: - specifier: 4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 zod-to-json-schema: specifier: 3.25.1 - version: 3.25.1(zod@4.3.6) + version: 3.25.1(zod@4.4.3) zod3: specifier: npm:zod@3.25.76 version: zod@3.25.76 @@ -4235,8 +4235,8 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.3.6: - resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} zx@8.8.5: resolution: {integrity: sha512-SNgDF5L0gfN7FwVOdEFguY3orU5AkfFZm9B5YSHog/UDHv+lvmd82ZAsOenOkQixigwH2+yyH198AwNdKhj+RA==} @@ -8709,12 +8709,12 @@ snapshots: dependencies: zod: 3.25.76 - zod-to-json-schema@3.25.1(zod@4.3.6): + zod-to-json-schema@3.25.1(zod@4.4.3): dependencies: - zod: 4.3.6 + zod: 4.4.3 zod@3.25.76: {} - zod@4.3.6: {} + zod@4.4.3: {} zx@8.8.5: {} From b3982963c0b7d16caad550ec7cedfc42631a8f64 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 08:52:18 +0000 Subject: [PATCH 5/5] Update dependency zod to v4.4.3 --- package.json | 2 +- pnpm-lock.yaml | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 7cddba37..e3d7d2b7 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "valibot": "1.2.0", "vitest": "4.0.18", "yaml": "^2.8.2", - "zod": "4.3.6", + "zod": "4.4.3", "zod-to-json-schema": "3.25.1", "zod3": "npm:zod@3.25.76" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0ce548a7..ed7fdfa0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -109,11 +109,11 @@ importers: specifier: ^2.8.2 version: 2.8.2 zod: - specifier: 4.3.6 - version: 4.3.6 + specifier: 4.4.3 + version: 4.4.3 zod-to-json-schema: specifier: 3.25.1 - version: 3.25.1(zod@4.3.6) + version: 3.25.1(zod@4.4.3) zod3: specifier: npm:zod@3.25.76 version: zod@3.25.76 @@ -2552,6 +2552,7 @@ packages: glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true global-directory@4.0.1: @@ -4259,6 +4260,7 @@ packages: whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} @@ -4356,8 +4358,8 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.3.6: - resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} zx@8.8.5: resolution: {integrity: sha512-SNgDF5L0gfN7FwVOdEFguY3orU5AkfFZm9B5YSHog/UDHv+lvmd82ZAsOenOkQixigwH2+yyH198AwNdKhj+RA==} @@ -8958,12 +8960,12 @@ snapshots: dependencies: zod: 3.25.76 - zod-to-json-schema@3.25.1(zod@4.3.6): + zod-to-json-schema@3.25.1(zod@4.4.3): dependencies: - zod: 4.3.6 + zod: 4.4.3 zod@3.25.76: {} - zod@4.3.6: {} + zod@4.4.3: {} zx@8.8.5: {}