Skip to content

Zod V4 implementation #701

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

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

Zod V4 implementation #701

wants to merge 13 commits into from

Conversation

SamJB123
Copy link

@SamJB123 SamJB123 commented Jul 26, 2025

Ready for testing and refinement by community - but expect rough edges!

Current version includes several opinionated decisions with a goal of writing a schema once.

  • Uses ZodV4 internals to map Zod's wide range of higher-level niche typings (IPV6, email etc) to their base primitives.
  • The alignment allows for a bidirectional schema, two-way validation (writes and reads), and type safety in IDE, at build time, and at run time.
  • Tuples were the trickiest zod "primitive" to deal with. The helper stores as objects at rest, and the helper restores them to being real tuples automatically for client-side actions and functions on the Convex backend (so array methods are still available).
  • Transforms required the biggest value judgment. Landed on respecting Zod's intent that they are one way trips. There's still unused functions in ZodV4.ts from my attempts to create full two-way conversion for people who want to dabble, but given some transforms are lossy (e.g. cropping a longer body of text), the complexity-benefit payoff didn't make sense to me.
  • After a few weeks of testing, I mentally treat transforms like the mirror of Convex queries, but for writes. Once transforms are written to the database, those outputs are still validated - but against the post-transform type.
  • I have not attempted to touch overwrites in this PR. At best, they might work out of the box in the same way as normal transforms. But I can't say for sure.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

SamJB123 added 2 commits July 26, 2025 15:57
Ready for testing - but expect rough edges.
@ianmacartney
Copy link
Collaborator

in #707 i put up some fixes but I couldn't remember the right way to try to upstream them to yours. let me know if I should fork your fork or if I could have permissions to push to that branch to collaborate

  • I moved the gui test into the root convex/ and src/ folder and out of the package
  • If you could use the linting & prettier formatting for the repo it'll help
  • running npm run dev in the root will run the tests, keep generated code up to date, etc.

It's really promising! Thanks for all the work

optional: z.object({ a: z.string(), b: z.number() }).optional(),
// For Convex compatibility, we need to avoid patterns that produce undefined
// Instead, use union with null for nullable fields and .optional() for optional fields
nullableOptional: z.union([z.string(), z.null()]).optional(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be a nullable optional..

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah..this might be a hangover from before I revised the approach to optionals (overhauled it at one point during writing to recognise that objects can happily handle optionals without any special treatment)

@mikecann
Copy link

The tests are failing but I ran it through AI and was able to fix all outstanding issues. I can commit if you like?

@SamJB123
Copy link
Author

@mikecann I'm happy if you're happy! Added you as collaborator too in case it makes things easier somehow.

@ianmacartney
Copy link
Collaborator

I'll close out #707 as I just was able to push up my changes here

@ianmacartney ianmacartney mentioned this pull request Jul 30, 2025
All tests pass thanks to Claude so long as the expected values in the original test have the correct assumptions
@mikecann
Copy link

Okay I have added a commit that fixes the tests. Just to be clear the AI did all the hard work here based upon the expected values found in the failing tests.

So hopefully those expected values were correct otherwise these fixes will be incorrect.

I don't have enough context on Zod4 to say either way if this is correct or not but after scanning through the 3k lines of tests it all looks okay 🤷

I do like the look of the bidirectional schema that looks nice.

@hasanaktas
Copy link

Is there a package with zod v4 support on npm? The latest version of npm is 0.1.101-alpha.0

@ianmacartney
Copy link
Collaborator

@hasanaktas the latest alpha now has these changes

Copy link

pkg-pr-new bot commented Aug 4, 2025

Open in StackBlitz

npm i https://pkg.pr.new/get-convex/convex-helpers@701

commit: 3605661

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants