Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Dec 13, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Improved schema generation to correctly include inherited Prisma attributes and apply inherited indexing/uniqueness constraints.
  • New Features

    • Added an index on Asset.ownerId to improve lookup performance.
  • Tests

    • Updated test setup to exercise the revised schema generation behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 13, 2025 13:06
@coderabbitai
Copy link

coderabbitai bot commented Dec 13, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Move non-inheritable attribute filtering (exclude @@Map, @@unique, @@index) into core attribute retrieval in packages/language/src/utils.ts, remove generator-level inherited-attribute filtering in the Prisma schema generator, add an index on Asset.ownerId in test schemas, and update two tests to call createTestClient(schema, { usePrismaPush: true }).

Changes

Cohort / File(s) Summary
Core attribute inheritance
packages/language/src/utils.ts
Add isNonInheritableAttribute(attr) and apply it in getAllAttributes so inherited attributes named @@map, @@unique, or @@index are excluded at the attribute-retrieval layer. No public API changes.
Prisma schema generator
packages/sdk/src/prisma/prisma-schema-generator.ts
Remove isInheritedMapAttribute helper and stop applying additional inherited-attribute filtering; generator now processes Prisma attributes returned by getAllAttributes without extra inherited-map exclusion.
Test schemas (delegate)
tests/e2e/orm/schemas/delegate/schema.zmodel, tests/e2e/orm/schemas/delegate/schema.ts
Add an index on Asset.ownerId by introducing @@index([ownerId]) / corresponding @@index attribute in the test schema representation.
Regression tests update
tests/regression/test/v2-migrated/issue-1243.test.ts
Update two test calls from createTestClient(schema) to createTestClient(schema, { usePrismaPush: true }).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Inspect getAllAttributes changes and isNonInheritableAttribute for correct matching across attribute representations (name vs $refText).
  • Confirm removal of isInheritedMapAttribute in the generator does not reintroduce @@map/@@unique/@@index propagation due to the new utils filter.
  • Verify updated tests and added index in delegate schema reflect intended validation cases.

Possibly related PRs

Poem

🐰 I hopped through attributes bright and spry,
I nudged out @@Map, @@unique, @@index on the fly,
From utils I choose which traits may stay,
Generators now trust the path I lay,
A small index hops into tests — hooray! 🥕

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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: filtering non-inheritable attributes (@@Map, @@unique, @@index) in the getAllAttributes function, which is the core fix across all modified files.
✨ 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/delegate-inherited-attrs

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f00f711 and 8a59d41.

📒 Files selected for processing (3)
  • tests/e2e/orm/schemas/delegate/schema.ts (1 hunks)
  • tests/e2e/orm/schemas/delegate/schema.zmodel (1 hunks)
  • tests/regression/test/v2-migrated/issue-1243.test.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/e2e/orm/schemas/delegate/schema.ts
  • tests/e2e/orm/schemas/delegate/schema.zmodel
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to tests/e2e/**/*.{ts,tsx} : E2E tests should validate real-world schema compatibility with established projects

Applied to files:

  • tests/regression/test/v2-migrated/issue-1243.test.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.test.{ts,tsx} : ORM package tests should include comprehensive client API tests and policy tests

Applied to files:

  • tests/regression/test/v2-migrated/issue-1243.test.ts
🧬 Code graph analysis (1)
tests/regression/test/v2-migrated/issue-1243.test.ts (1)
packages/testtools/src/client.ts (1)
  • createTestClient (101-248)
⏰ 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). (3)
  • GitHub Check: build-test (20.x, sqlite)
  • GitHub Check: build-test (20.x, postgresql)
  • GitHub Check: claude-review
🔇 Additional comments (1)
tests/regression/test/v2-migrated/issue-1243.test.ts (1)

27-27: The use of usePrismaPush: true is appropriate for these regression tests. This option validates the generated Prisma schema through Prisma's db push rather than ZenStack's $pushSchema, providing stricter validation. Since the PR changes how @@delegate filters out uninheritable attributes (@@map, @@unique, @@index), this more rigorous validation helps ensure the generated schema is correct. This pattern is consistent with other complex schema tests in the suite.


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.

