@mikro-orm/core 6.3.13-dev.9 → 6.3.14-dev.0

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.
@@ -115,7 +115,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
115
115
  setFlushMode(flushMode?: FlushMode): void;
116
116
  protected processWhere<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: string, where: FilterQuery<Entity>, options: FindOptions<Entity, Hint, Fields, Excludes> | FindOneOptions<Entity, Hint, Fields, Excludes>, type: 'read' | 'update' | 'delete'): Promise<FilterQuery<Entity>>;
117
117
  protected applyDiscriminatorCondition<Entity extends object>(entityName: string, where: FilterQuery<Entity>): FilterQuery<Entity>;
118
- protected createPopulateWhere<Entity extends object>(cond: ObjectQuery<Entity>, options: FindOptions<Entity, any, any, any> | FindOneOptions<Entity, any, any, any>): ObjectQuery<Entity>;
118
+ protected createPopulateWhere<Entity extends object>(cond: ObjectQuery<Entity>, options: FindOptions<Entity, any, any, any> | FindOneOptions<Entity, any, any, any> | CountOptions<Entity, any>): ObjectQuery<Entity>;
119
119
  protected getJoinedFilters<Entity extends object>(meta: EntityMetadata<Entity>, cond: ObjectQuery<Entity>, options: FindOptions<Entity, any, any, any> | FindOneOptions<Entity, any, any, any>): Promise<ObjectQuery<Entity>>;
