@mikro-orm/core 7.0.0-dev.251 → 7.0.0-dev.253

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.
@@ -515,7 +515,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
515
515
  private lockAndPopulate;
516
516
  private buildFields;
517
517
  /** @internal */
518
- preparePopulate<Entity extends object>(entityName: EntityName<Entity>, options: Pick<FindOptions<Entity, any, any, any>, 'populate' | 'strategy' | 'fields' | 'flags' | 'filters' | 'exclude'>, validate?: boolean): Promise<PopulateOptions<Entity>[]>;
518
+ preparePopulate<Entity extends object>(entityName: EntityName<Entity>, options: Pick<FindOptions<Entity, any, any, any>, 'populate' | 'strategy' | 'fields' | 'flags' | 'filters' | 'exclude' | 'populateHints'>, validate?: boolean): Promise<PopulateOptions<Entity>[]>;
519
519
  /**
520
520
  * when the entity is found in identity map, we check if it was partially loaded or we are trying to populate
521
521
  * some additional lazy properties, if so, we reload and merge the data from database
package/EntityManager.js CHANGED
@@ -17,7 +17,7 @@ import { EventType, FlushMode, LoadStrategy, LockMode, PopulateHint, PopulatePat
17
17
  import { EventManager } from './events/EventManager.js';
18
18
  import { TransactionEventBroadcaster } from './events/TransactionEventBroadcaster.js';
19
19
  import { OptimisticLockError, ValidationError } from './errors.js';
20
- import { getLoadingStrategy } from './entity/utils.js';
20
+ import { applyPopulateHints, getLoadingStrategy } from './entity/utils.js';
21
21
  import { TransactionManager } from './utils/TransactionManager.js';
22
22
  /**
23
23
  * The EntityManager is the central access point to ORM functionality. It is a facade to all different ORM subsystems
@@ -1683,12 +1683,15 @@ export class EntityManager {
1683
1683
  throw ValidationError.invalidPropertyName(entityName, invalid.field);
1684
1684
  }
1685
1685
  await this.autoJoinRefsForFilters(meta, { ...options, populate });
1686
- return populate.map(field => {
1686
+ for (const field of populate) {
1687
1687
  // force select-in strategy when populating all relations as otherwise we could cause infinite loops when self-referencing
1688
1688
  const all = field.all ?? (Array.isArray(options.populate) && options.populate.includes('*'));
1689
1689
  field.strategy = all ? LoadStrategy.SELECT_IN : (options.strategy ?? field.strategy);
1690
- return field;
1691
- });
1690
+ }
1691
+ if (options.populateHints) {
1692
+ applyPopulateHints(populate, options.populateHints);
1693
+ }
1694
+ return populate;
1692
1695
  }
1693
1696
  /**
1694
1697
  * when the entity is found in identity map, we check if it was partially loaded or we are trying to populate
@@ -1,4 +1,4 @@
1
- import type { ConnectionType, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName } from '../typings.js';
1
+ import type { ConnectionType, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName, PopulateHintOptions, Prefixes } from '../typings.js';
2
2
  import type { Connection, QueryResult, Transaction } from '../connections/Connection.js';
3
3
  import type { FlushMode, LockMode, QueryOrderMap, QueryFlag, LoadStrategy, PopulateHint, PopulatePath } from '../enums.js';
4
4
  import type { Platform } from '../platforms/Platform.js';
@@ -107,6 +107,10 @@ export interface FindOptions<Entity, Hint extends string = never, Fields extends
107
107
  populateFilter?: ObjectQuery<Entity>;
108
108
  /** Used for ordering of the populate queries. If not specified, the value of `options.orderBy` is used. */
109
109
  populateOrderBy?: OrderDefinition<Entity>;
110
+ /** Per-relation overrides for populate loading behavior. Keys are populate paths (same as used in `populate`). */
111
+ populateHints?: [Hint] extends [never] ? never : {
112
+ [K in Prefixes<Hint>]?: PopulateHintOptions;
113
+ };
110
114
  /** Ordering of the results.Can be an object or array of objects, keys are property names, values are ordering (asc/desc) */
111
115
  orderBy?: OrderDefinition<Entity>;
112
116
  /** Control result caching for this query. Result cache is by default disabled, not to be confused with the identity map. */
package/entity/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { EntityMetadata, PopulateOptions } from '../typings.js';
1
+ import type { EntityMetadata, PopulateHintOptions, PopulateOptions } from '../typings.js';
2
2
  import { LoadStrategy, ReferenceKind } from '../enums.js';
3
3
  /**
4
4
  * @internal
@@ -10,3 +10,8 @@ export declare function expandDotPaths<Entity>(meta: EntityMetadata<Entity>, pop
10
10
  * @internal
11
11
  */
12
12
  export declare function getLoadingStrategy(strategy: LoadStrategy | `${LoadStrategy}`, kind: ReferenceKind): LoadStrategy.SELECT_IN | LoadStrategy.JOINED;
13
+ /**
14
+ * Applies per-relation overrides from `populateHints` to the normalized populate tree.
15
+ * @internal
16
+ */
17
+ export declare function applyPopulateHints<Entity>(populate: PopulateOptions<Entity>[], hints: Record<string, PopulateHintOptions>): void;
package/entity/utils.js CHANGED
@@ -67,3 +67,36 @@ export function getLoadingStrategy(strategy, kind) {
67
67
  }
68
68
  return strategy;
69
69
  }
