@mikro-orm/core 7.0.0-dev.13 → 7.0.0-dev.130

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 (207) hide show
  1. package/EntityManager.d.ts +85 -56
  2. package/EntityManager.js +333 -294
  3. package/MikroORM.d.ts +41 -32
  4. package/MikroORM.js +100 -140
  5. package/README.md +3 -2
  6. package/cache/FileCacheAdapter.d.ts +1 -1
  7. package/cache/FileCacheAdapter.js +8 -7
  8. package/cache/GeneratedCacheAdapter.d.ts +0 -1
  9. package/cache/GeneratedCacheAdapter.js +0 -2
  10. package/cache/index.d.ts +0 -1
  11. package/cache/index.js +0 -1
  12. package/connections/Connection.d.ts +16 -7
  13. package/connections/Connection.js +23 -14
  14. package/drivers/DatabaseDriver.d.ts +25 -16
  15. package/drivers/DatabaseDriver.js +40 -24
  16. package/drivers/IDatabaseDriver.d.ts +38 -17
  17. package/entity/BaseEntity.d.ts +2 -2
  18. package/entity/BaseEntity.js +0 -3
  19. package/entity/Collection.d.ts +95 -30
  20. package/entity/Collection.js +439 -99
  21. package/entity/EntityAssigner.d.ts +1 -1
  22. package/entity/EntityAssigner.js +26 -18
  23. package/entity/EntityFactory.d.ts +7 -0
  24. package/entity/EntityFactory.js +72 -53
  25. package/entity/EntityHelper.d.ts +2 -2
  26. package/entity/EntityHelper.js +35 -15
  27. package/entity/EntityLoader.d.ts +7 -6
  28. package/entity/EntityLoader.js +84 -72
  29. package/entity/EntityRepository.d.ts +1 -1
  30. package/entity/EntityRepository.js +2 -2
  31. package/entity/Reference.d.ts +6 -5
  32. package/entity/Reference.js +34 -9
  33. package/entity/WrappedEntity.d.ts +2 -7
  34. package/entity/WrappedEntity.js +3 -8
  35. package/entity/defineEntity.d.ts +575 -0
  36. package/entity/defineEntity.js +529 -0
  37. package/entity/index.d.ts +3 -2
  38. package/entity/index.js +3 -2
  39. package/entity/utils.d.ts +7 -0
  40. package/entity/utils.js +16 -4
  41. package/entity/validators.d.ts +11 -0
  42. package/entity/validators.js +65 -0
  43. package/enums.d.ts +22 -6
  44. package/enums.js +15 -1
  45. package/errors.d.ts +18 -9
  46. package/errors.js +44 -21
  47. package/events/EventManager.d.ts +2 -1
  48. package/events/EventManager.js +19 -11
  49. package/hydration/Hydrator.js +1 -2
  50. package/hydration/ObjectHydrator.d.ts +4 -4
  51. package/hydration/ObjectHydrator.js +50 -33
  52. package/index.d.ts +2 -2
  53. package/index.js +1 -2
  54. package/logging/DefaultLogger.d.ts +1 -1
  55. package/logging/DefaultLogger.js +1 -0
  56. package/logging/SimpleLogger.d.ts +1 -1
  57. package/logging/colors.d.ts +1 -1
  58. package/logging/colors.js +7 -6
  59. package/logging/index.d.ts +1 -0
  60. package/logging/index.js +1 -0
  61. package/logging/inspect.d.ts +2 -0
  62. package/logging/inspect.js +11 -0
  63. package/metadata/EntitySchema.d.ts +22 -24
  64. package/metadata/EntitySchema.js +73 -51
  65. package/metadata/MetadataDiscovery.d.ts +6 -10
  66. package/metadata/MetadataDiscovery.js +292 -299
  67. package/metadata/MetadataProvider.d.ts +11 -2
  68. package/metadata/MetadataProvider.js +46 -2
  69. package/metadata/MetadataStorage.d.ts +13 -11
  70. package/metadata/MetadataStorage.js +70 -37
  71. package/metadata/MetadataValidator.d.ts +11 -9
  72. package/metadata/MetadataValidator.js +50 -38
  73. package/metadata/discover-entities.d.ts +5 -0
  74. package/metadata/discover-entities.js +40 -0
  75. package/metadata/index.d.ts +1 -1
  76. package/metadata/index.js +1 -1
  77. package/metadata/types.d.ts +480 -0
  78. package/metadata/types.js +1 -0
  79. package/naming-strategy/AbstractNamingStrategy.d.ts +8 -4
  80. package/naming-strategy/AbstractNamingStrategy.js +8 -2
  81. package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
  82. package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
  83. package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
  84. package/naming-strategy/MongoNamingStrategy.js +6 -6
  85. package/naming-strategy/NamingStrategy.d.ts +14 -4
  86. package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
  87. package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
  88. package/not-supported.d.ts +2 -0
  89. package/not-supported.js +4 -0
  90. package/package.json +19 -11
  91. package/platforms/ExceptionConverter.js +1 -1
  92. package/platforms/Platform.d.ts +6 -13
  93. package/platforms/Platform.js +17 -43
  94. package/serialization/EntitySerializer.d.ts +5 -0
  95. package/serialization/EntitySerializer.js +47 -27
  96. package/serialization/EntityTransformer.js +28 -18
  97. package/serialization/SerializationContext.d.ts +6 -6
  98. package/serialization/SerializationContext.js +16 -13
  99. package/types/ArrayType.d.ts +1 -1
  100. package/types/ArrayType.js +2 -3
  101. package/types/BigIntType.d.ts +8 -6
  102. package/types/BigIntType.js +1 -1
  103. package/types/BlobType.d.ts +0 -1
  104. package/types/BlobType.js +0 -3
  105. package/types/BooleanType.d.ts +2 -1
  106. package/types/BooleanType.js +3 -0
  107. package/types/DecimalType.d.ts +6 -4
  108. package/types/DecimalType.js +3 -3
  109. package/types/DoubleType.js +2 -2
  110. package/types/EnumArrayType.js +1 -2
  111. package/types/JsonType.d.ts +1 -1
  112. package/types/JsonType.js +7 -2
  113. package/types/TinyIntType.js +1 -1
  114. package/types/Type.d.ts +2 -4
  115. package/types/Type.js +3 -3
  116. package/types/Uint8ArrayType.d.ts +0 -1
  117. package/types/Uint8ArrayType.js +1 -4
  118. package/types/index.d.ts +1 -1
  119. package/typings.d.ts +157 -112
  120. package/typings.js +55 -42
  121. package/unit-of-work/ChangeSet.d.ts +2 -6
  122. package/unit-of-work/ChangeSet.js +4 -5
  123. package/unit-of-work/ChangeSetComputer.d.ts +1 -3
  124. package/unit-of-work/ChangeSetComputer.js +14 -12
  125. package/unit-of-work/ChangeSetPersister.d.ts +5 -4
  126. package/unit-of-work/ChangeSetPersister.js +65 -33
  127. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  128. package/unit-of-work/CommitOrderCalculator.js +13 -13
  129. package/unit-of-work/UnitOfWork.d.ts +10 -3
  130. package/unit-of-work/UnitOfWork.js +139 -96
  131. package/utils/AbstractSchemaGenerator.d.ts +5 -5
  132. package/utils/AbstractSchemaGenerator.js +18 -16
  133. package/utils/AsyncContext.d.ts +6 -0
  134. package/utils/AsyncContext.js +42 -0
  135. package/utils/Configuration.d.ts +754 -207
  136. package/utils/Configuration.js +146 -190
  137. package/utils/ConfigurationLoader.d.ts +1 -54
  138. package/utils/ConfigurationLoader.js +1 -352
  139. package/utils/Cursor.d.ts +0 -3
  140. package/utils/Cursor.js +9 -6
  141. package/utils/DataloaderUtils.d.ts +15 -5
  142. package/utils/DataloaderUtils.js +65 -17
  143. package/utils/EntityComparator.d.ts +13 -9
  144. package/utils/EntityComparator.js +85 -43
  145. package/utils/QueryHelper.d.ts +14 -6
  146. package/utils/QueryHelper.js +87 -25
  147. package/utils/RawQueryFragment.d.ts +48 -25
  148. package/utils/RawQueryFragment.js +66 -70
  149. package/utils/RequestContext.js +2 -2
  150. package/utils/TransactionContext.js +2 -2
  151. package/utils/TransactionManager.d.ts +65 -0
  152. package/utils/TransactionManager.js +223 -0
  153. package/utils/Utils.d.ts +12 -119
  154. package/utils/Utils.js +97 -373
  155. package/utils/clone.js +8 -23
  156. package/utils/env-vars.d.ts +7 -0
  157. package/utils/env-vars.js +97 -0
  158. package/utils/fs-utils.d.ts +32 -0
  159. package/utils/fs-utils.js +178 -0
  160. package/utils/index.d.ts +2 -1
  161. package/utils/index.js +2 -1
  162. package/utils/upsert-utils.d.ts +9 -4
  163. package/utils/upsert-utils.js +55 -4
  164. package/decorators/Check.d.ts +0 -3
  165. package/decorators/Check.js +0 -13
  166. package/decorators/CreateRequestContext.d.ts +0 -3
  167. package/decorators/CreateRequestContext.js +0 -32
  168. package/decorators/Embeddable.d.ts +0 -8
  169. package/decorators/Embeddable.js +0 -11
  170. package/decorators/Embedded.d.ts +0 -18
  171. package/decorators/Embedded.js +0 -18
  172. package/decorators/Entity.d.ts +0 -18
  173. package/decorators/Entity.js +0 -12
  174. package/decorators/Enum.d.ts +0 -9
  175. package/decorators/Enum.js +0 -16
  176. package/decorators/Filter.d.ts +0 -2
  177. package/decorators/Filter.js +0 -8
  178. package/decorators/Formula.d.ts +0 -4
  179. package/decorators/Formula.js +0 -15
  180. package/decorators/Indexed.d.ts +0 -19
  181. package/decorators/Indexed.js +0 -20
  182. package/decorators/ManyToMany.d.ts +0 -40
  183. package/decorators/ManyToMany.js +0 -14
  184. package/decorators/ManyToOne.d.ts +0 -30
  185. package/decorators/ManyToOne.js +0 -14
  186. package/decorators/OneToMany.d.ts +0 -28
  187. package/decorators/OneToMany.js +0 -17
  188. package/decorators/OneToOne.d.ts +0 -24
  189. package/decorators/OneToOne.js +0 -7
  190. package/decorators/PrimaryKey.d.ts +0 -8
  191. package/decorators/PrimaryKey.js +0 -20
  192. package/decorators/Property.d.ts +0 -250
  193. package/decorators/Property.js +0 -32
  194. package/decorators/Transactional.d.ts +0 -13
  195. package/decorators/Transactional.js +0 -28
  196. package/decorators/hooks.d.ts +0 -16
  197. package/decorators/hooks.js +0 -47
  198. package/decorators/index.d.ts +0 -17
  199. package/decorators/index.js +0 -17
  200. package/entity/ArrayCollection.d.ts +0 -116
  201. package/entity/ArrayCollection.js +0 -402
  202. package/entity/EntityValidator.d.ts +0 -19
  203. package/entity/EntityValidator.js +0 -150
  204. package/metadata/ReflectMetadataProvider.d.ts +0 -8
  205. package/metadata/ReflectMetadataProvider.js +0 -44
  206. package/utils/resolveContextProvider.d.ts +0 -10
  207. package/utils/resolveContextProvider.js +0 -28
