Skip to content

feat(core): Extend custom relational field config#4448

Open
LucidityDesign wants to merge 15 commits into
vendurehq:masterfrom
LucidityDesign:feat/custom-field-relations
Open

feat(core): Extend custom relational field config#4448
LucidityDesign wants to merge 15 commits into
vendurehq:masterfrom
LucidityDesign:feat/custom-field-relations

Conversation

@LucidityDesign
Copy link
Copy Markdown
Contributor

@LucidityDesign LucidityDesign commented Feb 28, 2026

Description

Adds properties like cascade, onDelete and onUpdate to custom fields of type relation

Breaking changes

Does this PR include any breaking changes we should be aware of?

Screenshots

You can add screenshots here if applicable.

Checklist

📌 Always:

  • I have set a clear title
  • My PR is small and contains a single feature
  • I have checked my own PR

👍 Most of the time:

  • I have added or updated test cases
  • I have updated the README if needed

Adds properties like cascade, onDelete and onUpdate
@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
vendure-storybook Ready Ready Preview, Comment Mar 14, 2026 0:29am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The RelationCustomFieldConfig type was updated to reuse TypeORM's RelationOptions by adding the properties cascade, onDelete, onUpdate, and eager (removing the locally declared eager). The custom-entity field registration now reads cascade, onDelete, onUpdate, and eager from relation custom fields and forwards nullable, cascade, onDelete, onUpdate, and eager to the ManyToMany and ManyToOne decorators. Documentation was edited to document and provide examples for the cascade, onDelete, and onUpdate options for relation custom fields.

Suggested reviewers

  • michaelbromley
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature: extending custom relational field configuration with new TypeORM-related properties.
Description check ✅ Passed The description includes the required sections with adequate detail about the changes, breaking changes status, and completed checklist items, though test additions and README updates are not marked.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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
Collaborator

@grolmus grolmus left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! Exposing TypeORM relation options on custom fields is a useful feature. A few things to address before this can go in:

Must address

1. nullable silently injected into relation decorators

The diff passes nullable (from the outer destructure on line 42) into both ManyToMany and ManyToOne options, but this wasn't part of the type change or PR description.

  • ManyToMany: nullable is semantically meaningless here — ManyToMany uses a junction table, there's no nullable FK column on the entity itself. TypeORM accepts it silently but it does nothing. Should be removed from the ManyToMany call.
  • ManyToOne: nullable does make sense, but this is an undocumented behavioral change. Previously, nullable: false on a relation custom field was silently ignored. Now it gets enforced. This should either be called out explicitly or handled in a separate commit.

2. Auto-generated reference docs edited directly

docs/docs/reference/typescript-api/custom-fields/typed-custom-single-field-config.mdx is auto-generated and will be overwritten on the next npm run docs:build. This file shouldn't be edited manually — the line number change will happen automatically when the source types change.

3. Documentation for new properties

The new sections for cascade, onDelete, and onUpdate in the custom fields guide look good. Consider adding a note about the implications of cascade delete — e.g., that using onDelete: 'CASCADE' on a relation to a core entity could cascade-delete core data.

Should address

4. No guardrails on cascade delete of core entities

With this change, a plugin author could write:

{
    name: 'myThing',
    type: 'relation',
    entity: Product,
    onDelete: 'CASCADE',
}

This would cascade-delete Product rows through a custom field relation. At minimum, a runtime Logger.warn() when cascade delete targets a built-in Vendure entity would help prevent accidents.

5. No tests

Adding options that affect database schema and cascade behavior should ideally have at least a basic test — e.g., verifying that onDelete/cascade are passed through to the TypeORM metadata correctly.

Looks good

The Pick<RelationOptions, 'cascade' | 'onDelete' | 'onUpdate' | 'eager'> approach is clean and keeps the types in sync with TypeORM. The eager type didn't change, so this is backwards-compatible.

@LucidityDesign
Copy link
Copy Markdown
Contributor Author

LucidityDesign commented Mar 14, 2026

Thanks for the comprehensive feedback!

  1. nullable

    This should either be called out explicitly or handled in a separate commit.

    Do you mean separate commit or PR?

  2. Auto-generated reference docs edited directly
    The changes were generated by running npm run docs:build. Is this fine to leave in this PR?

I will implement the rest of the feedback asap.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/docs/guides/developer-guide/custom-fields/index.mdx`:
- Line 1361: The sentence uses singular agreement incorrectly; update the text
so it reads that the various configuration options for each of the built-in form
inputs (e.g. `suffix`) are documented in the `DefaultFormConfigHash` object,
i.e., change "form input ... is documented" to "form inputs ... are documented"
and keep the reference to `DefaultFormConfigHash`.
- Around line 1189-1192: The docs currently describe onDelete: 'CASCADE'
backwards; update the text around the onDelete: 'CASCADE' explanation so it
states that when the referenced entity is deleted the database will cascade and
delete the rows that reference it (i.e. the owning/child rows), not that
deleting the owner deletes the referenced entity; adjust the ProductVariant
example to show that if the referenced ProductVariant is deleted any entities
that reference it will be removed, and add a short caution to use onDelete:
'CASCADE' only when you intend child rows to be removed on referenced-entity
deletion.

In `@packages/core/src/entity/register-custom-entity-fields.ts`:
- Around line 51-60: The warning logic incorrectly triggers for all relation
kinds and misstates the delete direction; update the check so it only runs for
ManyToOne relations (e.g. guard on relation type / kind === 'ManyToOne' or
equivalent) in the register-custom-entity-fields flow, and change the
Logger.warn text (while still referencing relatedEntityName and coreEntitiesMap)
to say that deleting the referenced core entity will cascade and delete the
custom entity rows that reference it (not the reverse). Ensure the condition
still checks onDelete === 'CASCADE' and coreEntitiesMap membership before
logging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1241bc36-91fa-4ac1-b131-185abdb966cd

📥 Commits

Reviewing files that changed from the base of the PR and between a92e6b4 and 7ae0423.

📒 Files selected for processing (2)
  • docs/docs/guides/developer-guide/custom-fields/index.mdx
  • packages/core/src/entity/register-custom-entity-fields.ts

Comment thread docs/docs/guides/developer-guide/custom-fields/index.mdx Outdated
Comment thread docs/docs/guides/developer-guide/custom-fields/index.mdx Outdated
Comment thread packages/core/src/entity/register-custom-entity-fields.ts
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The tests are vibe coded. They seem to test the right behaviour and look good to me. But please double check and I would need some help if anything is missing in the test file.

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