70
+ /**
71
+ * Applies per-relation overrides from `populateHints` to the normalized populate tree.
72
+ * @internal
73
+ */
74
+ export function applyPopulateHints(populate, hints) {
75
+ for (const [path, hint] of Object.entries(hints)) {
76
+ const entry = findPopulateEntry(populate, path.split('.'));
77
+ if (!entry) {
78
+ continue;
79
+ }
80
+ if (hint.strategy != null) {
81
+ entry.strategy = hint.strategy;
82
+ }
83
+ if (hint.joinType != null) {
84
+ entry.joinType = hint.joinType;
85
+ }
86
+ }
87
+ }
88
+ function findPopulateEntry(populate, parts) {
89
+ let current = populate;
90
+ for (let i = 0; i < parts.length; i++) {
91
+ const entry = current.find(p => p.field.split(':')[0] === parts[i]);
92
+ if (!entry) {
93
+ return undefined;
94
+ }
95
+ if (i === parts.length - 1) {
96
+ return entry;
97
+ }
98
+ current = (entry.children ?? []);
99
+ }
100
+ /* v8 ignore next */
101
+ return undefined;
102
+ }
package/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * @module core
4
4
  */
5
5
  export { EntityMetadata, PrimaryKeyProp, EntityRepositoryType, OptionalProps, EagerProps, HiddenProps, Config } from './typings.js';
6
- export type { CompiledFunctions, Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, RequiredEntityData, CheckCallback, IndexCallback, FormulaCallback, FormulaTable, SchemaTable, SchemaColumns, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, } from './typings.js';
6
+ export type { CompiledFunctions, Constructor, ConnectionType, Dictionary, Primary, IPrimaryKey, ObjectQuery, FilterQuery, IWrappedEntity, EntityName, EntityData, Highlighter, MaybePromise, AnyEntity, EntityClass, EntityProperty, PopulateOptions, Populate, Loaded, New, LoadedReference, LoadedCollection, IMigrator, IMigrationGenerator, MigratorEvent, GetRepository, MigrationObject, DeepPartial, PrimaryProperty, Cast, IsUnknown, EntityDictionary, EntityDTO, MigrationDiff, GenerateOptions, FilterObject, IEntityGenerator, ISeedManager, RequiredEntityData, CheckCallback, IndexCallback, FormulaCallback, FormulaTable, SchemaTable, SchemaColumns, SimpleColumnMeta, Rel, Ref, ScalarRef, EntityRef, ISchemaGenerator, UmzugMigration, MigrateOptions, MigrationResult, MigrationRow, EntityKey, EntityValue, EntityDataValue, FilterKey, EntityType, FromEntityType, Selected, IsSubset, EntityProps, ExpandProperty, ExpandScalar, FilterItemValue, ExpandQuery, Scalar, ExpandHint, FilterValue, MergeLoaded, MergeSelected, TypeConfig, AnyString, ClearDatabaseOptions, CreateSchemaOptions, EnsureDatabaseOptions, UpdateSchemaOptions, DropSchemaOptions, RefreshDatabaseOptions, AutoPath, UnboxArray, MetadataProcessor, ImportsResolver, RequiredNullable, DefineConfig, Opt, Hidden, EntitySchemaWithMeta, InferEntity, CheckConstraint, GeneratedColumnCallback, FilterDef, EntityCtor, Subquery, PopulateHintOptions, Prefixes, } from './typings.js';
7
7
  export * from './enums.js';
8
8
  export * from './errors.js';
9
9
  export * from './exceptions.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
3
  "type": "module",
4
- "version": "7.0.0-dev.251",
4
+ "version": "7.0.0-dev.253",
5
5
  "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.",
6
6
  "exports": {
7
7
  "./package.json": "./package.json",
package/typings.d.ts CHANGED
@@ -151,7 +151,7 @@ declare const __loadHint: unique symbol;
151
151
  * This reflects that loading 'a.b.c' means 'a' and 'a.b' are also loaded.
152
152
  * Special case: '*' returns string to ensure Loaded<T, '*'> is assignable to any Loaded<T, Hint>.
153
153
  */
154
- type Prefixes<S extends string> = S extends '*' ? string : S extends `${infer H}.${infer T}` ? H | `${H}.${Prefixes<T>}` : S;
154
+ export type Prefixes<S extends string> = S extends '*' ? string : S extends `${infer H}.${infer T}` ? H | `${H}.${Prefixes<T>}` : S;
155
155
  export type UnwrapPrimary<T> = T extends Scalar ? T : T extends ReferenceShape<infer U> ? Primary<U> : Primary<T>;
156
156
  type PrimaryPropToType<T, Keys extends (keyof T)[]> = {
157
157
  [Index in keyof Keys]: UnwrapPrimary<T[Keys[Index]]>;
@@ -924,6 +924,10 @@ export type PopulateOptions<T> = {
924
924
  /** When true, ignores `mapToPk` on the property and returns full entity data instead of just PKs. */
925
925
  dataOnly?: boolean;
926
926
  };
927
+ export type PopulateHintOptions = {
928
+ strategy?: LoadStrategy.JOINED | LoadStrategy.SELECT_IN | 'joined' | 'select-in';
929
+ joinType?: 'inner join' | 'left join';
930
+ };
927
931
  type ExtractType<T> = T extends CollectionShape<infer U> ? U : T extends ReferenceShape<infer U> ? U : T extends Ref<infer U> ? U : T extends readonly (infer U)[] ? U : T;
928
932
  type ExtractStringKeys<T> = {
929
933
  [K in keyof T]-?: CleanKeys<T, K>;
package/utils/Utils.js CHANGED
@@ -123,7 +123,7 @@ export function parseJsonSafe(value) {
123
123
  }
124
124
  export class Utils {
125
125
  static PK_SEPARATOR = '~~~';
126
- static #ORM_VERSION = '7.0.0-dev.251';
126
+ static #ORM_VERSION = '7.0.0-dev.253';
127
127
  /**
128
128
  * Checks if the argument is instance of `Object`. Returns false for arrays.
129
129
  */