Skip to content

feat(orm): implement delegateMap attribute#2676

Merged
ymc9 merged 3 commits into
zenstackhq:devfrom
wolflu05:delegate-map
May 22, 2026
Merged

feat(orm): implement delegateMap attribute#2676
ymc9 merged 3 commits into
zenstackhq:devfrom
wolflu05:delegate-map

Conversation

@wolflu05
Copy link
Copy Markdown
Contributor

@wolflu05 wolflu05 commented May 20, 2026

This PR implement custom delegate mapping as per option 3 described in #2558. This is my first "larger" PR to this project, so please let me know if there is anything that could be improved.

closes #2558

Summary by CodeRabbit

  • New Features

    • Added a delegate-map attribute to map delegate sub-models to specific discriminator values
    • Generated model metadata now conditionally includes delegate-map info
  • Improvements

    • Support for enum-typed discriminator fields in polymorphic delegate models
    • Stronger validation and uniqueness checks for delegate mappings
    • Improved type-safety in discriminator resolution and query results
  • Tests

    • Added/updated tests and e2e typechecks to assert enum-based discriminator behavior

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

📝 Walkthrough

Walkthrough

Adds @@delegateMap attribute, validates its usage and values, emits delegateMap metadata, updates ORM typing and runtime discriminator resolution, and adapts tests/schemas to use enum-based discriminator literals.

Changes

Delegate Map Feature

Layer / File(s) Summary
Language schema definition and validation
packages/language/res/stdlib.zmodel, packages/language/src/validators/datamodel-validator.ts, packages/language/test/delegate.test.ts
Add @@delegateMap attribute and implement validation to ensure correct usage only on models extending delegate bases, validate discriminator values against enum types, detect duplicate mappings, and provide comprehensive test coverage for valid/invalid scenarios.
Schema metadata and code generation
packages/schema/src/schema.ts, packages/sdk/src/ts-schema-generator.ts
Add optional delegateMap?: string field to ModelDef, introduce GetModelDelegateMapValue conditional type for discriminator typing, and generate delegateMap metadata in SDK-generated model objects via new getDelegateMapValue helper.
ORM type system and discriminator computation
packages/orm/src/client/crud-types.ts, packages/orm/src/client/query-utils.ts, packages/orm/src/client/crud/operations/base.ts
Update DelegateUnionResult to use GetModelDelegateMapValue for discriminator typing, export getDelegateDiscriminatorValue helper that resolves delegateMap or defaults to model name, and apply it in BaseOperationHandler for single-entity and bulk create operations.
E2E test schema and assertions
tests/e2e/orm/schemas/delegate/schema.zmodel, tests/e2e/orm/schemas/delegate/schema.ts, tests/e2e/orm/schemas/delegate/typecheck.ts, tests/e2e/orm/client-api/delegate.test.ts
Update test schema to use enum types for discriminator fields, add @@delegateMap attributes mapping to enum constants, regenerate schema metadata, and update all test assertions and type narrowing checks to expect enum-based discriminator literals instead of model names.

🎯 4 (Complex) | ⏱️ ~60 minutes

🐰 A mapping so divine, where enums dance in polymorphic lines,
Custom discriminators shine, where delegates now align!
No more model names decree, just values we define with glee,
Delegate maps make it free!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(orm): implement delegateMap attribute' clearly summarizes the main change—adding a new delegateMap attribute to support custom delegate mapping in the ORM layer.
Linked Issues check ✅ Passed The PR fully implements option 3 from issue #2558: a child-level @@delegateMap attribute that allows custom discriminator values via enums or strings, with fallback to model names and validation for uniqueness.
Out of Scope Changes check ✅ Passed All changes directly support the delegateMap implementation: schema definitions, validators, type generation, ORM logic, and comprehensive test coverage across unit and e2e tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/language/src/validators/datamodel-validator.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

packages/language/test/delegate.test.ts

ESLint skipped: the ESLint configuration for this file 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.

