@mikro-orm/core 7.0.0-dev.5 → 7.0.0-dev.50

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.
Files changed (115) hide show
  1. package/EntityManager.d.ts +81 -27
  2. package/EntityManager.js +287 -175
  3. package/MikroORM.d.ts +6 -6
  4. package/MikroORM.js +31 -74
  5. package/README.md +3 -2
  6. package/cache/FileCacheAdapter.d.ts +2 -1
  7. package/cache/FileCacheAdapter.js +6 -4
  8. package/connections/Connection.d.ts +9 -5
  9. package/connections/Connection.js +16 -13
  10. package/decorators/Embedded.d.ts +5 -11
  11. package/decorators/Entity.d.ts +18 -3
  12. package/decorators/Indexed.d.ts +2 -2
  13. package/decorators/ManyToMany.d.ts +2 -0
  14. package/decorators/ManyToOne.d.ts +4 -0
  15. package/decorators/OneToOne.d.ts +4 -0
  16. package/decorators/Property.d.ts +53 -9
  17. package/decorators/Transactional.d.ts +1 -0
  18. package/decorators/Transactional.js +3 -3
  19. package/decorators/index.d.ts +1 -1
  20. package/drivers/DatabaseDriver.d.ts +10 -5
  21. package/drivers/DatabaseDriver.js +4 -4
  22. package/drivers/IDatabaseDriver.d.ts +28 -4
  23. package/entity/ArrayCollection.d.ts +6 -4
  24. package/entity/ArrayCollection.js +26 -9
  25. package/entity/BaseEntity.d.ts +0 -1
  26. package/entity/BaseEntity.js +0 -3
  27. package/entity/Collection.d.ts +3 -4
  28. package/entity/Collection.js +37 -17
  29. package/entity/EntityAssigner.d.ts +1 -1
  30. package/entity/EntityAssigner.js +9 -1
  31. package/entity/EntityFactory.d.ts +7 -0
  32. package/entity/EntityFactory.js +29 -11
  33. package/entity/EntityHelper.js +25 -8
  34. package/entity/EntityLoader.d.ts +5 -4
  35. package/entity/EntityLoader.js +69 -36
  36. package/entity/EntityRepository.d.ts +1 -1
  37. package/entity/EntityValidator.js +1 -1
  38. package/entity/Reference.d.ts +9 -7
  39. package/entity/Reference.js +30 -3
  40. package/entity/WrappedEntity.d.ts +0 -2
  41. package/entity/WrappedEntity.js +1 -5
  42. package/entity/defineEntity.d.ts +555 -0
  43. package/entity/defineEntity.js +529 -0
  44. package/entity/index.d.ts +2 -0
  45. package/entity/index.js +2 -0
  46. package/entity/utils.d.ts +7 -0
  47. package/entity/utils.js +15 -3
  48. package/enums.d.ts +16 -3
  49. package/enums.js +13 -0
  50. package/errors.d.ts +6 -1
  51. package/errors.js +14 -4
  52. package/events/EventSubscriber.d.ts +3 -1
  53. package/hydration/ObjectHydrator.d.ts +4 -4
  54. package/hydration/ObjectHydrator.js +35 -24
  55. package/index.d.ts +2 -1
  56. package/index.js +1 -1
  57. package/logging/DefaultLogger.d.ts +1 -1
  58. package/logging/SimpleLogger.d.ts +1 -1
  59. package/metadata/EntitySchema.d.ts +8 -4
  60. package/metadata/EntitySchema.js +39 -19
  61. package/metadata/MetadataDiscovery.d.ts +4 -4
  62. package/metadata/MetadataDiscovery.js +139 -122
  63. package/metadata/MetadataStorage.js +1 -1
  64. package/metadata/MetadataValidator.js +4 -3
  65. package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
  66. package/naming-strategy/AbstractNamingStrategy.js +7 -1
  67. package/naming-strategy/NamingStrategy.d.ts +11 -1
  68. package/package.json +5 -5
  69. package/platforms/Platform.d.ts +5 -3
  70. package/platforms/Platform.js +4 -8
  71. package/serialization/EntitySerializer.d.ts +2 -0
  72. package/serialization/EntitySerializer.js +23 -5
  73. package/serialization/EntityTransformer.js +16 -6
  74. package/serialization/SerializationContext.js +14 -11
  75. package/types/BigIntType.d.ts +9 -6
  76. package/types/BigIntType.js +3 -0
  77. package/types/BooleanType.d.ts +1 -1
  78. package/types/DecimalType.d.ts +6 -4
  79. package/types/DecimalType.js +1 -1
  80. package/types/DoubleType.js +1 -1
  81. package/types/JsonType.d.ts +1 -1
  82. package/types/JsonType.js +7 -2
  83. package/types/Type.d.ts +2 -1
  84. package/types/Type.js +1 -1
  85. package/types/index.d.ts +1 -1
  86. package/typings.d.ts +89 -49
  87. package/typings.js +31 -31
  88. package/unit-of-work/ChangeSetComputer.js +8 -3
  89. package/unit-of-work/ChangeSetPersister.d.ts +4 -2
  90. package/unit-of-work/ChangeSetPersister.js +37 -16
  91. package/unit-of-work/UnitOfWork.d.ts +8 -1
  92. package/unit-of-work/UnitOfWork.js +110 -53
  93. package/utils/AbstractSchemaGenerator.js +3 -1
  94. package/utils/Configuration.d.ts +29 -16
  95. package/utils/Configuration.js +17 -18
  96. package/utils/ConfigurationLoader.d.ts +9 -22
  97. package/utils/ConfigurationLoader.js +49 -72
  98. package/utils/Cursor.d.ts +3 -3
  99. package/utils/Cursor.js +3 -0
  100. package/utils/DataloaderUtils.d.ts +7 -2
  101. package/utils/DataloaderUtils.js +38 -7
  102. package/utils/EntityComparator.d.ts +6 -2
  103. package/utils/EntityComparator.js +104 -58
  104. package/utils/QueryHelper.d.ts +9 -1
  105. package/utils/QueryHelper.js +66 -5
  106. package/utils/RawQueryFragment.d.ts +36 -4
  107. package/utils/RawQueryFragment.js +34 -13
  108. package/utils/TransactionManager.d.ts +65 -0
  109. package/utils/TransactionManager.js +223 -0
  110. package/utils/Utils.d.ts +13 -11
  111. package/utils/Utils.js +82 -55
  112. package/utils/index.d.ts +1 -0
  113. package/utils/index.js +1 -0
  114. package/utils/upsert-utils.d.ts +7 -2
  115. package/utils/upsert-utils.js +52 -1