@@ -1,5 +1,3 @@
1
- import { basename, extname } from 'node:path';
2
- import globby from 'globby';
3
1
  import { EntityMetadata, } from '../typings.js';
4
2
  import { Utils } from '../utils/Utils.js';
5
3
  import { MetadataValidator } from './MetadataValidator.js';
@@ -7,16 +5,16 @@ import { MetadataStorage } from './MetadataStorage.js';
7
5
  import { EntitySchema } from './EntitySchema.js';
8
6
  import { Cascade, ReferenceKind } from '../enums.js';
9
7
  import { MetadataError } from '../errors.js';
10
- import { ArrayType, BigIntType, BlobType, DateType, DecimalType, DoubleType, EnumArrayType, IntervalType, JsonType, t, Type, Uint8ArrayType, UnknownType, } from '../types/index.js';
8
+ import { t, Type } from '../types/index.js';
11
9
  import { colors } from '../logging/colors.js';
12
- import { raw, RawQueryFragment } from '../utils/RawQueryFragment.js';
10
+ import { raw, Raw } from '../utils/RawQueryFragment.js';
11
+ import { BaseEntity } from '../entity/BaseEntity.js';
13
12
  export class MetadataDiscovery {
14
13
  metadata;
15
14
  platform;
16
15
  config;
17
16
  namingStrategy;
18
17
  metadataProvider;
19
- cache;
20
18
  logger;
21
19
  schemaHelper;
22
20
  validator = new MetadataValidator();
@@ -27,11 +25,11 @@ export class MetadataDiscovery {
27
25
  this.config = config;
28
26
  this.namingStrategy = this.config.getNamingStrategy();
29
27
  this.metadataProvider = this.config.getMetadataProvider();
30
- this.cache = this.config.getMetadataCacheAdapter();
31
28
  this.logger = this.config.getLogger();
32
29
  this.schemaHelper = this.platform.getSchemaHelper();
33
30
  }
34
31
  async discover(preferTs = true) {
32
+ this.discovered.length = 0;
35
33
  const startTime = Date.now();
36
34
  this.logger.log('discovery', `ORM entity discovery started, using ${colors.cyan(this.metadataProvider.constructor.name)}`);
37
35
  await this.findEntities(preferTs);
@@ -47,10 +45,12 @@ export class MetadataDiscovery {
47
45
  await this.config.get('discovery').afterDiscovered?.(storage, this.platform);
48
46
  return storage;
49
47
  }
50
- discoverSync(preferTs = true) {
48
+ discoverSync() {
49
+ this.discovered.length = 0;
51
50
  const startTime = Date.now();
52
51
  this.logger.log('discovery', `ORM entity discovery started, using ${colors.cyan(this.metadataProvider.constructor.name)} in sync mode`);
53
- this.findEntities(preferTs, true);
52
+ const refs = this.config.get('entities');
53
+ this.discoverReferences(refs);
54
54
  for (const meta of this.discovered) {
55
55
  /* v8 ignore next */
56
56
  void this.config.get('discovery').onMetadata?.(meta, this.platform);
@@ -70,15 +70,48 @@ export class MetadataDiscovery {
70
70
  .sort((a, b) => b.root.name.localeCompare(a.root.name))
71
71
  .forEach(meta => {
72
72
  this.platform.validateMetadata(meta);
73
- discovered.set(meta.className, meta);
73
+ discovered.set(meta.class, meta);
74
74
  });
75
+ for (const meta of discovered) {
76
+ meta.root = discovered.get(meta.root.class);
77
+ }
75
78
  return discovered;
76
79
  }
80
+ initAccessors(meta) {
81
+ for (const prop of Object.values(meta.properties)) {
82
+ if (!prop.accessor || meta.properties[prop.accessor]) {
83
+ continue;
84
+ }
85
+ const desc = Object.getOwnPropertyDescriptor(meta.prototype, prop.name);
86
+ if (desc?.get || desc?.set) {
87
+ this.initFieldName(prop);
88
+ const accessor = prop.name;
89
+ prop.name = typeof prop.accessor === 'string' ? prop.accessor : prop.name;
90
+ if (prop.accessor === true) {
91
+ prop.getter = prop.setter = true;
92
+ }
93
+ else {
94
+ prop.getter = prop.setter = false;
95
+ }
96
+ prop.accessor = accessor;
97
+ prop.serializedName ??= accessor;
98
+ Utils.renameKey(meta.properties, accessor, prop.name);
99
+ }
100
+ else {
101
+ const name = prop.name;
102
+ prop.name = prop.accessor;
103
+ this.initFieldName(prop);
104
+ prop.serializedName ??= prop.accessor;
105
+ prop.name = name;
106
+ }
107
+ }
108
+ }
77
109
  processDiscoveredEntities(discovered) {
78
110
  for (const meta of discovered) {
79
111
  let i = 1;
80
112
  Object.values(meta.properties).forEach(prop => meta.propertyOrder.set(prop.name, i++));
81
113
  Object.values(meta.properties).forEach(prop => this.initPolyEmbeddables(prop, discovered));
114
+ this.initAccessors(meta);
82
115
  }
83
116
  // ignore base entities (not annotated with @Entity)
84
117
  const filtered = discovered.filter(meta => meta.root.name);
@@ -86,66 +119,61 @@ export class MetadataDiscovery {
86
119
  filtered.sort((a, b) => !a.embeddable === !b.embeddable ? 0 : (a.embeddable ? 1 : -1));
87
120
  filtered.forEach(meta => this.initSingleTableInheritance(meta, filtered));
88
121
  filtered.forEach(meta => this.defineBaseEntityProperties(meta));
89
- filtered.forEach(meta => this.metadata.set(meta.className, EntitySchema.fromMetadata(meta).init().meta));
122
+ filtered.forEach(meta => {
123
+ const newMeta = EntitySchema.fromMetadata(meta).init().meta;
124
+ return this.metadata.set(newMeta.class, newMeta);
125
+ });
90
126
  filtered.forEach(meta => this.initAutoincrement(meta));
91
- filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initEmbeddables(meta, prop)));
92
- filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initFactoryField(meta, prop)));
93
- filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initFieldName(prop)));
94
- filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initVersionProperty(meta, prop)));
95
- filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initCustomType(meta, prop)));
96
- filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initGeneratedColumn(meta, prop)));
127
+ const forEachProp = (cb) => {
128
+ filtered.forEach(meta => Object.values(meta.properties).forEach(prop => cb(meta, prop)));
129
+ };
130
+ forEachProp((m, p) => this.initFactoryField(m, p));
131
+ forEachProp((_m, p) => this.initRelation(p));
132
+ forEachProp((m, p) => this.initEmbeddables(m, p));
133
+ forEachProp((_m, p) => this.initFieldName(p));
134
+ forEachProp((m, p) => this.initVersionProperty(m, p));
135
+ forEachProp((m, p) => this.initCustomType(m, p));
136
+ forEachProp((m, p) => this.initGeneratedColumn(m, p));
97
137
  filtered.forEach(meta => this.initAutoincrement(meta)); // once again after we init custom types
98
138
  filtered.forEach(meta => this.initCheckConstraints(meta));
