fix(zod): treat @uuid without a version as any UUID version - #2832
Conversation
`addStringValidation` in packages/zod/src/utils.ts mapped the `@uuid` attribute with `if (version === 7) uuidv7() else uuidv4()`, so the no-version form fell into the v4 branch and rejected every other UUID version. stdlib.zmodel declares the version argument as optional and documents the attribute as "Validates a string field value is a valid UUID", and the `isUuid()` branch in the same file already passes an undefined version to `z.uuid()`, which accepts any version. Writing a v7 or v1 UUID into a `String @uuid` field therefore failed with `Validation error: Invalid UUID`. v7 is the shape ZenStack's own `uuid(7)` generator produces, at packages/orm/src/client/crud/operations/base.ts:1119. Only the no-version branch changes, to `result.uuid()`. `@uuid(4)` and `@uuid(7)` stay pinned, and the `@uuid` check in attribute-application-validator.ts already rejects any other version literal.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughChangesUUID validation
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to Bare Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Some tools did not complete. Review the errors below. 🔧 ESLint
packages/zod/src/utils.tsESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ymc9
left a comment
There was a problem hiding this comment.
Thanks for making this PR @MaxFreedomPollard . LGTM!
A bare
@uuidonly accepts v4. The version argument is declared optional and stdlib.zmodel documents the attribute as "Validates a string field value is a valid UUID", so@uuidwith no argument should accept any version, which is what the siblingisUuid()function already does.v7 is the shape ZenStack's own
uuid(7)generator produces, so a value read out of one model and written into a@uuidfield of another is rejected. Every non-v4 version fails, because the compiled pattern requires a literal4in the version nibble.Cause
addStringValidationinpackages/zod/src/utils.tsmaps the attribute withif (version === 7) result.uuidv7() else result.uuidv4(). Theelsecovers@uuid(4)and the no-version form alike, so a bare@uuidcompiles to zod's v4-only pattern^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$, whilepackages/orm/src/client/crud/operations/base.ts:1119generatesuuid.v7()foruuid(7). TheisUuidbranch ofevalCallin the same utils file passesversion: undefinedtoz.uuid()when the argument is omitted, which accepts any version, so the attribute path and the function path disagreed on identical semantics.Changes
@uuid(4)maps touuidv4(),@uuid(7)touuidv7(), and a bare@uuidtouuid(), which accepts any version. Those are the only three reachable branches, since the@uuidcheck inattribute-application-validator.tsalready rejects every other version literal.tests/e2e/orm/validation/toplevel.test.tsgains astr13 String? @uuid(4)field and four assertions: a bare@uuidaccepts a v7 value,@uuid(7)rejects a v4 value,@uuid(4)rejects a v7 value, and@uuid(4)accepts a v4 value. The last three pin the versioned forms so this does not get fixed in the other direction later.Verification
With the test change applied and
packages/zod/src/utils.tsreverted to dev,TEST_DB_PROVIDER=sqlite vitest run orm/validation/toplevel.test.tsintests/e2efails "works with string fields" withInvalid UUID at "data.str11", and the reportedpatternis the v4-only regex above. With the fix, that test passes.pnpm --filter @zenstackhq/zod testis 537 passed, no type errors.pnpm --filter @zenstackhq/zod lint,tsc --noEmitandprettier --checkon both changed files are clean.Two tests in
tests/e2e/orm/validationwere not run locally: "works with list fields" and "works with custom validation" declareInt[]fields and open a Postgres connection, which fails withECONNREFUSED 127.0.0.1:5432on my machine. Both fail identically on unmodified dev.Summary by CodeRabbit
Bug Fixes
@uuid(4)accepts version 4 UUIDs and rejects version 7 UUIDs.@uuid(7).@uuidvalidation continues to accept UUID values across supported versions.Tests