@@ -1,5 +1,5 @@
1
- import { type CountOptions, type DeleteOptions, type DriverMethodOptions, EntityManagerType, type FindOneOptions, type FindOptions, type IDatabaseDriver, type LockOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type OrderDefinition } from './IDatabaseDriver.js';
2
- import type { ConnectionType, Dictionary, EntityData, EntityDictionary, EntityMetadata, EntityProperty, FilterQuery, PopulateOptions, Primary } from '../typings.js';
1
+ import { type CountOptions, type DeleteOptions, type DriverMethodOptions, EntityManagerType, type FindOneOptions, type FindOptions, type IDatabaseDriver, type LockOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type OrderDefinition, type StreamOptions } from './IDatabaseDriver.js';
2
+ import type { ConnectionType, Dictionary, EntityData, EntityDictionary, EntityMetadata, EntityName, EntityProperty, FilterQuery, PopulateOptions, Primary } from '../typings.js';
3
3
  import type { MetadataStorage } from '../metadata/MetadataStorage.js';
4
4
  import type { Connection, QueryResult, Transaction } from '../connections/Connection.js';
5
5
  import { type Configuration, type ConnectionOptions } from '../utils/Configuration.js';
@@ -30,14 +30,18 @@ export declare abstract class DatabaseDriver<C extends Connection> implements ID
30
30
  abstract nativeDelete<T extends object>(entityName: string, where: FilterQuery<T>, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
31
31
  abstract count<T extends object, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;
32
32
  createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
33
- findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
33
+ findVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
34
34
  countVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: CountOptions<T, any>): Promise<number>;
35
35
  aggregate(entityName: string, pipeline: any[]): Promise<any[]>;
36
36
  loadFromPivotTable<T extends object, O extends object>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<any>, orderBy?: OrderDefinition<T>, ctx?: Transaction, options?: FindOptions<T, any, any, any>, pivotJoin?: boolean): Promise<Dictionary<T[]>>;
37
37
  syncCollections<T extends object, O extends object>(collections: Iterable<Collection<T, O>>, options?: DriverMethodOptions): Promise<void>;