99
- for (const meta of filtered) {
100
- for (const prop of Object.values(meta.properties)) {
101
- this.initDefaultValue(prop);
102
- this.inferTypeFromDefault(prop);
103
- this.initColumnType(prop);
104
- // change tracking on scalars is used only for "auto" flushMode
105
- if (this.config.get('flushMode') !== 'auto' && [ReferenceKind.SCALAR, ReferenceKind.EMBEDDED].includes(prop.kind)) {
106
- prop.trackChanges = false;
107
- }
108
- }
109
- }
110
- filtered.forEach(meta => Object.values(meta.properties).forEach(prop => this.initIndexes(meta, prop)));
139
+ forEachProp((_m, p) => {
140
+ this.initDefaultValue(p);
141
+ this.inferTypeFromDefault(p);
142
+ this.initRelation(p);
143
+ this.initColumnType(p);
144
+ });
145
+ forEachProp((m, p) => this.initIndexes(m, p));
111
146
  filtered.forEach(meta => this.autoWireBidirectionalProperties(meta));
112
- filtered.forEach(meta => this.findReferencingProperties(meta, filtered));
113
147
  for (const meta of filtered) {
114
148
  discovered.push(...this.processEntity(meta));
115
149
  }
116
150
  discovered.forEach(meta => meta.sync(true));
117
- const combinedCachePath = this.cache.combine?.();
118
- // override the path in the options, so we can log it from the CLI in `cache:generate` command
119
- if (combinedCachePath) {
120
- this.config.get('metadataCache').combined = combinedCachePath;
121
- }
151
+ this.metadataProvider.combineCache();
122
152
  return discovered.map(meta => {
123
- meta = this.metadata.get(meta.className);
153
+ meta = this.metadata.get(meta.class);
124
154
  meta.sync(true);
155
+ this.findReferencingProperties(meta, filtered);
125
156
  return meta;
126
157
  });
127
158
  }
