@mikro-orm/core
Advanced tools
@@ -73,2 +73,4 @@ import { type EntityDTO, type EntityKey, type EntityProperty, type FilterQuery, type IPrimaryKey, type Loaded, type LoadedCollection, type Populate, type Primary, CollectionBrand } from '../typings.js'; | ||
| private getEntityManager; | ||
| /** The owning-side property this collection is mapped by (the inverse of `mappedBy`); `undefined` for the owning side of m:n. */ | ||
| private get mappedByProp(); | ||
| private createCondition; | ||
@@ -75,0 +77,0 @@ private createManyToManyCondition; |
+12
-2
@@ -323,5 +323,10 @@ import { Utils } from '../utils/Utils.js'; | ||
| } | ||
| /** The owning-side property this collection is mapped by (the inverse of `mappedBy`); `undefined` for the owning side of m:n. */ | ||
| get mappedByProp() { | ||
| return this.property.mappedBy ? this.property.targetMeta.properties[this.property.mappedBy] : undefined; | ||
| } | ||
| createCondition(cond = {}) { | ||
| if (this.property.kind === ReferenceKind.ONE_TO_MANY) { | ||
| cond[this.property.mappedBy] = helper(this.owner).getPrimaryKey(); | ||
| // the owning FK may reference a non-PK column (`targetKey`), so match on that value when set | ||
| cond[this.property.mappedBy] = helper(this.owner).getTargetKeyValue(this.mappedByProp?.targetKey); | ||
| } | ||
@@ -348,3 +353,8 @@ else { | ||
| const wrapped = helper(this.owner); | ||
| const val = wrapped.__meta.compositePK ? { $in: wrapped.__primaryKeys } : wrapped.getPrimaryKey(); | ||
| const ownerProp = this.mappedByProp; | ||
| const val = ownerProp?.targetKey | ||
| ? wrapped.getTargetKeyValue(ownerProp.targetKey) | ||
| : wrapped.__meta.compositePK | ||
| ? { $in: wrapped.__primaryKeys } | ||
| : wrapped.getPrimaryKey(); | ||
| const dict = cond; | ||
@@ -351,0 +361,0 @@ if (this.property.kind === ReferenceKind.ONE_TO_MANY) { |
+27
-15
@@ -284,12 +284,21 @@ import { QueryHelper } from '../utils/QueryHelper.js'; | ||
| initializeOneToMany(filtered, children, prop, field, partial, readonly) { | ||
| const mapToPk = prop.targetMeta.properties[prop.mappedBy].mapToPk; | ||
| const ownerProp = prop.targetMeta.properties[prop.mappedBy]; | ||
| const targetKey = ownerProp.targetKey; | ||
| const map = {}; | ||
| // when the owning side targets a non-PK column, group by that value on both sides | ||
| const parentKey = (entity) => helper(entity).getSerializedTargetKey(targetKey); | ||
| for (const entity of filtered) { | ||
| const key = helper(entity).getSerializedPrimaryKey(); | ||
| map[key] = []; | ||
| map[parentKey(entity)] = []; | ||
| } | ||
| for (const child of children) { | ||
| const pk = child.__helper.__data[prop.mappedBy] ?? child[prop.mappedBy]; | ||
| if (pk) { | ||
| const key = helper(mapToPk ? this.#em.getReference(prop.targetMeta.class, pk) : pk).getSerializedPrimaryKey(); | ||
| const fk = child.__helper.__data[prop.mappedBy] ?? child[prop.mappedBy]; | ||
| if (fk) { | ||
| let key; | ||
| if (targetKey) { | ||
| // `fk` is the owner reference (resolve its targetKey) unless the relation maps to the raw PK value | ||
| key = Utils.isEntity(fk, true) ? helper(fk).getSerializedTargetKey(targetKey) : '' + fk; | ||
| } | ||
| else { | ||
| key = helper(ownerProp.mapToPk ? this.#em.getReference(prop.targetMeta.class, fk) : fk).getSerializedPrimaryKey(); | ||
| } | ||
| map[key]?.push(child); | ||
@@ -299,4 +308,3 @@ } | ||
| for (const entity of filtered) { | ||
| const key = helper(entity).getSerializedPrimaryKey(); | ||
| entity[field].hydrate(map[key], undefined, partial, readonly); | ||
| entity[field].hydrate(map[parentKey(entity)], undefined, partial, readonly); | ||
| } | ||
@@ -331,4 +339,6 @@ } | ||
| let polymorphicOwnerProp; | ||
| if (prop.kind === ReferenceKind.ONE_TO_MANY || (prop.kind === ReferenceKind.MANY_TO_MANY && !prop.owner)) { | ||
| const ownerProp = meta.properties[prop.mappedBy]; | ||
| const ownerProp = prop.kind === ReferenceKind.ONE_TO_MANY || (prop.kind === ReferenceKind.MANY_TO_MANY && !prop.owner) | ||
| ? meta.properties[prop.mappedBy] | ||
| : undefined; | ||
| if (ownerProp) { | ||
| if (ownerProp.polymorphic && ownerProp.fieldNames.length >= 2) { | ||
@@ -354,3 +364,5 @@ const idColumns = ownerProp.fieldNames.slice(1); | ||
| } | ||
| const ids = Utils.unique(children.map(e => (prop.targetKey ? e[prop.targetKey] : e.__helper.getPrimaryKey()))); | ||
| // for inverse sides the `targetKey` lives on the owning property, otherwise on the prop itself | ||
| const targetKey = prop.targetKey ?? ownerProp?.targetKey; | ||
| const ids = Utils.unique(children.map(e => e.__helper.getTargetKeyValue(targetKey))); | ||
| let where; | ||
@@ -424,3 +436,3 @@ if (polymorphicOwnerProp && Array.isArray(fk)) { | ||
| for (const item of items) { | ||
| itemsByKey.set('' + item[prop.targetKey], item); | ||
| itemsByKey.set(helper(item).getSerializedTargetKey(prop.targetKey), item); | ||
| } | ||
@@ -433,4 +445,3 @@ for (const entity of entities) { | ||
| } | ||
| // oxfmt-ignore | ||
| const keyValue = '' + (Reference.isReference(ref) ? ref.unwrap()[prop.targetKey] : ref[prop.targetKey]); | ||
| const keyValue = helper(ref).getSerializedTargetKey(prop.targetKey); | ||
| const loadedItem = itemsByKey.get(keyValue); | ||
@@ -446,3 +457,4 @@ if (loadedItem) { | ||
| const childrenMap = new Set(); | ||
| // Use targetKey value if set, otherwise use serialized PK | ||
| // `e` may be an unresolved reference here, so read the targetKey value directly instead of | ||
| // resolving it through the entity — that keeps orphaned references (missing target row) intact | ||
| const getKey = (e) => (prop.targetKey ? '' + e[prop.targetKey] : helper(e).getSerializedPrimaryKey()); | ||
@@ -449,0 +461,0 @@ for (const item of items) { |
@@ -82,2 +82,6 @@ import type { PopulatePath } from '../enums.js'; | ||
| getSerializedPrimaryKey(): string; | ||
| /** Returns the value a relation references on this entity — the `targetKey` column when set, otherwise the primary key. */ | ||
| getTargetKeyValue(targetKey?: string): Primary<Entity> | null; | ||
| /** Serialized counterpart of `getTargetKeyValue`, suitable for identity map / grouping keys. */ | ||
| getSerializedTargetKey(targetKey?: string): string; | ||
| get __meta(): EntityMetadata<Entity>; | ||
@@ -84,0 +88,0 @@ get __platform(): Platform; |
@@ -162,2 +162,10 @@ import { Reference } from './Reference.js'; | ||
| } | ||
| /** Returns the value a relation references on this entity — the `targetKey` column when set, otherwise the primary key. */ | ||
| getTargetKeyValue(targetKey) { | ||
| return targetKey ? this.entity[targetKey] : this.getPrimaryKey(); | ||
| } | ||
| /** Serialized counterpart of `getTargetKeyValue`, suitable for identity map / grouping keys. */ | ||
| getSerializedTargetKey(targetKey) { | ||
| return targetKey ? '' + this.entity[targetKey] : this.getSerializedPrimaryKey(); | ||
| } | ||
| get __meta() { | ||
@@ -164,0 +172,0 @@ return this.entity.__meta; |
+1
-1
| { | ||
| "name": "@mikro-orm/core", | ||
| "version": "7.1.4-dev.8", | ||
| "version": "7.1.4-dev.9", | ||
| "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
+1
-1
@@ -144,3 +144,3 @@ import { clone } from './clone.js'; | ||
| static PK_SEPARATOR = '~~~'; | ||
| static #ORM_VERSION = '7.1.4-dev.8'; | ||
| static #ORM_VERSION = '7.1.4-dev.9'; | ||
| /** | ||
@@ -147,0 +147,0 @@ * Checks if the argument is instance of `Object`. Returns false for arrays. |
Sorry, the diff of this file is too big to display
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
1563522
0.16%33484
0.11%