38
38
  mapResult<T extends object>(result: EntityDictionary<T>, meta?: EntityMetadata<T>, populate?: PopulateOptions<T>[]): EntityData<T> | null;
39
- connect(): Promise<C>;
40
- reconnect(): Promise<C>;
39
+ connect(options?: {
40
+ skipOnConnect?: boolean;
41
+ }): Promise<C>;
42
+ reconnect(options?: {
43
+ skipOnConnect?: boolean;
44
+ }): Promise<C>;
41
45
  getConnection(type?: ConnectionType): C;
42
46
  close(force?: boolean): Promise<void>;
43
47
  getPlatform(): Platform;
@@ -55,6 +59,7 @@ export declare abstract class DatabaseDriver<C extends Connection> implements ID
55
59
  protected getPrimaryKeyFields(entityName: string): string[];
56
60
  protected createReplicas(cb: (c: ConnectionOptions) => C): C[];
57
61
  lockPessimistic<T extends object>(entity: T, options: LockOptions): Promise<void>;
62
+ abstract stream<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: StreamOptions<T>): AsyncIterableIterator<T>;
58
63
  /**
59
64
  * @inheritDoc
60
65
  */
@@ -65,14 +65,14 @@ export class DatabaseDriver {
65
65
  }
66
66
  return this.comparator.mapResult(meta.className, result);
67
67
  }