128
- findEntities(preferTs, sync = false) {
129
- this.discovered.length = 0;
130
- const options = this.config.get('discovery');
131
- const key = (preferTs && this.config.get('preferTs', Utils.detectTypeScriptSupport()) && this.config.get('entitiesTs').length > 0) ? 'entitiesTs' : 'entities';
132
- const paths = this.config.get(key).filter(item => Utils.isString(item));
133
- const refs = this.config.get(key).filter(item => !Utils.isString(item));
134
- if (paths.length > 0) {
135
- if (sync || options.requireEntitiesArray) {
136
- throw new Error(`[requireEntitiesArray] Explicit list of entities is required, please use the 'entities' option.`);
159
+ async findEntities(preferTs) {
160
+ const { entities, entitiesTs, baseDir } = this.config.getAll();
161
+ const targets = (preferTs && entitiesTs.length > 0) ? entitiesTs : entities;
162
+ const processed = [];
163
+ const paths = [];
164
+ for (const entity of targets) {
165
+ if (typeof entity === 'string') {
166
+ paths.push(entity);
167
+ }
168
+ else {
169
+ processed.push(entity);
137
170
  }
138
- return this.discoverDirectories(paths).then(() => {
139
- this.discoverReferences(refs);
140
- this.discoverMissingTargets();
141
- this.validator.validateDiscovered(this.discovered, options);
142
- return this.discovered;
143
- });
144
171
  }
145
- this.discoverReferences(refs);
146
- this.discoverMissingTargets();
147
- this.validator.validateDiscovered(this.discovered, options);
148
- return this.discovered;
172
+ if (paths.length > 0) {
173
+ const { discoverEntities } = await import('@mikro-orm/core/file-discovery');
174
+ processed.push(...await discoverEntities(paths, { baseDir }));
175
+ }
176
+ return this.discoverReferences(processed);
149
177
  }
150
178
  discoverMissingTargets() {
151
179
  const unwrap = (type) => type
@@ -154,17 +182,22 @@ export class MetadataDiscovery {
154
182
  .replace(/\((.*)\)/, '$1'); // unwrap union types
155
183
  const missing = [];
156
184
  this.discovered.forEach(meta => Object.values(meta.properties).forEach(prop => {
157
- if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.pivotEntity && !this.discovered.find(m => m.className === Utils.className(prop.pivotEntity))) {
158
- const target = typeof prop.pivotEntity === 'function'
159
- ? prop.pivotEntity()
160
- : prop.pivotEntity;
161
- missing.push(target);
185
+ if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.pivotEntity) {
186
+ const pivotEntity = prop.pivotEntity;
187
+ const target = typeof pivotEntity === 'function' && !pivotEntity.prototype
188
+ ? pivotEntity()
189
+ : pivotEntity;
190
+ if (!this.discovered.find(m => m.className === Utils.className(target))) {
191
+ missing.push(target);
192
+ }
162
193
  }
163
- if (prop.kind !== ReferenceKind.SCALAR && !unwrap(prop.type).split(/ ?\| ?/).every(type => this.discovered.find(m => m.className === type))) {
164
- const target = typeof prop.entity === 'function'
194
+ if (prop.kind !== ReferenceKind.SCALAR) {
195
+ const target = typeof prop.entity === 'function' && !prop.entity.prototype
165
196
  ? prop.entity()
166
197
  : prop.type;
167
- missing.push(...Utils.asArray(target));
198
+ if (!unwrap(prop.type).split(/ ?\| ?/).every(type => this.discovered.find(m => m.className === type))) {
199
+ missing.push(...Utils.asArray(target));
200
+ }
168
201
  }
169
202
  }));
170
203
  if (missing.length > 0) {
@@ -173,122 +206,99 @@ export class MetadataDiscovery {
173
206
  }
174
207
  tryDiscoverTargets(targets) {
175
208
  for (const target of targets) {
176
- if (typeof target === 'function' && target.name && !this.metadata.has(target.name)) {
177
- this.discoverReferences([target]);
209
+ const isDiscoverable = typeof target === 'function' || target instanceof EntitySchema;
210
+ if (isDiscoverable && target.name && !this.metadata.has(target)) {
211
+ this.discoverReferences([target], false);
178
212
  this.discoverMissingTargets();
179
213
  }
180
214
  }
181
215
  }
182
- async discoverDirectories(paths) {
183
- paths = paths.map(path => Utils.normalizePath(path));
184
- const files = await globby(paths, { cwd: Utils.normalizePath(this.config.get('baseDir')) });
185
- this.logger.log('discovery', `- processing ${colors.cyan('' + files.length)} files`);
186
- const found = [];
187
- for (const filepath of files) {
188
- const filename = basename(filepath);
189
- if (!filename.match(/\.[cm]?[jt]s$/) ||
190
- filename.endsWith('.js.map') ||
191
- filename.match(/\.d\.[cm]?ts/) ||
192
- filename.startsWith('.') ||
193
- filename.match(/index\.[cm]?[jt]s$/)) {
194
- this.logger.log('discovery', `- ignoring file ${filename}`);
195
- continue;
196
- }
197
- const name = this.namingStrategy.getClassName(filename);
198
- const path = Utils.normalizePath(this.config.get('baseDir'), filepath);
199
- const targets = await this.getEntityClassOrSchema(path, name);
200
- for (const target of targets) {
201
- if (!(target instanceof Function) && !(target instanceof EntitySchema)) {
202
- this.logger.log('discovery', `- ignoring file ${filename}`);
203
- continue;
204
- }
205
- const entity = this.prepare(target);
206
- const schema = this.getSchema(entity, path);
207
- const meta = schema.init().meta;
208
- this.metadata.set(meta.className, meta);
209
- found.push([schema, path]);
210
- }
211
- }
212
- for (const [schema, path] of found) {
213
- this.discoverEntity(schema, path);
214
- }
215
- }
216
- discoverReferences(refs) {
216
+ discoverReferences(refs, validate = true) {
217
217
  const found = [];
218
218
  for (const entity of refs) {
219
- const schema = this.getSchema(this.prepare(entity));
219
+ if (typeof entity === 'string') {
220
+ throw new Error('Folder based discovery requires the async `MikroORM.init()` method.');
221
+ }
222
+ const schema = this.getSchema(entity);
220
223
  const meta = schema.init().meta;
221
- this.metadata.set(meta.className, meta);
224
+ this.metadata.set(meta.class, meta);
222
225
  found.push(schema);
223
226
  }
224
227
  // discover parents (base entities) automatically
225
228
  for (const meta of this.metadata) {
226
229
  let parent = meta.extends;
227
- if (parent instanceof EntitySchema && !this.metadata.has(parent.meta.className)) {
228
- this.discoverReferences([parent]);
230
+ if (parent instanceof EntitySchema && !this.metadata.has(parent.init().meta.class)) {
231
+ this.discoverReferences([parent], false);
229
232
  }
230
- /* v8 ignore next 3 */
233
+ if (typeof parent === 'function' && parent.name && !this.metadata.has(parent)) {
234
+ this.discoverReferences([parent], false);
235
+ }
236
+ /* v8 ignore next */
231
237
  if (!meta.class) {
232
238
  continue;
233
239
  }
234
240
  parent = Object.getPrototypeOf(meta.class);
235
- if (parent.name !== '' && !this.metadata.has(parent.name)) {
236
- this.discoverReferences([parent]);
241
+ if (parent.name !== '' && !this.metadata.has(parent) && parent !== BaseEntity) {
242
+ this.discoverReferences([parent], false);
237
243
  }
238
244
  }
239
245
  for (const schema of found) {
240
246
  this.discoverEntity(schema);
241
247
  }
248
+ this.discoverMissingTargets();
249
+ if (validate) {
250
+ this.validator.validateDiscovered(this.discovered, this.config.get('discovery'));
251
+ }
242
252
  return this.discovered.filter(meta => found.find(m => m.name === meta.className));
243
253
  }
244
- reset(className) {
245
- const exists = this.discovered.findIndex(m => m.className === className);
254
+ reset(entityName) {
255
+ const exists = this.discovered.findIndex(m => m.class === entityName || m.className === Utils.className(entityName));
246
256
  if (exists !== -1) {
247
- this.metadata.reset(this.discovered[exists].className);
257
+ this.metadata.reset(this.discovered[exists].class);
248
258
  this.discovered.splice(exists, 1);
249
259
  }
250
260
  }
251
- prepare(entity) {
252
- /* v8 ignore next 3 */
253
- if ('schema' in entity && entity.schema instanceof EntitySchema) {
254
- return entity.schema;
255
- }
261
+ getSchema(entity) {
256
262
  if (EntitySchema.REGISTRY.has(entity)) {
257
- return EntitySchema.REGISTRY.get(entity);
263
+ entity = EntitySchema.REGISTRY.get(entity);
258
264
  }
259
- return entity;
260
- }
261
- getSchema(entity, filepath) {
262
265
  if (entity instanceof EntitySchema) {
263
- if (filepath) {
264
- // initialize global metadata for given entity
265
- MetadataStorage.getMetadata(entity.meta.className, filepath);
266
- }
267
- return entity;
266
+ const meta = Utils.copy(entity.meta, false);
267
+ return EntitySchema.fromMetadata(meta);
268
268
  }
269
269
  const path = entity[MetadataStorage.PATH_SYMBOL];
270
270
  if (path) {
271
271
  const meta = Utils.copy(MetadataStorage.getMetadata(entity.name, path), false);
272
- meta.path = Utils.relativePath(path, this.config.get('baseDir'));
273
- this.metadata.set(entity.name, meta);
272
+ meta.path = path;
273
+ this.metadata.set(entity, meta);
274
274
  }
275
- const exists = this.metadata.has(entity.name);
276
- const meta = this.metadata.get(entity.name, true);
275
+ const exists = this.metadata.has(entity);
276
+ const meta = this.metadata.get(entity, true);
277
277
  meta.abstract ??= !(exists && meta.name);
278
278
  const schema = EntitySchema.fromMetadata(meta);
279
279
  schema.setClass(entity);
280
280
  return schema;
281
281
  }
282
- discoverEntity(schema, path) {
283
- this.logger.log('discovery', `- processing entity ${colors.cyan(schema.meta.className)}${colors.grey(path ? ` (${path})` : '')}`);
282
+ getRootEntity(meta) {
283
+ const base = meta.extends && this.metadata.find(meta.extends);
284
+ if (!base || base === meta) { // make sure we do not fall into infinite loop
285
+ return meta;
286
+ }
287
+ const root = this.getRootEntity(base);
288
+ if (root.discriminatorColumn) {
289
+ return root;
290
+ }
291
+ return meta;
292
+ }
293
+ discoverEntity(schema) {
284
294
  const meta = schema.meta;
285
- const root = Utils.getRootEntity(this.metadata, meta);
286
- schema.meta.path = Utils.relativePath(path || meta.path, this.config.get('baseDir'));
287
- const cache = this.metadataProvider.useCache() && meta.path && this.cache.get(meta.className + extname(meta.path));
295
+ const path = meta.path;
296
+ this.logger.log('discovery', `- processing entity ${colors.cyan(meta.className)}${colors.grey(path ? ` (${path})` : '')}`);
297
+ const root = this.getRootEntity(meta);
298
+ schema.meta.path = meta.path;
299
+ const cache = this.metadataProvider.getCachedMetadata(meta, root);
288
300
  if (cache) {
289
301
  this.logger.log('discovery', `- using cached metadata for entity ${colors.cyan(meta.className)}`);
290
- this.metadataProvider.loadFromCache(meta, cache);
291
- meta.root = root;
292
302
  this.discovered.push(meta);
293
303
  return;
294
304
  }
@@ -297,50 +307,18 @@ export class MetadataDiscovery {
297
307
  this.inferDefaultValue(meta, prop);
298
308
  }
299
309
  // if the definition is using EntitySchema we still want it to go through the metadata provider to validate no types are missing
300
- this.metadataProvider.loadEntityMetadata(meta, meta.className);
301
- if (!meta.collection && meta.name) {
310
+ this.metadataProvider.loadEntityMetadata(meta);
311
+ if (!meta.tableName && meta.name) {
302
312
  const entityName = root.discriminatorColumn ? root.name : meta.name;
303
- meta.collection = this.namingStrategy.classToTableName(entityName);
313
+ meta.tableName = this.namingStrategy.classToTableName(entityName);
304
314
  }
305
- delete meta.root; // to allow caching (as root can contain cycles)
306
- this.saveToCache(meta);
315
+ this.metadataProvider.saveToCache(meta);
307
316
  meta.root = root;
308
317
  this.discovered.push(meta);
309
318
  }
310
- saveToCache(meta) {
311
- if (!this.metadataProvider.useCache()) {
312
- return;
313
- }
314
- const copy = Utils.copy(meta, false);
315
- for (const prop of copy.props) {
316
- if (Type.isMappedType(prop.type)) {
317
- Reflect.deleteProperty(prop, 'type');
318
- Reflect.deleteProperty(prop, 'customType');
319
- }
320
- if (prop.default) {
321
- const raw = RawQueryFragment.getKnownFragment(prop.default);
322
- if (raw) {
323
- prop.defaultRaw ??= this.platform.formatQuery(raw.sql, raw.params);
324
- Reflect.deleteProperty(prop, 'default');
325
- }
326
- }
327
- Reflect.deleteProperty(prop, 'targetMeta');
328
- }
329
- [
330
- 'prototype', 'props', 'referencingProperties', 'propertyOrder', 'relations',
331
- 'concurrencyCheckKeys', 'checks',
332
- ].forEach(key => delete copy[key]);
333
- // base entity without properties might not have path, but nothing to cache there
334
- if (meta.path) {
335
- this.cache.set(meta.className + extname(meta.path), copy, meta.path);
336
- }
337
- }
338
319
  initNullability(prop) {
339
- if (prop.kind === ReferenceKind.MANY_TO_ONE) {
340
- return Utils.defaultValue(prop, 'nullable', prop.optional || prop.cascade.includes(Cascade.REMOVE) || prop.cascade.includes(Cascade.ALL));
341
- }
342
320
  if (prop.kind === ReferenceKind.ONE_TO_ONE) {
343
- return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner || prop.cascade.includes(Cascade.REMOVE) || prop.cascade.includes(Cascade.ALL));
321
+ return Utils.defaultValue(prop, 'nullable', prop.optional || !prop.owner);
344
322
  }
345
323
  return Utils.defaultValue(prop, 'nullable', prop.optional);
346
324
  }
@@ -375,7 +353,7 @@ export class MetadataDiscovery {
375
353
  if (prop.joinColumns.length !== prop.columnTypes.length) {
376
354
  prop.columnTypes = prop.joinColumns.flatMap(field => {
377
355
  const matched = meta.props.find(p => p.fieldNames?.includes(field));
378
- /* v8 ignore next 3 */
356
+ /* v8 ignore next */
379
357
  if (!matched) {
380
358
  throw MetadataError.fromWrongForeignKey(meta, prop, 'columnTypes');
381
359
  }
@@ -402,7 +380,7 @@ export class MetadataDiscovery {
402
380
  }
403
381
  }
404
382
  initManyToOneFieldName(prop, name) {
405
- const meta2 = this.metadata.get(prop.type);
383
+ const meta2 = prop.targetMeta;
406
384
  const ret = [];
407
385
  for (const primaryKey of meta2.primaryKeys) {
408
386
  this.initFieldName(meta2.properties[primaryKey]);
@@ -413,11 +391,11 @@ export class MetadataDiscovery {
413
391
  return ret;
414
392
  }
415
393
  initManyToManyFieldName(prop, name) {
416
- const meta2 = this.metadata.get(prop.type);
394
+ const meta2 = prop.targetMeta;
417
395
  return meta2.primaryKeys.map(() => this.namingStrategy.propertyToColumnName(name));
418
396
  }
419
397
  initManyToManyFields(meta, prop) {
420
- const meta2 = this.metadata.get(prop.type);
398
+ const meta2 = prop.targetMeta;
421
399
  Utils.defaultValue(prop, 'fixedOrder', !!prop.fixedOrderColumn);
422
400
  const pivotMeta = this.metadata.find(prop.pivotEntity);
423
401
  const props = Object.values(pivotMeta?.properties ?? {});
@@ -438,26 +416,26 @@ export class MetadataDiscovery {
438
416
  prop.inverseJoinColumns ??= second.fieldNames;
439
417
  }
440
418
  if (!prop.pivotTable && prop.owner && this.platform.usesPivotTable()) {
441
- prop.pivotTable = this.namingStrategy.joinTableName(meta.tableName, meta2.tableName, prop.name);
419
+ prop.pivotTable = this.namingStrategy.joinTableName(meta.className, meta2.tableName, prop.name, meta.tableName);
442
420
  }
443
421
  if (prop.mappedBy) {
444
422
  const prop2 = meta2.properties[prop.mappedBy];
445
423
  this.initManyToManyFields(meta2, prop2);
446
424
  prop.pivotTable = prop2.pivotTable;
447
- prop.pivotEntity = prop2.pivotEntity ?? prop2.pivotTable;
425
+ prop.pivotEntity = prop2.pivotEntity;
448
426
  prop.fixedOrder = prop2.fixedOrder;
449
427
  prop.fixedOrderColumn = prop2.fixedOrderColumn;
450
428
  prop.joinColumns = prop2.inverseJoinColumns;
451
429
  prop.inverseJoinColumns = prop2.joinColumns;
452
430
  }
453
431
  prop.referencedColumnNames ??= Utils.flatten(meta.primaryKeys.map(primaryKey => meta.properties[primaryKey].fieldNames));
454
- prop.joinColumns ??= prop.referencedColumnNames.map(referencedColumnName => this.namingStrategy.joinKeyColumnName(meta.root.className, referencedColumnName, meta.compositePK));
432
+ prop.joinColumns ??= prop.referencedColumnNames.map(referencedColumnName => this.namingStrategy.joinKeyColumnName(meta.root.className, referencedColumnName, meta.compositePK, meta.root.tableName));
455
433
  prop.inverseJoinColumns ??= this.initManyToOneFieldName(prop, meta2.root.className);
456
434
  }
457
435
  initManyToOneFields(prop) {
458
- const meta2 = this.metadata.get(prop.type);
436
+ const meta2 = prop.targetMeta;
459
437
  const fieldNames = Utils.flatten(meta2.primaryKeys.map(primaryKey => meta2.properties[primaryKey].fieldNames));
460
- Utils.defaultValue(prop, 'referencedTableName', meta2.collection);
438
+ Utils.defaultValue(prop, 'referencedTableName', meta2.tableName);
461
439
  if (!prop.joinColumns) {
462
440
  prop.joinColumns = fieldNames.map(fieldName => this.namingStrategy.joinKeyColumnName(prop.name, fieldName, fieldNames.length > 1));
463
441
  }
@@ -466,7 +444,7 @@ export class MetadataDiscovery {
466
444
  }
467
445
  }
468
446
  initOneToManyFields(prop) {
469
- const meta2 = this.metadata.get(prop.type);
447
+ const meta2 = prop.targetMeta;
470
448
  if (!prop.joinColumns) {
471
449
  prop.joinColumns = [this.namingStrategy.joinColumnName(prop.name)];
472
450
  }
@@ -484,7 +462,7 @@ export class MetadataDiscovery {
484
462
  pks[0].deleteRule ??= 'cascade';
485
463
  }
486
464
  meta.forceConstructor ??= this.shouldForceConstructorUsage(meta);
487
- this.validator.validateEntityDefinition(this.metadata, meta.className, this.config.get('discovery'));
465
+ this.validator.validateEntityDefinition(this.metadata, meta.class, this.config.get('discovery'));
488
466
  for (const prop of Object.values(meta.properties)) {
489
467
  this.initNullability(prop);
490
468
  this.applyNamingStrategy(meta, prop);
@@ -497,15 +475,21 @@ export class MetadataDiscovery {
497
475
  }
498
476
  this.initOwnColumns(meta);
499
477
  meta.simplePK = pks.length === 1 && pks[0].kind === ReferenceKind.SCALAR && !pks[0].customType && pks[0].runtimeType !== 'Date';
500
- meta.serializedPrimaryKey = this.platform.getSerializedPrimaryKeyField(meta.primaryKeys[0]);
501
- const serializedPKProp = meta.properties[meta.serializedPrimaryKey];
502
- if (serializedPKProp && meta.serializedPrimaryKey !== meta.primaryKeys[0]) {
503
- serializedPKProp.persist = false;
478
+ meta.serializedPrimaryKey ??= meta.props.find(prop => prop.serializedPrimaryKey)?.name;
479
+ if (meta.serializedPrimaryKey && meta.serializedPrimaryKey !== meta.primaryKeys[0]) {
480
+ meta.properties[meta.serializedPrimaryKey].persist ??= false;
504
481
  }
505
482
  if (this.platform.usesPivotTable()) {
506
483
  return Object.values(meta.properties)
507
484
  .filter(prop => prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && prop.pivotTable)
508
- .map(prop => this.definePivotTableEntity(meta, prop));
485
+ .map(prop => {
486
+ const pivotMeta = this.definePivotTableEntity(meta, prop);
487
+ prop.pivotEntity = pivotMeta.class;
488
+ if (prop.inversedBy) {
489
+ prop.targetMeta.properties[prop.inversedBy].pivotEntity = pivotMeta.class;
490
+ }
491
+ return pivotMeta;
492
+ });
509
493
  }
510
494
  return [];
511
495
  }
@@ -522,8 +506,11 @@ export class MetadataDiscovery {
522
506
  ['mappedBy', 'inversedBy', 'pivotEntity'].forEach(type => {
523
507
  const value = prop[type];
524
508
  if (value instanceof Function) {
525
- const meta2 = this.metadata.get(prop.type);
509
+ const meta2 = prop.targetMeta ?? this.metadata.get(prop.target);
526
510
  prop[type] = value(meta2.properties)?.name;
511
+ if (type === 'pivotEntity' && value) {
512
+ prop[type] = value(meta2.properties);
513
+ }
527
514
  if (prop[type] == null) {
528
515
  throw MetadataError.fromWrongReference(meta, prop, type);
529
516
  }
@@ -539,9 +526,9 @@ export class MetadataDiscovery {
539
526
  }
540
527
  else if (fks.length >= 2) {
541
528
  [first, second] = fks;
542
- /* v8 ignore next 3 */
543
529
  }
544
530
  else {
531
+ /* v8 ignore next */
545
532
  return [];
546
533
  }
547
534
  // wrong FK order, first FK needs to point to the owning side
@@ -555,7 +542,9 @@ export class MetadataDiscovery {
555
542
  return [first, second];
556
543
  }
557
544
  definePivotTableEntity(meta, prop) {
558
- const pivotMeta = this.metadata.find(prop.pivotEntity);
545
+ const pivotMeta = prop.pivotEntity
546
+ ? this.metadata.find(prop.pivotEntity)
547
+ : this.metadata.getByClassName(prop.pivotTable, false);
559
548
  // ensure inverse side exists so we can join it when populating via pivot tables
560
549
  if (!prop.inversedBy && prop.targetMeta) {
561
550
  const inverseName = `${meta.className}_${prop.name}__inverse`;
@@ -564,6 +553,8 @@ export class MetadataDiscovery {
564
553
  name: inverseName,
565
554
  kind: ReferenceKind.MANY_TO_MANY,
566
555
  type: meta.className,
556
+ target: meta.class,
557
+ targetMeta: meta,
567
558
  mappedBy: prop.name,
568
559
  pivotEntity: prop.pivotEntity,
569
560
  pivotTable: prop.pivotTable,
@@ -572,55 +563,51 @@ export class MetadataDiscovery {
572
563
  };
573
564
  this.applyNamingStrategy(prop.targetMeta, inverseProp);
574
565
  this.initCustomType(prop.targetMeta, inverseProp);
575
- this.initRelation(inverseProp);
576
566
  prop.targetMeta.properties[inverseName] = inverseProp;
577
567
  }
578
568
  if (pivotMeta) {
569
+ prop.pivotEntity = pivotMeta.class;
579
570
  this.ensureCorrectFKOrderInPivotEntity(pivotMeta, prop);
580
571
  return pivotMeta;
581
572
  }
582
- const exists = this.metadata.find(prop.pivotTable);
583
- if (exists) {
584
- prop.pivotEntity = exists.className;
585
- return exists;
586
- }
587
573
  let tableName = prop.pivotTable;
588
574
  let schemaName;
589
575
  if (prop.pivotTable.includes('.')) {
590
576
  [schemaName, tableName] = prop.pivotTable.split('.');
591
577
  }
592
578
  schemaName ??= meta.schema;
593
- const targetType = prop.targetMeta.className;
594
- const data = new EntityMetadata({
579
+ const targetMeta = prop.targetMeta;
580
+ const targetType = targetMeta.className;
581
+ const pivotMeta2 = new EntityMetadata({
595
582
  name: prop.pivotTable,
596
583
  className: prop.pivotTable,
597
584
  collection: tableName,
598
585
  schema: schemaName,
599
586
  pivotTable: true,
600
587
  });
601
- prop.pivotEntity = data.className;
588
+ prop.pivotEntity = pivotMeta2.class;
602
589
  if (prop.fixedOrder) {
603
- const primaryProp = this.defineFixedOrderProperty(prop, targetType);
604
- data.properties[primaryProp.name] = primaryProp;
590
+ const primaryProp = this.defineFixedOrderProperty(prop, targetMeta);
591
+ pivotMeta2.properties[primaryProp.name] = primaryProp;
605
592
  }
606
593
  else {
607
- data.compositePK = true;
594
+ pivotMeta2.compositePK = true;
608
595
  }
609
596
  // handle self-referenced m:n with same default field names
610
597
  if (meta.className === targetType && prop.joinColumns.every((joinColumn, idx) => joinColumn === prop.inverseJoinColumns[idx])) {
611
- prop.joinColumns = prop.referencedColumnNames.map(name => this.namingStrategy.joinKeyColumnName(meta.className + '_1', name, meta.compositePK));
612
- prop.inverseJoinColumns = prop.referencedColumnNames.map(name => this.namingStrategy.joinKeyColumnName(meta.className + '_2', name, meta.compositePK));
598
+ prop.joinColumns = prop.referencedColumnNames.map(name => this.namingStrategy.joinKeyColumnName(meta.tableName + '_1', name, meta.compositePK));
599
+ prop.inverseJoinColumns = prop.referencedColumnNames.map(name => this.namingStrategy.joinKeyColumnName(meta.tableName + '_2', name, meta.compositePK));
613
600
  if (prop.inversedBy) {
614
- const prop2 = this.metadata.get(targetType).properties[prop.inversedBy];
601
+ const prop2 = targetMeta.properties[prop.inversedBy];
615
602
  prop2.inverseJoinColumns = prop.joinColumns;
616
603
  prop2.joinColumns = prop.inverseJoinColumns;
617
604
  }
618
605
  }
619
- data.properties[meta.name + '_owner'] = this.definePivotProperty(prop, meta.name + '_owner', meta.className, targetType + '_inverse', true, meta.className === targetType);
620
- data.properties[targetType + '_inverse'] = this.definePivotProperty(prop, targetType + '_inverse', targetType, meta.name + '_owner', false, meta.className === targetType);
621
- return this.metadata.set(data.className, data);
606
+ pivotMeta2.properties[meta.name + '_owner'] = this.definePivotProperty(prop, meta.name + '_owner', meta.class, targetType + '_inverse', true, meta.className === targetType);
607
+ pivotMeta2.properties[targetType + '_inverse'] = this.definePivotProperty(prop, targetType + '_inverse', targetMeta.class, meta.name + '_owner', false, meta.className === targetType);
608
+ return this.metadata.set(pivotMeta2.class, EntitySchema.fromMetadata(pivotMeta2).init().meta);
622
609
  }
623
- defineFixedOrderProperty(prop, targetType) {
610
+ defineFixedOrderProperty(prop, targetMeta) {
624
611
  const pk = prop.fixedOrderColumn || this.namingStrategy.referenceColumnName();
625
612
  const primaryProp = {
626
613
  name: pk,
@@ -634,7 +621,7 @@ export class MetadataDiscovery {
634
621
  this.initColumnType(primaryProp);
635
622
  prop.fixedOrderColumn = pk;
636
623
  if (prop.inversedBy) {
637
- const prop2 = this.metadata.get(targetType).properties[prop.inversedBy];
624
+ const prop2 = targetMeta.properties[prop.inversedBy];
638
625
  prop2.fixedOrder = true;
639
626
  prop2.fixedOrderColumn = pk;
640
627
  }
@@ -643,7 +630,8 @@ export class MetadataDiscovery {
643
630
  definePivotProperty(prop, name, type, inverse, owner, selfReferencing) {
644
631
  const ret = {
645
632
  name,
646
- type,
633
+ type: Utils.className(type),
634
+ target: type,
647
635
  kind: ReferenceKind.MANY_TO_ONE,
648
636
  cascade: [Cascade.ALL],
649
637
  fixedOrder: prop.fixedOrder,
@@ -653,6 +641,7 @@ export class MetadataDiscovery {
653
641
  autoincrement: false,
654
642
  updateRule: prop.updateRule,
655
643
  deleteRule: prop.deleteRule,
644
+ createForeignKeyConstraint: prop.createForeignKeyConstraint,
656
645
  };
657
646
  if (selfReferencing && !this.platform.supportsMultipleCascadePaths()) {
658
647
  ret.updateRule ??= 'no action';
@@ -700,7 +689,7 @@ export class MetadataDiscovery {
700
689
  Object.values(meta.properties)
701
690
  .filter(prop => prop.kind !== ReferenceKind.SCALAR && !prop.owner && prop.mappedBy)
702
691
  .forEach(prop => {
703
- const meta2 = this.metadata.get(prop.type);
692
+ const meta2 = prop.targetMeta;
704
693
  const prop2 = meta2.properties[prop.mappedBy];
705
694
  if (prop2 && !prop2.inversedBy) {
706
695
  prop2.inversedBy = prop.name;
@@ -708,7 +697,7 @@ export class MetadataDiscovery {
708
697
  });
709
698
  }
710
699
  defineBaseEntityProperties(meta) {
711
- const base = meta.extends && this.metadata.get(Utils.className(meta.extends));
700
+ const base = meta.extends && this.metadata.get(meta.extends);
712
701
  if (!base || base === meta) { // make sure we do not fall into infinite loop
713
702
  return 0;
714
703
  }
@@ -739,12 +728,9 @@ export class MetadataDiscovery {
739
728
  Utils.keys(base.hooks).forEach(type => {
740
729
  meta.hooks[type] = Utils.unique([...base.hooks[type], ...(meta.hooks[type] || [])]);
741
730
  });
742
- if (meta.constructorParams.length === 0 && base.constructorParams.length > 0) {
731
+ if ((meta.constructorParams?.length ?? 0) === 0 && (base.constructorParams?.length ?? 0) > 0) {
743
732
  meta.constructorParams = [...base.constructorParams];
744
733
  }
745
- if (meta.toJsonParams.length === 0 && base.toJsonParams.length > 0) {
746
- meta.toJsonParams = [...base.toJsonParams];
747
- }
748
734
  return order;
749
735
  }
750
736
  initPolyEmbeddables(embeddedProp, discovered, visited = new Set()) {
@@ -820,22 +806,30 @@ export class MetadataDiscovery {
820
806
  }
821
807
  return prop.embedded ? isParentObject(meta.properties[prop.embedded[0]]) : false;
822
808
  };
809
+ const isParentArray = (prop) => {
810
+ if (prop.array) {
811
+ return true;
812
+ }
813
+ return prop.embedded ? isParentArray(meta.properties[prop.embedded[0]]) : false;
814
+ };
823
815
  const rootProperty = getRootProperty(embeddedProp);
824
816
  const parentProperty = meta.properties[embeddedProp.embedded?.[0] ?? ''];
825
817
  const object = isParentObject(embeddedProp);
818
+ const array = isParentArray(embeddedProp);
826
819
  this.initFieldName(embeddedProp, rootProperty !== embeddedProp && object);
827
820
  // the prefix of the parent cannot be a boolean; it already passed here
828
821
  const prefix = this.getPrefix(embeddedProp, parentProperty);
829
822
  const glue = object ? '~' : '_';
830
823
  for (const prop of Object.values(embeddable.properties)) {
831
824
  const name = (embeddedProp.embeddedPath?.join(glue) ?? embeddedProp.fieldNames[0] + glue) + prop.name;
832
- meta.properties[name] = Utils.copy(prop, false);
825
+ meta.properties[name] = Utils.copy(prop);
833
826
  meta.properties[name].name = name;
834
827
  meta.properties[name].embedded = [embeddedProp.name, prop.name];
835
828
  meta.propertyOrder.set(name, (order += 0.01));
836
829
  embeddedProp.embeddedProps[prop.name] = meta.properties[name];
837
830
  meta.properties[name].persist ??= embeddedProp.persist;
838
- if (embeddedProp.nullable) {
831
+ const refInArray = array && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && prop.owner;
832
+ if (embeddedProp.nullable || refInArray) {
839
833
  meta.properties[name].nullable = true;
840
834
  }
841
835
  if (meta.properties[name].fieldNames) {
@@ -865,14 +859,17 @@ export class MetadataDiscovery {
865
859
  path = [embeddedProp.fieldNames[0]];
866
860
  }
867
861
  this.initFieldName(prop, true);
862
+ this.initRelation(prop);
868
863
  path.push(prop.fieldNames[0]);
869
864
  meta.properties[name].fieldNames = prop.fieldNames;
870
865
  meta.properties[name].embeddedPath = path;
871
- const fieldName = raw(this.platform.getSearchJsonPropertySQL(path.join('->'), prop.runtimeType ?? prop.type, true));
866
+ const targetProp = prop.targetMeta?.getPrimaryProp() ?? prop;
867
+ const fieldName = raw(this.platform.getSearchJsonPropertySQL(path.join('->'), targetProp.runtimeType ?? targetProp.type, true));
872
868
  meta.properties[name].fieldNameRaw = fieldName.sql; // for querying in SQL drivers
873
869
  meta.properties[name].persist = false; // only virtual as we store the whole object
874
870
  meta.properties[name].userDefined = false; // mark this as a generated/internal property, so we can distinguish from user-defined non-persist properties
875
871
  meta.properties[name].object = true;
872
+ this.initCustomType(meta, meta.properties[name], false, true);
876
873
  }
877
874
  this.initEmbeddables(meta, meta.properties[name], visited);
878
875
  }
@@ -895,7 +892,7 @@ export class MetadataDiscovery {
895
892
  }
896
893
  initSingleTableInheritance(meta, metadata) {
897
894
  if (meta.root !== meta && !meta.__processed) {
898
- meta.root = metadata.find(m => m.className === meta.root.className);
895
+ meta.root = metadata.find(m => m.class === meta.root.class);
899
896
  meta.root.__processed = true;
900
897
  }
901
898
  else {
@@ -904,17 +901,23 @@ export class MetadataDiscovery {
904
901
  if (!meta.root.discriminatorColumn) {
905
902
  return;
906
903
  }
907
- if (!meta.root.discriminatorMap) {
904
+ if (meta.root.discriminatorMap) {
905
+ const map = meta.root.discriminatorMap;
906
+ Object.keys(map)
907
+ .filter(key => typeof map[key] === 'string')
908
+ .forEach(key => map[key] = this.metadata.getByClassName(map[key]).class);
909
+ }
910
+ else {
908
911
  meta.root.discriminatorMap = {};
909
912
  const children = metadata
910
- .filter(m => m.root.className === meta.root.className && !m.abstract)
913
+ .filter(m => m.root.class === meta.root.class && !m.abstract)
911
914
  .sort((a, b) => a.className.localeCompare(b.className));
912
915
  for (const m of children) {
913
916
  const name = m.discriminatorValue ?? this.namingStrategy.classToTableName(m.className);
914
- meta.root.discriminatorMap[name] = m.className;
917
+ meta.root.discriminatorMap[name] = m.class;
915
918
  }
916
919
  }
917
- meta.discriminatorValue = Object.entries(meta.root.discriminatorMap).find(([, className]) => className === meta.className)?.[0];
920
+ meta.discriminatorValue = Object.entries(meta.root.discriminatorMap).find(([, cls]) => cls === meta.class)?.[0];
918
921
  if (!meta.root.properties[meta.root.discriminatorColumn]) {
919
922
  this.createDiscriminatorProperty(meta.root);
920
923
  }
@@ -941,10 +944,10 @@ export class MetadataDiscovery {
941
944
  newProp.items = Utils.unique([...meta.root.properties[prop.name].items, ...prop.items]);
942
945
  }
943
946
  newProp.nullable = true;
944
- newProp.inherited = true;
947
+ newProp.inherited = !meta.root.properties[prop.name];
945
948
  meta.root.addProperty(newProp);
946
949
  });
947
- meta.collection = meta.root.collection;
950
+ meta.tableName = meta.root.tableName;
948
951
  meta.root.indexes = Utils.unique([...meta.root.indexes, ...meta.indexes]);
949
952
  meta.root.uniques = Utils.unique([...meta.root.uniques, ...meta.uniques]);
950
953
  meta.root.checks = Utils.unique([...meta.root.checks, ...meta.checks]);
@@ -966,7 +969,7 @@ export class MetadataDiscovery {
966
969
  }
967
970
  }
968
971
  initCheckConstraints(meta) {
969
- const map = this.createColumnMappingObject(meta);
972
+ const map = meta.createColumnMappingObject();
970
973
  for (const check of meta.checks) {
971
974
  const columns = check.property ? meta.properties[check.property].fieldNames : [];
972
975
  check.name ??= this.namingStrategy.indexName(meta.tableName, columns, 'check');
@@ -976,7 +979,7 @@ export class MetadataDiscovery {
976
979
  }
977
980
  if (this.platform.usesEnumCheckConstraints() && !meta.embeddable) {
978
981
  for (const prop of meta.props) {
979
- if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => Utils.isString(item))) {
982
+ if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
980
983
  this.initFieldName(prop);
981
984
  meta.checks.push({
982
985
  name: this.namingStrategy.indexName(meta.tableName, prop.fieldNames, 'check'),
@@ -1001,38 +1004,28 @@ export class MetadataDiscovery {
1001
1004
  }
1002
1005
  return;
1003
1006
  }
1004
- const map = this.createColumnMappingObject(meta);
1007
+ const map = meta.createColumnMappingObject();
1005
1008
  if (prop.generated instanceof Function) {
1006
1009
  prop.generated = prop.generated(map);
1007
1010
  }
1008
1011
  }
1009
- createColumnMappingObject(meta) {
1010
- return Object.values(meta.properties).reduce((o, prop) => {
1011
- if (prop.fieldNames) {
1012
- o[prop.name] = prop.fieldNames[0];
1013
- }
1014
- return o;
1015
- }, {});
1016
- }
1017
- getDefaultVersionValue(prop) {
1012
+ getDefaultVersionValue(meta, prop) {
1018
1013
  if (typeof prop.defaultRaw !== 'undefined') {
1019
1014
  return prop.defaultRaw;
1020
1015
  }
1021
- /* v8 ignore next 3 */
1016
+ /* v8 ignore next */
1022
1017
  if (prop.default != null) {
1023
1018
  return '' + this.platform.quoteVersionValue(prop.default, prop);
1024
1019
  }
1025
- if (prop.type.toLowerCase() === 'date') {
1020
+ this.initCustomType(meta, prop, true);
1021
+ const type = prop.customType?.runtimeType ?? prop.runtimeType ?? prop.type;
1022
+ if (type === 'Date') {
1026
1023
  prop.length ??= this.platform.getDefaultVersionLength();
1027
1024
  return this.platform.getCurrentTimestampSQL(prop.length);
1028
1025
  }
1029
1026
  return '1';
1030
1027
  }
1031
1028
  inferDefaultValue(meta, prop) {
1032
- /* v8 ignore next 3 */
1033
- if (!meta.class) {
1034
- return;
1035
- }
1036
1029
  try {
1037
1030
  // try to create two entity instances to detect the value is stable
1038
1031
  const now = Date.now();
@@ -1060,12 +1053,12 @@ export class MetadataDiscovery {
1060
1053
  return;
1061
1054
  }
1062
1055
  let val = prop.default;
1063
- const raw = RawQueryFragment.getKnownFragment(val);
1056
+ const raw = Raw.getKnownFragment(val);
1064
1057
  if (raw) {
1065
1058
  prop.defaultRaw = this.platform.formatQuery(raw.sql, raw.params);
1066
1059
  return;
1067
1060
  }
1068
- if (prop.customType instanceof ArrayType && Array.isArray(prop.default)) {
1061
+ if (Array.isArray(prop.default) && prop.customType) {
1069
1062
  val = prop.customType.convertToDatabaseValue(prop.default, this.platform);
1070
1063
  }
1071
1064
  prop.defaultRaw = typeof val === 'string' ? `'${val}'` : '' + val;
@@ -1093,13 +1086,13 @@ export class MetadataDiscovery {
1093
1086
  if (prop.version) {
1094
1087
  this.initDefaultValue(prop);
1095
1088
  meta.versionProperty = prop.name;
1096
- prop.defaultRaw = this.getDefaultVersionValue(prop);
1089
+ prop.defaultRaw = this.getDefaultVersionValue(meta, prop);
1097
1090
  }
1098
1091
  if (prop.concurrencyCheck && !prop.primary) {
1099
1092
  meta.concurrencyCheckKeys.add(prop.name);
1100
1093
  }
1101
1094
  }
1102
- initCustomType(meta, prop) {
1095
+ initCustomType(meta, prop, simple = false, objectEmbeddable = false) {
1103
1096
  // `prop.type` might be actually instance of custom type class
1104
1097
  if (Type.isMappedType(prop.type) && !prop.customType) {
1105
1098
  prop.customType = prop.type;
@@ -1107,47 +1100,70 @@ export class MetadataDiscovery {
1107
1100
  }
1108
1101
  // `prop.type` might also be custom type class (not instance), so `typeof MyType` will give us `function`, not `object`
1109
1102
  if (typeof prop.type === 'function' && Type.isMappedType(prop.type.prototype) && !prop.customType) {
1110
- prop.customType = new prop.type();
1111
- prop.type = prop.customType.constructor.name;
1103
+ // if the type is an ORM defined mapped type without `ensureComparable: true`,
1104
+ // we use just the type name, to have more performant hydration code
1105
+ const type = Utils.keys(t).find(type => {
1106
+ return !Type.getType(t[type]).ensureComparable(meta, prop) && prop.type === t[type];
1107
+ });
1108
+ if (type) {
1109
+ prop.type = type === 'datetime' ? 'Date' : type;
1110
+ }
1111
+ else {
1112
+ prop.customType = new prop.type();
1113
+ prop.type = prop.customType.constructor.name;
1114
+ }
1115
+ }
1116
+ if (simple) {
1117
+ return;
1112
1118
  }
1113
1119
  if (!prop.customType && ['json', 'jsonb'].includes(prop.type?.toLowerCase())) {
1114
- prop.customType = new JsonType();
1120
+ prop.customType = new t.json();
1115
1121
  }
1116
1122
  if (prop.kind === ReferenceKind.SCALAR && !prop.customType && prop.columnTypes && ['json', 'jsonb'].includes(prop.columnTypes[0])) {
1117
- prop.customType = new JsonType();
1123
+ prop.customType = new t.json();
1124
+ }
1125
+ if (prop.kind === ReferenceKind.EMBEDDED && !prop.customType && (prop.object || prop.array)) {
1126
+ prop.customType = new t.json();
1118
1127
  }
1119
1128
  if (!prop.customType && prop.array && prop.items) {
1120
- prop.customType = new EnumArrayType(`${meta.className}.${prop.name}`, prop.items);
1129
+ prop.customType = new t.enumArray(`${meta.className}.${prop.name}`, prop.items);
1130
+ }
1131
+ const isArray = prop.type?.toLowerCase() === 'array' || prop.type?.toString().endsWith('[]');
1132
+ if (objectEmbeddable && !prop.customType && isArray) {
1133
+ prop.customType = new t.json();
1121
1134
  }
1122
1135
  // for number arrays we make sure to convert the items to numbers
1123
1136
  if (!prop.customType && prop.type === 'number[]') {
1124
- prop.customType = new ArrayType(i => +i);
1137
+ prop.customType = new t.array(i => +i);
1125
1138
  }
1126
1139
  // `string[]` can be returned via ts-morph, while reflect metadata will give us just `array`
1127
- if (!prop.customType && (prop.type?.toLowerCase() === 'array' || prop.type?.toString().endsWith('[]'))) {
1128
- prop.customType = new ArrayType();
1140
+ if (!prop.customType && isArray) {
1141
+ prop.customType = new t.array();
1129
1142
  }
1130
1143
  if (!prop.customType && prop.type?.toLowerCase() === 'buffer') {
1131
- prop.customType = new BlobType();
1144
+ prop.customType = new t.blob();
1132
1145
  }
1133
1146
  if (!prop.customType && prop.type?.toLowerCase() === 'uint8array') {
1134
- prop.customType = new Uint8ArrayType();
1147
+ prop.customType = new t.uint8array();
1135
1148
  }
1136
1149
  const mappedType = this.getMappedType(prop);
1137
1150
  if (prop.fieldNames?.length === 1 && !prop.customType) {
1138
- [BigIntType, DoubleType, DecimalType, IntervalType, DateType]
1151
+ [t.bigint, t.double, t.decimal, t.interval, t.date]
1139
1152
  .filter(type => mappedType instanceof type)
1140
- .forEach(type => prop.customType = new type());
1153
+ .forEach((type) => prop.customType = new type());
1141
1154
  }
1142
1155
  if (prop.customType && !prop.columnTypes) {
1143
1156
  const mappedType = this.getMappedType({ columnTypes: [prop.customType.getColumnType(prop, this.platform)] });
1144
- if (prop.customType.compareAsType() === 'any' && ![JsonType].some(t => prop.customType instanceof t)) {
1157
+ if (prop.customType.compareAsType() === 'any' && ![t.json].some(t => prop.customType instanceof t)) {
1145
1158
  prop.runtimeType ??= mappedType.runtimeType;
1146
1159
  }
1147
1160
  else {
1148
1161
  prop.runtimeType ??= prop.customType.runtimeType;
1149
1162
  }
1150
1163
  }
1164
+ else if (prop.runtimeType === 'object') {
1165
+ prop.runtimeType = mappedType.runtimeType;
1166
+ }
1151
1167
  else {
1152
1168
  prop.runtimeType ??= mappedType.runtimeType;
1153
1169
  }
@@ -1158,16 +1174,16 @@ export class MetadataDiscovery {
1158
1174
  prop.columnTypes ??= [prop.customType.getColumnType(prop, this.platform)];
1159
1175
  prop.hasConvertToJSValueSQL = !!prop.customType.convertToJSValueSQL && prop.customType.convertToJSValueSQL('', this.platform) !== '';
1160
1176
  prop.hasConvertToDatabaseValueSQL = !!prop.customType.convertToDatabaseValueSQL && prop.customType.convertToDatabaseValueSQL('', this.platform) !== '';
1161
- if (prop.customType instanceof BigIntType && ['string', 'bigint', 'number'].includes(prop.runtimeType.toLowerCase())) {
1177
+ if (prop.customType instanceof t.bigint && ['string', 'bigint', 'number'].includes(prop.runtimeType.toLowerCase())) {
1162
1178
  prop.customType.mode = prop.runtimeType.toLowerCase();
1163
1179
  }
1164
1180
  }
1165
- if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !prop.type?.toString().endsWith('[]')) {
1181
+ if (Type.isMappedType(prop.customType) && prop.kind === ReferenceKind.SCALAR && !isArray) {
1166
1182
  prop.type = prop.customType.name;
1167
1183
  }
1168
- if (!prop.customType && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && this.metadata.get(prop.type).compositePK) {
1184
+ if (!prop.customType && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && prop.targetMeta.compositePK) {
1169
1185
  prop.customTypes = [];
1170
- for (const pk of this.metadata.get(prop.type).getPrimaryProps()) {
1186
+ for (const pk of prop.targetMeta.getPrimaryProps()) {
1171
1187
  if (pk.customType) {
1172
1188
  prop.customTypes.push(pk.customType);
1173
1189
  prop.hasConvertToJSValueSQL ||= !!pk.customType.convertToJSValueSQL && pk.customType.convertToJSValueSQL('', this.platform) !== '';
@@ -1179,7 +1195,7 @@ export class MetadataDiscovery {
1179
1195
  }
1180
1196
  }
1181
1197
  }
1182
- if (prop.kind === ReferenceKind.SCALAR && !(mappedType instanceof UnknownType)) {
1198
+ if (prop.kind === ReferenceKind.SCALAR && !(mappedType instanceof t.unknown)) {
1183
1199
  if (!prop.columnTypes && prop.nativeEnumName && meta.schema !== this.platform.getDefaultSchemaName() && meta.schema && !prop.nativeEnumName.includes('.')) {
1184
1200
  prop.columnTypes = [`${meta.schema}.${prop.nativeEnumName}`];
1185
1201
  }
@@ -1197,7 +1213,8 @@ export class MetadataDiscovery {
1197
1213
  if (prop.kind === ReferenceKind.SCALAR) {
1198
1214
  return;
1199
1215
  }
1200
- const meta2 = this.discovered.find(m => m.className === prop.type);
1216
+ // when the target is a polymorphic embedded entity, `prop.target` is an array of classes, we need to get the metadata by the type name instead
1217
+ const meta2 = this.metadata.find(prop.target) ?? this.metadata.getByClassName(prop.type);
1201
1218
  prop.referencedPKs = meta2.primaryKeys;
1202
1219
  prop.targetMeta = meta2;
1203
1220
  if (!prop.formula && prop.persist === false && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && !prop.embedded) {
@@ -1206,7 +1223,7 @@ export class MetadataDiscovery {
1206
1223
  }
1207
1224
  initColumnType(prop) {
1208
1225
  this.initUnsigned(prop);
1209
- this.metadata.find(prop.type)?.getPrimaryProps().map(pk => {
1226
+ prop.targetMeta?.getPrimaryProps().map(pk => {
1210
1227
  prop.length ??= pk.length;
1211
1228
  prop.precision ??= pk.precision;
1212
1229
  prop.scale ??= pk.scale;
@@ -1222,8 +1239,7 @@ export class MetadataDiscovery {
1222
1239
  if (prop.kind === ReferenceKind.SCALAR) {
1223
1240
  const mappedType = this.getMappedType(prop);
1224
1241
  const SCALAR_TYPES = ['string', 'number', 'boolean', 'bigint', 'Date', 'Buffer', 'RegExp', 'any', 'unknown'];
1225
- if (mappedType instanceof UnknownType
1226
- && !prop.columnTypes
1242
+ if (mappedType instanceof t.unknown
1227
1243
  // it could be a runtime type from reflect-metadata
1228
1244
  && !SCALAR_TYPES.includes(prop.type)
1229
1245
  // or it might be inferred via ts-morph to some generic type alias
@@ -1236,11 +1252,12 @@ export class MetadataDiscovery {
1236
1252
  }
1237
1253
  return;
1238
1254
  }
1239
- if (prop.kind === ReferenceKind.EMBEDDED && prop.object && !prop.columnTypes) {
1255
+ /* v8 ignore next */
1256
+ if (prop.kind === ReferenceKind.EMBEDDED && prop.object) {
1240
1257
  prop.columnTypes = [this.platform.getJsonDeclarationSQL()];
1241
1258
  return;
1242
1259
  }
1243
- const targetMeta = this.metadata.get(prop.type);
1260
+ const targetMeta = prop.targetMeta;
1244
1261
  prop.columnTypes = [];
1245
1262
  for (const pk of targetMeta.getPrimaryProps()) {
1246
1263
  this.initCustomType(targetMeta, pk);
@@ -1266,7 +1283,7 @@ export class MetadataDiscovery {
1266
1283
  t = 'enum';
1267
1284
  }
1268
1285
  else if (prop.enum) {
1269
- t = prop.items?.every(item => Utils.isString(item)) ? 'enum' : 'tinyint';
1286
+ t = prop.items?.every(item => typeof item === 'string') ? 'enum' : 'tinyint';
1270
1287
  }
1271
1288
  if (t === 'Date') {
1272
1289
  t = 'datetime';
@@ -1290,7 +1307,7 @@ export class MetadataDiscovery {
1290
1307
  return;
1291
1308
  }
1292
1309
  if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
1293
- const meta2 = this.metadata.get(prop.type);
1310
+ const meta2 = prop.targetMeta;
1294
1311
  prop.unsigned = meta2.getPrimaryProps().some(pk => {
1295
1312
  this.initUnsigned(pk);
1296
1313
  return pk.unsigned;
@@ -1305,30 +1322,6 @@ export class MetadataDiscovery {
1305
1322
  prop.index ??= true;
1306
1323
  }
1307
1324
  }
1308
- async getEntityClassOrSchema(path, name) {
1309
- const exports = await Utils.dynamicImport(path);
1310
- const targets = Object.values(exports)
1311
- .filter(item => item instanceof EntitySchema || (item instanceof Function && MetadataStorage.isKnownEntity(item.name)));
1312
- // ignore class implementations that are linked from an EntitySchema
1313
- for (const item of targets) {
1314
- if (item instanceof EntitySchema) {
1315
- targets.forEach((item2, idx) => {
1316
- if (item.meta.class === item2) {
1317
- targets.splice(idx, 1);
1318
- }
1319
- });
1320
- }
1321
- }
1322
- if (targets.length > 0) {
1323
- return targets;
1324
- }
1325
- const target = exports.default ?? exports[name];
1326
- /* v8 ignore next 3 */
1327
- if (!target) {
1328
- throw MetadataError.entityNotFound(name, path.replace(this.config.get('baseDir'), '.'));
1329
- }
1330
- return [target];
1331
- }
1332
1325
  shouldForceConstructorUsage(meta) {
1333
1326
  const forceConstructor = this.config.get('forceEntityConstructor');
1334
1327
  if (Array.isArray(forceConstructor)) {