-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
feat: entity schema support trees #11606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds tree metadata support to EntitySchema: a new optional Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor App
participant EntitySchema as EntitySchema (with options.trees)
participant Transformer as EntitySchemaTransformer
participant Storage as metadataArgsStorage
App->>Transformer: transform(EntitySchema)
Transformer->>Transformer: transformColumnsRecursive(...)
alt options.trees present
loop each tree option
Transformer->>Storage: trees.push({ target, type, options })
end
else no trees
note over Transformer: no tree metadata collected
end
Transformer-->>App: Metadata arguments updated
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. 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. Comment |
commit: |
There was a problem hiding this 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 (5)
src/entity-schema/EntitySchemaOptions.ts (1)
140-141: Clarify API semantics: document that only a single tree strategy is supported per entityDecorator-based entities only support one @Tree(...) per entity. The plural shape (trees: []) is OK for consistency with other arrays, but without guidance it invites multiple entries, which would be undefined behavior. At minimum, add JSDoc that this array must contain at most one element and is equivalent to @Tree(...).
Apply this diff to document intent:
- trees?: Omit<TreeMetadataArgs, "target">[] + /** + * Tree configuration for this entity (equivalent to using `@Tree(...)`). + * Note: only a single tree strategy is supported per entity; provide at most one entry. + */ + trees?: Omit<TreeMetadataArgs, "target">[]src/entity-schema/EntitySchemaTransformer.ts (1)
400-408: Enforce single tree per entity; optional: emit tree metadata at top-level (not during embedded recursion)Registering tree metadata is correct. Two improvements:
- Prevent multiple tree strategies on a single entity (only one is supported).
- Optional: consider moving this block to the top-level transform (alongside table/ inheritance) to avoid accidental emission from embeddeds if someone mistakenly places trees on an embedded schema.
Apply this guard to avoid multiple entries:
- if (options.trees) { - options.trees.forEach((tree) => { + if (options.trees) { + if (options.trees.length > 1) { + throw new Error( + `Only one tree strategy is supported per entity schema (${String( + options.target || options.name, + )}).`, + ) + } + options.trees.forEach((tree) => { metadataArgsStorage.trees.push({ target: options.target || options.name, type: tree.type, options: tree.options, }) }) }If you prefer, I can follow up with a small refactor to move this emission to transform(), right after pushing the table metadata.
test/functional/entity-schema/trees/nested-set/entity/Category.ts (2)
21-31: Add inverseSide to make relations explicit and self-documentingTree-specific flags work, but adding inverseSide reduces ambiguity and matches patterns used elsewhere in the codebase.
Apply this diff:
parentCategory: { type: "many-to-one", treeParent: true, target: "Category", + inverseSide: "childCategories", }, childCategories: { type: "one-to-many", treeChildren: true, target: "Category", cascade: true, + inverseSide: "parentCategory", },
3-8: Improve typings to avoidany(optional)Using any/any[] here works for tests but loses type-safety. Consider introducing a small model type to keep generics aligned without colliding with the exported constant name.
For example:
type CategoryModel = { id: number name: string parentCategory: CategoryModel | null childCategories: CategoryModel[] } export const Category = new EntitySchema<CategoryModel>({ /* ... */ })test/functional/entity-schema/trees/nested-set/nested-set.ts (1)
23-68: Solid happy-path coverage; consider adding a negative test for multiple rootsThe flow validates roots/ancestors/descendants and exercises the new schema-based tree metadata. To match decorator-based coverage, consider adding a test asserting that saving a second root is rejected for nested-set trees.
You can append a separate spec:
it("should reject multiple roots for nested-set", () => Promise.all( connections.map(async (connection) => { const repo = connection.getTreeRepository(Category) const a1 = await repo.save({ name: "a1" }) // Attempt a second root await repo .save({ name: "b1" }) .then(() => { throw new Error("expected rejection for multiple roots") }) .catch((err) => { err.message.should.match(/Nested sets do not support multiple root entities/i) }) }), ))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
src/entity-schema/EntitySchemaOptions.ts(2 hunks)src/entity-schema/EntitySchemaTransformer.ts(1 hunks)test/functional/entity-schema/trees/nested-set/entity/Category.ts(1 hunks)test/functional/entity-schema/trees/nested-set/nested-set.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/functional/entity-schema/trees/nested-set/entity/Category.ts (3)
test/github-issues/7068/entity/Category.ts (1)
Category(14-29)test/github-issues/8443/nested-set/entity/Category.ts (1)
Category(11-29)test/github-issues/9534/entity/Category.ts (1)
Category(11-41)
🔇 Additional comments (2)
src/entity-schema/EntitySchemaOptions.ts (1)
17-17: LGTM: Tree metadata import is appropriateImporting TreeMetadataArgs here is correct and keeps the new option strongly typed.
test/functional/entity-schema/trees/nested-set/entity/Category.ts (1)
33-34: LGTM: Tree configuration via EntitySchema is correctly wiredtrees: [{ type: "nested-set" }] is the expected declaration for the nested-set strategy.
gioboa
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your help @wszgrcy
a3ea81f to
d5892c7
Compare
There was a problem hiding this 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 (2)
src/entity-schema/EntitySchemaOptions.ts (1)
139-141: Prefer a singulartreeoption (one tree per entity).Decorator parity: entities support exactly one tree type. An array invites invalid configs (multiple entries). Recommend a singular property and adjust the transformer accordingly.
Apply:
- trees?: Omit<TreeMetadataArgs, "target">[] + /** + * Tree configuration for this entity (e.g. "closure-table", "nested-set", "materialized-path"). + */ + tree?: Omit<TreeMetadataArgs, "target">If keeping
treesfor backward symmetry with array-based options, at least validate length ≤ 1 in the transformer and use the first entry.Would you confirm whether multiple trees per entity are intended? If not, I can provide a follow-up patch to enforce a single entry.
src/entity-schema/EntitySchemaTransformer.ts (1)
400-408: Enforce a single tree and simplify handling.Current code allows multiple trees and processes within the recursive path. Recommend:
- Use a singular option and push once, avoiding embedded schemas.
If adopting
tree(singular), change this block to:- if (options.trees) { - options.trees.forEach((tree) => { - metadataArgsStorage.trees.push({ - target: options.target || options.name, - type: tree.type, - options: tree.options, - }) - }) - } + if (options.tree) { + metadataArgsStorage.trees.push({ + target: options.target || options.name, + type: options.tree.type, + options: options.tree.options, + }) + }If keeping an array, minimally guard against multiple entries and ignore/throw on extras; also consider moving this logic to the top-level
transform(non-recursive) to prevent accidental registration from embeddeds.Please confirm whether we should (a) reject multiple entries or (b) accept only the first. I can supply a precise patch for either path.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/entity-schema/EntitySchemaOptions.ts(2 hunks)src/entity-schema/EntitySchemaTransformer.ts(1 hunks)test/functional/entity-schema/trees/nested-set/entity/Category.ts(1 hunks)test/functional/entity-schema/trees/nested-set/nested-set.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- test/functional/entity-schema/trees/nested-set/entity/Category.ts
- test/functional/entity-schema/trees/nested-set/nested-set.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/entity-schema/EntitySchemaOptions.ts (1)
src/metadata-args/TreeMetadataArgs.ts (1)
TreeMetadataArgs(7-22)
⏰ 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). (20)
- GitHub Check: tests-linux (18) / better-sqlite3
- GitHub Check: tests-linux (20) / sap
- GitHub Check: tests-linux (18) / mysql_mariadb
- GitHub Check: tests-linux (18) / mongodb
- GitHub Check: tests-linux (20) / mssql
- GitHub Check: tests-linux (18) / mssql
- GitHub Check: tests-linux (20) / cockroachdb
- GitHub Check: tests-linux (20) / mysql_mariadb
- GitHub Check: tests-linux (20) / sqljs
- GitHub Check: tests-linux (20) / mongodb
- GitHub Check: tests-linux (20) / mysql_mariadb_latest
- GitHub Check: tests-linux (20) / oracle
- GitHub Check: tests-linux (20) / better-sqlite3
- GitHub Check: tests-windows / sqljs
- GitHub Check: tests-linux (20) / sqlite
- GitHub Check: tests-linux (20) / postgres (14)
- GitHub Check: tests-linux (20) / postgres (17)
- GitHub Check: tests-windows / sqlite
- GitHub Check: tests-windows / better-sqlite3
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
src/entity-schema/EntitySchemaOptions.ts (1)
17-17: Import looks correct.Path and type usage align with existing metadata-args structure.
gioboa
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 tests are ✅ let's merge it
Thanks
Description of change
support entity schema trees, equal to
@TreePull-Request Checklist
masterbranchFixes #00000Summary by CodeRabbit
New Features
Tests