@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 CHANGED
@@ -1844,8 +1844,13 @@ export class EntityManager {
1844
1844
  return [];
1845
1845
  }
1846
1846
  const meta = this.metadata.find(entityName);
1847
- // infer populate hint if only `fields` are available
1848
- if (!options.populate && options.fields) {
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
- options.populate = pruneToOneRelations(meta, this.buildFields(options.fields));
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.18",
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.18';
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
  */