@mikro-orm/core 7.1.0-dev.18 → 7.1.0-dev.19
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 +17 -3
- package/metadata/MetadataDiscovery.d.ts +1 -0
- package/metadata/MetadataDiscovery.js +22 -1
- package/package.json +1 -1
- package/utils/Utils.js +1 -1
package/EntityManager.js
CHANGED
|
@@ -1844,8 +1844,13 @@ export class EntityManager {
|
|
|
1844
1844
|
return [];
|
|
1845
1845
|
}
|
|
1846
1846
|
const meta = this.metadata.find(entityName);
|
|
1847
|
-
// infer populate
|
|
1848
|
-
|
|
1847
|
+
// infer populate hints from `fields` when present; merge with explicit `populate` if both are set
|
|
1848
|
+
const fields = options.fields ? this.buildFields(options.fields) : undefined;
|
|
1849
|
+
const populateArray = Array.isArray(options.populate) ? options.populate : undefined;
|
|
1850
|
+
const hasNestedFields = fields?.some(f => f.includes('.')) ?? false;
|
|
1851
|
+
const shouldInfer = fields !== undefined && options.populate === undefined;
|
|
1852
|
+
const shouldMerge = fields !== undefined && populateArray !== undefined && populateArray.length > 0 && hasNestedFields;
|
|
1853
|
+
if (shouldInfer || shouldMerge) {
|
|
1849
1854
|
// we need to prune the `populate` hint from to-one relations, as partially loading them does not require their population, we want just the FK
|
|
1850
1855
|
const pruneToOneRelations = (meta, fields) => {
|
|
1851
1856
|
const ret = [];
|
|
@@ -1879,7 +1884,16 @@ export class EntityManager {
|
|
|
1879
1884
|
}
|
|
1880
1885
|
return Utils.unique(ret);
|
|
1881
1886
|
};
|
|
1882
|
-
|
|
1887
|
+
const fromFields = pruneToOneRelations(meta, fields);
|
|
1888
|
+
if (shouldInfer) {
|
|
1889
|
+
options.populate = fromFields;
|
|
1890
|
+
}
|
|
1891
|
+
else {
|
|
1892
|
+
// with an explicit populate, only nested paths (e.g. `item.id`) need to be merged in — they
|
|
1893
|
+
// require a JOIN to access sub-fields, whereas bare names are already handled by the driver
|
|
1894
|
+
const extras = fromFields.filter(f => f.includes('.'));
|
|
1895
|
+
options.populate = [...populateArray, ...extras];
|
|
1896
|
+
}
|
|
1883
1897
|
}
|
|
1884
1898
|
if (!options.populate) {
|
|
1885
1899
|
const populate = this.#entityLoader.normalizePopulate(entityName, [], options.strategy, true, options.exclude);
|
|
@@ -76,6 +76,7 @@ export declare class MetadataDiscovery {
|
|
|
76
76
|
private initPolyEmbeddables;
|
|
77
77
|
private initPolymorphicRelation;
|
|
78
78
|
private initEmbeddables;
|
|
79
|
+
private sameRelationTargetRoot;
|
|
79
80
|
private initSingleTableInheritance;
|
|
80
81
|
/**
|
|
81
82
|
* First pass of TPT initialization: sets up hierarchy relationships
|
|
@@ -1259,6 +1259,16 @@ export class MetadataDiscovery {
|
|
|
1259
1259
|
});
|
|
1260
1260
|
}
|
|
1261
1261
|
}
|
|
1262
|
+
sameRelationTargetRoot(rootProp, prop) {
|
|
1263
|
+
if (!rootProp || rootProp.kind !== prop.kind) {
|
|
1264
|
+
return false;
|
|
1265
|
+
}
|
|
1266
|
+
if (prop.kind !== ReferenceKind.MANY_TO_ONE && prop.kind !== ReferenceKind.ONE_TO_ONE) {
|
|
1267
|
+
return false;
|
|
1268
|
+
}
|
|
1269
|
+
const aRoot = this.#metadata.getByClassName(prop.type, false)?.root;
|
|
1270
|
+
return aRoot != null && aRoot === this.#metadata.getByClassName(rootProp.type, false)?.root;
|
|
1271
|
+
}
|
|
1262
1272
|
initSingleTableInheritance(meta, metadata) {
|
|
1263
1273
|
if (meta.root !== meta && !meta.__processed) {
|
|
1264
1274
|
meta.root = metadata.find(m => m.class === meta.root.class);
|
|
@@ -1299,11 +1309,16 @@ export class MetadataDiscovery {
|
|
|
1299
1309
|
Object.values(meta.properties).forEach(prop => {
|
|
1300
1310
|
const newProp = { ...prop };
|
|
1301
1311
|
const rootProp = meta.root.properties[prop.name];
|
|
1312
|
+
// A child that narrows a relation to a subclass of the root's declared
|
|
1313
|
+
// target (same STI hierarchy) shares the FK column with the root; treat
|
|
1314
|
+
// that as matching so the rename branch below doesn't run (which would
|
|
1315
|
+
// crash — `targetMeta` is only populated later, in `initRelation`).
|
|
1316
|
+
const narrowedRelationOverride = rootProp != null && rootProp.type !== prop.type && this.sameRelationTargetRoot(rootProp, prop);
|
|
1302
1317
|
// stiMerged is set during inlineProperties when a property was merged
|
|
1303
1318
|
// from multiple polymorphic variants with different types. The flag is
|
|
1304
1319
|
// cleared implicitly when the first child claims the root property via
|
|
1305
1320
|
// addProperty below, so subsequent children correctly trigger renaming.
|
|
1306
|
-
const typesMatch = rootProp?.type === prop.type || rootProp?.stiMerged === true;
|
|
1321
|
+
const typesMatch = rootProp?.type === prop.type || rootProp?.stiMerged === true || narrowedRelationOverride;
|
|
1307
1322
|
if (rootProp &&
|
|
1308
1323
|
(!typesMatch ||
|
|
1309
1324
|
(rootProp.fieldNames && prop.fieldNames && !compareArrays(rootProp.fieldNames, prop.fieldNames)))) {
|
|
@@ -1353,6 +1368,12 @@ export class MetadataDiscovery {
|
|
|
1353
1368
|
}
|
|
1354
1369
|
newProp.nullable = true;
|
|
1355
1370
|
newProp.inherited = !rootProp;
|
|
1371
|
+
// For narrowed relation overrides, keep the root's declaration intact so
|
|
1372
|
+
// the full target union (e.g. `Food`) is preserved for populates from the
|
|
1373
|
+
// abstract root — otherwise the last child processed would win.
|
|
1374
|
+
if (narrowedRelationOverride) {
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1356
1377
|
meta.root.addProperty(newProp);
|
|
1357
1378
|
});
|
|
1358
1379
|
meta.tableName = meta.root.tableName;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.1.0-dev.
|
|
3
|
+
"version": "7.1.0-dev.19",
|
|
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.1.0-dev.
|
|
144
|
+
static #ORM_VERSION = '7.1.0-dev.19';
|
|
145
145
|
/**
|
|
146
146
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
147
147
|
*/
|