@mikro-orm/core 7.0.17-dev.1 → 7.0.17-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EntityManager.js +11 -4
- package/entity/EntityLoader.js +11 -5
- package/package.json +1 -1
- package/utils/Utils.js +1 -1
package/EntityManager.js
CHANGED
|
@@ -1743,9 +1743,13 @@ export class EntityManager {
|
|
|
1743
1743
|
return [];
|
|
1744
1744
|
}
|
|
1745
1745
|
const meta = this.metadata.find(entityName);
|
|
1746
|
-
// infer populate hints from `fields` when present; merge with explicit `populate` if both are set
|
|
1746
|
+
// infer populate hints from `fields` when present; merge with explicit `populate` if both are set.
|
|
1747
|
+
// `populateArray` is only kept when the entries are user-provided strings — when this method runs a
|
|
1748
|
+
// second time (e.g. from `lockAndPopulate`) the populate is already normalized and merging would be a no-op.
|
|
1747
1749
|
const fields = options.fields ? this.buildFields(options.fields) : undefined;
|
|
1748
|
-
const populateArray = Array.isArray(options.populate)
|
|
1750
|
+
const populateArray = Array.isArray(options.populate) && options.populate.every(p => typeof p === 'string')
|
|
1751
|
+
? options.populate
|
|
1752
|
+
: undefined;
|
|
1749
1753
|
const hasNestedFields = fields?.some(f => f.includes('.')) ?? false;
|
|
1750
1754
|
const shouldInfer = fields !== undefined && options.populate === undefined;
|
|
1751
1755
|
const shouldMerge = fields !== undefined && populateArray !== undefined && populateArray.length > 0 && hasNestedFields;
|
|
@@ -1789,8 +1793,11 @@ export class EntityManager {
|
|
|
1789
1793
|
}
|
|
1790
1794
|
else {
|
|
1791
1795
|
// with an explicit populate, only nested paths (e.g. `item.id`) need to be merged in — they
|
|
1792
|
-
// require a JOIN to access sub-fields, whereas bare names are already handled by the driver
|
|
1793
|
-
|
|
1796
|
+
// require a JOIN to access sub-fields, whereas bare names are already handled by the driver.
|
|
1797
|
+
// skip paths already in user's `populate` (regardless of `:ref` modifier) to avoid producing
|
|
1798
|
+
// both a `:ref` and a non-`:ref` entry for the same relation
|
|
1799
|
+
const existing = new Set(populateArray.map(p => p.split(':')[0]));
|
|
1800
|
+
const extras = fromFields.filter(f => f.includes('.') && !existing.has(f));
|
|
1794
1801
|
options.populate = [...populateArray, ...extras];
|
|
1795
1802
|
}
|
|
1796
1803
|
}
|
package/entity/EntityLoader.js
CHANGED
|
@@ -316,7 +316,7 @@ export class EntityLoader {
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
async findChildren(entities, prop, populate, options, ref) {
|
|
319
|
-
const children = Utils.unique(this.getChildReferences(entities, prop, options, ref));
|
|
319
|
+
const children = Utils.unique(this.getChildReferences(entities, prop, options, ref, populate));
|
|
320
320
|
const meta = prop.targetMeta;
|
|
321
321
|
// When targetKey is set, use it for FK lookup instead of the PK
|
|
322
322
|
let fk = prop.targetKey ?? Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
@@ -682,7 +682,7 @@ export class EntityLoader {
|
|
|
682
682
|
}
|
|
683
683
|
return ret;
|
|
684
684
|
}
|
|
685
|
-
getChildReferences(entities, prop, options, ref) {
|
|
685
|
+
getChildReferences(entities, prop, options, ref, populate) {
|
|
686
686
|
const filtered = this.filterCollections(entities, prop.name, options, ref);
|
|
687
687
|
if (prop.kind === ReferenceKind.ONE_TO_MANY) {
|
|
688
688
|
return filtered.map(e => e[prop.name].owner);
|
|
@@ -698,7 +698,7 @@ export class EntityLoader {
|
|
|
698
698
|
return filtered;
|
|
699
699
|
}
|
|
700
700
|
// MANY_TO_ONE or ONE_TO_ONE
|
|
701
|
-
return this.filterReferences(entities, prop.name, options, ref);
|
|
701
|
+
return this.filterReferences(entities, prop.name, options, ref, populate);
|
|
702
702
|
}
|
|
703
703
|
filterCollections(entities, field, options, ref) {
|
|
704
704
|
if (options.refresh) {
|
|
@@ -724,7 +724,7 @@ export class EntityLoader {
|
|
|
724
724
|
}
|
|
725
725
|
return this.isPropertyLoaded(entity[f], r.join('.'));
|
|
726
726
|
}
|
|
727
|
-
filterReferences(entities, field, options, ref) {
|
|
727
|
+
filterReferences(entities, field, options, ref, populate) {
|
|
728
728
|
if (ref) {
|
|
729
729
|
return [];
|
|
730
730
|
}
|
|
@@ -733,13 +733,19 @@ export class EntityLoader {
|
|
|
733
733
|
return children.map(e => Reference.unwrapReference(e[field]));
|
|
734
734
|
}
|
|
735
735
|
if (options.fields) {
|
|
736
|
+
// `:ref` populate children are satisfied by FK/PK and will be loaded lazily — they don't force a parent reload
|
|
737
|
+
const refChildren = new Set((populate?.children ?? [])
|
|
738
|
+
.map(c => c.field.split(':'))
|
|
739
|
+
.filter(parts => parts[1] === 'ref')
|
|
740
|
+
.map(parts => parts[0]));
|
|
736
741
|
return children
|
|
737
742
|
.map(e => Reference.unwrapReference(e[field]))
|
|
738
743
|
.filter(target => {
|
|
739
744
|
const wrapped = helper(target);
|
|
740
745
|
const childFields = options.fields
|
|
741
746
|
.filter(f => f.startsWith(`${field}.`))
|
|
742
|
-
.map(f => f.substring(field.length + 1))
|
|
747
|
+
.map(f => f.substring(field.length + 1))
|
|
748
|
+
.filter(cf => !refChildren.has(cf.split('.')[0]));
|
|
743
749
|
return !wrapped.__initialized || !childFields.every(cf => this.isPropertyLoaded(target, cf));
|
|
744
750
|
});
|
|
745
751
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.0.17-dev.
|
|
3
|
+
"version": "7.0.17-dev.2",
|
|
4
4
|
"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
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
package/utils/Utils.js
CHANGED
|
@@ -141,7 +141,7 @@ export function parseJsonSafe(value) {
|
|
|
141
141
|
/** Collection of general-purpose utility methods used throughout the ORM. */
|
|
142
142
|
export class Utils {
|
|
143
143
|
static PK_SEPARATOR = '~~~';
|
|
144
|
-
static #ORM_VERSION = '7.0.17-dev.
|
|
144
|
+
static #ORM_VERSION = '7.0.17-dev.2';
|
|
145
145
|
/**
|
|
146
146
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
147
147
|
*/
|