You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This pull request links relevant issues as Fixes #00000
There are new or updated tests validating the change (tests/**.test.ts)
Documentation has been updated to reflect this change (docs/docs/**.md)
PR Type
Bug fix
Description
Fix lazy one-to-many relation value assignment handling
Add property descriptor check for assigned lazy relation values
Enhance JSDoc documentation with missing parameter annotations
Add comprehensive test coverage for lazy and non-lazy relations
Diagram Walkthrough
flowchart LR
A["Lazy Relation Assignment"] --> B["getEntityValue Method"]
B --> C["Property Descriptor Check"]
C --> D["Return Assigned Value"]
E["Test Cases"] --> F["Non-lazy Relations"]
E --> G["Lazy Relations"]
F --> H["Verify User ID Update"]
G --> H
Loading
File Walkthrough
Relevant files
Bug fix
RelationMetadata.ts
Add descriptor check for lazy relation values
src/metadata/RelationMetadata.ts
Add property descriptor check in getEntityValue method to handle assigned lazy relation values
Check if property has a non-function getter before returning undefined
Return the assigned value directly when it exists as own property
Add missing JSDoc parameter annotations for multiple methods
The new lazy-relation handling relies on inspecting the entity’s own property descriptor to detect assigned values (including Promises) without triggering lazy loading. Please validate behavior for accessor-based lazy relations (properties defined via getter/setter), inherited properties (defined on the prototype, not as an “own” property), and cases where a relation property is explicitly set to null vs undefined.
The added logic changes what getEntityValue returns for lazy relations when an own data-property exists on the entity. Confirm this doesn’t break scenarios where userland code assigns a resolved array/object directly to a lazy relation property (instead of the internal __{propertyName}__ field), and ensure downstream persistence logic treats the returned value consistently (especially for one-to-many arrays).
The new tests cover assigning Promise.resolve([...]) to a lazy one-to-many and verifying the inverse foreign key update. Consider also validating the “direct assignment” variant (assigning an array directly to a lazy relation property, if supported/expected) and verifying that unresolved Promises do not accidentally trigger updates or are handled deterministically across drivers.
it("should update the user id of a post when the user is saved with a list of posts that already exist in the database",()=>Promise.all(dataSources.map(async(dataSource)=>{constentityManager=dataSource.manager// Create a post without a userconstpost=newPost()post.id="post-id"post.name="Post"constsavedPost=awaitentityManager.save(post)// Create a userconstuser=newUser()user.id="user-id"user.name="John"awaitentityManager.save(user)// Add the post to the userconstfetchedUser=awaitentityManager.findOneOrFail(User,{where: {id: user.id},})fetchedUser.posts=[savedPost]awaitentityManager.save(fetchedUser)// Check that the post has the user idconstupdatedPost=awaitentityManager.findOneOrFail(Post,{where: {name: "Post"},})expect(updatedPost.userId).to.equal(user.id)}),))it("should update the user id of a post when the user is saved with a list of posts that already exist in the database (with lazy relations)",()=>Promise.all(dataSources.map(async(dataSource)=>{constentityManager=dataSource.manager// Create a post without a userconstpost=newLazyPost()post.id="post-id"post.name="Lazy Post"constsavedPost=awaitentityManager.save(post)// Create a userconstuser=newLazyUser()user.id="user-id"user.name="Lazy John"awaitentityManager.save(user)// Add the post to the userconstfetchedUser=awaitentityManager.findOneOrFail(LazyUser,{where: {id: user.id},},)fetchedUser.posts=Promise.resolve([savedPost])awaitentityManager.save(fetchedUser)// Check that the post has the user idconstupdatedPost=awaitentityManager.findOneOrFail(LazyPost,{where: {name: "Lazy Post"},},)expect(updatedPost.userId).to.equal(user.id)}),))
To prevent accidentally triggering lazy-relation getters, refactor the logic to use Object.getOwnPropertyDescriptor to inspect properties and retrieve their values without invoking accessors.
-let hasGetter = false
let proto: object | null = entity
while (proto) {
- if (- Object.getOwnPropertyDescriptor(- proto,- this.propertyName,- )?.get- ) {- hasGetter = true- break+ const desc = Object.getOwnPropertyDescriptor(proto, this.propertyName)+ if (desc) {+ // Getter-based lazy relation: don't touch it+ if (typeof desc.get === "function") return undefined++ // Data property: safe to read without invoking getters+ const value = (desc as PropertyDescriptor).value+ return value instanceof Promise ? undefined : value
}
proto = Object.getPrototypeOf(proto)
}
-if (hasGetter || entity[this.propertyName] instanceof Promise) {- return undefined-}-return entity[this.propertyName]+return undefined
Apply / Chat
Suggestion importance[1-10]: 8
__
Why: The suggestion correctly identifies that accessing entity[this.propertyName] can unintentionally trigger a lazy-loading getter, which the PR aims to avoid. The proposed change is more robust and correct by using Object.getOwnPropertyDescriptor to safely inspect the property without invoking getters.
✅ Prevent lazy getter side effectsSuggestion Impact:Updated getter detection to iterate up the prototype chain using Object.getOwnPropertyDescriptor, aligning with the suggestion's approach for getter discovery; however the code still reads entity[this.propertyName] in the Promise check.
code diff:
- const hasGetter =- Object.getOwnPropertyDescriptor(entity, this.propertyName)- ?.get ||- Object.getOwnPropertyDescriptor(- Object.getPrototypeOf(entity),- this.propertyName,- )?.get+ let hasGetter = false+ let proto: object | null = entity+ while (proto) {+ if (+ Object.getOwnPropertyDescriptor(+ proto,+ this.propertyName,+ )?.get+ ) {+ hasGetter = true+ break+ }+ proto = Object.getPrototypeOf(proto)+ }
if (hasGetter || entity[this.propertyName] instanceof Promise) {
To prevent unintended lazy-loading, first check for a getter on the prototype chain without accessing the property value, and only if no getter exists, read the value to check if it is a promise.
Why: The suggestion correctly identifies a critical flaw where checking entity[this.propertyName] instanceof Promise will itself trigger a lazy-relation's getter, causing an unintended side-effect that the PR is trying to avoid.
High
✅ Detect inherited accessor gettersSuggestion Impact:Replaced the limited two-level getter check with a loop that walks up the entire prototype chain and detects any accessor getter for the property.
code diff:
- const hasGetter =- Object.getOwnPropertyDescriptor(entity, this.propertyName)- ?.get ||- Object.getOwnPropertyDescriptor(- Object.getPrototypeOf(entity),- this.propertyName,- )?.get+ let hasGetter = false+ let proto: object | null = entity+ while (proto) {+ if (+ Object.getOwnPropertyDescriptor(+ proto,+ this.propertyName,+ )?.get+ ) {+ hasGetter = true+ break+ }+ proto = Object.getPrototypeOf(proto)+ }
Improve getter detection by traversing the entire prototype chain to reliably find inherited accessors, as the current code only checks the instance and its immediate prototype.
-const hasGetter =- Object.getOwnPropertyDescriptor(entity, this.propertyName)- ?.get ||- Object.getOwnPropertyDescriptor(- Object.getPrototypeOf(entity),- this.propertyName,- )?.get+const hasGetter = (() => {+ let proto: any = entity+ while ((proto = Object.getPrototypeOf(proto))) {+ const desc = Object.getOwnPropertyDescriptor(proto, this.propertyName)+ if (desc?.get) return true+ }+ return false+})()
Suggestion importance[1-10]: 7
__
Why: The suggestion correctly points out that the getter detection is incomplete as it does not traverse the full prototype chain, and the proposed fix makes the implementation more robust.
✅ Fix lazy relation getter detectionSuggestion Impact:The commit updated the logic to inspect both the entity's own property descriptor and its prototype's descriptor for a getter, incorporating prototype-based accessor detection as suggested (though the final conditional behavior differs from the suggested logic).
Improve lazy relation getter detection by checking the entity's prototype in addition to its own properties to correctly identify accessor-based promises.
Why: The suggestion correctly identifies a critical flaw in the PR's logic, where Object.getOwnPropertyDescriptor fails to check the prototype for lazy relation getters, and provides a robust fix.
The new lazy-relation getter detection calls Object.getOwnPropertyDescriptor on
Object.getPrototypeOf(entity) without guarding against a null prototype, which can throw a TypeError
and break persistence/transform flows operating on plain objects.
RelationMetadata.getEntityValue now unconditionally passes Object.getPrototypeOf(entity) into
Object.getOwnPropertyDescriptor; if prototype is null, that call throws. TypeORM code explicitly
considers Object.create(null) objects as “plain objects”, and relation.getEntityValue is invoked on
user-provided plain objects during transformation/merge operations, making this a plausible runtime
crash.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` calls `Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), ...)` without checking if the prototype is `null`. For `Object.create(null)`-style objects, `Object.getPrototypeOf(entity)` returns `null`, and `Object.getOwnPropertyDescriptor(null, ...)` throws a `TypeError`.
## Issue Context
TypeORM utilities explicitly treat `Object.create(null)` objects as valid “plain objects”, and `relation.getEntityValue(...)` is called on user-provided plain objects in transformers.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-488]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation branch reads entity[this.propertyName] (including inside an `instanceof
Promise` check), which can invoke the lazy getter and start DB queries unexpectedly, and can also
return a Promise to callers that expect concrete relation values or undefined. This can cause
unexpected queries during initialization/validation and break persistence/transform flows when an
unresolved Promise is returned.
RelationLoader.enableLazyLoad defines a getter for lazy relations that calls
relationLoader.load(...) (DB query) when the property is accessed. EntityMetadata.create applies
this lazy getter to created instances. Then EntityMetadataValidator calls
relation.getEntityValue(entityInstance) during initialization just to detect initialized arrays;
with the new getEntityValue implementation, accessing entity[this.propertyName] can invoke the
getter, triggering unexpected queries and returning a Promise (ignored/not awaited), which can lead
to performance regressions and potential unhandled rejections.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` now accesses `entity[this.propertyName]` for lazy relations even when `getLazyRelationsPromiseValue` is `false`. If `this.propertyName` is a lazy-loading getter (as installed by `RelationLoader.enableLazyLoad`), that access can trigger a DB query and/or return a Promise into code paths that expect a concrete value or `undefined`.
### Issue Context
- Lazy relations are implemented using `Object.defineProperty(..., { get() { ... relationLoader.load(...) } })`.
- Multiple call sites (e.g. metadata validation and persistence subject building) call `getEntityValue(entity)` with the default flag and do not expect to cause IO or to receive a Promise.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[475-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation getter detection calls Object.getOwnPropertyDescriptor on
Object.getPrototypeOf(entity) without guarding against a null prototype, which can throw a TypeError
and break persistence/transform flows operating on plain objects.
RelationMetadata.getEntityValue now unconditionally passes Object.getPrototypeOf(entity) into
Object.getOwnPropertyDescriptor; if prototype is null, that call throws. TypeORM code explicitly
considers Object.create(null) objects as “plain objects”, and relation.getEntityValue is invoked on
user-provided plain objects during transformation/merge operations, making this a plausible runtime
crash.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` calls `Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), ...)` without checking if the prototype is `null`. For `Object.create(null)`-style objects, `Object.getPrototypeOf(entity)` returns `null`, and `Object.getOwnPropertyDescriptor(null, ...)` throws a `TypeError`.
## Issue Context
TypeORM utilities explicitly treat `Object.create(null)` objects as valid “plain objects”, and `relation.getEntityValue(...)` is called on user-provided plain objects in transformers.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-488]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation branch reads entity[this.propertyName] (including inside an `instanceof
Promise` check), which can invoke the lazy getter and start DB queries unexpectedly, and can also
return a Promise to callers that expect concrete relation values or undefined. This can cause
unexpected queries during initialization/validation and break persistence/transform flows when an
unresolved Promise is returned.
RelationLoader.enableLazyLoad defines a getter for lazy relations that calls
relationLoader.load(...) (DB query) when the property is accessed. EntityMetadata.create applies
this lazy getter to created instances. Then EntityMetadataValidator calls
relation.getEntityValue(entityInstance) during initialization just to detect initialized arrays;
with the new getEntityValue implementation, accessing entity[this.propertyName] can invoke the
getter, triggering unexpected queries and returning a Promise (ignored/not awaited), which can lead
to performance regressions and potential unhandled rejections.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` now accesses `entity[this.propertyName]` for lazy relations even when `getLazyRelationsPromiseValue` is `false`. If `this.propertyName` is a lazy-loading getter (as installed by `RelationLoader.enableLazyLoad`), that access can trigger a DB query and/or return a Promise into code paths that expect a concrete value or `undefined`.
### Issue Context
- Lazy relations are implemented using `Object.defineProperty(..., { get() { ... relationLoader.load(...) } })`.
- Multiple call sites (e.g. metadata validation and persistence subject building) call `getEntityValue(entity)` with the default flag and do not expect to cause IO or to receive a Promise.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[475-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation getter detection calls Object.getOwnPropertyDescriptor on
Object.getPrototypeOf(entity) without guarding against a null prototype, which can throw a TypeError
and break persistence/transform flows operating on plain objects.
RelationMetadata.getEntityValue now unconditionally passes Object.getPrototypeOf(entity) into
Object.getOwnPropertyDescriptor; if prototype is null, that call throws. TypeORM code explicitly
considers Object.create(null) objects as “plain objects”, and relation.getEntityValue is invoked on
user-provided plain objects during transformation/merge operations, making this a plausible runtime
crash.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` calls `Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), ...)` without checking if the prototype is `null`. For `Object.create(null)`-style objects, `Object.getPrototypeOf(entity)` returns `null`, and `Object.getOwnPropertyDescriptor(null, ...)` throws a `TypeError`.
## Issue Context
TypeORM utilities explicitly treat `Object.create(null)` objects as valid “plain objects”, and `relation.getEntityValue(...)` is called on user-provided plain objects in transformers.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-488]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation branch reads entity[this.propertyName] (including inside an `instanceof
Promise` check), which can invoke the lazy getter and start DB queries unexpectedly, and can also
return a Promise to callers that expect concrete relation values or undefined. This can cause
unexpected queries during initialization/validation and break persistence/transform flows when an
unresolved Promise is returned.
RelationLoader.enableLazyLoad defines a getter for lazy relations that calls
relationLoader.load(...) (DB query) when the property is accessed. EntityMetadata.create applies
this lazy getter to created instances. Then EntityMetadataValidator calls
relation.getEntityValue(entityInstance) during initialization just to detect initialized arrays;
with the new getEntityValue implementation, accessing entity[this.propertyName] can invoke the
getter, triggering unexpected queries and returning a Promise (ignored/not awaited), which can lead
to performance regressions and potential unhandled rejections.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` now accesses `entity[this.propertyName]` for lazy relations even when `getLazyRelationsPromiseValue` is `false`. If `this.propertyName` is a lazy-loading getter (as installed by `RelationLoader.enableLazyLoad`), that access can trigger a DB query and/or return a Promise into code paths that expect a concrete value or `undefined`.
### Issue Context
- Lazy relations are implemented using `Object.defineProperty(..., { get() { ... relationLoader.load(...) } })`.
- Multiple call sites (e.g. metadata validation and persistence subject building) call `getEntityValue(entity)` with the default flag and do not expect to cause IO or to receive a Promise.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[475-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation getter detection calls Object.getOwnPropertyDescriptor on
Object.getPrototypeOf(entity) without guarding against a null prototype, which can throw a TypeError
and break persistence/transform flows operating on plain objects.
RelationMetadata.getEntityValue now unconditionally passes Object.getPrototypeOf(entity) into
Object.getOwnPropertyDescriptor; if prototype is null, that call throws. TypeORM code explicitly
considers Object.create(null) objects as “plain objects”, and relation.getEntityValue is invoked on
user-provided plain objects during transformation/merge operations, making this a plausible runtime
crash.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` calls `Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), ...)` without checking if the prototype is `null`. For `Object.create(null)`-style objects, `Object.getPrototypeOf(entity)` returns `null`, and `Object.getOwnPropertyDescriptor(null, ...)` throws a `TypeError`.
## Issue Context
TypeORM utilities explicitly treat `Object.create(null)` objects as valid “plain objects”, and `relation.getEntityValue(...)` is called on user-provided plain objects in transformers.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-488]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation branch reads entity[this.propertyName] (including inside an `instanceof
Promise` check), which can invoke the lazy getter and start DB queries unexpectedly, and can also
return a Promise to callers that expect concrete relation values or undefined. This can cause
unexpected queries during initialization/validation and break persistence/transform flows when an
unresolved Promise is returned.
RelationLoader.enableLazyLoad defines a getter for lazy relations that calls
relationLoader.load(...) (DB query) when the property is accessed. EntityMetadata.create applies
this lazy getter to created instances. Then EntityMetadataValidator calls
relation.getEntityValue(entityInstance) during initialization just to detect initialized arrays;
with the new getEntityValue implementation, accessing entity[this.propertyName] can invoke the
getter, triggering unexpected queries and returning a Promise (ignored/not awaited), which can lead
to performance regressions and potential unhandled rejections.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` now accesses `entity[this.propertyName]` for lazy relations even when `getLazyRelationsPromiseValue` is `false`. If `this.propertyName` is a lazy-loading getter (as installed by `RelationLoader.enableLazyLoad`), that access can trigger a DB query and/or return a Promise into code paths that expect a concrete value or `undefined`.
### Issue Context
- Lazy relations are implemented using `Object.defineProperty(..., { get() { ... relationLoader.load(...) } })`.
- Multiple call sites (e.g. metadata validation and persistence subject building) call `getEntityValue(entity)` with the default flag and do not expect to cause IO or to receive a Promise.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[475-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Several new JSDoc @param tags were added without any descriptive text, adding comment noise and
style inconsistency. This conflicts with the requirement to avoid AI-like/low-value commentary
additions.
PR Compliance ID 4 requires avoiding AI-generated noise and inconsistent style; the PR adds multiple
bare @param lines that provide no additional information (only parameter names).
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Several JSDoc blocks add `@param <name>` entries with no descriptive text. These add low-value commentary and can be considered AI-generated noise / style inconsistency.
## Issue Context
The compliance checklist requires avoiding AI-like slop and inconsistent style. If parameter documentation is desired, it should include meaningful descriptions; otherwise, these tags should be removed.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[369-372]
- src/metadata/RelationMetadata.ts[385-392]
- src/metadata/RelationMetadata.ts[410-415]
- src/metadata/RelationMetadata.ts[499-506]
- src/metadata/RelationMetadata.ts[549-552]
- src/metadata/RelationMetadata.ts[600-605]
- src/metadata/RelationMetadata.ts[609-614]
- src/metadata/RelationMetadata.ts[632-636]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The PR changes runtime behavior for lazy one-to-many relation value retrieval, which can affect
application behavior. No documentation changes were included to reflect this user-facing behavior
fix.
Compliance requires documentation updates for user-facing changes; the PR modifies lazy relation
handling logic but does not include any accompanying doc update in the provided changes, and the PR
checklist item for docs is left unchecked.
Getter detection only checks the entity and its immediate prototype, so a getter higher in the
prototype chain can be missed and inadvertently executed when evaluating entity[propertyName]. This
can cause unexpected side effects (including lazy-load queries) in edge cases with non-trivial
prototype chains (e.g., inheritance/mixins).
The implementation only inspects one prototype level for an accessor, then may read
entity[this.propertyName]. TypeORM supports inheritance trees, and lazy-load accessors are
installed via Object.defineProperty (including on prototypes), which makes deeper prototype chains
a realistic shape; walking the chain would make the getter-avoidance logic robust.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue()` only checks for an accessor getter on the object itself and its immediate prototype. If a getter exists higher in the prototype chain, the method can still end up evaluating `entity[propertyName]`, invoking the getter and potentially triggering unexpected side effects.
### Issue Context
TypeORM supports inheritance trees and installs lazy relation accessors via `Object.defineProperty` (including on prototypes). A safer approach is to walk the prototype chain when checking for accessors.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Several new JSDoc @param tags were added without any descriptive text, adding comment noise and
style inconsistency. This conflicts with the requirement to avoid AI-like/low-value commentary
additions.
PR Compliance ID 4 requires avoiding AI-generated noise and inconsistent style; the PR adds multiple
bare @param lines that provide no additional information (only parameter names).
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Several JSDoc blocks add `@param <name>` entries with no descriptive text. These add low-value commentary and can be considered AI-generated noise / style inconsistency.
## Issue Context
The compliance checklist requires avoiding AI-like slop and inconsistent style. If parameter documentation is desired, it should include meaningful descriptions; otherwise, these tags should be removed.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[369-372]
- src/metadata/RelationMetadata.ts[385-392]
- src/metadata/RelationMetadata.ts[410-415]
- src/metadata/RelationMetadata.ts[499-506]
- src/metadata/RelationMetadata.ts[549-552]
- src/metadata/RelationMetadata.ts[600-605]
- src/metadata/RelationMetadata.ts[609-614]
- src/metadata/RelationMetadata.ts[632-636]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new prototype-chain scan treats the relation as “lazy/unassigned” if it finds any getter up the
chain, even when the entity defines its own data property that shadows that getter. In such cases
(e.g., entities/deserialized objects that define the property via defineProperty), an explicitly
assigned relation value can still be skipped during persistence.
+ let hasGetter = false+ let proto: object | null = entity+ while (proto) {+ if (+ Object.getOwnPropertyDescriptor(+ proto,+ this.propertyName,+ )?.get+ ) {+ hasGetter = true+ break+ }+ proto = Object.getPrototypeOf(proto)+ }++ if (hasGetter || entity[this.propertyName] instanceof Promise) {+ return undefined+ }+ return entity[this.propertyName]
Evidence
RelationMetadata now walks the prototype chain and returns undefined whenever any getter is found,
without stopping when a shadowing own property descriptor exists. TypeORM installs lazy accessors on
the entity prototype, so the prototype chain commonly contains a getter for lazy relations; if a
consumer shadows it with a data property, this logic will still find the prototype getter and
incorrectly ignore the shadowing value.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` scans the entire prototype chain for a getter and returns `undefined` if any getter exists, even if the relation name is shadowed by an own *data* property on the entity.
### Issue Context
This can cause explicitly assigned relation values to be ignored on entity-like objects that shadow the prototype accessor (e.g., via `Object.defineProperty` or certain deserialization patterns).
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-500]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new assigned-value handling was only added for non-embedded relations; the embedded relation
branch still returns undefined for lazy relations unless ____ is populated. Since embeddeds can
contain relations, the same class of bug remains for embedded lazy relations.
+ let hasGetter = false+ let proto: object | null = entity+ while (proto) {+ if (+ Object.getOwnPropertyDescriptor(+ proto,+ this.propertyName,+ )?.get+ ) {+ hasGetter = true+ break+ }+ proto = Object.getPrototypeOf(proto)+ }++ if (hasGetter || entity[this.propertyName] instanceof Promise) {+ return undefined+ }+ return entity[this.propertyName]
Evidence
RelationMetadata has a separate embeddedMetadata branch where lazy relations still always return
undefined unless the backing ____ exists or getLazyRelationsPromiseValue is true.
EmbeddedMetadata explicitly builds relationsFromTree, so relations-in-embedded is a
supported/considered feature and this branch is reachable.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The embedded-metadata branch of `RelationMetadata.getEntityValue` did not receive the new assigned-value handling for lazy relations, leaving embedded lazy relations unable to surface assigned values unless `__<prop>__` is set.
### Issue Context
Embeddeds can contain relations (`relationsFromTree`), so this branch is reachable for relation metadata.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[454-465]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
15. Test doesn't hit new code 🐞 Bug⛯ Reliability
Description
The added lazy test assigns Promise.resolve([...]), but save() yields await Promise.resolve()
before building subjects, allowing the lazy setter microtask to populate __posts__ so
getEntityValue returns early. This likely doesn’t exercise the newly added “no getter +
non-Promise value” code path, reducing confidence that the fix is validated.
RelationLoader.enableLazyLoad stores assigned Promises in __promise___ and transfers resolved
results into ____ in a .then(...) microtask. EntityPersistExecutor.execute begins by `await
Promise.resolve()` to flush microtasks before it proceeds to relation subject building, so by the
time persistence reads the relation, ____ is likely already set and the new getter/prototype
detection branch is bypassed.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The new functional test likely passes without executing the newly added `hasGetter`/non-Promise-return path in `RelationMetadata.getEntityValue`, so it may not validate the intended fix.
### Issue Context
`EntityPersistExecutor` performs `await Promise.resolve()` before building relation subjects, which flushes microtasks that populate `__<prop>__` for `Promise.resolve(...)` assignments via the lazy setter.
### Fix Focus Areas
- test/functional/persistence/one-to-many-lazy/persistence-one-to-many-lazy.test.ts[59-96]
- src/persistence/EntityPersistExecutor.ts[46-48]
- src/query-builder/RelationLoader.ts[419-474]
- src/metadata/RelationMetadata.ts[475-500]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Several new JSDoc @param tags were added without any descriptive text, adding comment noise and
style inconsistency. This conflicts with the requirement to avoid AI-like/low-value commentary
additions.
PR Compliance ID 4 requires avoiding AI-generated noise and inconsistent style; the PR adds multiple
bare @param lines that provide no additional information (only parameter names).
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Several JSDoc blocks add `@param <name>` entries with no descriptive text. These add low-value commentary and can be considered AI-generated noise / style inconsistency.
## Issue Context
The compliance checklist requires avoiding AI-like slop and inconsistent style. If parameter documentation is desired, it should include meaningful descriptions; otherwise, these tags should be removed.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[369-372]
- src/metadata/RelationMetadata.ts[385-392]
- src/metadata/RelationMetadata.ts[410-415]
- src/metadata/RelationMetadata.ts[499-506]
- src/metadata/RelationMetadata.ts[549-552]
- src/metadata/RelationMetadata.ts[600-605]
- src/metadata/RelationMetadata.ts[609-614]
- src/metadata/RelationMetadata.ts[632-636]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The PR changes runtime behavior for lazy one-to-many relation value retrieval, which can affect
application behavior. No documentation changes were included to reflect this user-facing behavior
fix.
Compliance requires documentation updates for user-facing changes; the PR modifies lazy relation
handling logic but does not include any accompanying doc update in the provided changes, and the PR
checklist item for docs is left unchecked.
Getter detection only checks the entity and its immediate prototype, so a getter higher in the
prototype chain can be missed and inadvertently executed when evaluating entity[propertyName]. This
can cause unexpected side effects (including lazy-load queries) in edge cases with non-trivial
prototype chains (e.g., inheritance/mixins).
The implementation only inspects one prototype level for an accessor, then may read
entity[this.propertyName]. TypeORM supports inheritance trees, and lazy-load accessors are
installed via Object.defineProperty (including on prototypes), which makes deeper prototype chains
a realistic shape; walking the chain would make the getter-avoidance logic robust.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue()` only checks for an accessor getter on the object itself and its immediate prototype. If a getter exists higher in the prototype chain, the method can still end up evaluating `entity[propertyName]`, invoking the getter and potentially triggering unexpected side effects.
### Issue Context
TypeORM supports inheritance trees and installs lazy relation accessors via `Object.defineProperty` (including on prototypes). A safer approach is to walk the prototype chain when checking for accessors.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Several new JSDoc @param tags were added without any descriptive text, adding comment noise and
style inconsistency. This conflicts with the requirement to avoid AI-like/low-value commentary
additions.
PR Compliance ID 4 requires avoiding AI-generated noise and inconsistent style; the PR adds multiple
bare @param lines that provide no additional information (only parameter names).
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Several JSDoc blocks add `@param <name>` entries with no descriptive text. These add low-value commentary and can be considered AI-generated noise / style inconsistency.
## Issue Context
The compliance checklist requires avoiding AI-like slop and inconsistent style. If parameter documentation is desired, it should include meaningful descriptions; otherwise, these tags should be removed.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[369-372]
- src/metadata/RelationMetadata.ts[385-392]
- src/metadata/RelationMetadata.ts[410-415]
- src/metadata/RelationMetadata.ts[499-506]
- src/metadata/RelationMetadata.ts[549-552]
- src/metadata/RelationMetadata.ts[600-605]
- src/metadata/RelationMetadata.ts[609-614]
- src/metadata/RelationMetadata.ts[632-636]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
ⓘ The new review experience is currently in Beta. Learn more
The new lazy-relation getter detection calls Object.getOwnPropertyDescriptor on
Object.getPrototypeOf(entity) without guarding against a null prototype, which can throw a TypeError
and break persistence/transform flows operating on plain objects.
RelationMetadata.getEntityValue now unconditionally passes Object.getPrototypeOf(entity) into
Object.getOwnPropertyDescriptor; if prototype is null, that call throws. TypeORM code explicitly
considers Object.create(null) objects as “plain objects”, and relation.getEntityValue is invoked on
user-provided plain objects during transformation/merge operations, making this a plausible runtime
crash.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` calls `Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), ...)` without checking if the prototype is `null`. For `Object.create(null)`-style objects, `Object.getPrototypeOf(entity)` returns `null`, and `Object.getOwnPropertyDescriptor(null, ...)` throws a `TypeError`.
## Issue Context
TypeORM utilities explicitly treat `Object.create(null)` objects as valid “plain objects”, and `relation.getEntityValue(...)` is called on user-provided plain objects in transformers.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-488]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation branch reads entity[this.propertyName] (including inside an `instanceof
Promise` check), which can invoke the lazy getter and start DB queries unexpectedly, and can also
return a Promise to callers that expect concrete relation values or undefined. This can cause
unexpected queries during initialization/validation and break persistence/transform flows when an
unresolved Promise is returned.
RelationLoader.enableLazyLoad defines a getter for lazy relations that calls
relationLoader.load(...) (DB query) when the property is accessed. EntityMetadata.create applies
this lazy getter to created instances. Then EntityMetadataValidator calls
relation.getEntityValue(entityInstance) during initialization just to detect initialized arrays;
with the new getEntityValue implementation, accessing entity[this.propertyName] can invoke the
getter, triggering unexpected queries and returning a Promise (ignored/not awaited), which can lead
to performance regressions and potential unhandled rejections.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` now accesses `entity[this.propertyName]` for lazy relations even when `getLazyRelationsPromiseValue` is `false`. If `this.propertyName` is a lazy-loading getter (as installed by `RelationLoader.enableLazyLoad`), that access can trigger a DB query and/or return a Promise into code paths that expect a concrete value or `undefined`.
### Issue Context
- Lazy relations are implemented using `Object.defineProperty(..., { get() { ... relationLoader.load(...) } })`.
- Multiple call sites (e.g. metadata validation and persistence subject building) call `getEntityValue(entity)` with the default flag and do not expect to cause IO or to receive a Promise.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[475-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
3. Lazy relation fix undocumented 📘 Rule violation✓ Correctness⭐ New
Description
The PR changes runtime behavior for lazy one-to-many relation value retrieval, which can affect
application behavior. No documentation changes were included to reflect this user-facing behavior
fix.
Compliance requires documentation updates for user-facing changes; the PR modifies lazy relation
handling logic but does not include any accompanying doc update in the provided changes, and the PR
checklist item for docs is left unchecked.
4. Getter check incomplete 🐞 Bug⛯ Reliability⭐ New
Description
Getter detection only checks the entity and its immediate prototype, so a getter higher in the
prototype chain can be missed and inadvertently executed when evaluating entity[propertyName]. This
can cause unexpected side effects (including lazy-load queries) in edge cases with non-trivial
prototype chains (e.g., inheritance/mixins).
The implementation only inspects one prototype level for an accessor, then may read
entity[this.propertyName]. TypeORM supports inheritance trees, and lazy-load accessors are
installed via Object.defineProperty (including on prototypes), which makes deeper prototype chains
a realistic shape; walking the chain would make the getter-avoidance logic robust.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
### Issue description
`RelationMetadata.getEntityValue()` only checks for an accessor getter on the object itself and its immediate prototype. If a getter exists higher in the prototype chain, the method can still end up evaluating `entity[propertyName]`, invoking the getter and potentially triggering unexpected side effects.
### Issue Context
TypeORM supports inheritance trees and installs lazy relation accessors via `Object.defineProperty` (including on prototypes). A safer approach is to walk the prototype chain when checking for accessors.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Several new JSDoc @param tags were added without any descriptive text, adding comment noise and
style inconsistency. This conflicts with the requirement to avoid AI-like/low-value commentary
additions.
PR Compliance ID 4 requires avoiding AI-generated noise and inconsistent style; the PR adds multiple
bare @param lines that provide no additional information (only parameter names).
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Several JSDoc blocks add `@param <name>` entries with no descriptive text. These add low-value commentary and can be considered AI-generated noise / style inconsistency.
## Issue Context
The compliance checklist requires avoiding AI-like slop and inconsistent style. If parameter documentation is desired, it should include meaningful descriptions; otherwise, these tags should be removed.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[369-372]
- src/metadata/RelationMetadata.ts[385-392]
- src/metadata/RelationMetadata.ts[410-415]
- src/metadata/RelationMetadata.ts[499-506]
- src/metadata/RelationMetadata.ts[549-552]
- src/metadata/RelationMetadata.ts[600-605]
- src/metadata/RelationMetadata.ts[609-614]
- src/metadata/RelationMetadata.ts[632-636]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
ⓘ The new review experience is currently in Beta. Learn more
The new lazy-relation getter detection calls Object.getOwnPropertyDescriptor on
Object.getPrototypeOf(entity) without guarding against a null prototype, which can throw a TypeError
and break persistence/transform flows operating on plain objects.
RelationMetadata.getEntityValue now unconditionally passes Object.getPrototypeOf(entity) into
Object.getOwnPropertyDescriptor; if prototype is null, that call throws. TypeORM code explicitly
considers Object.create(null) objects as “plain objects”, and relation.getEntityValue is invoked on
user-provided plain objects during transformation/merge operations, making this a plausible runtime
crash.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` calls `Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), ...)` without checking if the prototype is `null`. For `Object.create(null)`-style objects, `Object.getPrototypeOf(entity)` returns `null`, and `Object.getOwnPropertyDescriptor(null, ...)` throws a `TypeError`.
## Issue Context
TypeORM utilities explicitly treat `Object.create(null)` objects as valid “plain objects”, and `relation.getEntityValue(...)` is called on user-provided plain objects in transformers.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-488]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation branch reads entity[this.propertyName] (including inside an `instanceof
Promise` check), which can invoke the lazy getter and start DB queries unexpectedly, and can also
return a Promise to callers that expect concrete relation values or undefined. This can cause
unexpected queries during initialization/validation and break persistence/transform flows when an
unresolved Promise is returned.
RelationLoader.enableLazyLoad defines a getter for lazy relations that calls
relationLoader.load(...) (DB query) when the property is accessed. EntityMetadata.create applies
this lazy getter to created instances. Then EntityMetadataValidator calls
relation.getEntityValue(entityInstance) during initialization just to detect initialized arrays;
with the new getEntityValue implementation, accessing entity[this.propertyName] can invoke the
getter, triggering unexpected queries and returning a Promise (ignored/not awaited), which can lead
to performance regressions and potential unhandled rejections.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` now accesses `entity[this.propertyName]` for lazy relations even when `getLazyRelationsPromiseValue` is `false`. If `this.propertyName` is a lazy-loading getter (as installed by `RelationLoader.enableLazyLoad`), that access can trigger a DB query and/or return a Promise into code paths that expect a concrete value or `undefined`.
### Issue Context
- Lazy relations are implemented using `Object.defineProperty(..., { get() { ... relationLoader.load(...) } })`.
- Multiple call sites (e.g. metadata validation and persistence subject building) call `getEntityValue(entity)` with the default flag and do not expect to cause IO or to receive a Promise.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[475-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation getter detection calls Object.getOwnPropertyDescriptor on
Object.getPrototypeOf(entity) without guarding against a null prototype, which can throw a TypeError
and break persistence/transform flows operating on plain objects.
RelationMetadata.getEntityValue now unconditionally passes Object.getPrototypeOf(entity) into
Object.getOwnPropertyDescriptor; if prototype is null, that call throws. TypeORM code explicitly
considers Object.create(null) objects as “plain objects”, and relation.getEntityValue is invoked on
user-provided plain objects during transformation/merge operations, making this a plausible runtime
crash.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` calls `Object.getOwnPropertyDescriptor(Object.getPrototypeOf(entity), ...)` without checking if the prototype is `null`. For `Object.create(null)`-style objects, `Object.getPrototypeOf(entity)` returns `null`, and `Object.getOwnPropertyDescriptor(null, ...)` throws a `TypeError`.
## Issue Context
TypeORM utilities explicitly treat `Object.create(null)` objects as valid “plain objects”, and `relation.getEntityValue(...)` is called on user-provided plain objects in transformers.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-488]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new lazy-relation branch reads entity[this.propertyName] (including inside an `instanceof
Promise` check), which can invoke the lazy getter and start DB queries unexpectedly, and can also
return a Promise to callers that expect concrete relation values or undefined. This can cause
unexpected queries during initialization/validation and break persistence/transform flows when an
unresolved Promise is returned.
RelationLoader.enableLazyLoad defines a getter for lazy relations that calls
relationLoader.load(...) (DB query) when the property is accessed. EntityMetadata.create applies
this lazy getter to created instances. Then EntityMetadataValidator calls
relation.getEntityValue(entityInstance) during initialization just to detect initialized arrays;
with the new getEntityValue implementation, accessing entity[this.propertyName] can invoke the
getter, triggering unexpected queries and returning a Promise (ignored/not awaited), which can lead
to performance regressions and potential unhandled rejections.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue` now accesses `entity[this.propertyName]` for lazy relations even when `getLazyRelationsPromiseValue` is `false`. If `this.propertyName` is a lazy-loading getter (as installed by `RelationLoader.enableLazyLoad`), that access can trigger a DB query and/or return a Promise into code paths that expect a concrete value or `undefined`.
### Issue Context
- Lazy relations are implemented using `Object.defineProperty(..., { get() { ... relationLoader.load(...) } })`.
- Multiple call sites (e.g. metadata validation and persistence subject building) call `getEntityValue(entity)` with the default flag and do not expect to cause IO or to receive a Promise.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[475-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
5. Getter scan misses shadowing 🐞 Bug✓ Correctness⭐ New
Description
The new prototype-chain scan treats the relation as “lazy/unassigned” if it finds any getter up the
chain, even when the entity defines its own data property that shadows that getter. In such cases
(e.g., entities/deserialized objects that define the property via defineProperty), an explicitly
assigned relation value can still be skipped during persistence.
+ let hasGetter = false+ let proto: object | null = entity+ while (proto) {+ if (+ Object.getOwnPropertyDescriptor(+ proto,+ this.propertyName,+ )?.get+ ) {+ hasGetter = true+ break+ }+ proto = Object.getPrototypeOf(proto)+ }++ if (hasGetter || entity[this.propertyName] instanceof Promise) {+ return undefined+ }+ return entity[this.propertyName]
Evidence
RelationMetadata now walks the prototype chain and returns undefined whenever any getter is found,
without stopping when a shadowing own property descriptor exists. TypeORM installs lazy accessors on
the entity prototype, so the prototype chain commonly contains a getter for lazy relations; if a
consumer shadows it with a data property, this logic will still find the prototype getter and
incorrectly ignore the shadowing value.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
### Issue description
`RelationMetadata.getEntityValue` scans the entire prototype chain for a getter and returns `undefined` if any getter exists, even if the relation name is shadowed by an own *data* property on the entity.
### Issue Context
This can cause explicitly assigned relation values to be ignored on entity-like objects that shadow the prototype accessor (e.g., via `Object.defineProperty` or certain deserialization patterns).
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-500]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
6. Embedded lazy path unchanged 🐞 Bug✓ Correctness⭐ New
Description
The new assigned-value handling was only added for non-embedded relations; the embedded relation
branch still returns undefined for lazy relations unless __<prop>__ is populated. Since embeddeds
can contain relations, the same class of bug remains for embedded lazy relations.
+ let hasGetter = false+ let proto: object | null = entity+ while (proto) {+ if (+ Object.getOwnPropertyDescriptor(+ proto,+ this.propertyName,+ )?.get+ ) {+ hasGetter = true+ break+ }+ proto = Object.getPrototypeOf(proto)+ }++ if (hasGetter || entity[this.propertyName] instanceof Promise) {+ return undefined+ }+ return entity[this.propertyName]
Evidence
RelationMetadata has a separate embeddedMetadata branch where lazy relations still always return
undefined unless the backing __<prop>__ exists or getLazyRelationsPromiseValue is true.
EmbeddedMetadata explicitly builds relationsFromTree, so relations-in-embedded is a
supported/considered feature and this branch is reachable.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
### Issue description
The embedded-metadata branch of `RelationMetadata.getEntityValue` did not receive the new assigned-value handling for lazy relations, leaving embedded lazy relations unable to surface assigned values unless `__<prop>__` is set.
### Issue Context
Embeddeds can contain relations (`relationsFromTree`), so this branch is reachable for relation metadata.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[454-465]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
7. Test doesn't hit new code 🐞 Bug⛯ Reliability⭐ New
Description
The added lazy test assigns Promise.resolve([...]), but save() yields await Promise.resolve()
before building subjects, allowing the lazy setter microtask to populate __posts__ so
getEntityValue returns early. This likely doesn’t exercise the newly added “no getter +
non-Promise value” code path, reducing confidence that the fix is validated.
RelationLoader.enableLazyLoad stores assigned Promises in __promise_<prop>__ and transfers
resolved results into __<prop>__ in a .then(...) microtask. EntityPersistExecutor.execute
begins by await Promise.resolve() to flush microtasks before it proceeds to relation subject
building, so by the time persistence reads the relation, __<prop>__ is likely already set and the
new getter/prototype detection branch is bypassed.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
### Issue description
The new functional test likely passes without executing the newly added `hasGetter`/non-Promise-return path in `RelationMetadata.getEntityValue`, so it may not validate the intended fix.
### Issue Context
`EntityPersistExecutor` performs `await Promise.resolve()` before building relation subjects, which flushes microtasks that populate `__<prop>__` for `Promise.resolve(...)` assignments via the lazy setter.
### Fix Focus Areas
- test/functional/persistence/one-to-many-lazy/persistence-one-to-many-lazy.test.ts[59-96]
- src/persistence/EntityPersistExecutor.ts[46-48]
- src/query-builder/RelationLoader.ts[419-474]
- src/metadata/RelationMetadata.ts[475-500]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Several new JSDoc @param tags were added without any descriptive text, adding comment noise and
style inconsistency. This conflicts with the requirement to avoid AI-like/low-value commentary
additions.
PR Compliance ID 4 requires avoiding AI-generated noise and inconsistent style; the PR adds multiple
bare @param lines that provide no additional information (only parameter names).
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Several JSDoc blocks add `@param &lt;name&gt;` entries with no descriptive text. These add low-value commentary and can be considered AI-generated noise / style inconsistency.
## Issue Context
The compliance checklist requires avoiding AI-like slop and inconsistent style. If parameter documentation is desired, it should include meaningful descriptions; otherwise, these tags should be removed.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[369-372]
- src/metadata/RelationMetadata.ts[385-392]
- src/metadata/RelationMetadata.ts[410-415]
- src/metadata/RelationMetadata.ts[499-506]
- src/metadata/RelationMetadata.ts[549-552]
- src/metadata/RelationMetadata.ts[600-605]
- src/metadata/RelationMetadata.ts[609-614]
- src/metadata/RelationMetadata.ts[632-636]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The PR changes runtime behavior for lazy one-to-many relation value retrieval, which can affect
application behavior. No documentation changes were included to reflect this user-facing behavior
fix.
Compliance requires documentation updates for user-facing changes; the PR modifies lazy relation
handling logic but does not include any accompanying doc update in the provided changes, and the PR
checklist item for docs is left unchecked.
Getter detection only checks the entity and its immediate prototype, so a getter higher in the
prototype chain can be missed and inadvertently executed when evaluating entity[propertyName]. This
can cause unexpected side effects (including lazy-load queries) in edge cases with non-trivial
prototype chains (e.g., inheritance/mixins).
The implementation only inspects one prototype level for an accessor, then may read
entity[this.propertyName]. TypeORM supports inheritance trees, and lazy-load accessors are
installed via Object.defineProperty (including on prototypes), which makes deeper prototype chains
a realistic shape; walking the chain would make the getter-avoidance logic robust.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`RelationMetadata.getEntityValue()` only checks for an accessor getter on the object itself and its immediate prototype. If a getter exists higher in the prototype chain, the method can still end up evaluating `entity[propertyName]`, invoking the getter and potentially triggering unexpected side effects.
### Issue Context
TypeORM supports inheritance trees and installs lazy relation accessors via `Object.defineProperty` (including on prototypes). A safer approach is to walk the prototype chain when checking for accessors.
### Fix Focus Areas
- src/metadata/RelationMetadata.ts[482-493]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Several new JSDoc @param tags were added without any descriptive text, adding comment noise and
style inconsistency. This conflicts with the requirement to avoid AI-like/low-value commentary
additions.
PR Compliance ID 4 requires avoiding AI-generated noise and inconsistent style; the PR adds multiple
bare @param lines that provide no additional information (only parameter names).
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
Several JSDoc blocks add `@param &amp;lt;name&amp;gt;` entries with no descriptive text. These add low-value commentary and can be considered AI-generated noise / style inconsistency.
## Issue Context
The compliance checklist requires avoiding AI-like slop and inconsistent style. If parameter documentation is desired, it should include meaningful descriptions; otherwise, these tags should be removed.
## Fix Focus Areas
- src/metadata/RelationMetadata.ts[369-372]
- src/metadata/RelationMetadata.ts[385-392]
- src/metadata/RelationMetadata.ts[410-415]
- src/metadata/RelationMetadata.ts[499-506]
- src/metadata/RelationMetadata.ts[549-552]
- src/metadata/RelationMetadata.ts[600-605]
- src/metadata/RelationMetadata.ts[609-614]
- src/metadata/RelationMetadata.ts[632-636]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
ⓘ The new review experience is currently in Beta. Learn more
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Close #10190
Description of change
Pull-Request Checklist
masterbranchFixes #00000tests/**.test.ts)docs/docs/**.md)