@mikro-orm/core 6.4.16-dev.8 → 6.4.16

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.
@@ -27,6 +27,7 @@ export declare class EntityManager<Driver extends IDatabaseDriver = IDatabaseDri
27
27
  readonly name: string;
28
28
  protected readonly refLoader: DataLoader<[Reference<any>, (Omit<import("./entity").LoadReferenceOptions<any, any, "*", never>, "dataloader"> | undefined)?], any, [Reference<any>, (Omit<import("./entity").LoadReferenceOptions<any, any, "*", never>, "dataloader"> | undefined)?]>;
29
29
  protected readonly colLoader: DataLoader<[import("./entity").Collection<any, object>, (Omit<import("./entity").InitCollectionOptions<any, any, "*", never>, "dataloader"> | undefined)?], any, [import("./entity").Collection<any, object>, (Omit<import("./entity").InitCollectionOptions<any, any, "*", never>, "dataloader"> | undefined)?]>;
30
+ protected readonly colLoaderMtoN: DataLoader<[import("./entity").Collection<any, object>, (Omit<import("./entity").InitCollectionOptions<any, any, "*", never>, "dataloader"> | undefined)?], any, [import("./entity").Collection<any, object>, (Omit<import("./entity").InitCollectionOptions<any, any, "*", never>, "dataloader"> | undefined)?]>;
30
31
  private readonly validator;
31
32
  private readonly repositoryMap;
32
33
  private readonly entityLoader;
package/EntityManager.js CHANGED
@@ -29,6 +29,7 @@ class EntityManager {
29
29
  name;
30
30
  refLoader = new dataloader_1.default(utils_1.DataloaderUtils.getRefBatchLoadFn(this));
31
31
  colLoader = new dataloader_1.default(utils_1.DataloaderUtils.getColBatchLoadFn(this));
32
+ colLoaderMtoN = new dataloader_1.default(utils_1.DataloaderUtils.getManyToManyColBatchLoadFn(this));
32
33
  validator;
33
34
  repositoryMap = {};
34
35
  entityLoader;
@@ -488,7 +489,7 @@ class EntityManager {
488
489
  flushMode: enums_1.FlushMode.COMMIT,
489
490
  });
490
491
  if (reloaded) {
491
- this.config.getHydrator(this.metadata).hydrate(entity, (0, entity_1.helper)(entity).__meta, (0, entity_1.helper)(reloaded).toPOJO(), this.getEntityFactory(), 'full');
492
+ this.config.getHydrator(this.metadata).hydrate(entity, (0, entity_1.helper)(entity).__meta, (0, entity_1.helper)(reloaded).toPOJO(), this.getEntityFactory(), 'full', false, true);
492
493
  }
