@mikro-orm/core 7.0.3-dev.2 → 7.0.3-dev.20

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.
@@ -61,7 +61,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
61
61
  /**
62
62
  * Finds all entities matching your `where` query. You can pass additional options via the `options` parameter.
63
63
  */
64
- find<Entity extends object, Hint extends string = never, Fields extends string = PopulatePath.ALL, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
64
+ find<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
65
65
  /**
66
66
  * Finds all entities and returns an async iterable (async generator) that yields results one by one.
67
67
  * The results are merged and mapped to entity instances, without adding them to the identity map.
@@ -79,11 +79,11 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
79
79
  * }
80
80
  * ```
81
81
  */
82
- stream<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: EntityName<Entity>, options?: StreamOptions<NoInfer<Entity>, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
82
+ stream<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, options?: StreamOptions<NoInfer<Entity>, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
83
83
  /**
84
84
  * Finds all entities of given type, optionally matching the `where` condition provided in the `options` parameter.
85
85
  */
86
- findAll<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: EntityName<Entity>, options?: FindAllOptions<NoInfer<Entity>, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
86
+ findAll<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, options?: FindAllOptions<NoInfer<Entity>, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
87
87
  private getPopulateWhere;
88
88
  /**
89
89
  * Registers global filter to this entity manager. Global filters are enabled by default (unless disabled via last parameter).
@@ -110,7 +110,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
110
110
  }): T;
111
111
  /** Sets the flush mode for this EntityManager. Pass `undefined` to reset to the global default. */
112
112
  setFlushMode(flushMode?: FlushMode | `${FlushMode}`): void;
113
- protected processWhere<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<Entity>, options: FindOptions<Entity, Hint, Fields, Excludes> | FindOneOptions<Entity, Hint, Fields, Excludes>, type: 'read' | 'update' | 'delete'): Promise<FilterQuery<Entity>>;
113
+ protected processWhere<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<Entity>, options: FindOptions<Entity, Hint, Fields, Excludes> | FindOneOptions<Entity, Hint, Fields, Excludes>, type: 'read' | 'update' | 'delete'): Promise<FilterQuery<Entity>>;
114
114
  protected processUnionWhere<Entity extends object, Hint extends string = never>(entityName: EntityName<Entity>, options: FindOptions<Entity, Hint, any, any> | CountOptions<Entity, Hint> | UpdateOptions<Entity> | DeleteOptions<Entity>, type: 'read' | 'update' | 'delete'): Promise<void>;
115
115
  protected applyDiscriminatorCondition<Entity extends object>(entityName: EntityName<Entity>, where: FilterQuery<Entity>): FilterQuery<Entity>;
116
116
  protected createPopulateWhere<Entity extends object>(cond: ObjectQuery<Entity>, options: FindOptions<Entity, any, any, any> | FindOneOptions<Entity, any, any, any> | CountOptions<Entity, any>): ObjectQuery<Entity>;
@@ -130,7 +130,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
130
130
  * Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as tuple
131
131
  * where the first element is the array of entities, and the second is the count.
132
132
  */
133
- findAndCount<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<[Loaded<Entity, Hint, Fields, Excludes>[], number]>;
133
+ findAndCount<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<[Loaded<Entity, Hint, Fields, Excludes>[], number]>;
134
134
  /**
135
135
  * Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as {@apilink Cursor} object.
136
136
  * Supports `before`, `after`, `first` and `last` options while disallowing `limit` and `offset`. Explicit `orderBy` option
@@ -187,30 +187,30 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
187
187
  * }
188
188
  * ```
189
189
  */
190
- findByCursor<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never, IncludeCount extends boolean = true>(entityName: EntityName<Entity>, options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
190
+ findByCursor<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true>(entityName: EntityName<Entity>, options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
191
191
  /**
192
192
  * Refreshes the persistent state of an entity from the database, overriding any local changes that have not yet been
193
193
  * persisted. Returns the same entity instance (same object reference), but re-hydrated. If the entity is no longer
194
194
  * in database, the method throws an error just like `em.findOneOrFail()` (and respects the same config options).
195
195
  */
196
- refreshOrFail<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entity: Entity, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>): Promise<MergeLoaded<Entity, Naked, Hint, Fields, Excludes, true>>;
196
+ refreshOrFail<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entity: Entity, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>): Promise<MergeLoaded<Entity, Naked, Hint, Fields, Excludes, true>>;
197
197
  /**
198
198
  * Refreshes the persistent state of an entity from the database, overriding any local changes that have not yet been
199
199
  * persisted. Returns the same entity instance (same object reference), but re-hydrated. If the entity is no longer
200
200
  * in database, the method returns `null`.
201
201
  */
202
- refresh<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entity: Entity, options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<MergeLoaded<Entity, Naked, Hint, Fields, Excludes, true> | null>;
202
+ refresh<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entity: Entity, options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<MergeLoaded<Entity, Naked, Hint, Fields, Excludes, true> | null>;
203
203
  /**
204
204
  * Finds first entity matching your `where` query.
205
205
  */
206
- findOne<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
206
+ findOne<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
207
207
  /**
208
208
  * Finds first entity matching your `where` query. If nothing found, it will throw an error.
209
209
  * If the `strict` option is specified and nothing is found or more than one matching entity is found, it will throw an error.
210
210
  * You can override the factory for creating this method via `options.failHandler` locally
211
211
  * or via `Configuration.findOneOrFailHandler` (`findExactlyOneOrFailHandler` when specifying `strict`) globally.
212
212
  */
