Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Oct 29, 2025

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 29, 2025

📝 Walkthrough

Walkthrough

Adds configurable Zod versioning (accepts 'v3' or 'v4') by adding a zodVersion parameter, validating it in the generator, and threading it into the Transformer and generation paths so emitted imports and Zod type shapes reference the selected zod/{version} and generate version-specific types.

Changes

Cohort / File(s) Summary
Zod plugin generator & wiring
packages/schema/src/plugins/zod/generator.ts
Add and validate zodVersion option (only 'v3'
Transformer implementation
packages/schema/src/plugins/zod/transformer.ts
Add private zodVersion member and makeZodType(typeArg) helper; initialize from params; replace hard-coded z.ZodType<...> usages with makeZodType(...); update imports to zod/${this.zodVersion} and adjust refine function generation signature.
Types / params
packages/schema/src/plugins/zod/types.ts
Add `zodVersion: 'v3'
Tests & test harness
tests/regression/tests/issue-1378.test.ts, packages/server/tests/adapter/elysia.test.ts
Update test import from zodzod/v3; mark one test ("custom load path") skipped in elysia adapter tests with comment.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as Generator
  participant Gen as Zod generator
  participant TF as Transformer
  participant FS as Emitted files

  CLI->>Gen: parse options (includes zodVersion)
  Gen->>TF: construct Transformer(params + zodVersion)
  TF->>TF: makeZodType(typeArg) -> versioned ZodType form
  TF->>FS: emit imports "zod/{zodVersion}" and versioned schemas
  note right of FS #D3E6FF: Outputs: schemas, inputs, barrel index, tests
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay special attention to:
    • Validation and defaulting of zodVersion in generator.ts.
    • Correctness of makeZodType(...) for both v3 and v4 signatures and all replacement sites in transformer.ts.
    • Consistency of emitted import paths and any generated refine function signatures.
    • Test updates reflecting new import paths.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ❓ Inconclusive The pull request description is completely empty, with no content provided by the author. This means the description conveys no meaningful information about the changeset whatsoever, making it impossible to assess whether it relates to or describes any part of the changes. An empty description falls into the category of being extremely vague and generic, as it provides zero context or detail about the modifications being made. While the description is not explicitly off-topic (since it doesn't exist), the complete absence of information prevents any conclusive evaluation of relevance. Please provide a pull request description that explains the motivation for adding explicit Zod version control, the changes being made, and any relevant context or testing performed. Even a brief description explaining why this feature was added would help reviewers understand the intent of the PR.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "fix(zod): add option to control zod version explicitly" directly and clearly summarizes the main change in the changeset. The raw summary confirms that the PR introduces a new zodVersion property that allows explicit selection between Zod v3 and v4, with option-based validation accepting only these two values. The title is concise, specific, and accurately captures the primary intent of the modifications across the affected files. The use of "fix" and the specific mention of "control zod version" appropriately conveys what the changes accomplish.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/zod-ver

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4627b8 and 718f443.

📒 Files selected for processing (1)
  • packages/server/tests/adapter/elysia.test.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-test (20.x)
  • GitHub Check: OSSAR-Scan
  • GitHub Check: dependency-review
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
🔇 Additional comments (1)
packages/server/tests/adapter/elysia.test.ts (1)

87-117: Document the test failure cause or fix in this PR.

The search found no existing tracking issues for this test. Skipping tests reduces coverage, so either:

  1. Fix the test in this PR and document what was wrong
  2. Create a tracking issue with specific failure details (error output, conditions) so it can be addressed separately

Without knowing whether the failure relates to Zod versioning changes or another cause, it's hard to know which path is right. Please clarify the root cause and decide how to proceed.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/schema/src/plugins/zod/transformer.ts (2)

41-56: Default zodVersion for resilience

Consider defaulting to 'v3' if params.zodVersion is undefined to prevent accidental breakage.

- this.zodVersion = params.zodVersion;
+ this.zodVersion = params.zodVersion ?? 'v3';

108-112: Avoid zod/${version} import here as well

Same module‑resolution risk as in generator. Prefer import { z } from 'zod' (or @zenstackhq/runtime/zod).

-        let r = `import { z } from 'zod/${this.zodVersion}';\n`;
+        let r = `import { z } from 'zod';\n`;
♻️ Duplicate comments (3)
packages/schema/src/plugins/zod/generator.ts (1)

387-389: Same import-path concern as above

This repeats the zod/${version} import risk. Please apply the same fix here.

packages/schema/src/plugins/zod/transformer.ts (2)

505-507: Same makeZodType issue on JSON schema

The annotation const jsonSchema: ${this.makeZodType('Prisma.InputJsonValue')} inherits the same problem. Will be fixed once makeZodType is corrected.


891-895: Same makeZodType issue for operation args

The mapped Args types should be z.ZodType<Prisma.XxxArgs>; current v4 branch will not type‑check.

🧹 Nitpick comments (1)
packages/schema/src/plugins/zod/transformer.ts (1)

232-236: Optional: Prefer z.iso.datetime() in v4 branch

Small polish: for DateTime, when targeting v4 you can emit z.iso.datetime() instead of z.string().datetime() to match new APIs; keep v3 as-is.

Example:

- result.push(this.wrapWithZodValidators(['z.date()', 'z.string().datetime()'], field, inputType));
+ result.push(this.wrapWithZodValidators(
+   this.zodVersion === 'v4' ? ['z.date()', 'z.iso.datetime()'] : ['z.date()', 'z.string().datetime()'],
+   field, inputType
+ ));

Based on learnings

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2744da and 1ac2df7.

📒 Files selected for processing (3)
  • packages/schema/src/plugins/zod/generator.ts (8 hunks)
  • packages/schema/src/plugins/zod/transformer.ts (8 hunks)
  • packages/schema/src/plugins/zod/types.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/schema/src/plugins/zod/transformer.ts (2)
packages/runtime/src/local-helpers/upper-case-first.ts (1)
  • upperCaseFirst (1-3)
packages/sdk/src/utils.ts (1)
  • indentString (129-132)
packages/schema/src/plugins/zod/generator.ts (2)
packages/sdk/src/types.ts (1)
  • PluginError (115-119)
packages/schema/src/plugins/zod/index.ts (1)
  • name (5-5)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: dependency-review
  • GitHub Check: OSSAR-Scan
🔇 Additional comments (9)
packages/schema/src/plugins/zod/generator.ts (7)

53-54: LGTM: sane default

Defaulting to 'v3' is fine.


165-166: Threading zodVersion into Transformer looks good

Propagation is consistent.


266-267: Propagation LGTM

zodVersion correctly passed for enum generation.


297-298: Propagation LGTM

zodVersion correctly passed for object schemas.


733-738: Refine helper signature seems fine for both Zod v3 and v4

Using z.ZodType<T> is compatible. No issues spotted.

Ensure downstream consumers aren’t relying on the old two‑generic form in their typings.


236-247: Ignore this review comment; the Zod subpath import pattern is valid and documented.

Zod supports zod/v3 and zod/v4 as public subpath exports that are intended to remain available permanently. The code at lines 236-247 generates imports like import { z } from 'zod/v3'; (via zod/${this.zodVersion}), which is exactly the documented approach for version-specific code. This pattern will not fail module resolution—it's the recommended way to handle Zod's major version transitions.

Likely an incorrect or invalid review comment.


79-87: Cannot definitively verify: PluginOptions is defined externally

The PluginOptions type is imported from the external @zenstackhq/sdk package, so I cannot inspect its definition or verify whether version is documented as an official option key or whether zodVersion is already part of it. Additionally:

  • No documentation in this repository describes the expected version or zodVersion option
  • No tests demonstrate the expected usage
  • The review references a PR objective not visible in the codebase

The review's concern about naming clarity (using zodVersion over generic version) is reasonable, but without access to the external type definition and existing documentation/examples, I cannot confirm whether this is a breaking change, whether backward compatibility is needed, or if the suggested aliasing approach is compatible with how PluginOptions is currently defined.

packages/schema/src/plugins/zod/transformer.ts (2)

3-3: Minor import tidy

Moving upperCaseFirst here is fine.


957-959: Verify the ZodType generic fix against actual Zod v4 type definitions and generated code behavior

Based on my research, there's conflicting evidence about the correctness of the current implementation:

Web search findings:

  • v3 has three generics: ZodType<Output, Def extends ZodTypeDef, Input>
  • v4 uses two generics: ZodType<Output = unknown, Input = unknown>, with the Def generic removed

Current code analysis:

  • v3 generates: z.ZodType<${typeArg}> (one generic)
  • v4 generates: z.ZodType<${typeArg}, ${typeArg}> (two generics matching v4's Output and Input)

Issue with the review's claim:
The review states dual generics "break v4," but the current v4 implementation appears semantically correct—it explicitly specifies both Output and Input as the same type. However, the review suggests a single generic works for both versions. I cannot find definitive evidence that the current v4 code causes type errors, nor can I confirm that single generic produces the intended behavior when Input defaults to unknown in v4.

Recommendations for verification:

  1. Run TypeScript type checks against both generated schemas with Zod v3 and v4
  2. Confirm whether z.ZodType<T> in v4 (with Input=unknown) is semantically acceptable for the generated code's use cases
  3. Check if generated code that uses these type annotations actually compiles and behaves correctly

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/regression/tests/issue-1378.test.ts (1)

3-46: Consider adding test coverage for Zod v4.

Since the PR introduces configurable Zod versioning supporting both 'v3' and 'v4', consider adding a complementary test case to verify the v4 import path and generated code work correctly.

Add a new test case:

it('regression with zod v4', async () => {
    await loadSchema(
        `
        model User {
          id   String @id @default(cuid())
          todos Todo[]
        }
        
        model Todo {
          id String @id @default(cuid())
          name String @length(3,255)
          userId String @default(auth().id)
      
          user User @relation(fields: [userId], references: [id], onDelete: Cascade)
          @@allow("all", auth() == user)
      }
      `,
        {
            extraDependencies: ['zod'],
            zodVersion: 'v4',
            extraSourceFiles: [
                {
                    name: 'main.ts',
                    content: `
              import { z } from 'zod/v4';
              import { PrismaClient } from '@prisma/client';
              import { enhance } from '.zenstack/enhance';
              import { TodoCreateSchema } from '.zenstack/zod/models';
                            
              const prisma = new PrismaClient();
              const db = enhance(prisma);

              export const onSubmit = async (values: z.infer<typeof TodoCreateSchema>) => {
                await db.todo.create({
                  data: values,
                });
              };
              `,
                },
            ],
            compile: true,
        }
    );
});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ac2df7 and a4627b8.

📒 Files selected for processing (1)
  • tests/regression/tests/issue-1378.test.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: OSSAR-Scan
  • GitHub Check: dependency-review
🔇 Additional comments (1)
tests/regression/tests/issue-1378.test.ts (1)

27-27: ****

The 'zod/v3' import path is not an invalid reference to a non-existent npm package export. It's the expected generated code path from zenstack's zod plugin. When loadSchema() is called without an explicit zodVersion option, it defaults to 'v3', and the generated schemas in .zenstack/zod/ will automatically use matching imports (import { z } from 'zod/v3'). The test file's extraSourceFiles code correctly imports from the same generated path, so the imports will align. No explicit configuration or code changes are required.

Likely an incorrect or invalid review comment.

@ymc9
Copy link
Member Author

ymc9 commented Oct 29, 2025

fixes #2276

@ymc9 ymc9 merged commit 47849e1 into dev Oct 29, 2025
8 of 9 checks passed
@ymc9 ymc9 deleted the feat/zod-ver branch October 29, 2025 17:33
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.

2 participants