120
120
  /**
121
121
  * When filters are active on M:1 or 1:1 relations, we need to ref join them eagerly as they might affect the FK value.
package/EntityManager.js CHANGED
@@ -1230,6 +1230,12 @@ class EntityManager {
1230
1230
  await em.tryFlush(entityName, options);
1231
1231
  where = await em.processWhere(entityName, where, options, 'read');
1232
1232
  options.populate = await em.preparePopulate(entityName, options);
1233
+ options = { ...options };
1234
+ // save the original hint value so we know it was infer/all
1235
+ const meta = em.metadata.find(entityName);
1236
+ options._populateWhere = options.populateWhere ?? this.config.get('populateWhere');
1237
+ options.populateWhere = this.createPopulateWhere({ ...where }, options);
1238
+ options.populateFilter = await this.getJoinedFilters(meta, { ...where }, options);
1233
1239
  em.validator.validateParams(where);
1234
1240
  delete options.orderBy;
1235
1241
  const cacheKey = em.cacheKey(entityName, options, 'em.count', where);
@@ -1,9 +1,12 @@
1
1
  import type { AnyEntity } from '../typings';
2
2
  export declare function Embedded<T extends object>(type?: EmbeddedOptions | (() => AnyEntity), options?: EmbeddedOptions): (target: AnyEntity, propertyName: string) => any;
3
+ /** With `absolute` the prefix is set at the root of the entity (regardless of the nesting level) */
4
+ export type EmbeddedPrefixMode = 'absolute' | 'relative';
3
5
  export type EmbeddedOptions = {
4
6
  entity?: string | (() => AnyEntity | AnyEntity[]);
5
7
  type?: string;
6
8
  prefix?: string | boolean;
9
+ prefixMode?: EmbeddedPrefixMode;
7
10
  nullable?: boolean;
8
11
  object?: boolean;
9
12
  array?: boolean;
@@ -2,6 +2,7 @@ import { type Cascade, type LoadStrategy } from '../enums';
2
2
  import type { EntityName, Constructor, CheckCallback, GeneratedColumnCallback, AnyString, AnyEntity } from '../typings';
3
3
  import type { Type, types } from '../types';
4
4
  import type { EntityManager } from '../EntityManager';
5
+ import type { SerializeOptions } from '../serialization/EntitySerializer';
5
6
  export declare function Property<T extends object>(options?: PropertyOptions<T>): (target: any, propertyName: string) => any;
6
7
  export interface PropertyOptions<Owner> {
7
8
  /**
@@ -188,7 +189,7 @@ export interface PropertyOptions<Owner> {
188
189
  *
189
190
  * @see https://mikro-orm.io/docs/serializing#property-serializers
190
191
  */
191
- serializer?: (value: any) => any;
192
+ serializer?: (value: any, options?: SerializeOptions<any>) => any;
192
193
  /**
193
194
  * Specify name of key for the serialized value.
194
195
  */
@@ -86,7 +86,7 @@ export interface FindOptions<Entity, Hint extends string = never, Fields extends
86
86
  * Filter condition for populated relations. This is similar to `populateWhere`, but will produce a `left join`
87
87
  * when nesting the condition. This is used for implementation of joined filters.
88
88
  */
89
- populateFilter?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`;
89
+ populateFilter?: ObjectQuery<Entity>;
90
90
  /** Used for ordering of the populate queries. If not specified, the value of `options.orderBy` is used. */
91
91
  populateOrderBy?: OrderDefinition<Entity>;
92
92
  /** Ordering of the results.Can be an object or array of objects, keys are property names, values are ordering (asc/desc) */
@@ -182,6 +182,8 @@ export interface CountOptions<T extends object, P extends string = never> {
182
182
  having?: QBFilterQuery<T>;
183
183
  cache?: boolean | number | [string, number];
184
184
  populate?: Populate<T, P>;
185
+ populateWhere?: ObjectQuery<T> | PopulateHint | `${PopulateHint}`;
186
+ populateFilter?: ObjectQuery<T>;
185
187
  ctx?: Transaction;
186
188
  connectionType?: ConnectionType;
187
189
  flushMode?: FlushMode | `${FlushMode}`;
@@ -63,6 +63,7 @@ export declare class MetadataDiscovery {
63
63
  private initRelation;
64
64
  private initColumnType;
65
65
  private getMappedType;
66
+ private getPrefix;
66
67
  private initUnsigned;
67
68
  private initIndexes;
68
69
  private getEntityClassOrSchema;
@@ -797,11 +797,8 @@ class MetadataDiscovery {
797
797
  const parentProperty = meta.properties[embeddedProp.embedded?.[0] ?? ''];
798
798
  const object = isParentObject(embeddedProp);
799
799
  this.initFieldName(embeddedProp, rootProperty !== embeddedProp && object);
800
- const prefix = embeddedProp.prefix === false
801
- ? (parentProperty?.prefix || '')
802
- : embeddedProp.prefix === true
803
- ? embeddedProp.embeddedPath?.join('_') ?? embeddedProp.fieldNames[0] + '_'
804
- : embeddedProp.prefix;
800
+ // the prefix of the parent can not be a boolean; it already passed here
801
+ const prefix = this.getPrefix(embeddedProp, parentProperty);
805
802
  for (const prop of Object.values(embeddable.properties)) {
806
803
  const name = (embeddedProp.embeddedPath?.join('_') ?? embeddedProp.fieldNames[0] + '_') + prop.name;
807
804
  meta.properties[name] = Utils_1.Utils.copy(prop, false);
@@ -1231,6 +1228,18 @@ class MetadataDiscovery {
1231
1228
  }
1232
1229
  return this.platform.getMappedType(t);
1233
1230
  }
1231
+ getPrefix(prop, parent) {
1232
+ const { embeddedPath = [], fieldNames, prefix = true, prefixMode } = prop;
1233
+ if (prefix === true) {
1234
+ return (embeddedPath.length ? embeddedPath.join('_') : fieldNames[0]) + '_';
1235
+ }
1236
+ const prefixParent = parent ? this.getPrefix(parent, null) : '';
1237
+ if (prefix === false) {
1238
+ return prefixParent;
1239
+ }
1240
+ const mode = prefixMode ?? this.config.get('embeddables').prefixMode;
1241
+ return mode === 'absolute' ? prefix : prefixParent + prefix;
1242
+ }
1234
1243
  initUnsigned(prop) {
1235
1244
  if (prop.unsigned != null) {
1236
1245
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "6.3.13-dev.9",
3
+ "version": "6.3.14-dev.0",
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
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -64,7 +64,7 @@
64
64
  "esprima": "4.0.1",
65
65
  "fs-extra": "11.2.0",
66
66
  "globby": "11.1.0",
67
- "mikro-orm": "6.3.13-dev.9",
67
+ "mikro-orm": "6.3.14-dev.0",
68
68
  "reflect-metadata": "0.2.2"
69
69
  }
70
70
  }
@@ -118,7 +118,7 @@ class EntitySerializer {
118
118
  if (entity[prop] instanceof Function) {
119
119
  const returnValue = entity[prop]();
120
120
  if (!options.ignoreSerializers && serializer) {
121
- return serializer(returnValue);
121
+ return serializer(returnValue, this.extractChildOptions(options, prop));
122
122
  }
123
123
  return returnValue;
124
124
  }
package/typings.d.ts CHANGED
@@ -7,6 +7,7 @@ import type { Type, types } from './types';
7
7
  import type { Platform } from './platforms';
8
8
  import type { Configuration } from './utils';
9
9
  import type { EntityManager } from './EntityManager';
10
+ import type { EmbeddedPrefixMode } from './decorators/Embedded';
10
11
  import type { EventSubscriber } from './events';
11
12
  import type { FindOneOptions, FindOptions, LoadHint } from './drivers';
12
13
  export type Constructor<T = unknown> = new (...args: any[]) => T;
@@ -319,6 +320,7 @@ export interface EntityProperty<Owner = any, Target = any> {
319
320
  defaultRaw?: string;
320
321
  formula?: (alias: string) => string;
321
322
  prefix?: string | boolean;
323
+ prefixMode?: EmbeddedPrefixMode;
322
324
  embedded?: [EntityKey<Owner>, EntityKey<Owner>];
323
325
  embeddedPath?: string[];
324
326
  embeddable: EntityClass<Owner>;
@@ -366,7 +368,7 @@ export interface EntityProperty<Owner = any, Target = any> {
366
368
  referencedColumnNames: string[];
367
369
  referencedTableName: string;
368
370
  referencedPKs: EntityKey<Owner>[];
369
- serializer?: (value: any) => any;
371
+ serializer?: (value: any, options?: SerializeOptions<any>) => any;
370
372
  serializedName?: string;
371
373
  comment?: string;
372
374
  /** mysql only */
@@ -1,7 +1,7 @@
1
1
  import type { NamingStrategy } from '../naming-strategy';
2
2
  import { FileCacheAdapter, type SyncCacheAdapter, type CacheAdapter } from '../cache';
3
3
  import type { EntityRepository } from '../entity/EntityRepository';
4
- import type { AnyEntity, Constructor, Dictionary, EntityClass, EntityClassGroup, FilterDef, Highlighter, HydratorConstructor, IHydrator, IMigrationGenerator, IPrimaryKey, MaybePromise, MigrationObject, EntityMetadata, EnsureDatabaseOptions, GenerateOptions } from '../typings';
4
+ import type { AnyEntity, Constructor, Dictionary, EntityClass, EntityClassGroup, FilterDef, Highlighter, HydratorConstructor, IHydrator, IMigrationGenerator, IPrimaryKey, MaybePromise, MigrationObject, EntityMetadata, EnsureDatabaseOptions, GenerateOptions, Migration } from '../typings';
5
5
  import { ObjectHydrator } from '../hydration';
6
6
  import { NullHighlighter } from '../utils/NullHighlighter';
7
7
  import { type Logger, type LoggerNamespace, type LoggerOptions } from '../logging';
@@ -11,6 +11,7 @@ import type { EntitySchema } from '../metadata/EntitySchema';
11
11
  import type { MetadataProvider } from '../metadata/MetadataProvider';
12
12
  import type { MetadataStorage } from '../metadata/MetadataStorage';
13
13
  import { ReflectMetadataProvider } from '../metadata/ReflectMetadataProvider';
14
+ import type { EmbeddedPrefixMode } from '../decorators/Embedded';
14
15
  import type { EventSubscriber } from '../events';
15
16
  import type { AssignOptions } from '../entity/EntityAssigner';
16
17
  import type { EntityManagerType, IDatabaseDriver } from '../drivers/IDatabaseDriver';
@@ -97,6 +98,9 @@ export declare class Configuration<D extends IDatabaseDriver = IDatabaseDriver,
97
98
  createForeignKeyConstraints: true;
98
99
  ignoreSchema: never[];
99
100
  };
101
+ embeddables: {
102
+ prefixMode: "absolute";
103
+ };
100
104
  entityGenerator: {
101
105
  bidirectionalRelations: false;
102
106
  identifiedReferences: false;
@@ -253,7 +257,7 @@ export type MigrationsOptions = {
253
257
  emit?: 'js' | 'ts' | 'cjs';
254
258
  generator?: Constructor<IMigrationGenerator>;
255
259
  fileName?: (timestamp: string, name?: string) => string;
256
- migrationsList?: MigrationObject[];
260
+ migrationsList?: (MigrationObject | Constructor<Migration>)[];
257
261
  };
258
262
  export interface SeederOptions {
259
263
  path?: string;
@@ -367,6 +371,9 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
367
371
  ignoreSchema?: string[];
368
372
  managementDbName?: string;
369
373
  };
374
+ embeddables: {
375
+ prefixMode: EmbeddedPrefixMode;
376
+ };
370
377
  entityGenerator: GenerateOptions;
371
378
  metadataCache: {
372
379
  enabled?: boolean;
@@ -92,6 +92,9 @@ class Configuration {
92
92
  createForeignKeyConstraints: true,
93
93
  ignoreSchema: [],
94
94
  },
95
+ embeddables: {
96
+ prefixMode: 'absolute',
97
+ },
95
98
  entityGenerator: {
96
99
  bidirectionalRelations: false,
97
100
  identifiedReferences: false,