68
- async connect() {
69
- await this.connection.connect();
68
+ async connect(options) {
69
+ await this.connection.connect(options);
70
70
  await Promise.all(this.replicas.map(replica => replica.connect()));
71
71
  return this.connection;
72
72
  }
73
- async reconnect() {
73
+ async reconnect(options) {
74
74
  await this.close(true);
75
- await this.connect();
75
+ await this.connect(options);
76
76
  return this.connection;
77
77
  }
78
78
  getConnection(type = 'write') {
@@ -1,4 +1,4 @@
1
- import type { ConnectionType, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, QBFilterQuery, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate } from '../typings.js';
1
+ import type { ConnectionType, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, QBFilterQuery, IPrimaryKey, PopulateOptions, EntityDictionary, AutoPath, ObjectQuery, FilterObject, Populate, EntityName } 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';
@@ -14,9 +14,13 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
14
14
  [EntityManagerType]: EntityManager<this>;
15
15
  readonly config: Configuration;
16
16
  createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
17
- connect(): Promise<C>;
17
+ connect(options?: {
18
+ skipOnConnect?: boolean;
19
+ }): Promise<C>;
18
20
  close(force?: boolean): Promise<void>;
19
- reconnect(): Promise<C>;
21
+ reconnect(options?: {
22
+ skipOnConnect?: boolean;
23
+ }): Promise<C>;
20
24
  getConnection(type?: ConnectionType): C;
21
25
  /**
22
26
  * Finds selection of entities
@@ -27,6 +31,7 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
27
31
  */
28
32
  findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
29
33
  findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
34
+ stream<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: StreamOptions<T>): AsyncIterableIterator<T>;
30
35
  nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
31
36
  nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>, transform?: (sql: string) => string): Promise<QueryResult<T>>;
32
37
  nativeUpdate<T extends object>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
@@ -68,6 +73,18 @@ export type OrderDefinition<T> = (QueryOrderMap<T> & {
68
73
  export interface FindAllOptions<T, P extends string = never, F extends string = '*', E extends string = never> extends FindOptions<T, P, F, E> {
69
74
  where?: FilterQuery<T>;
70
75
  }
76
+ 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'> {
77
+ /**
78
+ * When populating to-many relations, the ORM streams fully merged entities instead of yielding every row.
79
+ * You can opt out of this behavior by specifying `mergeResults: false`. This will yield every row from
80
+ * the SQL result, but still mapped to entities, meaning that to-many collections will contain at most
81
+ * a single item, and you will get duplicate root entities when they have multiple items in the populated
82
+ * collection.
83
+ *
84
+ * @default true
85
+ */
86
+ mergeResults?: boolean;
87
+ }
71
88
  export type FilterOptions = Dictionary<boolean | Dictionary> | string[] | boolean;
72
89
  export interface LoadHint<Entity, Hint extends string = never, Fields extends string = PopulatePath.ALL, Excludes extends string = never> {
73
90
  populate?: Populate<Entity, Hint>;
@@ -146,8 +163,11 @@ export interface FindOptions<Entity, Hint extends string = never, Fields extends
146
163
  hintComments?: string | string[];
147
164
  loggerContext?: LogContext;
148
165
  logging?: LoggingOptions;
166
+ /** @internal used to apply filters to the auto-joined relations */
167
+ em?: EntityManager;
149
168
  }
150
- export interface FindByCursorOptions<T extends object, P extends string = never, F extends string = '*', E extends string = never> extends Omit<FindOptions<T, P, F, E>, 'limit' | 'offset'> {
169
+ export interface FindByCursorOptions<T extends object, P extends string = never, F extends string = '*', E extends string = never, I extends boolean = true> extends Omit<FindOptions<T, P, F, E>, 'limit' | 'offset'> {
170
+ includeCount?: I;
151
171
  }
152
172
  export interface FindOneOptions<T extends object, P extends string = never, F extends string = '*', E extends string = never> extends Omit<FindOptions<T, P, F, E>, 'limit' | 'lockMode'> {
153
173
  lockMode?: LockMode;
@@ -163,6 +183,7 @@ export interface NativeInsertUpdateOptions<T> {
163
183
  schema?: string;
164
184
  /** `nativeUpdate()` only option */
165
185
  upsert?: boolean;
186
+ loggerContext?: LogContext;
166
187
  }
167
188
  export interface NativeInsertUpdateManyOptions<T> extends NativeInsertUpdateOptions<T> {
168
189
  processCollections?: boolean;
@@ -197,6 +218,8 @@ export interface CountOptions<T extends object, P extends string = never> {
197
218
  hintComments?: string | string[];
198
219
  loggerContext?: LogContext;
199
220
  logging?: LoggingOptions;
221
+ /** @internal used to apply filters to the auto-joined relations */
222
+ em?: EntityManager;
200
223
  }
201
224
  export interface UpdateOptions<T> {
202
225
  filters?: FilterOptions;
@@ -218,6 +241,7 @@ export interface LockOptions extends DriverMethodOptions {
218
241
  export interface DriverMethodOptions {
219
242
  ctx?: Transaction;
220
243
  schema?: string;
244
+ loggerContext?: LogContext;
221
245
  }
222
246
  export interface GetReferenceOptions {
223
247
  wrapped?: boolean;
@@ -6,6 +6,7 @@ export declare class ArrayCollection<T extends object, O extends object> {
6
6
  protected readonly items: Set<T>;
7
7
  protected initialized: boolean;
8
8
  protected dirty: boolean;
9
+ protected partial: boolean;
9
10
  protected snapshot: T[] | undefined;
10
11
  protected _count?: number;
11
12
  private _property?;
@@ -14,8 +15,8 @@ export declare class ArrayCollection<T extends object, O extends object> {
14
15
  getItems(): T[];
15
16
  toArray<TT extends T>(): EntityDTO<TT>[];
16
17
  toJSON(): EntityDTO<T>[];
17
- getIdentifiers<U extends IPrimaryKey = Primary<T> & IPrimaryKey>(field?: string): U[];
18
- add(entity: T | Reference<T> | Iterable<T | Reference<T>>, ...entities: (T | Reference<T>)[]): void;
18
+ getIdentifiers<U extends IPrimaryKey = Primary<T> & IPrimaryKey>(field?: string | string[]): U[];
19
+ add(entity: T | Reference<T> | Iterable<T | Reference<T>>, ...entities: (T | Reference<T>)[]): number;
19
20
  /**
20
21
  * @internal
21
22
  */
@@ -25,14 +26,14 @@ export declare class ArrayCollection<T extends object, O extends object> {
25
26
  /**
26
27
  * @internal
27
28
  */
28
- hydrate(items: T[], forcePropagate?: boolean): void;
29
+ hydrate(items: T[], forcePropagate?: boolean, partial?: boolean): void;
29
30
  /**
30
31
  * Remove specified item(s) from the collection. Note that removing item from collection does not necessarily imply deleting the target entity,
31
32
  * it means we are disconnecting the relation - removing items from collection, not removing entities from database - `Collection.remove()`
32
33
  * is not the same as `em.remove()`. If we want to delete the entity by removing it from collection, we need to enable `orphanRemoval: true`,
33
34
  * which tells the ORM we don't want orphaned entities to exist, so we know those should be removed.
34
35
  */
35
- remove(entity: T | Reference<T> | Iterable<T | Reference<T>>, ...entities: (T | Reference<T>)[]): void;
36
+ remove(entity: T | Reference<T> | Iterable<T | Reference<T>>, ...entities: (T | Reference<T>)[]): number;
36
37
  /**
37
38
  * Remove all items from the collection. Note that removing items from collection does not necessarily imply deleting the target entity,
38
39
  * it means we are disconnecting the relation - removing items from collection, not removing entities from database - `Collection.remove()`
@@ -83,6 +84,7 @@ export declare class ArrayCollection<T extends object, O extends object> {
83
84
  count(): number;
84
85
  isInitialized(fully?: boolean): boolean;
85
86
  isDirty(): boolean;
87
+ isPartial(): boolean;
86
88
  isEmpty(): boolean;
87
89
  setDirty(dirty?: boolean): void;
88
90
  get length(): number;
@@ -9,6 +9,7 @@ export class ArrayCollection {
9
9
  items = new Set();
10
10
  initialized = true;
11
11
  dirty = false;
12
+ partial = false; // mark partially loaded collections, propagation is disabled for those
12
13
  snapshot = []; // used to create a diff of the collection at commit time, undefined marks overridden values so we need to wipe when flushing
13
14
  _count;
14
15
  _property;
@@ -40,28 +41,38 @@ export class ArrayCollection {
40
41
  }
41
42
  getIdentifiers(field) {
42
43
  const items = this.getItems();
44
+ const targetMeta = this.property.targetMeta;
43
45
  if (items.length === 0) {
44
46
  return [];
45
47
  }
46
- field ??= this.property.targetMeta.serializedPrimaryKey;
48
+ field ??= targetMeta.compositePK ? targetMeta.primaryKeys : targetMeta.serializedPrimaryKey;
49
+ const cb = (i, f) => {
50
+ if (Utils.isEntity(i[f], true)) {
51
+ return wrap(i[f], true).getPrimaryKey();
52
+ }
53
+ return i[f];
54
+ };
47
55
  return items.map(i => {
48
- if (Utils.isEntity(i[field], true)) {
49
- return wrap(i[field], true).getPrimaryKey();
56
+ if (Array.isArray(field)) {
57
+ return field.map(f => cb(i, f));
50
58
  }
51
- return i[field];
59
+ return cb(i, field);
52
60
  });
53
61
  }
54
62
  add(entity, ...entities) {
55
63
  entities = Utils.asArray(entity).concat(entities);
64
+ let added = 0;
56
65
  for (const item of entities) {
57
66
  const entity = Reference.unwrapReference(item);
58
67
  if (!this.contains(entity, false)) {
59
68
  this.incrementCount(1);
60
69
  this[this.items.size] = entity;
61
70
  this.items.add(entity);
71
+ added++;
62
72
  this.propagate(entity, 'add');
63
73
  }
64
74
  }
75
+ return added;
65
76
  }
66
77
  /**
67
78
  * @internal
@@ -100,11 +111,12 @@ export class ArrayCollection {
100
111
  /**
101
112
  * @internal
102
113
  */
103
- hydrate(items, forcePropagate) {
114
+ hydrate(items, forcePropagate, partial) {
104
115
  for (let i = 0; i < this.items.size; i++) {
105
116
  delete this[i];
106
117
  }
107
118
  this.initialized = true;
119
+ this.partial = !!partial;
108
120
  this.items.clear();
109
121
  this._count = 0;
110
122
  this.add(items);
@@ -118,7 +130,7 @@ export class ArrayCollection {
118
130
  */
119
131
  remove(entity, ...entities) {
120
132
  entities = Utils.asArray(entity).concat(entities);
121
- let modified = false;
133
+ let removed = 0;
122
134
  for (const item of entities) {
123
135
  if (!item) {
124
136
  continue;
@@ -128,12 +140,13 @@ export class ArrayCollection {
128
140
  this.incrementCount(-1);
129
141
  delete this[this.items.size]; // remove last item
130
142
  this.propagate(entity, 'remove');
131
- modified = true;
143
+ removed++;
132
144
  }
133
145
  }
134
- if (modified) {
146
+ if (removed > 0) {
135
147
  Object.assign(this, [...this.items]); // reassign array access
136
148
  }
149
+ return removed;
137
150
  }
138
151
  /**
139
152
  * Remove all items from the collection. Note that removing items from collection does not necessarily imply deleting the target entity,
@@ -147,6 +160,7 @@ export class ArrayCollection {
147
160
  this.snapshot = undefined;
148
161
  }
149
162
  this.remove(this.items);
163
+ this.setDirty();
150
164
  }
151
165
  /**
152
166
  * @internal
@@ -267,6 +281,9 @@ export class ArrayCollection {
267
281
  isDirty() {
268
282
  return this.dirty;
269
283
  }
284
+ isPartial() {
285
+ return this.partial;
286
+ }
270
287
  isEmpty() {
271
288
  return this.count() === 0;
272
289
  }
@@ -383,7 +400,7 @@ export class ArrayCollection {
383
400
  /** @ignore */
384
401
  [inspect.custom](depth = 2) {
385
402
  const object = { ...this };
386
- const hidden = ['items', 'owner', '_property', '_count', 'snapshot', '_populated', '_snapshot', '_lazyInitialized', '_em', 'readonly'];
403
+ const hidden = ['items', 'owner', '_property', '_count', 'snapshot', '_populated', '_snapshot', '_lazyInitialized', '_em', 'readonly', 'partial'];
387
404
  hidden.forEach(k => delete object[k]);
388
405
  const ret = inspect(object, { depth });
389
406
  const name = `${this.constructor.name}<${this.property?.type ?? 'unknown'}>`;
@@ -6,7 +6,6 @@ import { type SerializeOptions } from '../serialization/EntitySerializer.js';
6
6
  import type { FindOneOptions } from '../drivers/IDatabaseDriver.js';
7
7
  export declare abstract class BaseEntity {
8
8
  isInitialized(): boolean;
9
- isTouched(): boolean;
10
9
  populated(populated?: boolean): void;
11
10
  populate<Entity extends this = this, Hint extends string = never>(populate: AutoPath<Entity, Hint>[] | false, options?: EntityLoaderOptions<Entity>): Promise<Loaded<Entity, Hint>>;
12
11
  toReference<Entity extends this = this>(): Ref<Entity> & LoadedReference<Loaded<Entity, AddEager<Entity>>>;
@@ -6,9 +6,6 @@ export class BaseEntity {
6
6
  isInitialized() {
7
7
  return helper(this).__initialized;
8
8
  }
9
- isTouched() {
10
- return helper(this).__touched;
11
- }
12
9
  populated(populated = true) {
13
10
  helper(this).populated(populated);
14
11
  }
@@ -2,7 +2,7 @@ import type { EntityDTO, EntityKey, FilterQuery, Loaded, LoadedCollection, Popul
2
2
  import { ArrayCollection } from './ArrayCollection.js';
3
3
  import { Reference } from './Reference.js';
4
4
  import type { Transaction } from '../connections/Connection.js';
5
- import type { FindOptions, CountOptions } from '../drivers/IDatabaseDriver.js';
5
+ import type { CountOptions, FindOptions } from '../drivers/IDatabaseDriver.js';
6
6
  import type { EntityLoaderOptions } from './EntityLoader.js';
7
7
  export interface MatchingOptions<T extends object, P extends string = never> extends FindOptions<T, P> {
8
8
  where?: FilterQuery<T>;
@@ -12,7 +12,6 @@ export interface MatchingOptions<T extends object, P extends string = never> ext
12
12
  export declare class Collection<T extends object, O extends object = object> extends ArrayCollection<T, O> {
13
13
  private readonly?;
14
14
  private _populated?;
15
- private _em?;
16
15
  private _snapshot?;
17
16
  constructor(owner: O, items?: T[], initialized?: boolean);
18
17
  /**
@@ -40,11 +39,11 @@ export declare class Collection<T extends object, O extends object = object> ext
40
39
  */
41
40
  getItems(check?: boolean): T[];
42
41
  toJSON<TT extends T>(): EntityDTO<TT>[];
43
- add<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>>, ...entities: (TT | Reference<TT>)[]): void;
42
+ add<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>>, ...entities: (TT | Reference<TT>)[]): number;
44
43
  /**
45
44
  * @inheritDoc
46
45
  */
47
- remove<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>> | ((item: TT) => boolean), ...entities: (TT | Reference<TT>)[]): void;
46
+ remove<TT extends T>(entity: TT | Reference<TT> | Iterable<TT | Reference<TT>> | ((item: TT) => boolean), ...entities: (TT | Reference<TT>)[]): number;
48
47
  contains<TT extends T>(item: TT | Reference<TT>, check?: boolean): boolean;
49
48
  count(): number;
50
49
  isEmpty(): boolean;
@@ -1,13 +1,13 @@
1
1
  import { ArrayCollection } from './ArrayCollection.js';
2
2
  import { Utils } from '../utils/Utils.js';
3
3
  import { ValidationError } from '../errors.js';
4
- import { ReferenceKind, DataloaderType } from '../enums.js';
4
+ import { DataloaderType, ReferenceKind } from '../enums.js';
5
5
  import { Reference } from './Reference.js';
6
6
  import { helper } from './wrap.js';
7
+ import { QueryHelper } from '../utils/QueryHelper.js';
7
8
  export class Collection extends ArrayCollection {
8
9
  readonly;
9
10
  _populated;
10
- _em;
11
11
  // this is for some reason needed for TS, otherwise it can fail with `Type instantiation is excessively deep and possibly infinite.`
12
12
  _snapshot;
13
13
  constructor(owner, items, initialized = true) {
@@ -33,6 +33,7 @@ export class Collection extends ArrayCollection {
33
33
  async load(options = {}) {
34
34
  if (this.isInitialized(true) && !options.refresh) {
35
35
  const em = this.getEntityManager(this.items, false);
36
+ options = { ...options, filters: QueryHelper.mergePropertyFilters(this.property.filters, options.filters) };
36
37
  await em?.populate(this.items, options.populate, options);
37
38
  this.setSerializationContext(options);
38
39
  }
@@ -116,30 +117,33 @@ export class Collection extends ArrayCollection {
116
117
  entities = Utils.asArray(entity).concat(entities);
117
118
  const unwrapped = entities.map(i => Reference.unwrapReference(i));
118
119
  unwrapped.forEach(entity => this.validateItemType(entity));
119
- this.modify('add', unwrapped);
120
+ const added = this.modify('add', unwrapped);
120
121
  this.cancelOrphanRemoval(unwrapped);
122
+ return added;
121
123
  }
122
124
  /**
123
125
  * @inheritDoc
124
126
  */
125
127
  remove(entity, ...entities) {
126
128
  if (entity instanceof Function) {
129
+ let removed = 0;
127
130
  for (const item of this.items) {
128
131
  if (entity(item)) {
129
- this.remove(item);
132
+ removed += this.remove(item);
130
133
  }
131
134
  }
132
- return;
135
+ return removed;
133
136
  }
134
137
  entities = Utils.asArray(entity).concat(entities);
135
138
  const unwrapped = entities.map(i => Reference.unwrapReference(i));
136
- this.modify('remove', unwrapped);
139
+ const removed = this.modify('remove', unwrapped);
137
140
  const em = this.getEntityManager(unwrapped, false);
138
141
  if (this.property.orphanRemoval && em) {
139
142
  for (const item of unwrapped) {
140
143
  em.getUnitOfWork().scheduleOrphanRemoval(item);
141
144
  }
142
145
  }
146
+ return removed;
143
147
  }
144
148
  contains(item, check = true) {
145
149
  if (check) {
@@ -218,13 +222,24 @@ export class Collection extends ArrayCollection {
218
222
  return this;
219
223
  }
220
224
  const em = this.getEntityManager();
225
+ options = { ...options, filters: QueryHelper.mergePropertyFilters(this.property.filters, options.filters) };
221
226
  if (options.dataloader ?? [DataloaderType.ALL, DataloaderType.COLLECTION].includes(em.config.getDataloaderType())) {
222
227
  const order = [...this.items]; // copy order of references
223
- const customOrder = !!options.orderBy;
224
- // eslint-disable-next-line dot-notation
225
- const items = await em['colLoader'].load([this, options]);
226
- if (!customOrder) {
227
- this.reorderItems(items, order);
228
+ const orderBy = this.createOrderBy(options.orderBy);
229
+ const customOrder = orderBy.length > 0;
230
+ const pivotTable = this.property.kind === ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable();
231
+ const loader = pivotTable ? 'colLoaderMtoN' : 'colLoader';
232
+ const items = await em[loader].load([
233
+ this,
234
+ { ...options, orderBy },
235
+ ]);
236
+ if (this.property.kind === ReferenceKind.MANY_TO_MANY) {
237
+ this.initialized = true;
238
+ this.dirty = false;
239
+ if (!customOrder) {
240
+ this.reorderItems(items, order);
241
+ }
242
+ return this;
228
243
  }
229
244
  this.items.clear();
230
245
  let i = 0;
@@ -254,18 +269,17 @@ export class Collection extends ArrayCollection {
254
269
  }
255
270
  getEntityManager(items = [], required = true) {
256
271
  const wrapped = helper(this.owner);
257
- let em = (this._em ?? wrapped.__em);
272
+ let em = wrapped.__em;
273
+ // console.log('wat 1', em, this.owner);
258
274
  if (!em) {
259
275
  for (const i of items) {
276
+ // console.log('wat 2', i, i && helper(i).__em);
260
277
  if (i && helper(i).__em) {
261
278
  em = helper(i).__em;
262
279
  break;
263
280
  }
264
281
  }
265
282
  }
266
- if (em) {
267
- Object.defineProperty(this, '_em', { value: em });
268
- }
269
283
  if (!em && required) {
270
284
  throw ValidationError.entityNotManaged(this.owner);
271
285
  }
@@ -316,8 +330,14 @@ export class Collection extends ArrayCollection {
316
330
  this.checkInitialized();
317
331
  }
318
332
  this.validateModification(items);
319
- super[method](items);
320
- this.setDirty();
333
+ const modified = super[method](items);
334
+ if (modified > 0) {
335
+ this.setDirty();
336
+ }
337
+ if (this.property.kind === ReferenceKind.ONE_TO_MANY && (method === 'add' || !this.property.orphanRemoval)) {
338
+ this.getEntityManager(items, false)?.persist(items);
339
+ }
340
+ return modified;
321
341
  }
322
342
  checkInitialized() {
323
343
  if (!this.isInitialized()) {
@@ -36,7 +36,7 @@ export interface AssignOptions<Convert extends boolean> {
36
36
  */
37
37
  onlyProperties?: boolean;
38
38
  /**
39
- * With `onlyOwnProperties` enabled, to-many relations are skipped, and payloads of to-one relations are converted
39
+ * With `onlyOwnProperties` enabled, inverse sides of to-many relations are skipped, and payloads of other relations are converted
40
40
  * to foreign keys. Defaults to `false`.
41
41
  */
42
42
  onlyOwnProperties?: boolean;
@@ -42,9 +42,17 @@ export class EntityAssigner {
42
42
  }
43
43
  const prop = { ...props[propName], name: propName };
44
44
  if (prop && options.onlyOwnProperties) {
45
- if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind)) {
45
+ if ([ReferenceKind.ONE_TO_MANY].includes(prop.kind)) {
46
46
  return;
47
47
  }
48
+ if ([ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
49
+ if (!prop.owner) {
50
+ return;
51
+ }
52
+ else if (value?.map) {
53
+ value = value.map((v) => Utils.extractPK(v, prop.targetMeta));
54
+ }
55
+ }
48
56
  if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
49
57
  value = Utils.extractPK(value, prop.targetMeta);
50
58
  }
@@ -4,12 +4,18 @@ import type { EntityComparator } from '../utils/EntityComparator.js';
4
4
  export interface FactoryOptions {
5
5
  initialized?: boolean;
6
6
  newEntity?: boolean;
7
+ /**
8
+ * Property `onCreate` hooks are normally executed during `flush` operation.
9
+ * With this option, they will be processed early inside `em.create()` method.
10
+ */
11
+ processOnCreateHooksEarly?: boolean;
7
12
  merge?: boolean;
8
13
  refresh?: boolean;
9
14
  convertCustomTypes?: boolean;
10
15
  recomputeSnapshot?: boolean;
11
16
  schema?: string;
12
17
  parentSchema?: string;
18
+ normalizeAccessors?: boolean;
13
19
  }
14
20
  export declare class EntityFactory {
15
21
  private readonly em;
@@ -27,6 +33,7 @@ export declare class EntityFactory {
27
33
  createEmbeddable<T extends object>(entityName: EntityName<T>, data: EntityData<T>, options?: Pick<FactoryOptions, 'newEntity' | 'convertCustomTypes'>): T;
28
34
  getComparator(): EntityComparator;
29
35
  private createEntity;
36
+ private assignDefaultValues;
30
37
  private hydrate;
31
38
  private findEntity;
32
39
  private processDiscriminatorColumn;