❤️ Share

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

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/language/res/stdlib.zmodel`:
- Line 649: The @@delegateMap attribute must be marked single-use to prevent
multiple mappings being accepted but only one being resolved; update the
attribute declaration for @@delegateMap to include the single-use modifier
(e.g., add @@@once or the equivalent single-use flag) so the parser enforces
only one @@delegateMap per model and rejects additional entries, ensuring unique
mapping resolution for the model.

In `@packages/orm/src/client/query-utils.ts`:
- Around line 384-387: The fallback for the discriminator currently returns the
raw input parameter `model`, which can preserve incorrect casing; update
getDelegateDiscriminatorValue to use the canonical model name from the resolved
model definition instead of the input string when delegateMap is undefined: call
requireModel(schema, model) as already done, then return modelDef.delegateMap ??
modelDef.name (or the canonical name field on the modelDef) so the schema's
canonical casing is used; keep delegateMap precedence and only use the modelDef
canonical name as the default.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f8f43335-fb2a-4f23-876c-e4a882be0f16

📥 Commits

Reviewing files that changed from the base of the PR and between ed01275 and 7c07e2f.

📒 Files selected for processing (12)
  • packages/language/res/stdlib.zmodel
  • packages/language/src/validators/datamodel-validator.ts
  • packages/language/test/delegate.test.ts
  • packages/orm/src/client/crud-types.ts
  • packages/orm/src/client/crud/operations/base.ts
  • packages/orm/src/client/query-utils.ts
  • packages/schema/src/schema.ts
  • packages/sdk/src/ts-schema-generator.ts
  • tests/e2e/orm/client-api/delegate.test.ts
  • tests/e2e/orm/schemas/delegate/schema.ts
  • tests/e2e/orm/schemas/delegate/schema.zmodel
  • tests/e2e/orm/schemas/delegate/typecheck.ts

Comment thread packages/language/res/stdlib.zmodel
Comment thread packages/orm/src/client/query-utils.ts
Copy link
Copy Markdown
Member

@ymc9 ymc9 left a comment

Choose a reason for hiding this comment

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

Hi @wolflu05 , thanks for making this PR. Overall looking very good to me. I've left a few comments.

Comment thread packages/language/res/stdlib.zmodel
Comment thread packages/language/src/validators/datamodel-validator.ts Outdated
Comment thread packages/language/src/validators/datamodel-validator.ts Outdated
Comment thread packages/language/src/validators/datamodel-validator.ts Outdated
Comment thread packages/orm/src/client/query-utils.ts
@ymc9 ymc9 changed the title implement delegateMap attribute feat(orm): implement delegateMap attribute May 22, 2026
@wolflu05
Copy link
Copy Markdown
Contributor Author

Thanks for your review @ymc9 , that is really valuable. I have adjusted the things from your comments.

Copy link
Copy Markdown
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/language/res/stdlib.zmodel`:
- Line 649: You changed the ZModel schema by adding the attribute declaration
@@delegateMap(_ value: Any) in packages/language/res/stdlib.zmodel; run
`zenstack generate` to regenerate schema-driven artifacts, review and include
all resulting generated files in the commit (model, migrations, type outputs,
etc.), and re-run tests/lint to ensure nothing else broke before pushing the
updated PR.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7dd67e0d-e72e-4e9f-8823-0d332af42b4e

📥 Commits

Reviewing files that changed from the base of the PR and between a0962e0 and 70b60b7.

📒 Files selected for processing (3)
  • packages/language/res/stdlib.zmodel
  • packages/language/src/validators/datamodel-validator.ts
  • packages/language/test/delegate.test.ts

Comment thread packages/language/res/stdlib.zmodel
Copy link
Copy Markdown
Member

@ymc9 ymc9 left a comment

Choose a reason for hiding this comment

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

LGTM! I'm merging it and will publish a patch release.

@ymc9 ymc9 merged commit 7bc2fe5 into zenstackhq:dev May 22, 2026
17 checks passed
@wolflu05
Copy link
Copy Markdown
Contributor Author

Thanks for your so quick merge, I'm already looking forward to the next release.

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.

[Feature Request] Support Custom Mapping for @@delegate Type Attribute

2 participants