213
- findOneOrFail<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
213
+ findOneOrFail<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(entityName: EntityName<Entity>, where: FilterQuery<NoInfer<Entity>>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
214
214
  /**
215
215
  * Creates or updates the entity, based on whether it is already present in the database.
216
216
  * This method performs an `insert on conflict merge` query ensuring the database is in sync, returning a managed
@@ -512,7 +512,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
512
512
  * when the entity is found in identity map, we check if it was partially loaded or we are trying to populate
513
513
  * some additional lazy properties, if so, we reload and merge the data from database
514
514
  */
515
- protected shouldRefresh<T extends object, P extends string = never, F extends string = '*', E extends string = never>(meta: EntityMetadata<T>, entity: T, options: FindOneOptions<T, P, F, E>): boolean;
515
+ protected shouldRefresh<T extends object, P extends string = never, F extends string = never, E extends string = never>(meta: EntityMetadata<T>, entity: T, options: FindOneOptions<T, P, F, E>): boolean;
516
516
  protected prepareOptions(options: FindOptions<any, any, any, any> | FindOneOptions<any, any, any, any> | CountOptions<any, any>): void;
517
517
  /**
518
518
  * @internal
package/EntityManager.js CHANGED
@@ -405,8 +405,22 @@ export class EntityManager {
405
405
  continue;
406
406
  }
407
407
  options = { ...options, filters: QueryHelper.mergePropertyFilters(prop.filters, options.filters) };
408
- const cond = await this.applyFilters(prop.targetMeta.class, {}, options.filters, 'read', options);
409
- if (!Utils.isEmpty(cond)) {
408
+ // For polymorphic relations, check all targets for filters (not just the first targetMeta)
409
+ let hasActiveFilter = false;
410
+ if (prop.polymorphic && prop.polymorphTargets?.length) {
411
+ for (const targetMeta of prop.polymorphTargets) {
412
+ const cond = await this.applyFilters(targetMeta.class, {}, options.filters, 'read', options);
413
+ if (!Utils.isEmpty(cond)) {
414
+ hasActiveFilter = true;
415
+ break;
416
+ }
417
+ }
418
+ }
419
+ else {
420
+ const cond = await this.applyFilters(prop.targetMeta.class, {}, options.filters, 'read', options);
421
+ hasActiveFilter = !Utils.isEmpty(cond);
422
+ }
423
+ if (hasActiveFilter) {
410
424
  const populated = options.populate.filter(({ field }) => field.split(':')[0] === prop.name);
411
425
  let found = false;
412
426
  for (const hint of populated) {
package/README.md CHANGED
@@ -64,7 +64,7 @@ export class Book extends BookSchema.class {}
64
64
  BookSchema.setClass(Book);
65
65
  ```
66
66
 
67
- You can also define entities using [decorators](https://mikro-orm.io/docs/defining-entities) or [`EntitySchema`](https://mikro-orm.io/docs/entity-schema). See the [defining entities guide](https://mikro-orm.io/docs/defining-entities) for all options.
67
+ You can also define entities using [decorators](https://mikro-orm.io/docs/using-decorators) or [`EntitySchema`](https://mikro-orm.io/docs/define-entity#entityschema-low-level-api). See the [defining entities guide](https://mikro-orm.io/docs/defining-entities) for all options.
68
68
 
69
69
  ### Initialize and Use
70
70
 
@@ -21,8 +21,8 @@ export declare abstract class DatabaseDriver<C extends Connection> implements ID
21
21
  protected comparator: EntityComparator;
22
22
  protected metadata: MetadataStorage;
23
23
  protected constructor(config: Configuration, dependencies: string[]);
24
- abstract find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
25
- abstract findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
24
+ abstract find<T extends object, P extends string = never, F extends string = never, E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
25
+ abstract findOne<T extends object, P extends string = never, F extends string = never, E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
26
26
  abstract nativeInsert<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
27
27
  abstract nativeInsertMany<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>, transform?: (sql: string) => string): Promise<QueryResult<T>>;
28
28
  abstract nativeUpdate<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
@@ -33,11 +33,11 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
33
33
  /**
34
34
  * Finds selection of entities
35
35
  */
36
- find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
36
+ find<T extends object, P extends string = never, F extends string = never, E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
37
37
  /**
38
38
  * Finds single entity (table row, document)
39
39
  */
40
- findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
40
+ findOne<T extends object, P extends string = never, F extends string = never, E extends string = never>(entityName: EntityName<T>, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
41
41
  /** Finds entities backed by a virtual (expression-based) definition. */
42
42
  findVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
43
43
  /** Returns an async iterator that streams query results one entity at a time. */
@@ -100,11 +100,11 @@ export type OrderDefinition<T> = (QueryOrderMap<T> & {
100
100
  0?: never;
101
101
  }) | QueryOrderMap<T>[];
102
102
  /** Options for `em.findAll()`, extends FindOptions with an optional `where` clause. */
103
- export interface FindAllOptions<T, P extends string = never, F extends string = '*', E extends string = never> extends FindOptions<T, P, F, E> {
103
+ export interface FindAllOptions<T, P extends string = never, F extends string = never, E extends string = never> extends FindOptions<T, P, F, E> {
104
104
  where?: FilterQuery<T>;
105
105
  }
106
106
  /** Options for streaming query results via `em.stream()`. */
107
- export interface StreamOptions<Entity, Populate extends string = never, Fields extends string = '*', Exclude extends string = never> extends Omit<FindAllOptions<Entity, Populate, Fields, Exclude>, 'cache' | 'before' | 'after' | 'first' | 'last' | 'overfetch' | 'strategy'> {
107
+ export interface StreamOptions<Entity, Populate extends string = never, Fields extends string = never, Exclude extends string = never> extends Omit<FindAllOptions<Entity, Populate, Fields, Exclude>, 'cache' | 'before' | 'after' | 'first' | 'last' | 'overfetch' | 'strategy'> {
108
108
  /**
109
109
  * When populating to-many relations, the ORM streams fully merged entities instead of yielding every row.
110
110
  * You can opt out of this behavior by specifying `mergeResults: false`. This will yield every row from
@@ -119,13 +119,13 @@ export interface StreamOptions<Entity, Populate extends string = never, Fields e
119
119
  /** Configuration for enabling/disabling named filters on a query. */
120
120
  export type FilterOptions = Dictionary<boolean | Dictionary> | string[] | boolean;
121
121
  /** Specifies which relations to populate and which fields to select or exclude. */
122
- export interface LoadHint<Entity, Hint extends string = never, Fields extends string = PopulatePath.ALL, Excludes extends string = never> {
122
+ export interface LoadHint<Entity, Hint extends string = never, Fields extends string = never, Excludes extends string = never> {
123
123
  populate?: Populate<Entity, Hint>;
124
124
  fields?: readonly AutoPath<Entity, Fields, `${PopulatePath.ALL}`>[];
125
125
  exclude?: readonly AutoPath<Entity, Excludes>[];
126
126
  }
127
127
  /** Options for `em.find()` queries, including population, ordering, pagination, and locking. */
128
- export interface FindOptions<Entity, Hint extends string = never, Fields extends string = PopulatePath.ALL, Excludes extends string = never> extends LoadHint<Entity, Hint, Fields, Excludes> {
128
+ export interface FindOptions<Entity, Hint extends string = never, Fields extends string = never, Excludes extends string = never> extends LoadHint<Entity, Hint, Fields, Excludes> {
129
129
  /**
130
130
  * Where condition for populated relations. This will have no effect on the root entity.
131
131
  * With `select-in` strategy, this is applied only to the populate queries.
@@ -227,16 +227,16 @@ export interface FindOptions<Entity, Hint extends string = never, Fields extends
227
227
  em?: EntityManager;
228
228
  }
229
229
  /** Options for cursor-based pagination via `em.findByCursor()`. */
230
- export interface FindByCursorOptions<T extends object, P extends string = never, F extends string = '*', E extends string = never, I extends boolean = true> extends Omit<FindAllOptions<T, P, F, E>, 'limit' | 'offset'> {
230
+ export interface FindByCursorOptions<T extends object, P extends string = never, F extends string = never, E extends string = never, I extends boolean = true> extends Omit<FindAllOptions<T, P, F, E>, 'limit' | 'offset'> {
231
231
  includeCount?: I;
232
232
  }
233
233
  /** Options for `em.findOne()`, extends FindOptions with optimistic lock version support. */
234
- export interface FindOneOptions<T, P extends string = never, F extends string = '*', E extends string = never> extends Omit<FindOptions<T, P, F, E>, 'limit' | 'lockMode'> {
234
+ export interface FindOneOptions<T, P extends string = never, F extends string = never, E extends string = never> extends Omit<FindOptions<T, P, F, E>, 'limit' | 'lockMode'> {
235
235
  lockMode?: LockMode;
236
236
  lockVersion?: number | Date;
237
237
  }
238
238
  /** Options for `em.findOneOrFail()`, adds a custom error handler for missing entities. */
239
- export interface FindOneOrFailOptions<T extends object, P extends string = never, F extends string = '*', E extends string = never> extends FindOneOptions<T, P, F, E> {
239
+ export interface FindOneOrFailOptions<T extends object, P extends string = never, F extends string = never, E extends string = never> extends FindOneOptions<T, P, F, E> {
240
240
  failHandler?: (entityName: string, where: Dictionary | IPrimaryKey | any) => Error;
241
241
  strict?: boolean;
242
242
  }
@@ -84,7 +84,7 @@ export declare abstract class BaseEntity {
84
84
  /** Assigns the given data to this entity, updating its properties and relations. */
85
85
  assign<Entity extends this, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Convert extends boolean = false, Data extends EntityData<Naked, Convert> | Partial<EntityDTO<Naked>> = EntityData<Naked, Convert> | Partial<EntityDTO<Naked>>>(data: Data & IsSubset<EntityData<Naked>, Data>, options?: AssignOptions<Convert>): MergeSelected<Entity, Naked, keyof Data & string>;
86
86
  /** Initializes (refreshes) the entity by reloading it from the database. Returns null if not found. */
87
- init<Entity extends this = this, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
87
+ init<Entity extends this = this, Hint extends string = never, Fields extends string = never, Excludes extends string = never>(options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
88
88
  /** Returns the database schema this entity belongs to. */
89
89
  getSchema(): string | undefined;
90
90
  /** Sets the database schema for this entity. */
@@ -177,7 +177,7 @@ export declare class Collection<T extends object, O extends object = object> {
177
177
  protected incrementCount(value: number): void;
178
178
  }
179
179
  /** Options for initializing a collection via `init()` or `load()`. */
180
- export interface InitCollectionOptions<T, P extends string = never, F extends string = '*', E extends string = never> extends EntityLoaderOptions<T, F, E> {
180
+ export interface InitCollectionOptions<T, P extends string = never, F extends string = never, E extends string = never> extends EntityLoaderOptions<T, F, E> {
181
181
  /** Whether to use the dataloader for batching collection loads. */
182
182
  dataloader?: boolean;
183
183
  /** Relations to populate on the loaded items. */
@@ -4,7 +4,7 @@ import { LoadStrategy, type LockMode, type PopulateHint, PopulatePath, type Quer
4
4
  import type { FilterOptions } from '../drivers/IDatabaseDriver.js';
5
5
  import type { LoggingOptions } from '../logging/Logger.js';
6
6
  /** Options for controlling how relations are loaded by the EntityLoader. */
7
- export interface EntityLoaderOptions<Entity, Fields extends string = PopulatePath.ALL, Excludes extends string = never> {
7
+ export interface EntityLoaderOptions<Entity, Fields extends string = never, Excludes extends string = never> {
8
8
  /** Select specific fields to load (partial loading). */
9
9
  fields?: readonly AutoPath<Entity, Fields, `${PopulatePath.ALL}`>[];
10
10
  /** Fields to exclude from loading. */
@@ -46,7 +46,7 @@ export declare class EntityLoader {
46
46
  * Loads specified relations in batch.
47
47
  * This will execute one query for each relation, that will populate it on all the specified entities.
48
48
  */
49
- populate<Entity extends object, Fields extends string = PopulatePath.ALL>(entityName: EntityName<Entity>, entities: Entity[], populate: PopulateOptions<Entity>[] | boolean, options: EntityLoaderOptions<Entity, Fields>): Promise<void>;
49
+ populate<Entity extends object, Fields extends string = never>(entityName: EntityName<Entity>, entities: Entity[], populate: PopulateOptions<Entity>[] | boolean, options: EntityLoaderOptions<Entity, Fields>): Promise<void>;
50
50
  /** Normalizes populate hints into a structured array of PopulateOptions, expanding dot paths and eager relations. */
51
51
  normalizePopulate<Entity>(entityName: EntityName<Entity>, populate: (PopulateOptions<Entity> | boolean)[] | PopulateOptions<Entity> | boolean, strategy?: LoadStrategy, lookup?: boolean, exclude?: string[]): PopulateOptions<Entity>[];
52
52
  private setSerializationContext;
@@ -13,13 +13,13 @@ export declare class EntityRepository<Entity extends object> {
13
13
  /**
14
14
  * Finds first entity matching your `where` query.
15
15
  */
16
- findOne<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
16
+ findOne<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
17
17
  /**
18
18
  * Finds first entity matching your `where` query. If nothing is found, it will throw an error.
19
19
  * You can override the factory for creating this method via `options.failHandler` locally
20
20
  * or via `Configuration.findOneOrFailHandler` globally.
21
21
  */
22
- findOneOrFail<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
22
+ findOneOrFail<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOneOrFailOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>>;
23
23
  /**
24
24
  * Creates or updates the entity, based on whether it is already present in the database.
25
25
  * This method performs an `insert on conflict merge` query ensuring the database is in sync, returning a managed
@@ -72,24 +72,24 @@ export declare class EntityRepository<Entity extends object> {
72
72
  /**
73
73
  * Finds all entities matching your `where` query. You can pass additional options via the `options` parameter.
74
74
  */
75
- find<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
75
+ find<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
76
76
  /**
77
77
  * Calls `em.find()` and `em.count()` with the same arguments (where applicable) and returns the results as tuple
78
78
  * where first element is the array of entities, and the second is the count.
79
79
  */
80
- findAndCount<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<[Loaded<Entity, Hint, Fields, Excludes>[], number]>;
80
+ findAndCount<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(where: FilterQuery<Entity>, options?: FindOptions<Entity, Hint, Fields, Excludes>): Promise<[Loaded<Entity, Hint, Fields, Excludes>[], number]>;
81
81
  /**
82
82
  * @inheritDoc EntityManager.findByCursor
83
83
  */
84
- findByCursor<Hint extends string = never, Fields extends string = '*', Excludes extends string = never, IncludeCount extends boolean = true>(options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
84
+ findByCursor<Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true>(options: FindByCursorOptions<Entity, Hint, Fields, Excludes, IncludeCount>): Promise<Cursor<Entity, Hint, Fields, Excludes, IncludeCount>>;
85
85
  /**
86
86
  * Finds all entities of given type. You can pass additional options via the `options` parameter.
87
87
  */
88
- findAll<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(options?: FindAllOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
88
+ findAll<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(options?: FindAllOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes>[]>;
89
89
  /**
90
90
  * @inheritDoc EntityManager.stream
91
91
  */
92
- stream<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(options?: StreamOptions<Entity, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
92
+ stream<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(options?: StreamOptions<Entity, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
93
93
  /**
94
94
  * @inheritDoc EntityManager.insert
95
95
  */
@@ -32,12 +32,12 @@ export declare class Reference<T extends object> {
32
32
  * If the entity is not found in the database (e.g. it was deleted in the meantime, or currently active filters disallow loading of it)
33
33
  * the method returns `null`. Use `loadOrFail()` if you want an error to be thrown in such a case.
34
34
  */
35
- load<TT extends T, P extends string = never, F extends string = '*', E extends string = never>(options?: LoadReferenceOptions<TT, P, F, E>): Promise<Loaded<TT, P, F, E> | null>;
35
+ load<TT extends T, P extends string = never, F extends string = never, E extends string = never>(options?: LoadReferenceOptions<TT, P, F, E>): Promise<Loaded<TT, P, F, E> | null>;
36
36
  /**
37
37
  * Ensures the underlying entity is loaded first (without reloading it if it already is loaded).
38
38
  * Returns the entity or throws an error just like `em.findOneOrFail()` (and respects the same config options).
39
39
  */
40
- loadOrFail<TT extends T, P extends string = never, F extends string = '*', E extends string = never>(options?: LoadReferenceOrFailOptions<TT, P, F, E>): Promise<Loaded<TT, P, F, E>>;
40
+ loadOrFail<TT extends T, P extends string = never, F extends string = never, E extends string = never>(options?: LoadReferenceOrFailOptions<TT, P, F, E>): Promise<Loaded<TT, P, F, E>>;
41
41
  private set;
42
42
  /** Returns the underlying entity without checking initialization state. */
43
43
  unwrap(): T;
@@ -80,12 +80,12 @@ export declare class ScalarReference<Value> {
80
80
  isInitialized(): boolean;
81
81
  }
82
82
  /** Options for `Reference.load()` to control how the referenced entity is loaded. */
83
- export interface LoadReferenceOptions<T extends object, P extends string = never, F extends string = '*', E extends string = never> extends FindOneOptions<T, P, F, E> {
83
+ export interface LoadReferenceOptions<T extends object, P extends string = never, F extends string = never, E extends string = never> extends FindOneOptions<T, P, F, E> {
84
84
  /** Whether to use the dataloader for batching reference loads. */
85
85
  dataloader?: boolean;
86
86
  }
87
87
  /** Options for `Reference.loadOrFail()` which throws when the entity is not found. */
88
- export interface LoadReferenceOrFailOptions<T extends object, P extends string = never, F extends string = '*', E extends string = never> extends FindOneOrFailOptions<T, P, F, E> {
88
+ export interface LoadReferenceOrFailOptions<T extends object, P extends string = never, F extends string = never, E extends string = never> extends FindOneOrFailOptions<T, P, F, E> {
89
89
  /** Whether to use the dataloader for batching reference loads. */
90
90
  dataloader?: boolean;
91
91
  }
@@ -48,7 +48,7 @@ export declare class WrappedEntity<Entity extends object> {
48
48
  /** Marks the entity as populated or not for serialization purposes. */
49
49
  populated(populated?: boolean | undefined): void;
50
50
  /** Sets the serialization context with populate hints, field selections, and exclusions. */
51
- setSerializationContext<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(options: LoadHint<Entity, Hint, Fields, Exclude>): void;
51
+ setSerializationContext<Hint extends string = never, Fields extends string = never, Exclude extends string = never>(options: LoadHint<Entity, Hint, Fields, Exclude>): void;
52
52
  /** Returns a Reference wrapper for this entity, creating one if it does not already exist. */
53
53
  toReference(): Ref<Entity> & LoadedReference<Loaded<Entity, AddEager<Entity>>>;
54
54
  /** Converts the entity to a plain object representation, optionally excluding specified fields. */
@@ -62,7 +62,7 @@ export declare class WrappedEntity<Entity extends object> {
62
62
  /** Assigns the given data to this entity, updating its properties and relations. */
63
63
  assign<Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Convert extends boolean = false, Data extends EntityData<Naked, Convert> | Partial<EntityDTO<Naked>> = EntityData<Naked, Convert> | Partial<EntityDTO<Naked>>>(data: Data & IsSubset<EntityData<Naked>, Data>, options?: AssignOptions<Convert>): MergeSelected<Entity, Naked, keyof Data & string>;
64
64
  /** Initializes (refreshes) the entity by reloading it from the database. Returns null if not found. */
65
- init<Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
65
+ init<Hint extends string = never, Fields extends string = never, Excludes extends string = never>(options?: FindOneOptions<Entity, Hint, Fields, Excludes>): Promise<Loaded<Entity, Hint, Fields, Excludes> | null>;
66
66
  /** Loads the specified relations on this entity. */
67
67
  populate<Hint extends string = never, Fields extends string = never>(populate: AutoPath<Entity, Hint, PopulatePath.ALL>[] | false, options?: EntityLoaderOptions<Entity, Fields>): Promise<Loaded<Entity, Hint>>;
68
68
  /** Returns whether this entity has a primary key value set. */
@@ -1,5 +1,5 @@
1
1
  import type { EntityManager } from '../EntityManager.js';
2
- import type { ColumnType, PropertyOptions, ReferenceOptions, EnumOptions, EmbeddedOptions, ManyToOneOptions, OneToManyOptions, OneToOneOptions, ManyToManyOptions } from '../metadata/types.js';
2
+ import type { ColumnType, PropertyOptions, ReferenceOptions, EnumOptions, EmbeddedOptions, ManyToOneOptions, OneToManyOptions, OneToOneOptions, ManyToManyOptions, IndexColumnOptions } from '../metadata/types.js';
3
3
  import type { AnyString, GeneratedColumnCallback, Constructor, CheckCallback, FilterQuery, EntityName, Dictionary, EntityMetadata, PrimaryKeyProp, EntityRepositoryType, Hidden, Opt, Primary, EntityClass, EntitySchemaWithMeta, InferEntity, MaybeReturnType, Ref, IndexCallback, FormulaCallback, EntityCtor, IsNever, IWrappedEntity, DefineConfig, Config } from '../typings.js';
4
4
  import type { Raw } from '../utils/RawQueryFragment.js';
5
5
  import type { ScalarReference } from './Reference.js';
@@ -12,7 +12,7 @@ import type { Collection } from './Collection.js';
12
12
  import type { FilterOptions } from '../drivers/IDatabaseDriver.js';
13
13
  /** Union of all option keys supported across all property definition types (scalar, enum, embedded, relations). */
14
14
  export type UniversalPropertyKeys = keyof PropertyOptions<any> | keyof EnumOptions<any> | keyof EmbeddedOptions<any, any> | keyof ReferenceOptions<any, any> | keyof ManyToOneOptions<any, any> | keyof OneToManyOptions<any, any> | keyof OneToOneOptions<any, any> | keyof ManyToManyOptions<any, any>;
15
- type BuilderExtraKeys = '~options' | '~type' | '$type';
15
+ type BuilderExtraKeys = '~options' | '~type' | '$type' | 'strictNullable';
16
16
  type ExcludeKeys = 'entity' | 'items';
17
17
  type BuilderKeys = Exclude<UniversalPropertyKeys, ExcludeKeys> | BuilderExtraKeys;
18
18
  type IncludeKeysForProperty = Exclude<keyof PropertyOptions<any>, ExcludeKeys> | BuilderExtraKeys;
@@ -32,6 +32,10 @@ export interface PropertyChain<Value, Options> {
32
32
  nullable(): PropertyChain<Value, Omit<Options, 'nullable'> & {
33
33
  nullable: true;
34
34
  }>;
35
+ strictNullable(): PropertyChain<Value, Omit<Options, 'nullable' | 'strictNullable'> & {
36
+ nullable: true;
37
+ strictNullable: true;
38
+ }>;
35
39
  ref(): PropertyChain<Value, Omit<Options, 'ref'> & {
36
40
  ref: true;
37
41
  }>;
@@ -281,6 +285,14 @@ export declare class UniversalPropertyOptionsBuilder<Value, Options, IncludeKeys
281
285
  nullable(): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'nullable'> & {
282
286
  nullable: true;
283
287
  }, IncludeKeys>, IncludeKeys>;
288
+ /**
289
+ * Set column as nullable without adding `| undefined` to the type.
290
+ * Use this when the property is always explicitly set (e.g. in constructor) but can be `null`.
291
+ */
292
+ strictNullable(): Pick<UniversalPropertyOptionsBuilder<Value, Omit<Options, 'nullable' | 'strictNullable'> & {
293
+ nullable: true;
294
+ strictNullable: true;
295
+ }, IncludeKeys>, IncludeKeys>;
284
296
  /**
285
297
  * Set column as unsigned for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
286
298
  */
@@ -566,18 +578,28 @@ export interface EntityMetadataWithProperties<TName extends string, TTableName e
566
578
  concurrencyCheckKeys?: Set<AllKeys<TProperties, TBase>>;
567
579
  serializedPrimaryKey?: AllKeys<TProperties, TBase>;
568
580
  indexes?: {
569
- properties?: keyof TProperties | (keyof TProperties)[];
581
+ properties?: NoInfer<AllKeys<TProperties, TBase>> | NoInfer<AllKeys<TProperties, TBase>>[];
570
582
  name?: string;
571
583
  type?: string;
572
584
  options?: Dictionary;
573
585
  expression?: string | IndexCallback<InferEntityFromProperties<TProperties, TPK, TBase>>;
586
+ columns?: IndexColumnOptions[];
587
+ include?: NoInfer<AllKeys<TProperties, TBase>> | NoInfer<AllKeys<TProperties, TBase>>[];
588
+ fillFactor?: number;
589
+ invisible?: boolean;
590
+ disabled?: boolean;
591
+ clustered?: boolean;
574
592
  }[];
575
593
  uniques?: {
576
- properties?: keyof TProperties | (keyof TProperties)[];
594
+ properties?: NoInfer<AllKeys<TProperties, TBase>> | NoInfer<AllKeys<TProperties, TBase>>[];
577
595
  name?: string;
578
596
  options?: Dictionary;
579
597
  expression?: string | IndexCallback<InferEntityFromProperties<TProperties, TPK, TBase>>;
580
598
  deferMode?: DeferMode | `${DeferMode}`;
599
+ columns?: IndexColumnOptions[];
600
+ include?: NoInfer<AllKeys<TProperties, TBase>> | NoInfer<AllKeys<TProperties, TBase>>[];
601
+ fillFactor?: number;
602
+ disabled?: boolean;
581
603
  }[];
582
604
  }
583
605
  /** Defines an entity schema using property builders, with full type inference from the property definitions. */
@@ -663,7 +685,9 @@ type MaybeMapToPk<Value, Options> = Options extends {
663
685
  } ? Primary<Value> : Value;
664
686
  type MaybeNullable<Value, Options> = Options extends {
665
687
  nullable: true;
666
- } ? Value | null | undefined : Value;
688
+ } ? Options extends {
689
+ strictNullable: true;
690
+ } ? Value | null : Value | null | undefined : Value;
667
691
  type MaybeRelationRef<Value, Options> = Options extends {
668
692
  mapToPk: true;
669
693
  } ? Value : Options extends {
@@ -145,6 +145,13 @@ export class UniversalPropertyOptionsBuilder {
145
145
  nullable() {
146
146
  return this.assignOptions({ nullable: true });
147
147
  }
148
+ /**
149
+ * Set column as nullable without adding `| undefined` to the type.
150
+ * Use this when the property is always explicitly set (e.g. in constructor) but can be `null`.
151
+ */
152
+ strictNullable() {
153
+ return this.assignOptions({ nullable: true });
154
+ }
148
155
  /**
149
156
  * Set column as unsigned for {@link https://mikro-orm.io/docs/schema-generator Schema Generator}. (SQL only)
150
157
  */
@@ -1726,12 +1726,12 @@ export class MetadataDiscovery {
1726
1726
  }
1727
1727
  }
1728
1728
  if (prop.kind === ReferenceKind.SCALAR && !(mappedType instanceof t.unknown)) {
1729
- if (!prop.columnTypes &&
1730
- prop.nativeEnumName &&
1729
+ if (prop.nativeEnumName &&
1731
1730
  meta.schema !== this.#platform.getDefaultSchemaName() &&
1732
1731
  meta.schema &&
1733
1732
  !prop.nativeEnumName.includes('.')) {
1734
- prop.columnTypes = [`${meta.schema}.${prop.nativeEnumName}`];
1733
+ const suffix = prop.columnTypes?.[0]?.endsWith('[]') ? '[]' : '';
1734
+ prop.columnTypes = [`${meta.schema}.${prop.nativeEnumName}${suffix}`];
1735
1735
  }
1736
1736
  else {
1737
1737
  prop.columnTypes ??= [mappedType.getColumnType(prop, this.#platform)];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "7.0.3-dev.2",
3
+ "version": "7.0.3-dev.20",
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",
@@ -1,4 +1,4 @@
1
- import type { ArrayElement, AutoPath, CleanTypeConfig, SerializeDTO, FromEntityType, TypeConfig, UnboxArray } from '../typings.js';
1
+ import type { ArrayElement, AutoPath, CleanTypeConfig, ExtractFieldsHint, FromEntityType, SerializeDTO, TypeConfig, UnboxArray } from '../typings.js';
2
2
  import { type PopulatePath } from '../enums.js';
3
3
  /** Converts entity instances to plain DTOs via `serialize()`, with fine-grained control over populate, exclude, and serialization groups. */
4
4
  export declare class EntitySerializer {
@@ -41,4 +41,4 @@ export interface SerializeOptions<T, P extends string = never, E extends string
41
41
  * const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true });
42
42
  * ```
43
43
  */
44
- export declare function serialize<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Populate extends string = never, Exclude extends string = never, Config extends TypeConfig = never>(entity: Entity, options?: Config & SerializeOptions<UnboxArray<Entity>, Populate, Exclude>): Naked extends object[] ? SerializeDTO<ArrayElement<Naked>, Populate, Exclude, CleanTypeConfig<Config>>[] : SerializeDTO<Naked, Populate, Exclude, CleanTypeConfig<Config>>;
44
+ export declare function serialize<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Populate extends string = never, Exclude extends string = never, Config extends TypeConfig = never>(entity: Entity, options?: Config & SerializeOptions<UnboxArray<Entity>, Populate, Exclude>): Naked extends object[] ? SerializeDTO<ArrayElement<Naked>, Populate, Exclude, CleanTypeConfig<Config>>[] : SerializeDTO<Naked, Populate, Exclude, CleanTypeConfig<Config>, ExtractFieldsHint<Entity>>;
package/typings.d.ts CHANGED
@@ -201,6 +201,7 @@ export interface TypeConfig {
201
201
  declare const __selectedType: unique symbol;
202
202
  declare const __loadedType: unique symbol;
203
203
  declare const __loadHint: unique symbol;
204
+ declare const __fieldsHint: unique symbol;
204
205
  /**
205
206
  * Expands a populate hint into all its prefixes.
206
207
  * e.g., Prefixes<'a.b.c'> = 'a' | 'a.b' | 'a.b.c'
@@ -331,7 +332,7 @@ export interface IWrappedEntity<Entity extends object> {
331
332
  isManaged(): boolean;
332
333
  populated(populated?: boolean): void;
333
334
  populate<Hint extends string = never, Fields extends string = never>(populate: readonly AutoPath<Entity, Hint, PopulatePath.ALL>[] | false, options?: EntityLoaderOptions<Entity, Fields>): Promise<Loaded<Entity, Hint>>;
334
- init<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(options?: FindOneOptions<Entity, Hint, Fields, Exclude>): Promise<Loaded<Entity, Hint, Fields, Exclude> | null>;
335
+ init<Hint extends string = never, Fields extends string = never, Exclude extends string = never>(options?: FindOneOptions<Entity, Hint, Fields, Exclude>): Promise<Loaded<Entity, Hint, Fields, Exclude> | null>;
335
336
  toReference(): Ref<Entity> & LoadedReference<Loaded<Entity, AddEager<Entity>>>;
336
337
  toObject(): EntityDTO<Entity>;
337
338
  toObject(ignoreFields: never[]): EntityDTO<Entity>;
@@ -339,7 +340,7 @@ export interface IWrappedEntity<Entity extends object> {
339
340
  toJSON(...args: any[]): EntityDTO<Entity>;
340
341
  toPOJO(): EntityDTO<Entity>;
341
342
  serialize<Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Hint extends string = never, Exclude extends string = never>(options?: SerializeOptions<Naked, Hint, Exclude>): SerializeDTO<Naked, Hint, Exclude>;
342
- setSerializationContext<Hint extends string = never, Fields extends string = '*', Exclude extends string = never>(options: LoadHint<Entity, Hint, Fields, Exclude>): void;
343
+ setSerializationContext<Hint extends string = never, Fields extends string = never, Exclude extends string = never>(options: LoadHint<Entity, Hint, Fields, Exclude>): void;
343
344
  assign<Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Convert extends boolean = false, Data extends EntityData<Naked, Convert> | Partial<EntityDTO<Naked>> = EntityData<Naked, Convert> | Partial<EntityDTO<Naked>>>(data: Data & IsSubset<EntityData<Naked, Convert>, Data>, options?: AssignOptions<Convert>): MergeSelected<Entity, Naked, keyof Data & string>;
344
345
  getSchema(): string | undefined;
345
346
  setSchema(schema?: string): void;
@@ -527,13 +528,18 @@ export type EntityDTOFlat<T, C extends TypeConfig = never> = {
527
528
  */
528
529
  type SerializeTopHints<H extends string> = H extends `${infer Top}.${string}` ? Top : H;
529
530
  type SerializeSubHints<K extends string, H extends string> = H extends `${K}.${infer Rest}` ? Rest : never;
531
+ type SerializeSubFields<K extends string, F extends string> = K extends F ? '*' : [F extends `${K & string}.${infer Rest}` ? Rest : never] extends [never] ? '*' : F extends `${K & string}.${infer Rest}` ? Rest : never;
532
+ type SerializeFieldsFilter<T, K extends keyof T, F extends string> = K extends Prefix<T, F> | PrimaryProperty<T> ? K : never;
530
533
  type SerializePropValue<T, K extends keyof T, H extends string, C extends TypeConfig = never> = K & string extends SerializeTopHints<H> ? NonNullable<T[K]> extends CollectionShape<infer U> ? SerializeDTO<U & object, SerializeSubHints<K & string, H>, never, C>[] : SerializeDTO<ExpandProperty<T[K]>, SerializeSubHints<K & string, H>, never, C> | Extract<T[K], null | undefined> : EntityDTOProp<T, T[K], C>;
534
+ type SerializePropValueWithFields<T, K extends keyof T, H extends string, C extends TypeConfig, F extends string> = K & string extends SerializeTopHints<H> ? NonNullable<T[K]> extends CollectionShape<infer U> ? SerializeDTO<U & object, SerializeSubHints<K & string, H>, never, C, SerializeSubFields<K & string, F>>[] : SerializeDTO<ExpandProperty<T[K]>, SerializeSubHints<K & string, H>, never, C, SerializeSubFields<K & string, F>> | Extract<T[K], null | undefined> : EntityDTOProp<T, T[K], C>;
531
535
  /**
532
536
  * Return type of `serialize()`. Combines Loaded + EntityDTO in a single pass for better performance.
533
- * Respects populate hints (`H`) and exclude hints (`E`).
537
+ * Respects populate hints (`H`), exclude hints (`E`), and fields hints (`F`).
534
538
  */
535
- export type SerializeDTO<T, H extends string = never, E extends string = never, C extends TypeConfig = never> = string extends H ? EntityDTOFlat<T, C> : {
539
+ export type SerializeDTO<T, H extends string = never, E extends string = never, C extends TypeConfig = never, F extends string = '*'> = string extends H ? EntityDTOFlat<T, C> : [F] extends ['*'] ? {
536
540
  [K in keyof T as ExcludeHidden<T, K> & CleanKeys<T, K> & (IsNever<E> extends true ? K : Exclude<K, E>)]: SerializePropValue<T, K, H, C> | Extract<T[K], null | undefined>;
541
+ } : {
542
+ [K in keyof T as ExcludeHidden<T, K> & CleanKeys<T, K> & (IsNever<E> extends true ? K : Exclude<K, E>) & SerializeFieldsFilter<T, K, F>]: SerializePropValueWithFields<T, K, H, C, F> | Extract<T[K], null | undefined>;
537
543
  };
538
544
  type TargetKeys<T> = T extends EntityClass<infer P> ? keyof P : keyof T;
539
545
  type PropertyName<T> = IsUnknown<T> extends false ? TargetKeys<T> : string;
@@ -1186,6 +1192,7 @@ export type Selected<T, L extends string = never, F extends string = '*'> = {
1186
1192
  [K in keyof T as IsPrefixed<T, K, L | F | AddEager<T>> | FunctionKeys<T, K>]: T[K] extends Function ? T[K] : NonNullable<T[K]> extends Scalar ? T[K] : LoadedProp<NonNullable<T[K]>, Suffix<K, L, true>, Suffix<K, F, true>> | AddOptional<T[K]>;
1187
1193
  } & {
1188
1194
  [__selectedType]?: T;
1195
+ [__fieldsHint]?: (hint: F) => void;
1189
1196
  };
1190
1197
  type LoadedEntityType<T> = {
1191
1198
  [__loadedType]?: T;
@@ -1196,6 +1203,10 @@ type LoadedEntityType<T> = {
1196
1203
  export type EntityType<T> = T | LoadedEntityType<T>;
1197
1204
  /** Extracts the base entity type from a `Loaded`/`Selected` wrapper, or returns `T` as-is. */
1198
1205
  export type FromEntityType<T> = T extends LoadedEntityType<infer U> ? U : T;
1206
+ /** Extracts the fields hint (`F`) from a `Loaded`/`Selected` type, or returns `'*'` (all fields) for unwrapped entities. */
1207
+ export type ExtractFieldsHint<T> = T extends {
1208
+ [__fieldsHint]?: (hint: infer F extends string) => void;
1209
+ } ? F : '*';
1199
1210
  type LoadedInternal<T, L extends string = never, F extends string = '*', E extends string = never> = [F] extends ['*'] ? IsNever<E> extends true ? T & {
1200
1211
  [K in keyof T as IsPrefixed<T, K, ExpandHint<T, L>>]: LoadedProp<NonNullable<T[K]>, Suffix<K, L>, Suffix<K, F>, Suffix<K, E>> | AddOptional<T[K]>;
1201
1212
  } : {
package/utils/Cursor.d.ts CHANGED
@@ -48,7 +48,7 @@ import { type QueryOrder } from '../enums.js';
48
48
  * }
49
49
  * ```
50
50
  */
51
- export declare class Cursor<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never, IncludeCount extends boolean = true> {
51
+ export declare class Cursor<Entity extends object, Hint extends string = never, Fields extends string = never, Excludes extends string = never, IncludeCount extends boolean = true> {
52
52
  #private;
53
53
  readonly items: Loaded<Entity, Hint, Fields, Excludes>[];
54
54
  readonly totalCount: IncludeCount extends true ? number : undefined;
package/utils/Utils.js CHANGED
@@ -129,7 +129,7 @@ export function parseJsonSafe(value) {
129
129
  /** Collection of general-purpose utility methods used throughout the ORM. */
130
130
  export class Utils {
131
131
  static PK_SEPARATOR = '~~~';
132
- static #ORM_VERSION = '7.0.3-dev.2';
132
+ static #ORM_VERSION = '7.0.3-dev.20';
133
133
  /**
134
134
  * Checks if the argument is instance of `Object`. Returns false for arrays.
135
135
  */
@@ -802,14 +802,11 @@ export class Utils {
802
802
  return await import(module);
803
803
  }
804
804
  catch (err) {
805
- if (err.code === 'ERR_MODULE_NOT_FOUND') {
806
- if (warning) {
807
- // eslint-disable-next-line no-console
808
- console.warn(warning);
809
- }
810
- return undefined;
805
+ if (warning && err.code === 'ERR_MODULE_NOT_FOUND') {
806
+ // eslint-disable-next-line no-console
807
+ console.warn(warning);
811
808
  }
812
- throw err;
809
+ return undefined;
813
810
  }
814
811
  }
815
812
  static xor(a, b) {