From a78716d91da7649a61016b81c27f49fd9e79a81e Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Tue, 16 Sep 2025 02:25:34 -0700 Subject: [PATCH 01/17] Update zshy (#5249) --- package.json | 2 +- play.ts | 11 +++-------- pnpm-lock.yaml | 46 +++++++++++++++++++++++++++++++++------------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 3a0473651..aa7c9fcc6 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "vitest": "^2.1.9", "zod": "workspace:*", "zod3": "npm:zod@~3.24.0", - "zshy": "^0.3.5" + "zshy": "^0.4.2" }, "lint-staged": { "packages/*/src/**/*.ts": [ diff --git a/play.ts b/play.ts index fa23e12e3..17d4f70e7 100644 --- a/play.ts +++ b/play.ts @@ -1,10 +1,5 @@ -import * as z from "zod"; +const test = () => 1; -z; +test.something = () => 2; -z.superRefine((val, ctx) => { - ctx.addIssue({ - code: "custom", - message: "Custom message", - }); -}); +test.something; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35820af35..fbaf394f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,8 +105,8 @@ importers: specifier: npm:zod@~3.24.0 version: zod@3.24.3 zshy: - specifier: ^0.3.5 - version: 0.3.5(typescript@5.5.4) + specifier: ^0.4.2 + version: 0.4.2(typescript@5.5.4) packages/bench: devDependencies: @@ -2810,6 +2810,10 @@ packages: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + ansi-styles@2.2.1: resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} engines: {node: '>=0.10.0'} @@ -2822,6 +2826,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + ansis@4.0.0: resolution: {integrity: sha512-P8nrHI1EyW9OfBt1X7hMSwGN2vwRuqHSKJAT1gbLWZRzDa24oHjYwGHvEgHeBepupzk878yS/HBZ0NMPYtbolw==} engines: {node: '>=14'} @@ -3197,8 +3205,8 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} - detect-libc@2.0.4: - resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + detect-libc@2.1.0: + resolution: {integrity: sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==} engines: {node: '>=8'} detect-node-es@1.1.0: @@ -5203,6 +5211,10 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} + strip-bom-string@1.0.0: resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} engines: {node: '>=0.10.0'} @@ -5718,8 +5730,8 @@ packages: zod@4.0.8: resolution: {integrity: sha512-+MSh9cZU9r3QKlHqrgHMTSr3QwMGv4PLfR0M4N/sYWV5/x67HgXEhIGObdBkpnX8G78pTgWnIrBL2lZcNJOtfg==} - zshy@0.3.5: - resolution: {integrity: sha512-snxs1iCIgLHY+eavk06UD54bTioXbXHzZ0XnsrDNjrztG7qrhagL6VyJ/jdBODZ0sCn+ZdqgXLwYLxZLydYdTA==} + zshy@0.4.2: + resolution: {integrity: sha512-q3OkMn4dXqVhwihg/XT5Rd/9kK38hFCpq+fM2uorXy8GjBMFjOSwW9P8wFHIBZQsyUakBFn/s7j7no8L2FU91w==} hasBin: true peerDependencies: typescript: '>5.5.0' @@ -6282,7 +6294,7 @@ snapshots: dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 @@ -7926,6 +7938,8 @@ snapshots: ansi-regex@6.1.0: {} + ansi-regex@6.2.2: {} + ansi-styles@2.2.1: {} ansi-styles@4.3.0: @@ -7934,6 +7948,8 @@ snapshots: ansi-styles@6.2.1: {} + ansi-styles@6.2.3: {} + ansis@4.0.0: {} ansis@4.1.0: {} @@ -8305,7 +8321,7 @@ snapshots: detect-libc@2.0.3: {} - detect-libc@2.0.4: + detect-libc@2.1.0: optional: true detect-node-es@1.1.0: {} @@ -9237,7 +9253,7 @@ snapshots: lightningcss@1.29.3: dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.0 optionalDependencies: lightningcss-darwin-arm64: 1.29.3 lightningcss-darwin-x64: 1.29.3 @@ -10908,7 +10924,7 @@ snapshots: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 string-width@7.2.0: dependencies: @@ -10939,6 +10955,10 @@ snapshots: dependencies: ansi-regex: 6.1.0 + strip-ansi@7.1.2: + dependencies: + ansi-regex: 6.2.2 + strip-bom-string@1.0.0: {} strip-final-newline@4.0.0: {} @@ -11411,9 +11431,9 @@ snapshots: wrap-ansi@8.1.0: dependencies: - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 string-width: 5.1.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 wrap-ansi@9.0.0: dependencies: @@ -11459,7 +11479,7 @@ snapshots: zod@4.0.8: {} - zshy@0.3.5(typescript@5.5.4): + zshy@0.4.2(typescript@5.5.4): dependencies: arg: 5.0.2 globby: 14.1.0 From 923af801fde9f033cfd7e0e753b421a554fe3be8 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Tue, 16 Sep 2025 02:26:56 -0700 Subject: [PATCH 02/17] Publish zod@4.1.9 --- packages/zod/jsr.json | 2 +- packages/zod/package.json | 2 +- packages/zod/src/v4/core/versions.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/zod/jsr.json b/packages/zod/jsr.json index 10b70b28f..508051f5e 100644 --- a/packages/zod/jsr.json +++ b/packages/zod/jsr.json @@ -1,6 +1,6 @@ { "name": "@zod/zod", - "version": "4.1.8", + "version": "4.1.9", "exports": { "./package.json": "./package.json", ".": "./src/index.ts", diff --git a/packages/zod/package.json b/packages/zod/package.json index feb1808bb..96077a587 100644 --- a/packages/zod/package.json +++ b/packages/zod/package.json @@ -1,6 +1,6 @@ { "name": "zod", - "version": "4.1.8", + "version": "4.1.9", "type": "module", "license": "MIT", "author": "Colin McDonnell ", diff --git a/packages/zod/src/v4/core/versions.ts b/packages/zod/src/v4/core/versions.ts index f27405f93..fc36b07dc 100644 --- a/packages/zod/src/v4/core/versions.ts +++ b/packages/zod/src/v4/core/versions.ts @@ -1,5 +1,5 @@ export const version = { major: 4, minor: 1, - patch: 8 as number, + patch: 9 as number, } as const; From 7ffedd00169d8dc2e7cb7c6d878f29b03e05b3a3 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sat, 20 Sep 2025 09:38:04 -0700 Subject: [PATCH 03/17] Fix shape caching (#5263) Fixes #5241 --- packages/zod/src/v4/classic/schemas.ts | 26 ++++----- .../v4/classic/tests/recursive-types.test.ts | 43 +++++++++++++++ packages/zod/src/v4/core/schemas.ts | 18 ++++++- packages/zod/src/v4/mini/schemas.ts | 20 ++----- play.ts | 53 +++++++++++++++++-- 5 files changed, 121 insertions(+), 39 deletions(-) diff --git a/packages/zod/src/v4/classic/schemas.ts b/packages/zod/src/v4/classic/schemas.ts index 6130b1f5c..e3a50f3dc 100644 --- a/packages/zod/src/v4/classic/schemas.ts +++ b/packages/zod/src/v4/classic/schemas.ts @@ -146,16 +146,14 @@ export const ZodType: core.$constructor = /*@__PURE__*/ core.$construct // base methods inst.check = (...checks) => { return inst.clone( - { - ...def, + util.mergeDefs(def, { checks: [ ...(def.checks ?? []), ...checks.map((ch) => typeof ch === "function" ? { _zod: { check: ch, def: { check: "custom" }, onattach: [] } } : ch ), ], - } - // { parent: true } + }) ); }; inst.clone = (def, params) => core.clone(inst, def, params); @@ -1196,7 +1194,10 @@ export const ZodObject: core.$constructor = /*@__PURE__*/ core.$const core.$ZodObjectJIT.init(inst, def); ZodType.init(inst, def); - util.defineLazy(inst, "shape", () => def.shape); + util.defineLazy(inst, "shape", () => { + return def.shape; + }); + inst.keyof = () => _enum(Object.keys(inst._zod.def.shape)) as any; inst.catchall = (catchall) => inst.clone({ ...inst._zod.def, catchall: catchall as any as core.$ZodType }) as any; inst.passthrough = () => inst.clone({ ...inst._zod.def, catchall: unknown() }); @@ -1223,10 +1224,7 @@ export function object, core.$strip> { const def: core.$ZodObjectDef = { type: "object", - get shape() { - util.assignProp(this, "shape", shape ? util.objectClone(shape) : {}); - return this.shape; - }, + shape: shape!, ...util.normalizeParams(params), }; return new ZodObject(def) as any; @@ -1240,10 +1238,7 @@ export function strictObject( ): ZodObject { return new ZodObject({ type: "object", - get shape() { - util.assignProp(this, "shape", util.objectClone(shape)); - return this.shape; - }, + shape, catchall: never(), ...util.normalizeParams(params), }) as any; @@ -1257,10 +1252,7 @@ export function looseObject( ): ZodObject { return new ZodObject({ type: "object", - get shape() { - util.assignProp(this, "shape", util.objectClone(shape)); - return this.shape; - }, + shape, catchall: unknown(), ...util.normalizeParams(params), }) as any; diff --git a/packages/zod/src/v4/classic/tests/recursive-types.test.ts b/packages/zod/src/v4/classic/tests/recursive-types.test.ts index 8f9821647..5ec7e48d2 100644 --- a/packages/zod/src/v4/classic/tests/recursive-types.test.ts +++ b/packages/zod/src/v4/classic/tests/recursive-types.test.ts @@ -537,3 +537,46 @@ export type RecursiveA = z.ZodUnion< }>, ] >; + +test("recursive type with `id` meta", () => { + const AType = z.object({ + type: z.literal("a"), + name: z.string(), + }); + + const BType = z.object({ + type: z.literal("b"), + name: z.string(), + }); + + const CType = z.object({ + type: z.literal("c"), + name: z.string(), + }); + + const Schema = z.object({ + type: z.literal("special").meta({ description: "Type" }), + config: z.object({ + title: z.string().meta({ description: "Title" }), + get elements() { + return z.array(z.discriminatedUnion("type", [AType, BType, CType])).meta({ + id: "SpecialElements", + title: "SpecialElements", + description: "Array of elements", + }); + }, + }), + }); + + Schema.parse({ + type: "special", + config: { + title: "Special", + elements: [ + { type: "a", name: "John" }, + { type: "b", name: "Jane" }, + { type: "c", name: "Jim" }, + ], + }, + }); +}); diff --git a/packages/zod/src/v4/core/schemas.ts b/packages/zod/src/v4/core/schemas.ts index 98aa588b1..55cbfc50f 100644 --- a/packages/zod/src/v4/core/schemas.ts +++ b/packages/zod/src/v4/core/schemas.ts @@ -1739,7 +1739,7 @@ export interface $ZodObjectDef extends $Zod export interface $ZodObjectInternals< /** @ts-ignore Cast variance */ - out Shape extends Readonly<$ZodShape> = Readonly<$ZodShape>, + out Shape extends $ZodShape = $ZodShape, out Config extends $ZodObjectConfig = $ZodObjectConfig, > extends _$ZodTypeInternals { def: $ZodObjectDef; @@ -1825,6 +1825,21 @@ function handleCatchall( export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$constructor("$ZodObject", (inst, def) => { // requires cast because technically $ZodObject doesn't extend $ZodType.init(inst, def); + // const sh = def.shape; + const desc = Object.getOwnPropertyDescriptor(def, "shape"); + if (!desc!.get) { + const sh = def.shape; + Object.defineProperty(def, "shape", { + get: () => { + const newSh = { ...sh }; + Object.defineProperty(def, "shape", { + value: newSh, + }); + + return newSh; + }, + }); + } const _normalized = util.cached(() => normalizeDef(def)); @@ -1853,7 +1868,6 @@ export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$con payload.issues.push({ expected: "object", code: "invalid_type", - input, inst, }); diff --git a/packages/zod/src/v4/mini/schemas.ts b/packages/zod/src/v4/mini/schemas.ts index 8dcd73aaa..b5f065bfd 100644 --- a/packages/zod/src/v4/mini/schemas.ts +++ b/packages/zod/src/v4/mini/schemas.ts @@ -769,10 +769,7 @@ export function object>( ): ZodMiniObject { const def: core.$ZodObjectDef = { type: "object", - get shape() { - util.assignProp(this, "shape", { ...shape }); - return this.shape; - }, + shape: shape!, ...util.normalizeParams(params), }; return new ZodMiniObject(def) as any; @@ -785,11 +782,7 @@ export function strictObject( ): ZodMiniObject { return new ZodMiniObject({ type: "object", - // shape: shape as core.$ZodLooseShape, - get shape() { - util.assignProp(this, "shape", { ...shape }); - return this.shape; - }, + shape, catchall: never(), ...util.normalizeParams(params), }) as any; @@ -802,14 +795,7 @@ export function looseObject( ): ZodMiniObject { return new ZodMiniObject({ type: "object", - // shape: shape as core.$ZodLooseShape, - get shape() { - util.assignProp(this, "shape", { ...shape }); - return this.shape; - }, - // get optional() { - // return util.optionalKeys(shape); - // }, + shape, catchall: unknown(), ...util.normalizeParams(params), }) as any; diff --git a/play.ts b/play.ts index 17d4f70e7..25ffd69f2 100644 --- a/play.ts +++ b/play.ts @@ -1,5 +1,52 @@ -const test = () => 1; +import * as z from "zod"; -test.something = () => 2; +z; -test.something; +// export const LinesSchema = >(schema: T) => +// z +// .string() +// .transform((input) => input.trim().split("\n")) +// .pipe(z.array(schema)); + +const AType = z.object({ + type: z.literal("a"), + name: z.string(), +}); + +const BType = z.object({ + type: z.literal("b"), + name: z.string(), +}); + +const CType = z.object({ + type: z.literal("c"), + name: z.string(), +}); + +const Schema = z.object({ + type: z.literal("special").meta({ description: "Type" }), + config: z.object({ + title: z.string().meta({ description: "Title" }), + get elements() { + return z.array(z.discriminatedUnion("type", [AType, BType, CType])).meta({ + id: "SpecialElements", + title: "SpecialElements", + description: "Array of elements", + }); + }, + }), +}); + +console.log( + Schema.parse({ + type: "special", + config: { + title: "Special", + elements: [ + { type: "a", name: "John" }, + { type: "b", name: "Jane" }, + { type: "c", name: "Jim" }, + ], + }, + }) +); From 82cd717a0e7ee4e1737a783c7be278fa93fd8104 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sat, 20 Sep 2025 12:40:44 -0400 Subject: [PATCH 04/17] v4.1.10 --- packages/zod/jsr.json | 2 +- packages/zod/package.json | 2 +- packages/zod/src/v4/core/versions.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/zod/jsr.json b/packages/zod/jsr.json index 508051f5e..257690111 100644 --- a/packages/zod/jsr.json +++ b/packages/zod/jsr.json @@ -1,6 +1,6 @@ { "name": "@zod/zod", - "version": "4.1.9", + "version": "4.1.10", "exports": { "./package.json": "./package.json", ".": "./src/index.ts", diff --git a/packages/zod/package.json b/packages/zod/package.json index 96077a587..602426f72 100644 --- a/packages/zod/package.json +++ b/packages/zod/package.json @@ -1,6 +1,6 @@ { "name": "zod", - "version": "4.1.9", + "version": "4.1.10", "type": "module", "license": "MIT", "author": "Colin McDonnell ", diff --git a/packages/zod/src/v4/core/versions.ts b/packages/zod/src/v4/core/versions.ts index fc36b07dc..34b962c64 100644 --- a/packages/zod/src/v4/core/versions.ts +++ b/packages/zod/src/v4/core/versions.ts @@ -1,5 +1,5 @@ export const version = { major: 4, minor: 1, - patch: 9 as number, + patch: 10 as number, } as const; From 2bed4b39760d8e4d678203b5c8fcaf24c182fc9f Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sat, 20 Sep 2025 13:14:57 -0400 Subject: [PATCH 05/17] 4.1.11 --- packages/zod/jsr.json | 2 +- packages/zod/package.json | 2 +- packages/zod/src/v4/classic/schemas.ts | 2 +- packages/zod/src/v4/core/schemas.ts | 2 +- packages/zod/src/v4/core/versions.ts | 2 +- packages/zod/src/v4/mini/schemas.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/zod/jsr.json b/packages/zod/jsr.json index 257690111..61fecc5f9 100644 --- a/packages/zod/jsr.json +++ b/packages/zod/jsr.json @@ -1,6 +1,6 @@ { "name": "@zod/zod", - "version": "4.1.10", + "version": "4.1.11", "exports": { "./package.json": "./package.json", ".": "./src/index.ts", diff --git a/packages/zod/package.json b/packages/zod/package.json index 602426f72..467822288 100644 --- a/packages/zod/package.json +++ b/packages/zod/package.json @@ -1,6 +1,6 @@ { "name": "zod", - "version": "4.1.10", + "version": "4.1.11", "type": "module", "license": "MIT", "author": "Colin McDonnell ", diff --git a/packages/zod/src/v4/classic/schemas.ts b/packages/zod/src/v4/classic/schemas.ts index e3a50f3dc..6f611d3f9 100644 --- a/packages/zod/src/v4/classic/schemas.ts +++ b/packages/zod/src/v4/classic/schemas.ts @@ -1224,7 +1224,7 @@ export function object, core.$strip> { const def: core.$ZodObjectDef = { type: "object", - shape: shape!, + shape: shape ?? {}, ...util.normalizeParams(params), }; return new ZodObject(def) as any; diff --git a/packages/zod/src/v4/core/schemas.ts b/packages/zod/src/v4/core/schemas.ts index 55cbfc50f..65fb1df72 100644 --- a/packages/zod/src/v4/core/schemas.ts +++ b/packages/zod/src/v4/core/schemas.ts @@ -1827,7 +1827,7 @@ export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$con $ZodType.init(inst, def); // const sh = def.shape; const desc = Object.getOwnPropertyDescriptor(def, "shape"); - if (!desc!.get) { + if (!desc?.get) { const sh = def.shape; Object.defineProperty(def, "shape", { get: () => { diff --git a/packages/zod/src/v4/core/versions.ts b/packages/zod/src/v4/core/versions.ts index 34b962c64..c20df22e8 100644 --- a/packages/zod/src/v4/core/versions.ts +++ b/packages/zod/src/v4/core/versions.ts @@ -1,5 +1,5 @@ export const version = { major: 4, minor: 1, - patch: 10 as number, + patch: 11 as number, } as const; diff --git a/packages/zod/src/v4/mini/schemas.ts b/packages/zod/src/v4/mini/schemas.ts index b5f065bfd..e79ee00a8 100644 --- a/packages/zod/src/v4/mini/schemas.ts +++ b/packages/zod/src/v4/mini/schemas.ts @@ -769,7 +769,7 @@ export function object>( ): ZodMiniObject { const def: core.$ZodObjectDef = { type: "object", - shape: shape!, + shape: shape ?? {}, ...util.normalizeParams(params), }; return new ZodMiniObject(def) as any; From 0b109c37c6b0b10e3901b56bcccb72e29a0b846f Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Sat, 20 Sep 2025 10:52:35 -0700 Subject: [PATCH 06/17] docs(ecosystem): add bupkis to the ecosystem section (#5237) [BUPKIS](https://bupkis.zip) is a new assertion library which encourages using Zod schemas to define custom assertions. --- packages/docs/components/ecosystem.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/docs/components/ecosystem.tsx b/packages/docs/components/ecosystem.tsx index a60c6ebdc..d12036e6e 100644 --- a/packages/docs/components/ecosystem.tsx +++ b/packages/docs/components/ecosystem.tsx @@ -210,6 +210,12 @@ const poweredByZodProjects: ZodResource[] = [ description: "A xlsx based resource validator using Zod schemas for data imports and more", slug: "sidwebworks/zod-xlsx", }, + { + name: "bupkis", + url: "https://github.com/boneskull/bupkis", + description: "Uncommonly extensible assertions for the beautiful people", + slug: "boneskull/bupkis", + } ]; const zodUtilities: ZodResource[] = [ From d22ec0d26fab27151b0f1d1f98bffeaf8b011f57 Mon Sep 17 00:00:00 2001 From: Laurent Blondy <51233631+L-Blondy@users.noreply.github.com> Date: Sat, 20 Sep 2025 19:52:49 +0200 Subject: [PATCH 07/17] docs(ecosystem): add upfetch (#5238) --- packages/docs/components/ecosystem.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/docs/components/ecosystem.tsx b/packages/docs/components/ecosystem.tsx index d12036e6e..dc3bbe847 100644 --- a/packages/docs/components/ecosystem.tsx +++ b/packages/docs/components/ecosystem.tsx @@ -52,7 +52,12 @@ const apiLibraries: ZodResource[] = [ description: "Type-safe JSON-RPC 2.0 client/server library using Zod.", slug: "danscan/zod-jsonrpc", }, - + { + name: "upfetch", + url: "https://github.com/L-Blondy/up-fetch", + description: "Advanced fetch client builder", + slug: "L-Blondy/up-fetch", + }, // https://github.com/honojs/middleware/tree/main/packages/zod-validator // { // name: "@hono/zod-validator", From c56a4f6fab42c542b191228af61974b2328dc52f Mon Sep 17 00:00:00 2001 From: Marco Pasqualetti <24919330+marcalexiei@users.noreply.github.com> Date: Sat, 20 Sep 2025 20:02:55 +0200 Subject: [PATCH 08/17] docs(ecosystem): add `eslint-plugin-zod-x` (#5261) --- packages/docs/components/ecosystem.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/docs/components/ecosystem.tsx b/packages/docs/components/ecosystem.tsx index dc3bbe847..b9089f753 100644 --- a/packages/docs/components/ecosystem.tsx +++ b/packages/docs/components/ecosystem.tsx @@ -236,6 +236,12 @@ const zodUtilities: ZodResource[] = [ description: "Interactive playground for testing and exploring Zod and Zod mini schemas in real-time.", slug: "marilari88/zod-playground", }, + { + name: "eslint-plugin-zod-x", + url: "https://github.com/marcalexiei/eslint-plugin-zod-x", + description: "ESLint plugin that adds custom linting rules to enforce best practices when using Zod", + slug: "marcalexiei/eslint-plugin-zod-x", + }, ]; export { From a0abcc02900a4293dd4f30cd81580efcdd5230bb Mon Sep 17 00:00:00 2001 From: "S. Mahdi Mir-Ismaili" Date: Sat, 20 Sep 2025 21:33:29 +0330 Subject: [PATCH 09/17] docs(metadata.mdx): fix a mistake in an example output (#5248) --- packages/docs/content/metadata.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/content/metadata.mdx b/packages/docs/content/metadata.mdx index 9404c2957..354f3b8ba 100644 --- a/packages/docs/content/metadata.mdx +++ b/packages/docs/content/metadata.mdx @@ -151,7 +151,7 @@ Metadata is associated with a *specific schema instance.* This is important to k ```ts const A = z.string().meta({ description: "A cool string" }); -A.meta(); // => { hello: "true" } +A.meta(); // => { description: "A cool string" } const B = A.refine(_ => true); B.meta(); // => undefined From 62bf4e439e287e55c843245b49f8d34b1ad024ee Mon Sep 17 00:00:00 2001 From: Meet Dhorajiya Date: Sun, 21 Sep 2025 22:43:23 +0530 Subject: [PATCH 10/17] fix(ZodError): prevent flatten() from crashing on 'toString' key (#5266) Uses Object.create(null) to create a prototype-less error object, avoiding collisions with built-in Object properties.Issue #5265 --- packages/zod/src/v3/ZodError.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/zod/src/v3/ZodError.ts b/packages/zod/src/v3/ZodError.ts index 6ee33c14a..b4c6865c4 100644 --- a/packages/zod/src/v3/ZodError.ts +++ b/packages/zod/src/v3/ZodError.ts @@ -296,7 +296,7 @@ export class ZodError extends Error { flatten(): typeToFlattenedError; flatten(mapper?: (issue: ZodIssue) => U): typeToFlattenedError; flatten(mapper: (issue: ZodIssue) => U = (issue: ZodIssue) => issue.message as any): any { - const fieldErrors: any = {}; + const fieldErrors: any = Object.create(null); const formErrors: U[] = []; for (const sub of this.issues) { if (sub.path.length > 0) { From 02a584010ac92ac8a351632ae5aea3983a6f17d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gromit=20=28=EC=A0=84=EB=AF=BC=EC=9E=AC=29?= <64779472+ssi02014@users.noreply.github.com> Date: Thu, 2 Oct 2025 02:25:55 +0900 Subject: [PATCH 11/17] refac(errors): Unify code structure and improve types (#5278) * refac(errors): Unify code structure and improve types * refac: fixed type --- packages/zod/src/v4/core/errors.ts | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/packages/zod/src/v4/core/errors.ts b/packages/zod/src/v4/core/errors.ts index 4d8465606..29c247b51 100644 --- a/packages/zod/src/v4/core/errors.ts +++ b/packages/zod/src/v4/core/errors.ts @@ -226,9 +226,9 @@ type _FlattenedError = { export function flattenError(error: $ZodError): _FlattenedError; export function flattenError(error: $ZodError, mapper?: (issue: $ZodIssue) => U): _FlattenedError; -export function flattenError(error: $ZodError, mapper = (issue: $ZodIssue) => issue.message): any { - const fieldErrors: any = {}; - const formErrors: any[] = []; +export function flattenError(error: $ZodError, mapper = (issue: $ZodIssue) => issue.message as U) { + const fieldErrors: Record = {}; + const formErrors: U[] = []; for (const sub of error.issues) { if (sub.path.length > 0) { fieldErrors[sub.path[0]!] = fieldErrors[sub.path[0]!] || []; @@ -254,12 +254,7 @@ export type $ZodFormattedError = { export function formatError(error: $ZodError): $ZodFormattedError; export function formatError(error: $ZodError, mapper?: (issue: $ZodIssue) => U): $ZodFormattedError; -export function formatError(error: $ZodError, _mapper?: any) { - const mapper: (issue: $ZodIssue) => any = - _mapper || - function (issue: $ZodIssue) { - return issue.message; - }; +export function formatError(error: $ZodError, mapper = (issue: $ZodIssue) => issue.message as U) { const fieldErrors: $ZodFormattedError = { _errors: [] } as any; const processError = (error: { issues: $ZodIssue[] }) => { for (const issue of error.issues) { @@ -307,13 +302,8 @@ export type $ZodErrorTree = T extends util.Primitive export function treeifyError(error: $ZodError): $ZodErrorTree; export function treeifyError(error: $ZodError, mapper?: (issue: $ZodIssue) => U): $ZodErrorTree; -export function treeifyError(error: $ZodError, _mapper?: any) { - const mapper: (issue: $ZodIssue) => any = - _mapper || - function (issue: $ZodIssue) { - return issue.message; - }; - const result: $ZodErrorTree = { errors: [] } as any; +export function treeifyError(error: $ZodError, mapper = (issue: $ZodIssue) => issue.message as U) { + const result: $ZodErrorTree = { errors: [] } as any; const processError = (error: { issues: $ZodIssue[] }, path: PropertyKey[] = []) => { for (const issue of error.issues) { if (issue.code === "invalid_union" && issue.errors.length) { From 4b1922ad714e12dafaa83a40ec03275a39ac980c Mon Sep 17 00:00:00 2001 From: Noritaka Kobayashi Date: Thu, 2 Oct 2025 02:26:39 +0900 Subject: [PATCH 12/17] docs(content/v4/index): fix zod version (#5289) --- packages/docs/content/v4/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/content/v4/index.mdx b/packages/docs/content/v4/index.mdx index 26ac355b7..8b4b4ea24 100644 --- a/packages/docs/content/v4/index.mdx +++ b/packages/docs/content/v4/index.mdx @@ -287,7 +287,7 @@ The core bundle is ~57% smaller in Zod 4 (2.3x). That's good! But we can do a lo Zod's method-heavy API is fundamentally difficult to tree-shake. Even our simple `z.boolean()` script pulls in the implementations of a bunch of methods we didn't use, like `.optional()`, `.array()`, etc. Writing slimmer implementations can only get you so far. That's where Zod Mini comes in. ```sh -npm install zod@^3.25.0 +npm install zod@^4.0.0 ``` It's a Zod variant with a functional, tree-shakable API that corresponds one-to-one with `zod`. Where Zod uses methods, Zod Mini generally uses wrapper functions: From 3fcb20ff348e49aec70f45e0dca3de8a61450e77 Mon Sep 17 00:00:00 2001 From: Schalk Venter Date: Wed, 1 Oct 2025 19:27:14 +0200 Subject: [PATCH 13/17] Add frrm to ecosystem (#5292) --- packages/docs/components/ecosystem.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/docs/components/ecosystem.tsx b/packages/docs/components/ecosystem.tsx index b9089f753..37b3ac704 100644 --- a/packages/docs/components/ecosystem.tsx +++ b/packages/docs/components/ecosystem.tsx @@ -99,6 +99,12 @@ const formIntegrations: ZodResource[] = [ description: "Svelte 5 library for creating forms based on JSON schema.", slug: "x0k/svelte-jsonschema-form", }, + { + name: "frrm", + url: "https://www.npmjs.com/package/frrm", + description: "Tiny 0.5kb Zod-based, HTML form abstraction that goes brr.", + slug: "schalkventer/frrm", + }, ]; const zodToXConverters: ZodResource[] = [ From fda4c7c2afbd7649261be1e7954f8c4d4de24a07 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sun, 5 Oct 2025 13:36:48 -0700 Subject: [PATCH 14/17] Make docs work without token --- packages/docs/components/ecosystem-v3.tsx | 619 ---------------------- packages/docs/components/ecosystem.tsx | 14 +- packages/docs/loaders/stars.ts | 23 +- 3 files changed, 27 insertions(+), 629 deletions(-) delete mode 100644 packages/docs/components/ecosystem-v3.tsx diff --git a/packages/docs/components/ecosystem-v3.tsx b/packages/docs/components/ecosystem-v3.tsx deleted file mode 100644 index ba852fcfd..000000000 --- a/packages/docs/components/ecosystem-v3.tsx +++ /dev/null @@ -1,619 +0,0 @@ -import { fetchStars } from "@/loaders/stars"; -import type React from "react"; - -interface ZodResource { - name: string; - url: string; - description: React.ReactNode; - slug: string; - stars?: number; - /** Whether the library has confirmed support for Zod 4 */ - v4?: boolean; -} - -const apiLibraries: ZodResource[] = [ - { - name: "tRPC", - url: "https://github.com/trpc/trpc", - description: "Build end-to-end typesafe APIs without GraphQL.", - slug: "trpc/trpc", - v4: true, - }, - { - name: "@anatine/zod-nestjs", - url: "https://github.com/anatine/zod-plugins/tree/main/packages/zod-nestjs", - description: "Helper methods for using Zod in a NestJS project.", - slug: "anatine/zod-plugins", - }, - { - name: "zod-endpoints", - url: "https://github.com/flock-community/zod-endpoints", - description: "Contract-first strictly typed endpoints with Zod. OpenAPI compatible.", - slug: "flock-community/zod-endpoints", - }, - { - name: "zhttp", - url: "https://github.com/evertdespiegeleer/zhttp", - description: "An OpenAPI compatible, strictly typed http library with Zod input and response validation.", - slug: "evertdespiegeleer/zhttp", - }, - { - name: "domain-functions", - url: "https://github.com/SeasonedSoftware/domain-functions/", - description: - "Decouple your business logic from your framework using composable functions. With first-class type inference from end to end powered by Zod schemas.", - slug: "SeasonedSoftware/domain-functions", - }, - { - name: "@zodios/core", - url: "https://github.com/ecyrbe/zodios", - description: "A typescript API client with runtime and compile time validation backed by axios and zod.", - slug: "ecyrbe/zodios", - }, - { - name: "express-zod-api", - url: "https://github.com/RobinTail/express-zod-api", - description: "Build Express-based APIs with I/O schema validation and custom middlewares.", - slug: "RobinTail/express-zod-api", - }, - { - name: "tapiduck", - url: "https://github.com/sumukhbarve/monoduck/blob/main/src/tapiduck/README.md", - description: "End-to-end typesafe JSON APIs with Zod and Express; a bit like tRPC, but simpler.", - slug: "sumukhbarve/monoduck", - }, - { - name: "koa-zod-router", - url: "https://github.com/JakeFenley/koa-zod-router", - description: "Create typesafe routes in Koa with I/O validation using Zod.", - slug: "JakeFenley/koa-zod-router", - }, - { - name: "zod-sockets", - url: "https://github.com/RobinTail/zod-sockets", - description: "Zod-powered Socket.IO microframework with I/O validation and built-in AsyncAPI specs", - slug: "RobinTail/zod-sockets", - }, - { - name: "oas-tszod-gen", - url: "https://github.com/inkognitro/oas-tszod-gen", - description: - "Client SDK code generator to convert OpenApi v3 specifications into TS endpoint caller functions with Zod types.", - slug: "inkognitro/oas-tszod-gen", - }, - { - name: "GQLoom", - url: "https://github.com/modevol-com/gqloom", - description: "Weave GraphQL schema and resolvers using Zod.", - slug: "modevol-com/gqloom", - v4: true, - }, -]; - -const formIntegrations: ZodResource[] = [ - { - name: "react-hook-form", - url: "https://github.com/react-hook-form/resolvers#zod", - description: "A first-party Zod resolver for React Hook Form.", - slug: "react-hook-form/react-hook-form", - }, - { - name: "zod-validation-error", - url: "https://github.com/causaly/zod-validation-error", - description: "Generate user-friendly error messages from ZodError instances.", - slug: "causaly/zod-validation-error", - }, - { - name: "zod-formik-adapter", - url: "https://github.com/robertLichtnow/zod-formik-adapter", - description: "A community-maintained Formik adapter for Zod.", - slug: "robertLichtnow/zod-formik-adapter", - }, - { - name: "react-zorm", - url: "https://github.com/esamattis/react-zorm", - description: "Standalone `
` generation and validation for React using Zod.", - slug: "esamattis/react-zorm", - }, - { - name: "zodix", - url: "https://github.com/rileytomasek/zodix", - description: "Zod utilities for FormData and URLSearchParams in Remix loaders and actions.", - slug: "rileytomasek/zodix", - }, - { - name: "conform", - url: "https://conform.guide/api/zod/parseWithZod", - description: - "A typesafe form validation library for progressive enhancement of HTML forms. Works with Remix and Next.js.", - slug: "edmundhung/conform", - }, - { - name: "remix-params-helper", - url: "https://github.com/kiliman/remix-params-helper", - description: "Simplify integration of Zod with standard URLSearchParams and FormData for Remix apps.", - slug: "kiliman/remix-params-helper", - }, - { - name: "formik-validator-zod", - url: "https://github.com/glazy/formik-validator-zod", - description: "Formik-compliant validator library that simplifies using Zod with Formik.", - slug: "glazy/formik-validator-zod", - }, - { - name: "zod-i18n-map", - url: "https://github.com/aiji42/zod-i18n", - description: "Useful for translating Zod error messages.", - slug: "aiji42/zod-i18n", - }, - { - name: "@modular-forms/solid", - url: "https://github.com/fabian-hiller/modular-forms", - description: "Modular form library for SolidJS that supports Zod for validation.", - slug: "fabian-hiller/modular-forms", - }, - { - name: "houseform", - url: "https://github.com/crutchcorn/houseform/", - description: "A React form library that uses Zod for validation.", - slug: "crutchcorn/houseform", - }, - { - name: "sveltekit-superforms", - url: "https://github.com/ciscoheat/sveltekit-superforms", - description: "Supercharged form library for SvelteKit with Zod validation.", - slug: "ciscoheat/sveltekit-superforms", - }, - { - name: "mobx-zod-form", - url: "https://github.com/MonoidDev/mobx-zod-form", - description: "Data-first form builder based on MobX & Zod.", - slug: "MonoidDev/mobx-zod-form", - }, - { - name: "@vee-validate/zod", - url: "https://github.com/logaretm/vee-validate/tree/main/packages/zod", - description: "Form library for Vue.js with Zod schema validation.", - slug: "logaretm/vee-validate", - }, - { - name: "zod-form-renderer", - url: "https://github.com/thepeaklab/zod-form-renderer", - description: "Auto-infer form fields from zod schema and render them with react-hook-form with E2E type safety.", - slug: "thepeaklab/zod-form-renderer", - }, - { - name: "antd-zod", - url: "https://github.com/MrBr/antd-zod", - description: "Zod adapter for Ant Design form fields validation.", - slug: "MrBr/antd-zod", - }, - { - name: "frrm", - url: "https://github.com/schalkventer/frrm", - description: "Tiny 0.5kb Zod-based, HTML form abstraction that goes brr.", - slug: "schalkventer/frrm", - }, - { - name: "regle", - url: "https://github.com/victorgarciaesgi/regle", - description: "Headless form validation library for Vue.js.", - slug: "victorgarciaesgi/regle", - v4: true, - }, -]; - -const zodToXConverters: ZodResource[] = [ - { - name: "zod-to-ts", - url: "https://github.com/sachinraja/zod-to-ts", - description: "Generate TypeScript definitions from Zod schemas.", - slug: "sachinraja/zod-to-ts", - }, - { - name: "zod-to-json-schema", - url: "https://github.com/StefanTerdell/zod-to-json-schema", - description: "Convert your Zod schemas into JSON Schemas.", - slug: "StefanTerdell/zod-to-json-schema", - }, - { - name: "@anatine/zod-openapi", - url: "https://github.com/anatine/zod-plugins/tree/main/packages/zod-openapi", - description: "Converts a Zod schema to an OpenAPI v3.x `SchemaObject`.", - slug: "anatine/zod-plugins", - }, - { - name: "zod-fast-check", - url: "https://github.com/DavidTimms/zod-fast-check", - description: "Generate `fast-check` arbitraries from Zod schemas.", - slug: "DavidTimms/zod-fast-check", - }, - { - name: "zod-dto", - url: "https://github.com/kbkk/abitia/tree/master/packages/zod-dto", - description: "Generate Nest.js DTOs from a Zod schema.", - slug: "kbkk/abitia", - }, - { - name: "fastify-type-provider-zod", - url: "https://github.com/turkerdev/fastify-type-provider-zod", - description: "Create Fastify type providers from Zod schemas.", - slug: "turkerdev/fastify-type-provider-zod", - }, - { - name: "zod-to-openapi", - url: "https://github.com/asteasolutions/zod-to-openapi", - description: "Generate full OpenAPI (Swagger) docs from Zod, including schemas, endpoints & parameters.", - slug: "asteasolutions/zod-to-openapi", - }, - { - name: "nestjs-graphql-zod", - url: "https://github.com/incetarik/nestjs-graphql-zod", - description: - "Generates NestJS GraphQL model classes from Zod schemas. Provides GraphQL method decorators working with Zod schemas.", - slug: "incetarik/nestjs-graphql-zod", - }, - { - name: "zod-openapi", - url: "https://github.com/samchungy/zod-openapi", - description: "Create full OpenAPI v3.x documentation from Zod schemas.", - slug: "samchungy/zod-openapi", - }, - { - name: "fastify-zod-openapi", - url: "https://github.com/samchungy/fastify-zod-openapi", - description: "Fastify type provider, validation, serialization and @fastify/swagger support for Zod schemas.", - slug: "samchungy/fastify-zod-openapi", - }, - { - name: "typeschema", - url: "https://typeschema.com/", - description: "Universal adapter for schema validation.", - slug: "decs/typeschema", - }, - { - name: "zodex", - url: "https://github.com/commonbaseapp/zodex", - description: "(De)serialization for zod schemas", - slug: "commonbaseapp/zodex", - }, - { - name: "zod2md", - url: "https://github.com/matejchalk/zod2md", - description: "Generate Markdown docs from Zod schemas", - slug: "matejchalk/zod2md", - }, -]; - -const xToZodConverters: ZodResource[] = [ - { - name: "ts-to-zod", - url: "https://github.com/fabien0102/ts-to-zod", - description: "Convert TypeScript definitions into Zod schemas.", - slug: "fabien0102/ts-to-zod", - }, - { - name: "@runtyping/zod", - url: "https://github.com/johngeorgewright/runtyping", - description: "Generate Zod from static types & JSON schema.", - slug: "johngeorgewright/runtyping", - }, - { - name: "json-schema-to-zod", - url: "https://github.com/StefanTerdell/json-schema-to-zod", - description: "Convert your JSON Schemas into Zod schemas.", - slug: "StefanTerdell/json-schema-to-zod", - }, - { - name: "json-to-zod", - url: "https://github.com/rsinohara/json-to-zod", - description: "Convert JSON objects into Zod schemas.", - slug: "rsinohara/json-to-zod", - }, - { - name: "GraphQL schema gen", - url: "https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema", - description: "GraphQL Code Generator plugin to generate form validation schema from your GraphQL schema.", - slug: "Code-Hex/graphql-codegen-typescript-validation-schema", - }, - { - name: "zod-prisma", - url: "https://github.com/CarterGrimmeisen/zod-prisma", - description: "Generate Zod schemas from your Prisma schema.", - slug: "CarterGrimmeisen/zod-prisma", - }, - { - name: "Supervillain", - url: "https://github.com/Southclaws/supervillain", - description: "Generate Zod schemas from your Go structs.", - slug: "Southclaws/supervillain", - }, - { - name: "prisma-zod-generator", - url: "https://github.com/omar-dulaimi/prisma-zod-generator", - description: "Emit Zod schemas from your Prisma schema.", - slug: "omar-dulaimi/prisma-zod-generator", - }, - { - name: "drizzle-zod", - url: "https://orm.drizzle.team/docs/zod", - description: "Emit Zod schemas from your Drizzle schema.", - slug: "drizzle-team/drizzle-orm", - }, - { - name: "prisma-trpc-generator", - url: "https://github.com/omar-dulaimi/prisma-trpc-generator", - description: "Emit fully implemented tRPC routers and their validation schemas using Zod.", - slug: "omar-dulaimi/prisma-trpc-generator", - }, - { - name: "zod-prisma-types", - url: "https://github.com/chrishoermann/zod-prisma-types", - description: "Create Zod types from your Prisma models.", - slug: "chrishoermann/zod-prisma-types", - }, - { - name: "quicktype", - url: "https://app.quicktype.io/", - description: "Convert JSON objects and JSON schemas into Zod schemas.", - slug: "glideapps/quicktype", - }, - { - name: "@sanity-typed/zod", - url: "https://github.com/saiichihashimoto/sanity-typed/tree/main/packages/zod", - description: "Generate Zod Schemas from Sanity Schemas.", - slug: "saiichihashimoto/sanity-typed", - }, - { - name: "java-to-zod", - url: "https://github.com/ivangreene/java-to-zod", - description: "Convert POJOs to Zod schemas", - slug: "ivangreene/java-to-zod", - }, - { - name: "Orval", - url: "https://github.com/anymaniax/orval", - description: "Generate Zod schemas from OpenAPI schemas", - slug: "anymaniax/orval", - v4: true, - }, - { - name: "Kubb", - url: "https://github.com/kubb-labs/kubb", - description: "Generate SDKs and Zod schemas from your OpenAPI schemas", - slug: "kubb-labs/kubb", - v4: true, - }, - { - name: "Hey API", - url: "https://heyapi.dev/openapi-ts/plugins/zod/v3", - description: "The OpenAPI to TypeScript codegen. Generate clients, SDKs, validators, and more.", - slug: "hey-api/openapi-ts", - v4: true, - }, -]; - -const mockingLibraries: ZodResource[] = [ - { - name: "@anatine/zod-mock", - url: "https://github.com/anatine/zod-plugins/tree/main/packages/zod-mock", - description: "Generate mock data from a Zod schema. Powered by faker.js.", - slug: "anatine/zod-plugins", - }, - { - name: "zod-mocking", - url: "https://github.com/dipasqualew/zod-mocking", - description: "Generate mock data from your Zod schemas.", - slug: "dipasqualew/zod-mocking", - }, - { - name: "zod-fixture", - url: "https://github.com/timdeschryver/zod-fixture", - description: - "Use your zod schemas to automate the generation of non-relevant test fixtures in a deterministic way.", - slug: "timdeschryver/zod-fixture", - }, - { - name: "zocker", - url: "https://zocker.sigrist.dev", - description: "Generate plausible mock-data from your schemas.", - slug: "LorisSigrist/zocker", - }, - { - name: "zodock", - url: "https://github.com/ItMaga/zodock", - description: "Generate mock data based on Zod schemas.", - slug: "ItMaga/zodock", - }, - { - name: "zod-schema-faker", - url: "https://github.com/soc221b/zod-schema-faker", - description: "Generates mock data from Zod schemas. Powered by @faker-js/faker and randexp.js", - slug: "soc221b/zod-schema-faker", - v4: true, - }, -]; - -const poweredByZodProjects: ZodResource[] = [ - { - name: "freerstore", - url: "https://github.com/JacobWeisenburger/freerstore", - description: "Firestore cost optimizer.", - slug: "JacobWeisenburger/freerstore", - }, - { - name: "slonik", - url: "https://github.com/gajus/slonik/tree/gajus/add-zod-validation-backwards-compatible#runtime-validation-and-static-type-inference", - description: "Node.js Postgres client with strong Zod integration.", - slug: "gajus/slonik", - }, - { - name: "schemql", - url: "https://github.com/a2lix/schemql", - description: "Enhances your SQL workflow by combining raw SQL with targeted type safety and schema validation.", - slug: "a2lix/schemql", - }, - { - name: "soly", - url: "https://github.com/mdbetancourt/soly", - description: "Create CLI applications with zod.", - slug: "mdbetancourt/soly", - }, - { - name: "pastel", - url: "reesericci/zod-struct", - description: "Create CLI applications with react, zod, and ink.", - slug: "vadimdemedes/pastel", - }, - { - name: "zod-xlsx", - url: "https://github.com/sidwebworks/zod-xlsx", - description: "A xlsx based resource validator using Zod schemas.", - slug: "sidwebworks/zod-xlsx", - }, - { - name: "znv", - url: "https://github.com/lostfictions/znv", - description: "Type-safe environment parsing and validation for Node.js with Zod schemas.", - slug: "lostfictions/znv", - }, - { - name: "zod-config", - url: "https://github.com/alexmarqs/zod-config", - description: "Load configurations across multiple sources with flexible adapters, ensuring type safety with Zod.", - slug: "alexmarqs/zod-config", - v4: true, - }, - { - name: "unplugin-environment", - url: "https://github.com/r17x/js/tree/main/packages/unplugin-environment#readme", - description: - "A plugin for loading environment variables safely with schema validation, simple with virtual module, type-safe with intellisense, and better DX 🔥 🚀 👷. Powered by Zod.", - slug: "r17x/js", - }, - { - name: "zod-struct", - url: "https://codeberg.org/reesericci/zod-struct", - description: "Create runtime-checked structs with Zod.", - slug: "reesericci/zod-struct", - stars: 0, - }, - { - name: "Composable Functions", - url: "https://github.com/seasonedcc/composable-functions", - description: "Types and functions to make composition easy and safe.", - slug: "seasonedcc/composable-functions", - v4: true, - }, -]; - -const zodUtilities: ZodResource[] = [ - { - name: "zod_utilz", - url: "https://github.com/JacobWeisenburger/zod_utilz", - description: "Framework agnostic utilities for Zod.", - slug: "JacobWeisenburger/zod_utilz", - }, - { - name: "zod-playground", - url: "https://github.com/marilari88/zod-playground", - description: "A tool for learning and testing Zod schema validation functionalities.", - slug: "marilari88/zod-playground", - }, - { - name: "zod-sandbox", - url: "https://github.com/nereumelo/zod-sandbox", - description: "Controlled environment for testing zod schemas.", - slug: "nereumelo/zod-sandbox", - }, - { - name: "zod-dev", - url: "https://github.com/schalkventer/zod-dev", - description: "Conditionally disables Zod runtime parsing in production.", - slug: "schalkventer/zod-dev", - }, - { - name: "zod-accelerator", - url: "https://github.com/duplojs/duplojs-zod-accelerator", - description: "Accelerates Zod's throughput up to ~100x.", - slug: "duplojs/duplojs-zod-accelerator", - }, -]; - -export { - // resources, - apiLibraries, - formIntegrations, - zodToXConverters, - xToZodConverters, - mockingLibraries, - poweredByZodProjects, - zodUtilities, -}; - -export function Table(props: { resources: ZodResource[] }) { - return ( - - - - - - - - - - - {props.resources.map((resource) => ( - - - - - - - ))} - -
NameStarsZod 4 supportDescription
- - {resource.name} - - {`⭐️ ${resource.stars ?? "ERR"}`}{`${resource.v4 ? "✅" : ""}`}{resource.description}
- ); -} - -type ResourceTableProps = { - resources: ZodResource[]; -}; - -async function ResourceTable({ resources }: ResourceTableProps) { - await fetchStars(resources); - - return ; -} - -export async function ApiLibraries() { - return ; -} - -export async function FormIntegrations() { - return ; -} - -export async function ZodToX() { - return ; -} - -export async function XToZod() { - return ; -} - -export async function MockingLibraries() { - return ; -} - -export async function PoweredByZod() { - return ; -} - -export async function ZodUtilities() { - return ; -} diff --git a/packages/docs/components/ecosystem.tsx b/packages/docs/components/ecosystem.tsx index 37b3ac704..d5ac86a7d 100644 --- a/packages/docs/components/ecosystem.tsx +++ b/packages/docs/components/ecosystem.tsx @@ -37,7 +37,8 @@ const apiLibraries: ZodResource[] = [ { name: "nestjs-zod", url: "https://github.com/BenLorantfy/nestjs-zod", - description: "Integrate nestjs and zod. Create nestjs DTOs using zod, serialize with zod, and generate OpenAPI documentation from zod schemas", + description: + "Integrate nestjs and zod. Create nestjs DTOs using zod, serialize with zod, and generate OpenAPI documentation from zod schemas", slug: "BenLorantfy/nestjs-zod", }, { @@ -135,7 +136,7 @@ const zodToXConverters: ZodResource[] = [ { name: "@traversable/zod", url: "https://github.com/traversable/schema/tree/main/packages/zod", - description: "Build your own \"Zod to x\" library, or pick one of 25+ off-the-shelf transformers", + description: 'Build your own "Zod to x" library, or pick one of 25+ off-the-shelf transformers', slug: "traversable/schema", }, ]; @@ -154,7 +155,6 @@ const xToZodConverters: ZodResource[] = [ slug: "kubb-labs/kubb", }, { - name: "Hey API", url: "https://heyapi.dev/openapi-ts/plugins/zod", description: "The OpenAPI to TypeScript codegen. Generate clients, SDKs, validators, and more.", @@ -169,7 +169,8 @@ const xToZodConverters: ZodResource[] = [ { name: "Prisma Zod Generator", url: "https://github.com/omar-dulaimi/prisma-zod-generator", - description: "Generates Zod schemas with input/result/pure variants, minimal/full/custom, selective emit/filtering, single/multi-file output, @zod rules, relation depth guards.", + description: + "Generates Zod schemas with input/result/pure variants, minimal/full/custom, selective emit/filtering, single/multi-file output, @zod rules, relation depth guards.", slug: "omar-dulaimi/prisma-zod-generator", }, { @@ -197,7 +198,8 @@ const mockingLibraries: ZodResource[] = [ { name: "@traversable/zod-test", url: "https://github.com/traversable/schema/tree/main/packages/zod-test", - description: "Random zod schema generator built for fuzz testing; includes generators for both valid and invalid data", + description: + "Random zod schema generator built for fuzz testing; includes generators for both valid and invalid data", slug: "traversable/schema", }, ]; @@ -279,7 +281,7 @@ export function Table(props: { resources: ZodResource[] }) { {resource.name} - + {/* */} diff --git a/packages/docs/loaders/stars.ts b/packages/docs/loaders/stars.ts index e032eae50..163e442fb 100644 --- a/packages/docs/loaders/stars.ts +++ b/packages/docs/loaders/stars.ts @@ -1,7 +1,9 @@ const GITHUB_TOKEN = process.env.GITHUB_TOKEN!; const API_URL = "https://api.github.com/graphql"; -export async function fetchStars(resources: { slug: string; stars?: number }[]) { +export async function fetchStars( + resources: { slug: string; stars?: number }[], +) { try { if (resources.length === 0) return; const uniqueSlugs = Array.from( @@ -11,8 +13,8 @@ export async function fetchStars(resources: { slug: string; stars?: number }[]) .map((r, id) => ({ id, slug: r.slug, - })) - ) + })), + ), ); if (uniqueSlugs.length === 0) return; @@ -36,6 +38,16 @@ export async function fetchStars(resources: { slug: string; stars?: number }[]) body: JSON.stringify({ query }), }); + if (res.status > 400) { + console.error( + "Failed to fetch GitHub stars. Make sure you are providing a valid GITHUB_TOKEN in packages/docs/.env", + ); + if (process.env.NODE_ENV === "production") { + throw new Error("Failed to fetch GitHub stars."); + } + return; + } + const json = await res.json(); if (json.errors) { @@ -61,6 +73,9 @@ export async function fetchStars(resources: { slug: string; stars?: number }[]) resources.sort((a, b) => (b.stars || 0) - (a.stars || 0)); } catch (_) { console.log(_); - throw new Error("Failed to fetch GitHub stars"); + + if (process.env.NODE_ENV === "production") { + throw new Error("Failed to fetch GitHub stars"); + } } } From af447384379faef28aa857fb53ef1da702c6d408 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Sun, 5 Oct 2025 21:20:33 -0700 Subject: [PATCH 15/17] Fix lint --- packages/docs/loaders/stars.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/docs/loaders/stars.ts b/packages/docs/loaders/stars.ts index 163e442fb..4e698001d 100644 --- a/packages/docs/loaders/stars.ts +++ b/packages/docs/loaders/stars.ts @@ -1,9 +1,7 @@ const GITHUB_TOKEN = process.env.GITHUB_TOKEN!; const API_URL = "https://api.github.com/graphql"; -export async function fetchStars( - resources: { slug: string; stars?: number }[], -) { +export async function fetchStars(resources: { slug: string; stars?: number }[]) { try { if (resources.length === 0) return; const uniqueSlugs = Array.from( @@ -13,8 +11,8 @@ export async function fetchStars( .map((r, id) => ({ id, slug: r.slug, - })), - ), + })) + ) ); if (uniqueSlugs.length === 0) return; @@ -40,7 +38,7 @@ export async function fetchStars( if (res.status > 400) { console.error( - "Failed to fetch GitHub stars. Make sure you are providing a valid GITHUB_TOKEN in packages/docs/.env", + "Failed to fetch GitHub stars. Make sure you are providing a valid GITHUB_TOKEN in packages/docs/.env" ); if (process.env.NODE_ENV === "production") { throw new Error("Failed to fetch GitHub stars."); From 77c3c9f069a4cf168c0cbc58432803de887a6b1b Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Mon, 6 Oct 2025 09:28:21 -0700 Subject: [PATCH 16/17] Export bg.ts --- packages/zod/src/v4/locales/index.ts | 1 + play.ts | 49 ---------------------------- 2 files changed, 1 insertion(+), 49 deletions(-) diff --git a/packages/zod/src/v4/locales/index.ts b/packages/zod/src/v4/locales/index.ts index 8f7b48f42..9b360f804 100644 --- a/packages/zod/src/v4/locales/index.ts +++ b/packages/zod/src/v4/locales/index.ts @@ -1,6 +1,7 @@ export { default as ar } from "./ar.js"; export { default as az } from "./az.js"; export { default as be } from "./be.js"; +export { default as bg } from "./bg.js"; export { default as ca } from "./ca.js"; export { default as cs } from "./cs.js"; export { default as da } from "./da.js"; diff --git a/play.ts b/play.ts index 25ffd69f2..4564a8e84 100644 --- a/play.ts +++ b/play.ts @@ -1,52 +1,3 @@ import * as z from "zod"; z; - -// export const LinesSchema = >(schema: T) => -// z -// .string() -// .transform((input) => input.trim().split("\n")) -// .pipe(z.array(schema)); - -const AType = z.object({ - type: z.literal("a"), - name: z.string(), -}); - -const BType = z.object({ - type: z.literal("b"), - name: z.string(), -}); - -const CType = z.object({ - type: z.literal("c"), - name: z.string(), -}); - -const Schema = z.object({ - type: z.literal("special").meta({ description: "Type" }), - config: z.object({ - title: z.string().meta({ description: "Title" }), - get elements() { - return z.array(z.discriminatedUnion("type", [AType, BType, CType])).meta({ - id: "SpecialElements", - title: "SpecialElements", - description: "Array of elements", - }); - }, - }), -}); - -console.log( - Schema.parse({ - type: "special", - config: { - title: "Special", - elements: [ - { type: "a", name: "John" }, - { type: "b", name: "Jane" }, - { type: "c", name: "Jim" }, - ], - }, - }) -); From 3b946107b6c94b2ac8ff9fb451160c34dc4dd794 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Mon, 6 Oct 2025 09:28:50 -0700 Subject: [PATCH 17/17] v4.1.12 --- packages/zod/jsr.json | 2 +- packages/zod/package.json | 2 +- packages/zod/src/v4/core/versions.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/zod/jsr.json b/packages/zod/jsr.json index 61fecc5f9..efd3af0af 100644 --- a/packages/zod/jsr.json +++ b/packages/zod/jsr.json @@ -1,6 +1,6 @@ { "name": "@zod/zod", - "version": "4.1.11", + "version": "4.1.12", "exports": { "./package.json": "./package.json", ".": "./src/index.ts", diff --git a/packages/zod/package.json b/packages/zod/package.json index 467822288..409817267 100644 --- a/packages/zod/package.json +++ b/packages/zod/package.json @@ -1,6 +1,6 @@ { "name": "zod", - "version": "4.1.11", + "version": "4.1.12", "type": "module", "license": "MIT", "author": "Colin McDonnell ", diff --git a/packages/zod/src/v4/core/versions.ts b/packages/zod/src/v4/core/versions.ts index c20df22e8..ff0889cb0 100644 --- a/packages/zod/src/v4/core/versions.ts +++ b/packages/zod/src/v4/core/versions.ts @@ -1,5 +1,5 @@ export const version = { major: 4, minor: 1, - patch: 11 as number, + patch: 12 as number, } as const;
{`⭐️ ${resource.stars ?? "ERR"}`}{`⭐️ ${resource.stars ?? "—"}`}{`⭐️ ${resource.v4 ? "✅" : ""}`}{resource.description}