8000 fix(zod): avoid importing Prisma enum, recognize enum fields with default by ymc9 · Pull Request #2307 · zenstackhq/zenstack · GitHub
[go: up one dir, main page]

Skip to content

Conversation

@ymc9
Copy link
Member
@ymc9 ymc9 commented Nov 22, 2025

fixes #2291

@coderabbitai
Copy link
Contributor
coderabbitai bot commented Nov 22, 2025
📝 Walkthrough

Walkthrough

Removed the output parameter from the Zod generator prelude/import helper and updated callers; stopped emitting conditional @prisma/client enum imports; added handling for enum-reference defaults (emit enum name as JSON string) and a transformer option to emit enums as literal strings; added a regression test validating enum default population when loading Zod schemas.

Changes

Cohort / File(s) Summary
Zod generator signature & import cleanup
packages/schema/src/plugins/zod/generator.ts
Removed output parameter from addPreludeAndImports signature and updated all call sites; removed conditional emission of @prisma/client enum imports; adjusted refine() generation formatting to place the closing brace on same line as join result.
Enum default handling in schema generation
packages/schema/src/plugins/zod/utils/schema-gen.ts
Imported isEnumFieldReference and extended getFieldSchemaDefault to detect enum field-reference defaults and return the enum's name as a JSON string when default is an enum reference.
Expression transformer option
packages/sdk/src/typescript-expression-transformer.ts
Added useLiteralEnum?: boolean option to TypeScriptExpressionTransformer; when true, enum expressions are emitted as JSON string literals instead of dot-qualified enum member expressions.
Regression test
tests/regression/tests/issue-2291.test.ts
Added test that loads an inline schema with an enum default and asserts parsing via generated Zod schema populates the default enum value.

Sequence Diagram(s)

sequenceDiagram
    participant Generator as ZodGenerator
    participant Prelude as addPreludeAndImports
    participant Writer as CodeBlockWriter
    participant SchemaGen as getFieldSchemaDefault
    participant Transformer as TypeScriptExpressionTransformer

    rect `#eef2ff`
      Generator->>Prelude: addPreludeAndImports(decl, writer)
      note right of Prelude `#f0fff4`: no `output` arg\nno conditional `@prisma/client` enum import
      Prelude-->>Writer: write prelude & imports
    end

    rect `#fff7ed`
      Generator->>SchemaGen: getFieldSchemaDefault(field)
      alt default is enum ref
        SchemaGen->>Transformer: transform enum reference (useLiteralEnum: true)
        Transformer-->>Generator: return JSON string literal (e.g. "Ex1")
      else other literals
        SchemaGen-->>Generator: return literal/default expression
      end
      Generator->>Writer: emit field default using returned value
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Files warranting extra attention:
    • packages/schema/src/plugins/zod/generator.ts — ensure all call sites and import emission logic remain correct after removing output.
    • packages/schema/src/plugins/zod/utils/schema-gen.ts — validate enum-reference detection and emitted JSON-string default integrates correctly with generated Zod code.
    • packages/sdk/src/typescript-expression-transformer.ts — verify the new useLiteralEnum option is used only where intended and doesn't change other expression emissions unexpectedly.
    • tests/regression/tests/issue-2291.test.ts — confirm test reliably exercises the intended code path and that the test harness uses the useLiteralEnum behavior.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
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.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly addresses the two main objectives: avoiding Prisma enum imports and recognizing enum fields with default values.
Description check ✅ Passed The description references issue #2291, which is the bug being fixed; the short description is related to the changeset.
Linked Issues check ✅ Passed All code changes directly address issue #2291: removing Prisma enum imports from generated Zod schemas, handling enum field defaults through local enum references, and adding test validation.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing issue #2291: generator modifications, utility functions for enum defaults, transformer options, and regression testing.
✨ 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 fix/issue-2291

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: 0

Caution

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

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

389-398: Remove dead code: importEnums collection is no longer used.

This code collects enum references but never uses the importEnums Set. Since the fix avoids importing enums from @prisma/client (using useLiteralEnum instead), this entire block can be removed.

Apply this diff to remove the dead code:

-        // import user-defined enums from Prisma as they might be referenced in the expressions
-        const importEnums = new Set<string>();
-        for (const node of streamAllContents(decl)) {
-            if (isEnumFieldReference(node)) {
-                const field = node.target.ref as EnumField;
-                if (!isFromStdlib(field.$container)) {
-                    importEnums.add(field.$container.name);
-                }
-            }
-        }
-
         // import enum schemas
🧹 Nitpick comments (1)
packages/schema/src/plugins/zod/generator.ts (1)

729-729: Minor: Consider moving the closing brace to a new line for readability.

The closing brace and semicolon are now on the same line as the template literal. Placing them on a new line would improve readability:

-    export function ${refineFuncName}<T>(schema: z.ZodType<T>) { return schema${refinements.join('\n')};
+    export function ${refineFuncName}<T>(schema: z.ZodType<T>) { 
+        return schema${refinements.join('\n')};
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a290d76 and 28cfe7c.

📒 Files selected for processing (2)
  • packages/schema/src/plugins/zod/generator.ts (5 hunks)
  • packages/sdk/src/typescript-expression-transformer.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/schema/src/plugins/zod/generator.ts (1)
packages/language/src/ast.ts (1)
  • DataModel (56-66)
⏰ 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). (4)
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: dependency-review
  • GitHub Check: build-test (20.x)
🔇 Additional comments (5)
packages/sdk/src/typescript-expression-transformer.ts (2)

43-43: LGTM: Clean addition of useLiteralEnum option.

The new optional boolean follows the existing pattern and enables the enum-to-literal transformation needed to fix issue #2291.


395-398: LGTM: Correct implementation of enum literal transformation.

The conditional logic properly returns the enum name as a JSON string literal when useLiteralEnum is true, avoiding the need for external enum imports.

packages/schema/src/plugins/zod/generator.ts (3)

386-386: LGTM: Unused parameter correctly removed.

The output parameter was not used in the method body. Removing it simplifies the signature.


343-343: LGTM: Call sites correctly updated.

Both invocations of addPreludeAndImports properly reflect the updated signature.

Also applies to: 447-447


763-763: LGTM: Correct usage of useLiteralEnum for validation rules.

Setting useLiteralEnum: true ensures enum references in @@validate expressions are rendered as string literals, eliminating the need for @prisma/client imports.

@ymc9 ymc9 merged commit fb0aa0f into dev Nov 22, 2025
8 checks passed
@ymc9 ymc9 deleted the fix/issue-2291 branch November 22, 2025 06:39
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

0