493
494
  else {
494
495
  this.getUnitOfWork().unsetIdentity(entity);
@@ -13,6 +13,7 @@ export type EntityOptions<T, E = T extends EntityClass<infer P> ? P : T> = {
13
13
  abstract?: boolean;
14
14
  readonly?: boolean;
15
15
  virtual?: boolean;
16
+ hasTriggers?: boolean;
16
17
  expression?: string | ((em: any, where: ObjectQuery<E>, options: FindOptions<E, any, any, any>) => object);
17
18
  repository?: () => Constructor;
18
19
  };
@@ -224,8 +224,9 @@ class Collection extends ArrayCollection_1.ArrayCollection {
224
224
  const order = [...this.items]; // copy order of references
225
225
  const orderBy = this.createOrderBy(options.orderBy);
226
226
  const customOrder = orderBy.length > 0;
227
- // eslint-disable-next-line dot-notation
228
- const items = await em['colLoader'].load([
227
+ const pivotTable = this.property.kind === enums_1.ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable();
228
+ const loader = pivotTable ? 'colLoaderMtoN' : 'colLoader';
229
+ const items = await em[loader].load([
229
230
  this,
230
231
  { ...options, orderBy },
231
232
  ]);
package/errors.d.ts CHANGED
@@ -24,6 +24,7 @@ export declare class ValidationError<T extends AnyEntity = AnyEntity> extends Er
24
24
  static cannotCommit(): ValidationError;
25
25
  static cannotUseGlobalContext(): ValidationError;
26
26
  static cannotUseOperatorsInsideEmbeddables(className: string, propName: string, payload: unknown): ValidationError;
27
+ static cannotUseGroupOperatorsInsideScalars(className: string, propName: string, payload: unknown): ValidationError;
27
28
  static invalidEmbeddableQuery(className: string, propName: string, embeddableType: string): ValidationError;
28
29
  }
29
30
  export declare class CursorError<T extends AnyEntity = AnyEntity> extends ValidationError<T> {
package/errors.js CHANGED
@@ -98,6 +98,9 @@ class ValidationError extends Error {
98
98
  static cannotUseOperatorsInsideEmbeddables(className, propName, payload) {
99
99
  return new ValidationError(`Using operators inside embeddables is not allowed, move the operator above. (property: ${className}.${propName}, payload: ${(0, node_util_1.inspect)(payload)})`);
100
100
  }
101
+ static cannotUseGroupOperatorsInsideScalars(className, propName, payload) {
102
+ return new ValidationError(`Using group operators ($and/$or) inside scalar properties is not allowed, move the operator above. (property: ${className}.${propName}, payload: ${(0, node_util_1.inspect)(payload)})`);
103
+ }
101
104
  static invalidEmbeddableQuery(className, propName, embeddableType) {
102
105
  return new ValidationError(`Invalid query for entity '${className}', property '${propName}' does not exist in embeddable '${embeddableType}'`);
103
106
  }
@@ -1004,7 +1004,7 @@ class MetadataDiscovery {
1004
1004
  return o;
1005
1005
  }, {});
1006
1006
  }
1007
- getDefaultVersionValue(prop) {
1007
+ getDefaultVersionValue(meta, prop) {
1008
1008
  if (typeof prop.defaultRaw !== 'undefined') {
1009
1009
  return prop.defaultRaw;
1010
1010
  }
@@ -1012,7 +1012,9 @@ class MetadataDiscovery {
1012
1012
  if (prop.default != null) {
1013
1013
  return '' + this.platform.quoteVersionValue(prop.default, prop);
1014
1014
  }
1015
- if (prop.type.toLowerCase() === 'date') {
1015
+ this.initCustomType(meta, prop, true);
1016
+ const type = prop.customType?.runtimeType ?? prop.runtimeType ?? prop.type;
1017
+ if (type === 'Date') {
1016
1018
  prop.length ??= this.platform.getDefaultVersionLength();
1017
1019
  return this.platform.getCurrentTimestampSQL(prop.length);
1018
1020
  }
@@ -1083,13 +1085,13 @@ class MetadataDiscovery {
1083
1085
  if (prop.version) {
1084
1086
  this.initDefaultValue(prop);
1085
1087
  meta.versionProperty = prop.name;
1086
- prop.defaultRaw = this.getDefaultVersionValue(prop);
1088
+ prop.defaultRaw = this.getDefaultVersionValue(meta, prop);
1087
1089
  }
1088
1090
  if (prop.concurrencyCheck && !prop.primary) {
1089
1091
  meta.concurrencyCheckKeys.add(prop.name);
1090
1092
  }
1091
1093
  }
1092
- initCustomType(meta, prop) {
1094
+ initCustomType(meta, prop, simple = false) {
1093
1095
  // `prop.type` might be actually instance of custom type class
1094
1096
  if (types_1.Type.isMappedType(prop.type) && !prop.customType) {
1095
1097
  prop.customType = prop.type;
@@ -1100,6 +1102,9 @@ class MetadataDiscovery {
1100
1102
  prop.customType = new prop.type();
1101
1103
  prop.type = prop.customType.constructor.name;
1102
1104
  }
1105
+ if (simple) {
1106
+ return;
1107
+ }
1103
1108
  if (!prop.customType && ['json', 'jsonb'].includes(prop.type?.toLowerCase())) {
1104
1109
  prop.customType = new types_1.JsonType();
1105
1110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "6.4.16-dev.8",
3
+ "version": "6.4.16",
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.3.0",
66
66
  "globby": "11.1.0",
67
- "mikro-orm": "6.4.16-dev.8",
67
+ "mikro-orm": "6.4.16",
68
68
  "reflect-metadata": "0.2.2"
69
69
  }
70
70
  }
package/typings.d.ts CHANGED
@@ -477,6 +477,7 @@ export interface EntityMetadata<T = any> {
477
477
  polymorphs?: EntityMetadata[];
478
478
  root: EntityMetadata<T>;
479
479
  definedProperties: Dictionary;
480
+ hasTriggers?: boolean;
480
481
  /** @internal can be used for computed numeric cache keys */
481
482
  readonly _id: number;
482
483
  }
@@ -35,9 +35,14 @@ export declare class DataloaderUtils {
35
35
  */
36
36
  static getColFilter<T, S extends T>(collection: Collection<any>): (result: T) => result is S;
37
37
  /**
38
- * Returns the collection dataloader batchLoadFn, which aggregates collections by entity,
38
+ * Returns the 1:M collection dataloader batchLoadFn, which aggregates collections by entity,
39
39
  * makes one query per entity and maps each input collection to the corresponding result.
40
40
  */
41
41
  static getColBatchLoadFn(em: EntityManager): DataLoader.BatchLoadFn<[Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?], any>;
42
+ /**
43
+ * Returns the M:N collection dataloader batchLoadFn, which aggregates collections by entity,
44
+ * makes one query per entity and maps each input collection to the corresponding result.
45
+ */
46
+ static getManyToManyColBatchLoadFn(em: EntityManager): DataLoader.BatchLoadFn<[Collection<any>, Omit<InitCollectionOptions<any, any>, 'dataloader'>?], any>;
42
47
  static getDataloaderType(dataloaderCfg: DataloaderType | boolean): DataloaderType;
43
48
  }
@@ -156,29 +156,11 @@ class DataloaderUtils {
156
156
  };
157
157
  }
158
158
  /**
159
- * Returns the collection dataloader batchLoadFn, which aggregates collections by entity,
159
+ * Returns the 1:M collection dataloader batchLoadFn, which aggregates collections by entity,
160
160
  * makes one query per entity and maps each input collection to the corresponding result.
161
161
  */
162
162
  static getColBatchLoadFn(em) {
163
163
  return async (collsWithOpts) => {
164
- const prop = collsWithOpts[0][0].property;
165
- if (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && em.getPlatform().usesPivotTable()) {
166
- const options = {};
167
- const wrap = (cond) => ({ [prop.name]: cond });
168
- const orderBy = Utils_1.Utils.asArray(collsWithOpts[0][1]?.orderBy).map(o => wrap(o));
169
- const populate = wrap(collsWithOpts[0][1]?.populate);
170
- const owners = collsWithOpts.map(c => c[0].owner);
171
- const $or = [];
172
- // a bit of a hack, but we need to prefix the key, since we have only a column name, not a property name
173
- const alias = em.config.getNamingStrategy().aliasName(prop.pivotEntity, 0);
174
- const fk = `${alias}.${Utils_1.Utils.getPrimaryKeyHash(prop.joinColumns)}`;
175
- for (const c of collsWithOpts) {
176
- $or.push({ $and: [c[1]?.where ?? {}, { [fk]: c[0].owner }] });
177
- options.refresh ??= c[1]?.refresh;
178
- }
179
- options.where = wrap({ $or });
180
- return em.getEntityLoader().findChildrenFromPivotTable(owners, prop, options, orderBy, populate, collsWithOpts[0][1]?.ref);
181
- }
182
164
  const entitiesAndOptsMap = DataloaderUtils.groupInversedOrMappedKeysByEntityAndOpts(collsWithOpts);
183
165
  const promises = DataloaderUtils.entitiesAndOptsMapToQueries(entitiesAndOptsMap, em);
184
166
  const resultsMap = new Map(await Promise.all(promises));
@@ -196,6 +178,42 @@ class DataloaderUtils {
196
178
  });
197
179
  };
198
180
  }
181
+ /**
182
+ * Returns the M:N collection dataloader batchLoadFn, which aggregates collections by entity,
183
+ * makes one query per entity and maps each input collection to the corresponding result.
184
+ */
185
+ static getManyToManyColBatchLoadFn(em) {
186
+ return async (collsWithOpts) => {
187
+ const groups = new Map();
188
+ for (const [col, opts] of collsWithOpts) {
189
+ const key = `${col.property.targetMeta.className}.${col.property.name}|${JSON.stringify(opts ?? {})}`;
190
+ const value = groups.get(key) ?? [];
191
+ value.push([col, opts ?? {}]);
192
+ groups.set(key, value);
193
+ }
194
+ const ret = [];
195
+ for (const group of groups.values()) {
196
+ const prop = group[0][0].property;
197
+ const options = {};
198
+ const wrap = (cond) => ({ [prop.name]: cond });
199
+ const orderBy = Utils_1.Utils.asArray(group[0][1]?.orderBy).map(o => wrap(o));
200
+ const populate = wrap(group[0][1]?.populate);
201
+ const owners = group.map(c => c[0].owner);
202
+ const $or = [];
203
+ // a bit of a hack, but we need to prefix the key, since we have only a column name, not a property name
204
+ const alias = em.config.getNamingStrategy().aliasName(prop.pivotEntity, 0);
205
+ const fk = `${alias}.${Utils_1.Utils.getPrimaryKeyHash(prop.joinColumns)}`;
206
+ for (const c of group) {
207
+ $or.push({ $and: [c[1]?.where ?? {}, { [fk]: c[0].owner }] });
208
+ options.refresh ??= c[1]?.refresh;
209
+ }
210
+ options.where = wrap({ $or });
211
+ const r = await em.getEntityLoader().findChildrenFromPivotTable(owners, prop, options, orderBy, populate, group[0][1]?.ref);
212
+ ret.push(...r);
213
+ }
214
+ return ret;
215
+ };
216
+ }
199
217
  static getDataloaderType(dataloaderCfg) {
200
218
  switch (dataloaderCfg) {
201
219
  case true: