@mikro-orm/core 6.3.11-dev.1 → 6.3.11-dev.10

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.
@@ -26,11 +26,12 @@ class EntityLoader {
26
26
  if (entities.length === 0 || Utils_1.Utils.isEmpty(populate)) {
27
27
  return this.setSerializationContext(entities, populate, options);
28
28
  }
29
+ const meta = this.metadata.find(entityName);
29
30
  if (entities.some(e => !e.__helper)) {
30
31
  const entity = entities.find(e => !Utils_1.Utils.isEntity(e));
31
- const meta = this.metadata.find(entityName);
32
32
  throw errors_1.ValidationError.notDiscoveredEntity(entity, meta, 'populate');
33
33
  }
34
+ const references = entities.filter(e => !(0, wrap_1.helper)(e).isInitialized());
34
35
  const visited = options.visited ??= new Set();
35
36
  options.where ??= {};
36
37
  options.orderBy ??= {};
@@ -39,6 +40,9 @@ class EntityLoader {
39
40
  options.validate ??= true;
40
41
  options.refresh ??= false;
41
42
  options.convertCustomTypes ??= true;
43
+ if (references.length > 0) {
44
+ await this.populateScalar(meta, references, options);
45
+ }
42
46
  populate = this.normalizePopulate(entityName, populate, options.strategy, options.lookup);
43
47
  const invalid = populate.find(({ field }) => !this.em.canPopulate(entityName, field));
44
48
  /* istanbul ignore next */
@@ -121,7 +125,7 @@ class EntityLoader {
121
125
  if (prop.kind === enums_1.ReferenceKind.MANY_TO_MANY && prop.owner && !this.driver.getPlatform().usesPivotTable()) {
122
126
  const filtered = entities.filter(e => !e[prop.name]?.isInitialized());
123
127
  if (filtered.length > 0) {
124
- await this.populateScalar(meta, filtered, options, prop);
128
+ await this.populateScalar(meta, filtered, { ...options, fields: [prop.name] });
125
129
  }
126
130
  }
127
131
  if (prop.kind === enums_1.ReferenceKind.SCALAR && prop.lazy) {
@@ -129,7 +133,7 @@ class EntityLoader {
129
133
  if (options.ignoreLazyScalarProperties || filtered.length === 0) {
130
134
  return entities;
131
135
  }
132
- await this.populateScalar(meta, filtered, options, prop);
136
+ await this.populateScalar(meta, filtered, { ...options, fields: [prop.name] });
133
137
  return entities;
134
138
  }
135
139
  if (prop.kind === enums_1.ReferenceKind.EMBEDDED) {
@@ -147,14 +151,14 @@ class EntityLoader {
147
151
  this.initializeCollections(filtered, prop, field, data, innerOrderBy.length > 0);
148
152
  return data;
149
153
  }
150
- async populateScalar(meta, filtered, options, prop) {
154
+ async populateScalar(meta, filtered, options) {
151
155
  const pk = Utils_1.Utils.getPrimaryKeyHash(meta.primaryKeys);
152
156
  const ids = Utils_1.Utils.unique(filtered.map(e => Utils_1.Utils.getPrimaryKeyValues(e, meta.primaryKeys, true)));
153
157
  const where = this.mergePrimaryCondition(ids, pk, options, meta, this.metadata, this.driver.getPlatform());
154
- const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging } = options;
158
+ const { filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging, fields } = options;
155
159
  await this.em.find(meta.className, where, {
156
160
  filters, convertCustomTypes, lockMode, strategy, populateWhere, connectionType, logging,
157
- fields: [prop.name],
161
+ fields: fields,
158
162
  populate: [],
159
163
  });
160
164
  }
@@ -466,7 +470,7 @@ class EntityLoader {
466
470
  return entities.filter(e => Utils_1.Utils.isCollection(e[field]) && !e[field].isInitialized(!ref));
467
471
  }
468
472
  isPropertyLoaded(entity, field) {
469
- if (!entity) {
473
+ if (!entity || field === '*') {
470
474
  return true;
471
475
  }
472
476
  const wrapped = (0, wrap_1.helper)(entity);
@@ -6,6 +6,7 @@ const Collection_1 = require("../entity/Collection");
6
6
  const Reference_1 = require("../entity/Reference");
7
7
  const Utils_1 = require("../utils/Utils");
8
8
  const enums_1 = require("../enums");
9
+ const RawQueryFragment_1 = require("../utils/RawQueryFragment");
9
10
  class ObjectHydrator extends Hydrator_1.Hydrator {
10
11
  hydrators = {
11
12
  full: new Map(),
@@ -48,6 +49,15 @@ class ObjectHydrator extends Hydrator_1.Hydrator {
48
49
  context.set('isPrimaryKey', Utils_1.Utils.isPrimaryKey);
49
50
  context.set('Collection', Collection_1.Collection);
50
51
  context.set('Reference', Reference_1.Reference);
52
+ const registerCustomType = (prop, convertorKey, method, context) => {
53
+ context.set(`${method}_${convertorKey}`, (val) => {
54
+ if (RawQueryFragment_1.RawQueryFragment.isKnownFragment(val)) {
55
+ return val;
56
+ }
57
+ return prop.customType[method](val, this.platform, { mode: 'serialization' });
58
+ });
59
+ return convertorKey;
60
+ };
51
61
  const hydrateScalar = (prop, object, path, dataKey) => {
52
62
  const entityKey = path.map(k => this.wrap(k)).join('');
53
63
  const tz = this.platform.getTimezone();
@@ -66,8 +76,8 @@ class ObjectHydrator extends Hydrator_1.Hydrator {
66
76
  ret.push(` entity${entityKey} = ${nullVal};`);
67
77
  ret.push(` } else if (typeof data${dataKey} !== 'undefined') {`);
68
78
  if (prop.customType) {
69
- context.set(`convertToJSValue_${convertorKey}`, (val) => prop.customType.convertToJSValue(val, this.platform));
70
- context.set(`convertToDatabaseValue_${convertorKey}`, (val) => prop.customType.convertToDatabaseValue(val, this.platform, { mode: 'hydration' }));
79
+ registerCustomType(prop, convertorKey, 'convertToJSValue', context);
80
+ registerCustomType(prop, convertorKey, 'convertToDatabaseValue', context);
71
81
  ret.push(` if (convertCustomTypes) {`, ` const value = convertToJSValue_${convertorKey}(data${dataKey});`);
72
82
  if (prop.customType.ensureComparable(meta, prop)) {
73
83
  ret.push(` data${dataKey} = convertToDatabaseValue_${convertorKey}(value);`);
@@ -142,7 +152,7 @@ class ObjectHydrator extends Hydrator_1.Hydrator {
142
152
  }
143
153
  }
144
154
  if (prop.customType?.ensureComparable(meta, prop)) {
145
- context.set(`convertToDatabaseValue_${this.safeKey(prop.name)}`, (val) => prop.customType.convertToDatabaseValue(val, this.platform, { mode: 'hydration' }));
155
+ registerCustomType(prop, this.safeKey(prop.name), 'convertToDatabaseValue', context);
146
156
  ret.push(` if (data${dataKey} != null && typeof data${dataKey} !== 'object' && convertCustomTypes) {`);
147
157
  ret.push(` data${dataKey} = convertToDatabaseValue_${this.safeKey(prop.name)}(entity${entityKey}.__helper.getPrimaryKey());`);
148
158
  ret.push(` }`);
@@ -1,17 +1,17 @@
1
- import type { Dictionary, Highlighter } from '../typings';
1
+ import type { AnyString, Dictionary, Highlighter } from '../typings';
2
2
  export interface Logger {
3
3
  /**
4
4
  * Logs a message inside given namespace.
5
5
  */
6
- log(namespace: LoggerNamespace, message: string, context?: LogContext): void;
6
+ log(namespace: LoggerNamespace | AnyString, message: string, context?: LogContext): void;
7
7
  /**
8
8
  * Logs error message inside given namespace.
9
9
  */
10
- error(namespace: LoggerNamespace, message: string, context?: LogContext): void;
10
+ error(namespace: LoggerNamespace | AnyString, message: string, context?: LogContext): void;
11
11
  /**
12
12
  * Logs warning message inside given namespace.
13
13
  */
14
- warn(namespace: LoggerNamespace, message: string, context?: LogContext): void;
14
+ warn(namespace: LoggerNamespace | AnyString, message: string, context?: LogContext): void;
15
15
  /**
16
16
  * Logs a message inside given namespace.
17
17
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
- "version": "6.3.11-dev.1",
3
+ "version": "6.3.11-dev.10",
4
4
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -64,7 +64,7 @@
64
64
  "esprima": "4.0.1",
65
65
  "fs-extra": "11.2.0",
66
66
  "globby": "11.1.0",
67
- "mikro-orm": "6.3.11-dev.1",
67
+ "mikro-orm": "6.3.11-dev.10",
68
68
  "reflect-metadata": "0.2.2"
69
69
  }
70
70
  }
@@ -175,6 +175,7 @@ export declare abstract class Platform {
175
175
  processDateProperty(value: unknown): string | number | Date;
176
176
  quoteIdentifier(id: string, quote?: string): string;
177
177
  quoteValue(value: any): string;
178
+ escape(value: any): string;
178
179
  formatQuery(sql: string, params: readonly any[]): string;
179
180
  cloneEmbeddable<T>(data: T): T;
180
181
  setConfig(config: Configuration): void;
@@ -361,6 +361,10 @@ class Platform {
361
361
  quoteValue(value) {
362
362
  return value;
363
363
  }
364
+ /* istanbul ignore next */
365
+ escape(value) {
366
+ return value;
367
+ }
364
368
  formatQuery(sql, params) {
365
369
  if (params.length === 0) {
366
370
  return sql;
@@ -68,9 +68,6 @@ class EntityTransformer {
68
68
  }
69
69
  ret[this.propertyName(meta, prop, wrapped.__platform, raw)] = val;
70
70
  }
71
- if (!visited) {
72
- root.visited.delete(entity);
73
- }
74
71
  if (!wrapped.isInitialized() && wrapped.hasPrimaryKey()) {
75
72
  return ret;
76
73
  }
@@ -69,6 +69,7 @@ export declare class EntityComparator {
69
69
  */
70
70
  private shouldSerialize;
71
71
  private getEmbeddedPropertySnapshot;
72
+ private registerCustomType;
72
73
  private getPropertySnapshot;
73
74
  /**
74
75
  * @internal Highly performance-sensitive method.
@@ -5,6 +5,7 @@ const clone_1 = require("./clone");
5
5
  const enums_1 = require("../enums");
6
6
  const Utils_1 = require("./Utils");
7
7
  const JsonType_1 = require("../types/JsonType");
8
+ const RawQueryFragment_1 = require("./RawQueryFragment");
8
9
  class EntityComparator {
9
10
  metadata;
10
11
  platform;
@@ -102,8 +103,7 @@ class EntityComparator {
102
103
  }
103
104
  else {
104
105
  if (meta.properties[pk].customType) {
105
- const convertorKey = this.safeKey(pk);
106
- context.set(`convertToDatabaseValue_${convertorKey}`, (val) => meta.properties[pk].customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' }));
106
+ const convertorKey = this.registerCustomType(meta.properties[pk], context);
107
107
  lines.push(` ${pk}: convertToDatabaseValue_${convertorKey}(entity${this.wrap(pk)}),`);
108
108
  }
109
109
  else {
@@ -121,8 +121,7 @@ class EntityComparator {
121
121
  lines.push(` if (entity${this.wrap(pk)} != null && (entity${this.wrap(pk)}.__entity || entity${this.wrap(pk)}.__reference)) return entity${this.wrap(pk)}.__helper.getPrimaryKey(true);`);
122
122
  }
123
123
  if (meta.properties[pk].customType) {
124
- const convertorKey = this.safeKey(pk);
125
- context.set(`convertToDatabaseValue_${convertorKey}`, (val) => meta.properties[pk].customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' }));
124
+ const convertorKey = this.registerCustomType(meta.properties[pk], context);
126
125
  lines.push(` return convertToDatabaseValue_${convertorKey}(entity${this.wrap(pk)});`);
127
126
  }
128
127
  else {
@@ -414,8 +413,7 @@ class EntityComparator {
414
413
  .split('\n').map(l => padding + l).join('\n');
415
414
  }
416
415
  if (shouldProcessCustomType(childProp)) {
417
- const convertorKey = this.safeKey(childProp.name);
418
- context.set(`convertToDatabaseValue_${convertorKey}`, (val) => childProp.customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' }));
416
+ const convertorKey = this.registerCustomType(childProp, context);
419
417
  if (['number', 'string', 'boolean', 'bigint'].includes(childProp.customType.compareAsType().toLowerCase())) {
420
418
  return `${padding} if (${childCond}) ret${childDataKey} = convertToDatabaseValue_${convertorKey}(entity${childEntityKey});`;
421
419
  }
@@ -428,8 +426,18 @@ class EntityComparator {
428
426
  }
429
427
  return `${ret}${padding}}`;
430
428
  }
431
- getPropertySnapshot(meta, prop, context, dataKey, entityKey, path, level = 1, object) {
429
+ registerCustomType(prop, context) {
432
430
  const convertorKey = this.safeKey(prop.name);
431
+ context.set(`convertToDatabaseValue_${convertorKey}`, (val) => {
432
+ /* istanbul ignore if */
433
+ if (RawQueryFragment_1.RawQueryFragment.isKnownFragment(val)) {
434
+ return val;
435
+ }
436
+ return prop.customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' });
437
+ });
438
+ return convertorKey;
439
+ }
440
+ getPropertySnapshot(meta, prop, context, dataKey, entityKey, path, level = 1, object) {
433
441
  const unwrap = prop.ref ? '?.unwrap()' : '';
434
442
  let ret = ` if (${this.getPropertyCondition(path)}) {\n`;
435
443
  if (['number', 'string', 'boolean'].includes(prop.type.toLowerCase())) {
@@ -444,7 +452,7 @@ class EntityComparator {
444
452
  if (prop.kind === enums_1.ReferenceKind.ONE_TO_ONE || prop.kind === enums_1.ReferenceKind.MANY_TO_ONE) {
445
453
  if (prop.mapToPk) {
446
454
  if (prop.customType) {
447
- context.set(`convertToDatabaseValue_${convertorKey}`, (val) => prop.customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' }));
455
+ const convertorKey = this.registerCustomType(prop, context);
448
456
  ret += ` ret${dataKey} = convertToDatabaseValue_${convertorKey}(entity${entityKey});\n`;
449
457
  }
450
458
  else {
@@ -468,7 +476,7 @@ class EntityComparator {
468
476
  return ret + ' }\n';
469
477
  }
470
478
  if (prop.customType) {
471
- context.set(`convertToDatabaseValue_${convertorKey}`, (val) => prop.customType.convertToDatabaseValue(val, this.platform, { mode: 'serialization' }));
479
+ const convertorKey = this.registerCustomType(prop, context);
472
480
  if (['number', 'string', 'boolean', 'bigint'].includes(prop.customType.compareAsType().toLowerCase())) {
473
481
  return ret + ` ret${dataKey} = convertToDatabaseValue_${convertorKey}(entity${entityKey}${unwrap});\n }\n`;
474
482
  }
package/utils/Utils.js CHANGED
@@ -49,10 +49,12 @@ function compareObjects(a, b) {
49
49
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
50
50
  return a.sql === b.sql && compareArrays(a.params, b.params);
51
51
  }
52
- if (a.valueOf !== Object.prototype.valueOf && typeof a.valueOf === 'function' && typeof b.valueOf === 'function') {
53
- return a.valueOf() === b.valueOf();
54
- }
55
- if (a.toString !== Object.prototype.toString && typeof a.toString === 'function' && typeof b.toString === 'function') {
52
+ if ((typeof a === 'function' && typeof b === 'function') ||
53
+ (typeof a === 'object' && a.client && ['Ref', 'Raw'].includes(a.constructor.name) && typeof b === 'object' && b.client && ['Ref', 'Raw'].includes(b.constructor.name)) || // knex qb
54
+ (a instanceof Date && b instanceof Date) ||
55
+ (a instanceof RegExp && b instanceof RegExp) ||
56
+ (a instanceof String && b instanceof String) ||
57
+ (a instanceof Number && b instanceof Number)) {
56
58
  return a.toString() === b.toString();
57
59
  }
58
60
  const keys = Object.keys(a);
@@ -881,8 +883,8 @@ class Utils {
881
883
  catch {
882
884
  // ignore
883
885
  }
884
- // For some reason, ".ts" files do not work with "file://" URLs on Windows.
885
- if (id.endsWith('.ts')) {
886
+ // If the extension is not registered, we need to fall back to a file path.
887
+ if (require.extensions && !require.extensions[(0, node_path_1.extname)(id)]) {
886
888
  id = (0, node_url_1.fileURLToPath)(id);
887
889
  }
888
890
  }