@claude
Copy link

claude bot commented Dec 13, 2025

Claude finished @ymc9's task —— View job


Code Review: fix(delegate): exclude uninheritable attributes properly

Todo List:

  • Read and analyze all changed files
  • Review delegate inheritance logic changes
  • Check for potential bugs and issues
  • Evaluate code quality and best practices
  • Assess test coverage
  • Provide comprehensive feedback

Summary

This PR fixes an issue with delegate inheritance where certain attributes (@@map, @@unique, @@index) were incorrectly being inherited from base models. The fix centralizes the logic in the language package and removes duplicate filtering logic from the schema generator.

Key Changes

1. Language Utils Enhancement (packages/language/src/utils.ts)

  • Added: isNonInheritableAttribute() helper function at utils.ts:573
  • Modified: getAllAttributes() to filter out non-inheritable attributes when collecting from base models at utils.ts:564
  • Attributes excluded: @@map, @@unique, @@index - these are table-specific and shouldn't be inherited

2. Schema Generator Simplification (packages/sdk/src/prisma/prisma-schema-generator.ts)

  • Removed: isInheritedMapAttribute() method (12 lines deleted)
  • Simplified: Attribute filtering now relies on centralized logic from language utils
  • Cleaner: Logic moved from schema generator to more appropriate location in language package

3. Test Updates

  • Schema: Added @@index([ownerId]) and @@unique([ownerId]) to Asset model
  • Generated: Schema properly reflects that these attributes are now included in inherited models

Code Quality Assessment

Strengths

  1. Single Responsibility: Moved filtering logic to the appropriate layer (language utils)
  2. DRY Principle: Eliminated duplicate filtering logic
  3. Clear Function Names: isNonInheritableAttribute is self-documenting
  4. Comprehensive: Covers all known non-inheritable attributes
  5. Test Coverage: Includes both schema and generated TypeScript updates

⚠️ Minor Concerns

  1. Magic Array: The hardcoded list ['@@map', '@@unique', '@@index'] at utils.ts:575 could potentially be made configurable
  2. Function Placement: isNonInheritableAttribute is a private function but could benefit from JSDoc comments for maintainability

Security & Performance

No Security Issues

  • Changes are purely structural/logical
  • No exposure of sensitive data or injection vulnerabilities

Performance

  • Positive: Reduces redundant filtering operations
  • Efficient: Single-pass filtering instead of multiple checks
  • Minimal Impact: Changes are in compilation-time code generation, not runtime

Test Coverage

Good Coverage

  • E2E Test: Updated delegate schema test covers the fix
  • Real Scenario: Tests actual inheritance behavior with @@index and @@unique
  • Generated Code: Validates that TypeScript generation works correctly

💡 Suggestions

  • Consider adding unit tests for isNonInheritableAttribute() function
  • Could add negative test cases (verifying attributes are NOT inherited)

Best Practices Compliance

Follows Patterns

  • Uses existing getAllAttributes pattern consistently
  • Maintains TypeScript type safety
  • Follows ZenStack naming conventions
  • Proper error handling with fallback to $refText

Recommendations

  1. Documentation: Add JSDoc to isNonInheritableAttribute function:

    /**
     * Determines if a model attribute should not be inherited by child models.
     * Non-inheritable attributes are table-specific constraints.
     */
  2. Future Enhancement: Consider making the non-inheritable attributes list configurable or move to constants file for easier maintenance.

Final Assessment

✅ This is a solid, well-implemented fix that:

  • Correctly addresses the delegate inheritance issue
  • Improves code organization and maintainability
  • Includes appropriate test coverage
  • Has no security or performance concerns
  • Follows established patterns and best practices

Recommendation: ✅ APPROVE - This PR is ready to merge.


Copy link

@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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac4a68c and f00f711.

📒 Files selected for processing (4)
  • packages/language/src/utils.ts (1 hunks)
  • packages/sdk/src/prisma/prisma-schema-generator.ts (1 hunks)
  • tests/e2e/orm/schemas/delegate/schema.ts (1 hunks)
  • tests/e2e/orm/schemas/delegate/schema.zmodel (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
tests/e2e/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

E2E tests should validate real-world schema compatibility with established projects

Files:

  • tests/e2e/orm/schemas/delegate/schema.ts
**/*.zmodel

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.zmodel: Always run zenstack generate after modifying ZModel schemas
ZModel schema files should define database structure and policies that compile to TypeScript via zenstack generate

Files:

  • tests/e2e/orm/schemas/delegate/schema.zmodel
🧠 Learnings (3)
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to tests/e2e/**/*.{ts,tsx} : E2E tests should validate real-world schema compatibility with established projects

Applied to files:

  • tests/e2e/orm/schemas/delegate/schema.ts
📚 Learning: 2025-10-21T16:09:31.218Z
Learnt from: ymc9
Repo: zenstackhq/zenstack-v3 PR: 319
File: packages/runtime/src/client/executor/zenstack-query-executor.ts:63-72
Timestamp: 2025-10-21T16:09:31.218Z
Learning: In ZenStack, TypeDefs can be inherited by models. When a TypeDef contains fields with `map` attributes, those mapped field names need to be processed by the QueryNameMapper since they become part of the inheriting model's schema. Therefore, when checking if a schema has mapped names (e.g., in `schemaHasMappedNames`), both `schema.models` and `schema.typeDefs` must be inspected for `@map` and `map` attributes.

Applied to files:

  • packages/sdk/src/prisma/prisma-schema-generator.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to **/*.zmodel : ZModel schema files should define database structure and policies that compile to TypeScript via `zenstack generate`

Applied to files:

  • tests/e2e/orm/schemas/delegate/schema.zmodel
🧬 Code graph analysis (2)
tests/e2e/orm/schemas/delegate/schema.ts (1)
packages/schema/src/expression-utils.ts (1)
  • ExpressionUtils (19-123)
packages/sdk/src/prisma/prisma-schema-generator.ts (1)
packages/language/src/utils.ts (1)
  • getAllAttributes (546-571)
⏰ 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). (3)
  • GitHub Check: Agent
  • GitHub Check: build-test (20.x, postgresql)
  • GitHub Check: build-test (20.x, sqlite)
🔇 Additional comments (4)
tests/e2e/orm/schemas/delegate/schema.ts (1)

148-156: LGTM!

The generated attributes and uniqueFields correctly reflect the @@index and @@unique constraints added to Asset.ownerId in the source schema. The submodels (Video, Image, RatedVideo) appropriately do not inherit these non-inheritable attributes, which aligns with the PR's objective.

packages/language/src/utils.ts (2)

564-565: LGTM!

The filtering of non-inheritable attributes from base models is correctly applied here, consolidating the logic in one place for better maintainability.


573-576: LGTM!

The helper function correctly identifies non-inheritable attributes. The three attributes (@@map, @@unique, @@index) are appropriately excluded from inheritance as they define model-specific metadata that shouldn't propagate to submodels. The defensive fallback to $refText handles cases where the reference isn't resolved.

packages/sdk/src/prisma/prisma-schema-generator.ts (1)

199-199: LGTM!

The removal of inherited map attribute filtering is appropriate here since getAllAttributes in utils.ts now handles filtering of non-inheritable attributes (including @@map, @@unique, and @@index) at the source. This consolidates the filtering logic in one location, improving maintainability.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug in delegate model inheritance where structural database attributes (@@map, @@unique, @@index) were incorrectly being inherited from base models. The fix centralizes the logic for filtering non-inheritable attributes in the getAllAttributes function in packages/language/src/utils.ts.

Key changes:

  • Added isNonInheritableAttribute helper function that filters out @@map, @@unique, and @@index attributes during base model inheritance
  • Simplified Prisma schema generator by removing duplicate filtering logic (isInheritedMapAttribute method)
  • Updated test schema to include @@index and @@unique attributes on delegate base model to validate the fix

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
packages/language/src/utils.ts Added isNonInheritableAttribute function to filter structural attributes during delegate base model inheritance
packages/sdk/src/prisma/prisma-schema-generator.ts Removed duplicate isInheritedMapAttribute method and simplified attribute filtering logic
tests/e2e/orm/schemas/delegate/schema.zmodel Added @@index and @@unique attributes to Asset model for testing
tests/e2e/orm/schemas/delegate/schema.ts Generated schema reflecting the new attributes and their non-inheritance in derived models

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@claude
Copy link

claude bot commented Dec 13, 2025

Claude finished @ymc9's task —— View job


Code Review: fix(delegate): exclude uninheritable attributes properly

Todo List:

  • Read and analyze all changed files
  • Review delegate inheritance logic changes
  • Check for potential bugs and issues
  • Evaluate code quality and best practices
  • Assess test coverage
  • Provide comprehensive feedback

Summary

This PR fixes an issue with delegate inheritance where certain attributes (@@map, @@unique, @@index) were incorrectly being inherited from base models. The fix centralizes the logic in the language package and removes duplicate filtering logic from the schema generator.

Key Changes

1. Language Utils Enhancement (packages/language/src/utils.ts)

  • Added: isNonInheritableAttribute() helper function at utils.ts:573
  • Modified: getAllAttributes() to filter out non-inheritable attributes when collecting from base models at utils.ts:564
  • Attributes excluded: @@map, @@unique, @@index - these are table-specific and shouldn't be inherited

2. Schema Generator Simplification (packages/sdk/src/prisma/prisma-schema-generator.ts)

  • Removed: isInheritedMapAttribute() method (12 lines deleted)
  • Simplified: Attribute filtering now relies on centralized logic from language utils
  • Cleaner: Logic moved from schema generator to more appropriate location in language package

3. Test Updates

  • Schema: Added @@index([ownerId]) and @@unique([ownerId]) to Asset model
  • Generated: Schema properly reflects that these attributes are now included in inherited models

Code Quality Assessment

Strengths

  1. Single Responsibility: Moved filtering logic to the appropriate layer (language utils)
  2. DRY Principle: Eliminated duplicate filtering logic
  3. Clear Function Names: isNonInheritableAttribute is self-documenting
  4. Comprehensive: Covers all known non-inheritable attributes
  5. Test Coverage: Includes both schema and generated TypeScript updates

⚠️ Minor Concerns

  1. Magic Array: The hardcoded list ['@@map', '@@unique', '@@index'] at utils.ts:575 could potentially be made configurable
  2. Function Placement: isNonInheritableAttribute is a private function but could benefit from JSDoc comments for maintainability

Security & Performance

No Security Issues

  • Changes are purely structural/logical
  • No exposure of sensitive data or injection vulnerabilities

Performance

  • Positive: Reduces redundant filtering operations
  • Efficient: Single-pass filtering instead of multiple checks
  • Minimal Impact: Changes are in compilation-time code generation, not runtime

Test Coverage

Good Coverage

  • E2E Test: Updated delegate schema test covers the fix
  • Real Scenario: Tests actual inheritance behavior with @@index and @@unique
  • Generated Code: Validates that TypeScript generation works correctly

💡 Suggestions

  • Consider adding unit tests for isNonInheritableAttribute() function
  • Could add negative test cases (verifying attributes are NOT inherited)

Best Practices Compliance

Follows Patterns

  • Uses existing getAllAttributes pattern consistently
  • Maintains TypeScript type safety
  • Follows ZenStack naming conventions
  • Proper error handling with fallback to $refText

Recommendations

  1. Documentation: Add JSDoc to isNonInheritableAttribute function:

    /**
     * Determines if a model attribute should not be inherited by child models.
     * Non-inheritable attributes are table-specific constraints.
     */
  2. Future Enhancement: Consider making the non-inheritable attributes list configurable or move to constants file for easier maintenance.

Final Assessment

✅ This is a solid, well-implemented fix that:

  • Correctly addresses the delegate inheritance issue
  • Improves code organization and maintainability
  • Includes appropriate test coverage
  • Has no security or performance concerns
  • Follows established patterns and best practices

Recommendation: ✅ APPROVE - This PR is ready to merge.


@ymc9 ymc9 merged commit eb1a0c2 into dev Dec 13, 2025
5 checks passed
@ymc9 ymc9 deleted the fix/delegate-inherited-attrs branch December 13, 2025 13:40
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