-
Notifications
You must be signed in to change notification settings - Fork 0
chore: update zod to version 4 #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughUpdated the zod dependency in package.json from ^3.25.62 to ^4.0.17. Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~2 minutes Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Lite
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (1)
package.json(1 hunks)
🔇 Additional comments (1)
package.json (1)
61-61: Versioning impact: validate your library’s semver after this upgradeIf this upgrade is observable to consumers (e.g., through peerDependencies or exported types that depend on Zod’s types), this may warrant a new major version of your package. If it’s entirely internal and non-breaking to consumers, the current versioning is fine.
Please confirm whether any public-facing types or runtime behavior depend on Zod specifics. If yes, consider aligning your package version accordingly and updating the CHANGELOG with migration notes.
| "cosmjs-types": "^0.9.0", | ||
| "immer": "^10.1.1", | ||
| "zod": "^3.25.62" | ||
| "zod": "^4.0.17" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Consider making zod a peerDependency (to avoid duplicate instances and type incompatibilities)
If any exported APIs expose Zod schemas/types or consumers are expected to use z.infer on your exported schemas, zod should be a peerDependency (and a devDependency for local build/tests) rather than a runtime dependency. This prevents multiple Zod copies in downstream apps and avoids type identity issues.
To decide, scan for Zod usage in exported surfaces:
If results indicate exposure, consider this change:
"dependencies": {
@@
- "zod": "^4.0.17"
+ },
+ "peerDependencies": {
+ "zod": "^4.0.0"
},
"devDependencies": {
@@
+ "zod": "^4.0.17",If Zod is strictly internal and never leaks through the public API, keeping it in dependencies is acceptable.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Exported symbols that reference z.* =="
rg -n --no-heading $'^export\\s+(type|interface|const|function|class)\\b[^{=]*\\{?[^\\n]*\\bz\\.' -S || true
echo
echo "== Exported types using z.infer =="
rg -n --no-heading $'^export\\s+type\\b[^=]*=\\s*z\\.infer' -S || true
echo
echo "== Direct re-exports from zod (should be none) =="
rg -n --no-heading $'^export\\s+\\*\\s+from\\s+[\'"]zod[\'"]' -S || trueLength of output: 4532
Move Zod into peerDependencies & devDependencies
Zod schemas and z.infer types are exposed in your public API (see src/schema/**/*.ts and src/utils/find-move-events.ts), so you must declare Zod as a peerDependency (and as a devDependency for tests/build) rather than a runtime dependency:
• Remove from dependencies (currently at package.json:61)
• Add to peerDependencies (e.g. "zod": "^4.0.0")
• Add to devDependencies (e.g. "zod": "^4.0.17")
Suggested diff in package.json:
"dependencies": {
- "zod": "^4.0.17"
},
+ "peerDependencies": {
+ "zod": "^4.0.0"
+ },
"devDependencies": {
+ "zod": "^4.0.17",
…other dev deps
}Note: if you officially support Yarn (classic/berry), you may keep Zod in dependencies to ensure installation for Yarn users (since Yarn does not auto‐install peerDependencies) while still declaring it as a peerDependency to avoid duplicate instances.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "zod": "^4.0.17" | |
| "dependencies": { | |
| }, | |
| "peerDependencies": { | |
| "zod": "^4.0.0" | |
| }, | |
| "devDependencies": { | |
| "zod": "^4.0.17", | |
| …other dev deps | |
| } |
💡 Verification agent
🧩 Analysis chain
Major version bump to Zod v4: audit for breaking changes and ESM/CJS interop
Upgrading from v3 → v4 is a breaking change. Given this package publishes both ESM and CJS builds (Lines 14–28), verify:
- Zod v4 compatibility with your current usage.
- Whether Zod v4 is ESM-only and how tsup handles it for your CJS output. If Zod remains externalized and ESM-only, requiring it from CJS can break.
Run the following to quickly assess impact in-repo and locate build config:
And please fetch authoritative details on v4 to confirm expectations:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Zod import sites =="
rg -n --no-heading $'from\\s+[\'"]zod[\'"]|require\\([\'"]zod[\'"]\\)' -S || true
echo
echo "== Potentially brittle deep imports (should be none) =="
rg -n --no-heading $'from\\s+[\'"]zod/|require\\([\'"]zod/' -S || true
echo
echo "== Common Zod API usage overview (for migration review) =="
rg -n --no-heading $'\\bz\\.(object|array|union|discriminatedUnion|enum|nativeEnum|string|number|bigint|boolean|date|literal|tuple|record|map|set|nullable|optional|default|catch|transform|preprocess|refine|superRefine|effects|coerce)' -S || true
echo
echo "== tsup configuration (to validate externals/bundling) =="
fd -H -a '^tsup\\.config\\.(ts|js|cjs|mjs)$' || trueLength of output: 25136
🌐 Web query:
Zod v4 migration guide and breaking changes. Also, does Zod v4 ship a CommonJS build or is it ESM-only?
💡 Result:
Zod v4 introduces several breaking changes (with an official migration guide), and it is published in a way that supports both ESM and CommonJS consumers—but Zod v4 is accessed via the subpath import zod/v4, which can require Node/TypeScript “Node16/NodeNext/Bundler” module resolution when used from CommonJS toolchains.[5][8][9]
Key Zod v4 breaking changes and migration notes
- Error path handling: Zod 4’s new parsing architecture no longer eagerly computes ctx.path; direct access to ctx.path was dropped to enable performance gains.[5]
- Function-as-second-argument overload removed: The old “horrifying overload” for refinements/transformers that accepted a function as a second argument has been removed; migrate to the v4 API forms documented in the guide.[5]
- Optional shorthand creators removed: Undocumented shorthands like z.ostring(), z.onumber(), etc., were dropped; switch to z.string().optional(), z.number().optional(), etc.[5]
- Static .create() factories removed: All Zod classes no longer have a static .create(); use the standalone factory functions (e.g., z.object(...), z.string(), etc.).[5]
- z.record() changes:
- Single-argument usage removed; you must provide both key and value schemas where appropriate.[5]
- Enum key support improved: passing an enum as the key schema now infers exhaustive records and enforces all enum keys exist; to get the old “partial” behavior use the new z.partialRecord().[5]
- z.intersection() behavior: On merge conflicts of incompatible results, Zod 4 now throws a regular Error (not a ZodError with "invalid_intersection_types"), signaling a structural schema issue.[5]
Official migration resources and ecosystem transition
- Versioning approach: Zod 4 is exported first at subpath "zod/v4" alongside Zod 3 at the root ("zod") and at "zod/v3", enabling incremental migration across apps and libraries; later, the package root switches to export Zod 4 while "zod/v4" remains available.[8]
- Practical impact: If you import from "zod/v4" you’re on v4 APIs; if you import from "zod" you may still be on v3 until the root flips (noted as already completed on that page). Libraries should import only from the versioned subpaths to remain compatible.[8]
- Community codemod: A community-maintained codemod zod-v3-to-v4 is available to help update common API changes (error handling, object/string APIs, and other breaking changes).[1][5]
ESM vs. CommonJS: does Zod v4 ship a CJS build?
- Packaging and consumption: The maintainers deliberately ship Zod 4 via the "zod/v4" subpath along with Zod 3, and it is consumable from both ESM and CommonJS projects; however, TypeScript module resolution needs to be compatible with package subpath exports (Node16/NodeNext/Bundler) when importing "zod/v4" from CJS builds.[8][9]
- Reported CJS friction and workaround: Users compiling a CommonJS build reported “Cannot find module 'zod/v4'” under classic TS moduleResolution; switching tsconfig to module: "Node16" and moduleResolution: "Node16" resolved it, aligning TS with Node’s subpath exports resolution.[9] If you remain purely "commonjs" with classic resolution, you may see TS1479 or resolution errors; dynamic import("zod/v4") is another workaround suggested by TypeScript when mixing CJS with ESM exports.[9]
- Summary: Zod v4 is not “ESM-only,” but its subpath export and type resolution expect modern Node/TypeScript module resolution settings. In CommonJS projects, configure TS to Node16/NodeNext/Bundler or use dynamic import if you cannot change settings.[8][9]
Additional notes and cautions
- Zod 3 and 4 co-publishing: During the transition, Zod 3 continued to be published while including Zod 4 under subpaths; some users found that upgrading Zod 3 to late 3.25.x inadvertently pulled in v4 code that requires newer TS (TS 5.x), causing breakages in TS 4.x toolchains. Pin to earlier 3.x if you must stay on TS 4.x.[2][8]
- Learning resources: The v4 migration guide lists changes in order of impact and is the canonical source for updating code.[5] A video overview is also available for a practical tour of new features.[7] A codemod can automate common changes.[1]
If you share a small snippet of your current Zod v3 usage, I can map the exact v4 replacements and flag any path/error handling you’ll need to adjust.[5][1]
Citations:
- 1: https://www.hypermod.io/explore/zod-v4
- 2: Latest Zod3 now includes Zod4, which causes breaking changes on minor zod upgrade colinhacks/zod#4923
- 3: https://betterstack.com/community/guides/scaling-nodejs/commonjs-vs-esm/
- 4: https://www.totaltypescript.com/bonuses/typescript-expert-interviews/colin-mcdonnell-talks-about-the-design-choices-behind-zod
- 5: https://zod.dev/v4/changelog
- 6: https://www.npmjs.com/package/zod-from-json-schema
- 7: https://www.youtube.com/watch?v=T4Q1NvSePxs
- 8: https://zod.dev/v4/versioning
- 9: Cannot find module 'zod/v4' — CommonJS colinhacks/zod#4372
- 10: https://betterstack.com/community/guides/scaling-nodejs/express-5-new-features/
Major version bump to Zod v4: replace default import & verify build interop
- In
src/schema/transaction.ts, change the default import to a named import (v4 no longer provides a default export):- import z from "zod"; + import { z } from "zod";
- No deep imports of
zod/…were found—every schema uses top-level APIs (z.object,z.union,z.preprocess,z.coerce, etc.), all compatible with v4. - Zod v4 ships both ESM and CJS from the root
"zod"; double-check your tsup build (inline CLI flags inpackage.json) to ensure:
•zodis either externalized or bundled correctly in both your ESM and CJS outputs
• your TypeScriptmoduleResolution(e.g. Node16/NodeNext) aligns with Node’s subpath export rules if you ever switch tozod/v4
Committable suggestion skipped: line range outside the PR's diff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@evilpeach any idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me check and test it first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider yarn which does not automatically install peerDependencies.
Summary by CodeRabbit