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

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 +883 -579
  2. package/EntityManager.js +1897 -1865
  3. package/MikroORM.d.ts +103 -72
  4. package/MikroORM.js +178 -177
  5. package/README.md +128 -294
  6. package/cache/CacheAdapter.d.ts +38 -36
  7. package/cache/FileCacheAdapter.d.ts +30 -24
  8. package/cache/FileCacheAdapter.js +80 -78
  9. package/cache/GeneratedCacheAdapter.d.ts +19 -20
  10. package/cache/GeneratedCacheAdapter.js +31 -30
  11. package/cache/MemoryCacheAdapter.d.ts +19 -20
  12. package/cache/MemoryCacheAdapter.js +36 -36
  13. package/cache/NullCacheAdapter.d.ts +17 -16
  14. package/cache/NullCacheAdapter.js +25 -24
  15. package/connections/Connection.d.ts +99 -75
  16. package/connections/Connection.js +166 -160
  17. package/drivers/DatabaseDriver.d.ts +187 -69
  18. package/drivers/DatabaseDriver.js +451 -432
  19. package/drivers/IDatabaseDriver.d.ts +464 -281
  20. package/drivers/IDatabaseDriver.js +1 -0
  21. package/entity/BaseEntity.d.ts +121 -73
  22. package/entity/BaseEntity.js +44 -33
  23. package/entity/Collection.d.ts +216 -157
  24. package/entity/Collection.js +728 -707
  25. package/entity/EntityAssigner.d.ts +90 -76
  26. package/entity/EntityAssigner.js +232 -229
  27. package/entity/EntityFactory.d.ts +68 -40
  28. package/entity/EntityFactory.js +427 -366
  29. package/entity/EntityHelper.d.ts +34 -22
  30. package/entity/EntityHelper.js +280 -267
  31. package/entity/EntityIdentifier.d.ts +4 -4
  32. package/entity/EntityIdentifier.js +10 -10
  33. package/entity/EntityLoader.d.ts +105 -56
  34. package/entity/EntityLoader.js +754 -722
  35. package/entity/EntityRepository.d.ts +317 -200
  36. package/entity/EntityRepository.js +214 -212
  37. package/entity/PolymorphicRef.d.ts +5 -5
  38. package/entity/PolymorphicRef.js +10 -10
  39. package/entity/Reference.d.ts +130 -66
  40. package/entity/Reference.js +280 -260
  41. package/entity/WrappedEntity.d.ts +116 -53
  42. package/entity/WrappedEntity.js +169 -147
  43. package/entity/defineEntity.d.ts +1290 -614
  44. package/entity/defineEntity.js +521 -511
  45. package/entity/utils.d.ts +13 -3
  46. package/entity/utils.js +71 -73
  47. package/entity/validators.js +43 -43
  48. package/entity/wrap.js +8 -8
  49. package/enums.d.ts +275 -138
  50. package/enums.js +268 -137
  51. package/errors.d.ts +120 -72
  52. package/errors.js +356 -253
  53. package/events/EventManager.d.ts +27 -10
  54. package/events/EventManager.js +80 -73
  55. package/events/EventSubscriber.d.ts +33 -29
  56. package/events/TransactionEventBroadcaster.d.ts +16 -7
  57. package/events/TransactionEventBroadcaster.js +15 -13
  58. package/exceptions.d.ts +23 -40
  59. package/exceptions.js +35 -52
  60. package/hydration/Hydrator.d.ts +43 -16
  61. package/hydration/Hydrator.js +44 -42
  62. package/hydration/ObjectHydrator.d.ts +51 -17
  63. package/hydration/ObjectHydrator.js +480 -416
  64. package/index.d.ts +116 -2
  65. package/index.js +10 -1
  66. package/logging/DefaultLogger.d.ts +35 -30
  67. package/logging/DefaultLogger.js +87 -84
  68. package/logging/Logger.d.ts +45 -40
  69. package/logging/SimpleLogger.d.ts +13 -11
  70. package/logging/SimpleLogger.js +22 -22
  71. package/logging/colors.d.ts +6 -6
  72. package/logging/colors.js +11 -10
  73. package/logging/inspect.js +7 -7
  74. package/metadata/EntitySchema.d.ts +214 -108
  75. package/metadata/EntitySchema.js +398 -379
  76. package/metadata/MetadataDiscovery.d.ts +115 -111
  77. package/metadata/MetadataDiscovery.js +1948 -1857
  78. package/metadata/MetadataProvider.d.ts +25 -14
  79. package/metadata/MetadataProvider.js +83 -77
  80. package/metadata/MetadataStorage.d.ts +39 -19
  81. package/metadata/MetadataStorage.js +119 -106
  82. package/metadata/MetadataValidator.d.ts +39 -39
  83. package/metadata/MetadataValidator.js +381 -338
  84. package/metadata/discover-entities.d.ts +5 -2
  85. package/metadata/discover-entities.js +27 -27
  86. package/metadata/types.d.ts +615 -531
  87. package/naming-strategy/AbstractNamingStrategy.d.ts +55 -39
  88. package/naming-strategy/AbstractNamingStrategy.js +91 -85
  89. package/naming-strategy/EntityCaseNamingStrategy.d.ts +6 -6
  90. package/naming-strategy/EntityCaseNamingStrategy.js +22 -22
  91. package/naming-strategy/MongoNamingStrategy.d.ts +7 -6
  92. package/naming-strategy/MongoNamingStrategy.js +19 -18
  93. package/naming-strategy/NamingStrategy.d.ts +109 -99
  94. package/naming-strategy/UnderscoreNamingStrategy.d.ts +8 -7
  95. package/naming-strategy/UnderscoreNamingStrategy.js +22 -21
  96. package/not-supported.js +7 -4
  97. package/package.json +1 -1
  98. package/platforms/ExceptionConverter.d.ts +2 -1
  99. package/platforms/ExceptionConverter.js +5 -4
  100. package/platforms/Platform.d.ts +310 -236
  101. package/platforms/Platform.js +661 -573
  102. package/serialization/EntitySerializer.d.ts +49 -25
  103. package/serialization/EntitySerializer.js +224 -216
  104. package/serialization/EntityTransformer.d.ts +11 -5
  105. package/serialization/EntityTransformer.js +220 -216
  106. package/serialization/SerializationContext.d.ts +27 -18
  107. package/serialization/SerializationContext.js +105 -100
  108. package/types/ArrayType.d.ts +9 -8
  109. package/types/ArrayType.js +34 -33
  110. package/types/BigIntType.d.ts +17 -10
  111. package/types/BigIntType.js +37 -37
  112. package/types/BlobType.d.ts +4 -3
  113. package/types/BlobType.js +14 -13
  114. package/types/BooleanType.d.ts +5 -4
  115. package/types/BooleanType.js +13 -12
  116. package/types/CharacterType.d.ts +3 -2
  117. package/types/CharacterType.js +7 -6
  118. package/types/DateTimeType.d.ts +6 -5
  119. package/types/DateTimeType.js +16 -15
  120. package/types/DateType.d.ts +6 -5
  121. package/types/DateType.js +16 -15
  122. package/types/DecimalType.d.ts +7 -7
  123. package/types/DecimalType.js +26 -26
  124. package/types/DoubleType.d.ts +3 -3
  125. package/types/DoubleType.js +12 -12
  126. package/types/EnumArrayType.d.ts +6 -5
  127. package/types/EnumArrayType.js +25 -24
  128. package/types/EnumType.d.ts +4 -3
  129. package/types/EnumType.js +12 -11
  130. package/types/FloatType.d.ts +4 -3
  131. package/types/FloatType.js +10 -9
  132. package/types/IntegerType.d.ts +4 -3
  133. package/types/IntegerType.js +10 -9
  134. package/types/IntervalType.d.ts +5 -4
  135. package/types/IntervalType.js +13 -12
  136. package/types/JsonType.d.ts +9 -8
  137. package/types/JsonType.js +33 -32
  138. package/types/MediumIntType.d.ts +2 -1
  139. package/types/MediumIntType.js +4 -3
  140. package/types/SmallIntType.d.ts +4 -3
  141. package/types/SmallIntType.js +10 -9
  142. package/types/StringType.d.ts +5 -4
  143. package/types/StringType.js +13 -12
  144. package/types/TextType.d.ts +4 -3
  145. package/types/TextType.js +10 -9
  146. package/types/TimeType.d.ts +6 -5
  147. package/types/TimeType.js +18 -17
  148. package/types/TinyIntType.d.ts +4 -3
  149. package/types/TinyIntType.js +11 -10
  150. package/types/Type.d.ts +88 -73
  151. package/types/Type.js +85 -74
  152. package/types/Uint8ArrayType.d.ts +5 -4
  153. package/types/Uint8ArrayType.js +22 -21
  154. package/types/UnknownType.d.ts +5 -4
  155. package/types/UnknownType.js +13 -12
  156. package/types/UuidType.d.ts +6 -5
  157. package/types/UuidType.js +20 -19
  158. package/types/index.d.ts +77 -49
  159. package/types/index.js +64 -26
  160. package/typings.d.ts +1388 -729
  161. package/typings.js +255 -231
  162. package/unit-of-work/ChangeSet.d.ts +28 -24
  163. package/unit-of-work/ChangeSet.js +58 -54
  164. package/unit-of-work/ChangeSetComputer.d.ts +13 -11
  165. package/unit-of-work/ChangeSetComputer.js +180 -159
  166. package/unit-of-work/ChangeSetPersister.d.ts +64 -41
  167. package/unit-of-work/ChangeSetPersister.js +443 -418
  168. package/unit-of-work/CommitOrderCalculator.d.ts +40 -40
  169. package/unit-of-work/CommitOrderCalculator.js +89 -88
  170. package/unit-of-work/IdentityMap.d.ts +32 -25
  171. package/unit-of-work/IdentityMap.js +106 -99
  172. package/unit-of-work/UnitOfWork.d.ts +182 -127
  173. package/unit-of-work/UnitOfWork.js +1201 -1169
  174. package/utils/AbstractMigrator.d.ts +111 -91
  175. package/utils/AbstractMigrator.js +275 -275
  176. package/utils/AbstractSchemaGenerator.d.ts +43 -34
  177. package/utils/AbstractSchemaGenerator.js +121 -122
  178. package/utils/AsyncContext.d.ts +3 -3
  179. package/utils/AsyncContext.js +34 -35
  180. package/utils/Configuration.d.ts +853 -801
  181. package/utils/Configuration.js +360 -337
  182. package/utils/Cursor.d.ts +40 -22
  183. package/utils/Cursor.js +135 -127
  184. package/utils/DataloaderUtils.d.ts +58 -43
  185. package/utils/DataloaderUtils.js +203 -198
  186. package/utils/EntityComparator.d.ts +99 -80
  187. package/utils/EntityComparator.js +825 -727
  188. package/utils/NullHighlighter.d.ts +2 -1
  189. package/utils/NullHighlighter.js +4 -3
  190. package/utils/QueryHelper.d.ts +79 -51
  191. package/utils/QueryHelper.js +372 -361
  192. package/utils/RawQueryFragment.d.ts +54 -28
  193. package/utils/RawQueryFragment.js +110 -99
  194. package/utils/RequestContext.d.ts +33 -32
  195. package/utils/RequestContext.js +52 -53
  196. package/utils/TransactionContext.d.ts +17 -16
  197. package/utils/TransactionContext.js +28 -27
  198. package/utils/TransactionManager.d.ts +58 -58
  199. package/utils/TransactionManager.js +199 -197
  200. package/utils/Utils.d.ts +210 -145
  201. package/utils/Utils.js +820 -813
  202. package/utils/clone.js +104 -113
  203. package/utils/env-vars.js +90 -88
  204. package/utils/fs-utils.d.ts +15 -15
  205. package/utils/fs-utils.js +180 -181
  206. package/utils/upsert-utils.d.ts +20 -5
  207. package/utils/upsert-utils.js +114 -116
@@ -1,4 +1,4 @@
1
- import { EntityManagerType, } from './IDatabaseDriver.js';
1
+ import { EntityManagerType } from './IDatabaseDriver.js';
2
2
  import { Utils } from '../utils/Utils.js';
3
3
  import { Cursor } from '../utils/Cursor.js';
4
4
  import { EntityComparator } from '../utils/EntityComparator.js';
@@ -11,464 +11,483 @@ import { helper } from '../entity/wrap.js';
11
11
  import { PolymorphicRef } from '../entity/PolymorphicRef.js';
12
12
  import { JsonType } from '../types/JsonType.js';
13
13
  import { MikroORM } from '../MikroORM.js';
14
+ /** Abstract base class for all database drivers, implementing common driver logic. */
14
15
  export class DatabaseDriver {
15
- config;
16
- dependencies;
17
- [EntityManagerType];
18
- connection;
19
- replicas = [];
20
- platform;
21
- comparator;
22
- metadata;
23
- constructor(config, dependencies) {
24
- this.config = config;
25
- this.dependencies = dependencies;
26
- }
27
- async nativeUpdateMany(entityName, where, data, options) {
28
- throw new Error(`Batch updates are not supported by ${this.constructor.name} driver`);
29
- }
30
- createEntityManager(useContext) {
31
- const EntityManagerClass = this.config.get('entityManager', EntityManager);
32
- return new EntityManagerClass(this.config, this, this.metadata, useContext);
33
- }
34
- /* v8 ignore next */
35
- async findVirtual(entityName, where, options) {
36
- throw new Error(`Virtual entities are not supported by ${this.constructor.name} driver.`);
37
- }
38
- /* v8 ignore next */
39
- async countVirtual(entityName, where, options) {
40
- throw new Error(`Counting virtual entities is not supported by ${this.constructor.name} driver.`);
41
- }
42
- async aggregate(entityName, pipeline) {
43
- throw new Error(`Aggregations are not supported by ${this.constructor.name} driver`);
44
- }
45
- async loadFromPivotTable(prop, owners, where, orderBy, ctx, options, pivotJoin) {
46
- throw new Error(`${this.constructor.name} does not use pivot tables`);
47
- }
48
- async syncCollections(collections, options) {
49
- for (const coll of collections) {
50
- /* v8 ignore else */
51
- if (!coll.property.owner) {
52
- if (coll.getSnapshot() === undefined) {
53
- throw ValidationError.cannotModifyInverseCollection(coll.owner, coll.property);
54
- }
55
- continue;
56
- }
57
- /* v8 ignore next */
58
- {
59
- const pk = coll.property.targetMeta.primaryKeys[0];
60
- const data = { [coll.property.name]: coll.getIdentifiers(pk) };
61
- await this.nativeUpdate(coll.owner.constructor, helper(coll.owner).getPrimaryKey(), data, options);
62
- }
16
+ config;
17
+ dependencies;
18
+ [EntityManagerType];
19
+ connection;
20
+ replicas = [];
21
+ platform;
22
+ comparator;
23
+ metadata;
24
+ constructor(config, dependencies) {
25
+ this.config = config;
26
+ this.dependencies = dependencies;
27
+ }
28
+ async nativeUpdateMany(entityName, where, data, options) {
29
+ throw new Error(`Batch updates are not supported by ${this.constructor.name} driver`);
30
+ }
31
+ /** Creates a new EntityManager instance bound to this driver. */
32
+ createEntityManager(useContext) {
33
+ const EntityManagerClass = this.config.get('entityManager', EntityManager);
34
+ return new EntityManagerClass(this.config, this, this.metadata, useContext);
35
+ }
36
+ /* v8 ignore next */
37
+ async findVirtual(entityName, where, options) {
38
+ throw new Error(`Virtual entities are not supported by ${this.constructor.name} driver.`);
39
+ }
40
+ /* v8 ignore next */
41
+ async countVirtual(entityName, where, options) {
42
+ throw new Error(`Counting virtual entities is not supported by ${this.constructor.name} driver.`);
43
+ }
44
+ async aggregate(entityName, pipeline) {
45
+ throw new Error(`Aggregations are not supported by ${this.constructor.name} driver`);
46
+ }
47
+ async loadFromPivotTable(prop, owners, where, orderBy, ctx, options, pivotJoin) {
48
+ throw new Error(`${this.constructor.name} does not use pivot tables`);
49
+ }
50
+ async syncCollections(collections, options) {
51
+ for (const coll of collections) {
52
+ /* v8 ignore else */
53
+ if (!coll.property.owner) {
54
+ if (coll.getSnapshot() === undefined) {
55
+ throw ValidationError.cannotModifyInverseCollection(coll.owner, coll.property);
63
56
  }
57
+ continue;
58
+ }
59
+ /* v8 ignore next */
60
+ {
61
+ const pk = coll.property.targetMeta.primaryKeys[0];
62
+ const data = { [coll.property.name]: coll.getIdentifiers(pk) };
63
+ await this.nativeUpdate(coll.owner.constructor, helper(coll.owner).getPrimaryKey(), data, options);
64
+ }
64
65
  }
65
- mapResult(result, meta, populate = []) {
66
- if (!result || !meta) {
67
- return result ?? null;
68
- }
69
- return this.comparator.mapResult(meta, result);
70
- }
71
- async connect(options) {
72
- await this.connection.connect(options);
73
- await Promise.all(this.replicas.map(replica => replica.connect()));
74
- return this.connection;
75
- }
76
- async reconnect(options) {
77
- await this.close(true);
78
- await this.connect(options);
79
- return this.connection;
66
+ }
67
+ /** Maps raw database result to entity data, converting column names to property names. */
68
+ mapResult(result, meta, populate = []) {
69
+ if (!result || !meta) {
70
+ return result ?? null;
80
71
  }
81
- getConnection(type = 'write') {
82
- if (type === 'write' || this.replicas.length === 0) {
83
- return this.connection;
84
- }
85
- const rand = Utils.randomInt(0, this.replicas.length - 1);
86
- return this.replicas[rand];
72
+ return this.comparator.mapResult(meta, result);
73
+ }
74
+ /** Opens the primary connection and all read replicas. */
75
+ async connect(options) {
76
+ await this.connection.connect(options);
77
+ await Promise.all(this.replicas.map(replica => replica.connect()));
78
+ return this.connection;
79
+ }
80
+ /** Closes all connections and re-establishes them. */
81
+ async reconnect(options) {
82
+ await this.close(true);
83
+ await this.connect(options);
84
+ return this.connection;
85
+ }
86
+ /** Returns the write connection or a random read replica. */
87
+ getConnection(type = 'write') {
88
+ if (type === 'write' || this.replicas.length === 0) {
89
+ return this.connection;
87
90
  }
88
- async close(force) {
89
- await Promise.all(this.replicas.map(replica => replica.close(force)));
90
- await this.connection.close(force);
91
+ const rand = Utils.randomInt(0, this.replicas.length - 1);
92
+ return this.replicas[rand];
93
+ }
94
+ /** Closes the primary connection and all read replicas. */
95
+ async close(force) {
96
+ await Promise.all(this.replicas.map(replica => replica.close(force)));
97
+ await this.connection.close(force);
98
+ }
99
+ /** Returns the database platform abstraction for this driver. */
100
+ getPlatform() {
101
+ return this.platform;
102
+ }
103
+ /** Sets the metadata storage and initializes the comparator for all connections. */
104
+ setMetadata(metadata) {
105
+ this.metadata = metadata;
106
+ this.comparator = new EntityComparator(this.metadata, this.platform);
107
+ this.connection.setMetadata(metadata);
108
+ this.connection.setPlatform(this.platform);
109
+ this.replicas.forEach(replica => {
110
+ replica.setMetadata(metadata);
111
+ replica.setPlatform(this.platform);
112
+ });
113
+ }
114
+ /** Returns the metadata storage used by this driver. */
115
+ getMetadata() {
116
+ return this.metadata;
117
+ }
118
+ /** Returns the names of native database dependencies required by this driver. */
119
+ getDependencies() {
120
+ return this.dependencies;
121
+ }
122
+ isPopulated(meta, prop, hint, name) {
123
+ if (hint.field === prop.name || hint.field === name || hint.all) {
124
+ return true;
91
125
  }
92
- getPlatform() {
93
- return this.platform;
126
+ if (prop.embedded && hint.children && meta.properties[prop.embedded[0]].name === hint.field) {
127
+ return hint.children.some(c => this.isPopulated(meta, prop, c, prop.embedded[1]));
94
128
  }
95
- setMetadata(metadata) {
96
- this.metadata = metadata;
97
- this.comparator = new EntityComparator(this.metadata, this.platform);
98
- this.connection.setMetadata(metadata);
99
- this.connection.setPlatform(this.platform);
100
- this.replicas.forEach(replica => {
101
- replica.setMetadata(metadata);
102
- replica.setPlatform(this.platform);
103
- });
129
+ return false;
130
+ }
131
+ processCursorOptions(meta, options, orderBy) {
132
+ const { first, last, before, after, overfetch } = options;
133
+ const limit = first ?? last;
134
+ const isLast = !first && !!last;
135
+ const definition = Cursor.getDefinition(meta, orderBy);
136
+ const $and = [];
137
+ // allow POJO as well, we care only about the correct key being present
138
+ const isCursor = (val, key) => {
139
+ return !!val && typeof val === 'object' && key in val;
140
+ };
141
+ const createCursor = (val, key, inverse = false) => {
142
+ let def = isCursor(val, key) ? val[key] : val;
143
+ if (Utils.isPlainObject(def)) {
144
+ def = Cursor.for(meta, def, orderBy);
145
+ }
146
+ /* v8 ignore next */
147
+ const offsets = def ? Cursor.decode(def) : [];
148
+ if (definition.length === offsets.length) {
149
+ return this.createCursorCondition(definition, offsets, inverse, meta);
150
+ }
151
+ /* v8 ignore next */
152
+ return {};
153
+ };
154
+ if (after) {
155
+ $and.push(createCursor(after, 'endCursor'));
104
156
  }
105
- getMetadata() {
106
- return this.metadata;
157
+ if (before) {
158
+ $and.push(createCursor(before, 'startCursor', true));
107
159
  }
108
- getDependencies() {
109
- return this.dependencies;
160
+ if (limit != null) {
161
+ options.limit = limit + (overfetch ? 1 : 0);
110
162
  }
111
- isPopulated(meta, prop, hint, name) {
112
- if (hint.field === prop.name || hint.field === name || hint.all) {
113
- return true;
163
+ const createOrderBy = (prop, direction) => {
164
+ if (Utils.isPlainObject(direction)) {
165
+ const value = Utils.getObjectQueryKeys(direction).reduce((o, key) => {
166
+ Object.assign(o, createOrderBy(key, direction[key]));
167
+ return o;
168
+ }, {});
169
+ return { [prop]: value };
170
+ }
171
+ const desc = direction === QueryOrderNumeric.DESC || direction.toString().toLowerCase() === 'desc';
172
+ const dir = Utils.xor(desc, isLast) ? 'desc' : 'asc';
173
+ return { [prop]: dir };
174
+ };
175
+ return {
176
+ orderBy: definition.map(([prop, direction]) => createOrderBy(prop, direction)),
177
+ where: $and.length > 1 ? { $and } : { ...$and[0] },
178
+ };
179
+ }
180
+ createCursorCondition(definition, offsets, inverse, meta) {
181
+ const createCondition = (prop, direction, offset, eq = false, path = prop) => {
182
+ if (Utils.isPlainObject(direction)) {
183
+ if (offset === undefined) {
184
+ throw CursorError.missingValue(meta.className, path);
114
185
  }
115
- if (prop.embedded && hint.children && meta.properties[prop.embedded[0]].name === hint.field) {
116
- return hint.children.some(c => this.isPopulated(meta, prop, c, prop.embedded[1]));
186
+ const value = Utils.keys(direction).reduce((o, key) => {
187
+ Object.assign(o, createCondition(key, direction[key], offset?.[key], eq, `${path}.${key}`));
188
+ return o;
189
+ }, {});
190
+ return { [prop]: value };
191
+ }
192
+ const isDesc = direction === QueryOrderNumeric.DESC || direction.toString().toLowerCase() === 'desc';
193
+ const dirStr = direction.toString().toLowerCase();
194
+ let nullsFirst;
195
+ if (dirStr.includes('nulls first')) {
196
+ nullsFirst = true;
197
+ } else if (dirStr.includes('nulls last')) {
198
+ nullsFirst = false;
199
+ } else {
200
+ // Default: NULLS LAST for ASC, NULLS FIRST for DESC (matches most databases)
201
+ nullsFirst = isDesc;
202
+ }
203
+ const operator = Utils.xor(isDesc, inverse) ? '$lt' : '$gt';
204
+ // For leaf-level properties, undefined means missing value
205
+ if (offset === undefined) {
206
+ throw CursorError.missingValue(meta.className, path);
207
+ }
208
+ // Handle null offset (intentional null cursor value)
209
+ if (offset === null) {
210
+ if (eq) {
211
+ // Equal to null
212
+ return { [prop]: null };
117
213
  }
118
- return false;
119
- }
120
- processCursorOptions(meta, options, orderBy) {
121
- const { first, last, before, after, overfetch } = options;
122
- const limit = first ?? last;
123
- const isLast = !first && !!last;
124
- const definition = Cursor.getDefinition(meta, orderBy);
125
- const $and = [];
126
- // allow POJO as well, we care only about the correct key being present
127
- const isCursor = (val, key) => {
128
- return !!val && typeof val === 'object' && key in val;
129
- };
130
- const createCursor = (val, key, inverse = false) => {
131
- let def = isCursor(val, key) ? val[key] : val;
132
- if (Utils.isPlainObject(def)) {
133
- def = Cursor.for(meta, def, orderBy);
134
- }
135
- /* v8 ignore next */
136
- const offsets = def ? Cursor.decode(def) : [];
137
- if (definition.length === offsets.length) {
138
- return this.createCursorCondition(definition, offsets, inverse, meta);
139
- }
140
- /* v8 ignore next */
141
- return {};
142
- };
143
- if (after) {
144
- $and.push(createCursor(after, 'endCursor'));
214
+ // Strict comparison with null cursor value
215
+ // hasItemsAfterNull: forward + nullsFirst, or backward + nullsLast
216
+ const hasItemsAfterNull = Utils.xor(nullsFirst, inverse);
217
+ if (hasItemsAfterNull) {
218
+ return { [prop]: { $ne: null } };
145
219
  }
146
- if (before) {
147
- $and.push(createCursor(before, 'startCursor', true));
220
+ // No items after null in this direction, return impossible condition
221
+ return { [prop]: [] };
222
+ }
223
+ // Non-null offset
224
+ return { [prop]: { [operator + (eq ? 'e' : '')]: offset } };
225
+ };
226
+ const [order, ...otherOrders] = definition;
227
+ const [offset, ...otherOffsets] = offsets;
228
+ const [prop, direction] = order;
229
+ if (!otherOrders.length) {
230
+ return createCondition(prop, direction, offset);
231
+ }
232
+ return {
233
+ ...createCondition(prop, direction, offset, true),
234
+ $or: [
235
+ createCondition(prop, direction, offset),
236
+ this.createCursorCondition(otherOrders, otherOffsets, inverse, meta),
237
+ ],
238
+ };
239
+ }
240
+ /** @internal */
241
+ mapDataToFieldNames(data, stringifyJsonArrays, properties, convertCustomTypes, object) {
242
+ if (!properties || data == null) {
243
+ return data;
244
+ }
245
+ data = Object.assign({}, data); // copy first
246
+ Object.keys(data).forEach(k => {
247
+ const prop = properties[k];
248
+ if (!prop) {
249
+ return;
250
+ }
251
+ if (prop.embeddedProps && !prop.object && !object) {
252
+ const copy = data[k];
253
+ delete data[k];
254
+ Object.assign(
255
+ data,
256
+ this.mapDataToFieldNames(copy, stringifyJsonArrays, prop.embeddedProps, convertCustomTypes),
257
+ );
258
+ return;
259
+ }
260
+ if (prop.embeddedProps && (object || prop.object)) {
261
+ const copy = data[k];
262
+ delete data[k];
263
+ if (prop.array) {
264
+ data[prop.fieldNames[0]] = copy?.map(item =>
265
+ this.mapDataToFieldNames(item, stringifyJsonArrays, prop.embeddedProps, convertCustomTypes, true),
266
+ );
267
+ } else {
268
+ data[prop.fieldNames[0]] = this.mapDataToFieldNames(
269
+ copy,
270
+ stringifyJsonArrays,
271
+ prop.embeddedProps,
272
+ convertCustomTypes,
273
+ true,
274
+ );
148
275
  }
149
- if (limit != null) {
150
- options.limit = limit + (overfetch ? 1 : 0);
276
+ if (stringifyJsonArrays && prop.array && !object) {
277
+ data[prop.fieldNames[0]] = this.platform.convertJsonToDatabaseValue(data[prop.fieldNames[0]]);
151
278
  }
152
- const createOrderBy = (prop, direction) => {
153
- if (Utils.isPlainObject(direction)) {
154
- const value = Utils.getObjectQueryKeys(direction).reduce((o, key) => {
155
- Object.assign(o, createOrderBy(key, direction[key]));
156
- return o;
157
- }, {});
158
- return { [prop]: value };
159
- }
160
- const desc = direction === QueryOrderNumeric.DESC || direction.toString().toLowerCase() === 'desc';
161
- const dir = Utils.xor(desc, isLast) ? 'desc' : 'asc';
162
- return { [prop]: dir };
163
- };
164
- return {
165
- orderBy: definition.map(([prop, direction]) => createOrderBy(prop, direction)),
166
- where: ($and.length > 1 ? { $and } : { ...$and[0] }),
167
- };
168
- }
169
- createCursorCondition(definition, offsets, inverse, meta) {
170
- const createCondition = (prop, direction, offset, eq = false, path = prop) => {
171
- if (Utils.isPlainObject(direction)) {
172
- if (offset === undefined) {
173
- throw CursorError.missingValue(meta.className, path);
174
- }
175
- const value = Utils.keys(direction).reduce((o, key) => {
176
- Object.assign(o, createCondition(key, direction[key], offset?.[key], eq, `${path}.${key}`));
177
- return o;
178
- }, {});
179
- return { [prop]: value };
180
- }
181
- const isDesc = direction === QueryOrderNumeric.DESC || direction.toString().toLowerCase() === 'desc';
182
- const dirStr = direction.toString().toLowerCase();
183
- let nullsFirst;
184
- if (dirStr.includes('nulls first')) {
185
- nullsFirst = true;
186
- }
187
- else if (dirStr.includes('nulls last')) {
188
- nullsFirst = false;
189
- }
190
- else {
191
- // Default: NULLS LAST for ASC, NULLS FIRST for DESC (matches most databases)
192
- nullsFirst = isDesc;
193
- }
194
- const operator = Utils.xor(isDesc, inverse) ? '$lt' : '$gt';
195
- // For leaf-level properties, undefined means missing value
196
- if (offset === undefined) {
197
- throw CursorError.missingValue(meta.className, path);
198
- }
199
- // Handle null offset (intentional null cursor value)
200
- if (offset === null) {
201
- if (eq) {
202
- // Equal to null
203
- return { [prop]: null };
204
- }
205
- // Strict comparison with null cursor value
206
- // hasItemsAfterNull: forward + nullsFirst, or backward + nullsLast
207
- const hasItemsAfterNull = Utils.xor(nullsFirst, inverse);
208
- if (hasItemsAfterNull) {
209
- return { [prop]: { $ne: null } };
210
- }
211
- // No items after null in this direction, return impossible condition
212
- return { [prop]: [] };
213
- }
214
- // Non-null offset
215
- return { [prop]: { [operator + (eq ? 'e' : '')]: offset } };
216
- };
217
- const [order, ...otherOrders] = definition;
218
- const [offset, ...otherOffsets] = offsets;
219
- const [prop, direction] = order;
220
- if (!otherOrders.length) {
221
- return createCondition(prop, direction, offset);
279
+ return;
280
+ }
281
+ // Handle polymorphic relations - convert tuple or PolymorphicRef to separate columns
282
+ // Tuple format: ['discriminator', id] or ['discriminator', id1, id2] for composite keys
283
+ // Must be checked BEFORE joinColumns array handling since polymorphic uses fieldNames (includes discriminator)
284
+ if (prop.polymorphic && prop.fieldNames && prop.fieldNames.length >= 2) {
285
+ let discriminator;
286
+ let ids;
287
+ if (Array.isArray(data[k]) && typeof data[k][0] === 'string' && prop.discriminatorMap?.[data[k][0]]) {
288
+ // Tuple format: ['discriminator', ...ids]
289
+ const [disc, ...rest] = data[k];
290
+ discriminator = disc;
291
+ ids = rest;
292
+ } else if (data[k] instanceof PolymorphicRef) {
293
+ // PolymorphicRef wrapper (internal use)
294
+ discriminator = data[k].discriminator;
295
+ const polyId = data[k].id;
296
+ // Handle object-style composite key IDs like { tenantId: 1, orgId: 100 }
297
+ if (polyId && typeof polyId === 'object' && !Array.isArray(polyId)) {
298
+ const targetEntity = prop.discriminatorMap?.[discriminator];
299
+ const targetMeta = this.metadata.get(targetEntity);
300
+ ids = targetMeta.primaryKeys.map(pk => polyId[pk]);
301
+ } else {
302
+ ids = Utils.asArray(polyId);
303
+ }
222
304
  }
223
- return {
224
- ...createCondition(prop, direction, offset, true),
225
- $or: [
226
- createCondition(prop, direction, offset),
227
- this.createCursorCondition(otherOrders, otherOffsets, inverse, meta),
228
- ],
229
- };
230
- }
231
- /** @internal */
232
- mapDataToFieldNames(data, stringifyJsonArrays, properties, convertCustomTypes, object) {
233
- if (!properties || data == null) {
234
- return data;
305
+ if (discriminator) {
306
+ const discriminatorColumn = prop.fieldNames[0];
307
+ const idColumns = prop.fieldNames.slice(1);
308
+ delete data[k];
309
+ data[discriminatorColumn] = discriminator;
310
+ idColumns.forEach((col, idx) => {
311
+ data[col] = ids[idx];
312
+ });
313
+ return;
235
314
  }
236
- data = Object.assign({}, data); // copy first
237
- Object.keys(data).forEach(k => {
238
- const prop = properties[k];
239
- if (!prop) {
240
- return;
241
- }
242
- if (prop.embeddedProps && !prop.object && !object) {
243
- const copy = data[k];
244
- delete data[k];
245
- Object.assign(data, this.mapDataToFieldNames(copy, stringifyJsonArrays, prop.embeddedProps, convertCustomTypes));
246
- return;
247
- }
248
- if (prop.embeddedProps && (object || prop.object)) {
249
- const copy = data[k];
250
- delete data[k];
251
- if (prop.array) {
252
- data[prop.fieldNames[0]] = copy?.map((item) => this.mapDataToFieldNames(item, stringifyJsonArrays, prop.embeddedProps, convertCustomTypes, true));
253
- }
254
- else {
255
- data[prop.fieldNames[0]] = this.mapDataToFieldNames(copy, stringifyJsonArrays, prop.embeddedProps, convertCustomTypes, true);
256
- }
257
- if (stringifyJsonArrays && prop.array && !object) {
258
- data[prop.fieldNames[0]] = this.platform.convertJsonToDatabaseValue(data[prop.fieldNames[0]]);
259
- }
260
- return;
261
- }
262
- // Handle polymorphic relations - convert tuple or PolymorphicRef to separate columns
263
- // Tuple format: ['discriminator', id] or ['discriminator', id1, id2] for composite keys
264
- // Must be checked BEFORE joinColumns array handling since polymorphic uses fieldNames (includes discriminator)
265
- if (prop.polymorphic && prop.fieldNames && prop.fieldNames.length >= 2) {
266
- let discriminator;
267
- let ids;
268
- if (Array.isArray(data[k]) && typeof data[k][0] === 'string' && prop.discriminatorMap?.[data[k][0]]) {
269
- // Tuple format: ['discriminator', ...ids]
270
- const [disc, ...rest] = data[k];
271
- discriminator = disc;
272
- ids = rest;
273
- }
274
- else if (data[k] instanceof PolymorphicRef) {
275
- // PolymorphicRef wrapper (internal use)
276
- discriminator = data[k].discriminator;
277
- const polyId = data[k].id;
278
- // Handle object-style composite key IDs like { tenantId: 1, orgId: 100 }
279
- if (polyId && typeof polyId === 'object' && !Array.isArray(polyId)) {
280
- const targetEntity = prop.discriminatorMap?.[discriminator];
281
- const targetMeta = this.metadata.get(targetEntity);
282
- ids = targetMeta.primaryKeys.map(pk => polyId[pk]);
283
- }
284
- else {
285
- ids = Utils.asArray(polyId);
286
- }
287
- }
288
- if (discriminator) {
289
- const discriminatorColumn = prop.fieldNames[0];
290
- const idColumns = prop.fieldNames.slice(1);
291
- delete data[k];
292
- data[discriminatorColumn] = discriminator;
293
- idColumns.forEach((col, idx) => {
294
- data[col] = ids[idx];
295
- });
296
- return;
297
- }
298
- }
299
- if (prop.joinColumns && Array.isArray(data[k])) {
300
- const copy = Utils.flatten(data[k]);
301
- delete data[k];
302
- prop.joinColumns.forEach((joinColumn, idx) => (data[joinColumn] = copy[idx]));
303
- return;
304
- }
305
- if (prop.joinColumns?.length > 1 && data[k] == null) {
306
- delete data[k];
307
- prop.ownColumns.forEach(joinColumn => (data[joinColumn] = null));
308
- return;
309
- }
310
- if (prop.customType &&
311
- convertCustomTypes &&
312
- !(prop.customType instanceof JsonType && object) &&
313
- !isRaw(data[k])) {
314
- data[k] = prop.customType.convertToDatabaseValue(data[k], this.platform, {
315
- fromQuery: true,
316
- key: k,
317
- mode: 'query-data',
318
- });
319
- }
320
- if (prop.hasConvertToDatabaseValueSQL && !prop.object && !isRaw(data[k])) {
321
- const quoted = this.platform.quoteValue(data[k]);
322
- const sql = prop.customType.convertToDatabaseValueSQL(quoted, this.platform);
323
- data[k] = raw(sql.replace(/\?/g, '\\?'));
324
- }
325
- if (prop.fieldNames) {
326
- Utils.renameKey(data, k, prop.fieldNames[0]);
327
- }
315
+ }
316
+ if (prop.joinColumns && Array.isArray(data[k])) {
317
+ const copy = Utils.flatten(data[k]);
318
+ delete data[k];
319
+ prop.joinColumns.forEach((joinColumn, idx) => (data[joinColumn] = copy[idx]));
320
+ return;
321
+ }
322
+ if (prop.joinColumns?.length > 1 && data[k] == null) {
323
+ delete data[k];
324
+ prop.ownColumns.forEach(joinColumn => (data[joinColumn] = null));
325
+ return;
326
+ }
327
+ if (
328
+ prop.customType &&
329
+ convertCustomTypes &&
330
+ !(prop.customType instanceof JsonType && object) &&
331
+ !isRaw(data[k])
332
+ ) {
333
+ data[k] = prop.customType.convertToDatabaseValue(data[k], this.platform, {
334
+ fromQuery: true,
335
+ key: k,
336
+ mode: 'query-data',
328
337
  });
329
- return data;
338
+ }
339
+ if (prop.hasConvertToDatabaseValueSQL && !prop.object && !isRaw(data[k])) {
340
+ const quoted = this.platform.quoteValue(data[k]);
341
+ const sql = prop.customType.convertToDatabaseValueSQL(quoted, this.platform);
342
+ data[k] = raw(sql.replace(/\?/g, '\\?'));
343
+ }
344
+ if (prop.fieldNames) {
345
+ Utils.renameKey(data, k, prop.fieldNames[0]);
346
+ }
347
+ });
348
+ return data;
349
+ }
350
+ inlineEmbeddables(meta, data, where) {
351
+ /* v8 ignore next */
352
+ if (data == null) {
353
+ return;
330
354
  }
331
- inlineEmbeddables(meta, data, where) {
332
- /* v8 ignore next */
333
- if (data == null) {
334
- return;
335
- }
336
- Utils.keys(data).forEach(k => {
337
- if (Utils.isOperator(k)) {
338
- Utils.asArray(data[k]).forEach(payload => this.inlineEmbeddables(meta, payload, where));
339
- }
340
- });
341
- meta.props.forEach(prop => {
342
- if (prop.kind === ReferenceKind.EMBEDDED && prop.object && !where && Utils.isObject(data[prop.name])) {
343
- return;
344
- }
345
- if (prop.kind === ReferenceKind.EMBEDDED && Utils.isObject(data[prop.name])) {
346
- const props = prop.embeddedProps;
347
- let unknownProp = false;
348
- Object.keys(data[prop.name]).forEach(kk => {
349
- // explicitly allow `$exists`, `$eq`, `$ne` and `$elemMatch` operators here as they can't be misused this way
350
- const operator = Object.keys(data[prop.name]).some(f => Utils.isOperator(f) && !['$exists', '$ne', '$eq', '$elemMatch'].includes(f));
351
- if (operator) {
352
- throw ValidationError.cannotUseOperatorsInsideEmbeddables(meta.class, prop.name, data);
353
- }
354
- if (prop.object && where) {
355
- const inline = (payload, sub, path) => {
356
- if (sub.kind === ReferenceKind.EMBEDDED && Utils.isObject(payload[sub.embedded[1]])) {
357
- return Object.keys(payload[sub.embedded[1]]).forEach(kkk => {
358
- if (!sub.embeddedProps[kkk]) {
359
- throw ValidationError.invalidEmbeddableQuery(meta.class, kkk, sub.type);
360
- }
361
- inline(payload[sub.embedded[1]], sub.embeddedProps[kkk], [...path, sub.fieldNames[0]]);
362
- });
363
- }
364
- data[`${path.join('.')}.${sub.fieldNames[0]}`] = payload[sub.embedded[1]];
365
- };
366
- const parentPropName = kk.substring(0, kk.indexOf('.'));
367
- // we might be using some native JSON operator, e.g. with mongodb's `$geoWithin` or `$exists`
368
- if (props[kk]) {
369
- /* v8 ignore next */
370
- inline(data[prop.name], props[kk] || props[parentPropName], [prop.fieldNames[0]]);
371
- }
372
- else if (props[parentPropName]) {
373
- data[`${prop.fieldNames[0]}.${kk}`] = data[prop.name][kk];
374
- }
375
- else {
376
- unknownProp = true;
377
- }
378
- }
379
- else if (props[kk]) {
380
- data[props[kk].fieldNames[0]] = data[prop.name][props[kk].embedded[1]];
381
- }
382
- else {
383
- throw ValidationError.invalidEmbeddableQuery(meta.class, kk, prop.type);
384
- }
355
+ Utils.keys(data).forEach(k => {
356
+ if (Utils.isOperator(k)) {
357
+ Utils.asArray(data[k]).forEach(payload => this.inlineEmbeddables(meta, payload, where));
358
+ }
359
+ });
360
+ meta.props.forEach(prop => {
361
+ if (prop.kind === ReferenceKind.EMBEDDED && prop.object && !where && Utils.isObject(data[prop.name])) {
362
+ return;
363
+ }
364
+ if (prop.kind === ReferenceKind.EMBEDDED && Utils.isObject(data[prop.name])) {
365
+ const props = prop.embeddedProps;
366
+ let unknownProp = false;
367
+ Object.keys(data[prop.name]).forEach(kk => {
368
+ // explicitly allow `$exists`, `$eq`, `$ne` and `$elemMatch` operators here as they can't be misused this way
369
+ const operator = Object.keys(data[prop.name]).some(
370
+ f => Utils.isOperator(f) && !['$exists', '$ne', '$eq', '$elemMatch'].includes(f),
371
+ );
372
+ if (operator) {
373
+ throw ValidationError.cannotUseOperatorsInsideEmbeddables(meta.class, prop.name, data);
374
+ }
375
+ if (prop.object && where) {
376
+ const inline = (payload, sub, path) => {
377
+ if (sub.kind === ReferenceKind.EMBEDDED && Utils.isObject(payload[sub.embedded[1]])) {
378
+ return Object.keys(payload[sub.embedded[1]]).forEach(kkk => {
379
+ if (!sub.embeddedProps[kkk]) {
380
+ throw ValidationError.invalidEmbeddableQuery(meta.class, kkk, sub.type);
381
+ }
382
+ inline(payload[sub.embedded[1]], sub.embeddedProps[kkk], [...path, sub.fieldNames[0]]);
385
383
  });
386
- if (!unknownProp) {
387
- delete data[prop.name];
388
- }
384
+ }
385
+ data[`${path.join('.')}.${sub.fieldNames[0]}`] = payload[sub.embedded[1]];
386
+ };
387
+ const parentPropName = kk.substring(0, kk.indexOf('.'));
388
+ // we might be using some native JSON operator, e.g. with mongodb's `$geoWithin` or `$exists`
389
+ if (props[kk]) {
390
+ /* v8 ignore next */
391
+ inline(data[prop.name], props[kk] || props[parentPropName], [prop.fieldNames[0]]);
392
+ } else if (props[parentPropName]) {
393
+ data[`${prop.fieldNames[0]}.${kk}`] = data[prop.name][kk];
394
+ } else {
395
+ unknownProp = true;
389
396
  }
397
+ } else if (props[kk]) {
398
+ data[props[kk].fieldNames[0]] = data[prop.name][props[kk].embedded[1]];
399
+ } else {
400
+ throw ValidationError.invalidEmbeddableQuery(meta.class, kk, prop.type);
401
+ }
390
402
  });
391
- }
392
- getPrimaryKeyFields(meta) {
393
- return meta.getPrimaryProps().flatMap(pk => pk.fieldNames);
394
- }
395
- createReplicas(cb) {
396
- const replicas = this.config.get('replicas', []);
397
- const ret = [];
398
- const props = [
399
- 'dbName',
400
- 'clientUrl',
401
- 'host',
402
- 'port',
403
- 'user',
404
- 'password',
405
- 'multipleStatements',
406
- 'pool',
407
- 'name',
408
- 'driverOptions',
409
- ];
410
- for (const conf of replicas) {
411
- const replicaConfig = Utils.copy(conf);
412
- for (const prop of props) {
413
- if (conf[prop]) {
414
- continue;
415
- }
416
- // do not copy options that can be inferred from explicitly provided `clientUrl`
417
- if (conf.clientUrl && ['clientUrl', 'host', 'port', 'user', 'password'].includes(prop)) {
418
- continue;
419
- }
420
- if (conf.clientUrl && prop === 'dbName' && new URL(conf.clientUrl).pathname) {
421
- continue;
422
- }
423
- replicaConfig[prop] = this.config.get(prop);
424
- }
425
- ret.push(cb(replicaConfig));
403
+ if (!unknownProp) {
404
+ delete data[prop.name];
426
405
  }
427
- return ret;
428
- }
429
- async lockPessimistic(entity, options) {
430
- throw new Error(`Pessimistic locks are not supported by ${this.constructor.name} driver`);
431
- }
432
- /**
433
- * @inheritDoc
434
- */
435
- convertException(exception) {
436
- if (exception instanceof DriverException) {
437
- return exception;
406
+ }
407
+ });
408
+ }
409
+ getPrimaryKeyFields(meta) {
410
+ return meta.getPrimaryProps().flatMap(pk => pk.fieldNames);
411
+ }
412
+ createReplicas(cb) {
413
+ const replicas = this.config.get('replicas', []);
414
+ const ret = [];
415
+ const props = [
416
+ 'dbName',
417
+ 'clientUrl',
418
+ 'host',
419
+ 'port',
420
+ 'user',
421
+ 'password',
422
+ 'multipleStatements',
423
+ 'pool',
424
+ 'name',
425
+ 'driverOptions',
426
+ ];
427
+ for (const conf of replicas) {
428
+ const replicaConfig = Utils.copy(conf);
429
+ for (const prop of props) {
430
+ if (conf[prop]) {
431
+ continue;
432
+ }
433
+ // do not copy options that can be inferred from explicitly provided `clientUrl`
434
+ if (conf.clientUrl && ['clientUrl', 'host', 'port', 'user', 'password'].includes(prop)) {
435
+ continue;
438
436
  }
439
- return this.platform.getExceptionConverter().convertException(exception);
437
+ if (conf.clientUrl && prop === 'dbName' && new URL(conf.clientUrl).pathname) {
438
+ continue;
439
+ }
440
+ replicaConfig[prop] = this.config.get(prop);
441
+ }
442
+ ret.push(cb(replicaConfig));
440
443
  }
441
- rethrow(promise) {
442
- return promise.catch(e => {
443
- throw this.convertException(e);
444
- });
444
+ return ret;
445
+ }
446
+ /** Acquires a pessimistic lock on the given entity. */
447
+ async lockPessimistic(entity, options) {
448
+ throw new Error(`Pessimistic locks are not supported by ${this.constructor.name} driver`);
449
+ }
450
+ /**
451
+ * @inheritDoc
452
+ */
453
+ convertException(exception) {
454
+ if (exception instanceof DriverException) {
455
+ return exception;
445
456
  }
446
- /**
447
- * @internal
448
- */
449
- getTableName(meta, options, quote = true) {
450
- const schema = this.getSchemaName(meta, options);
451
- const tableName = schema && schema !== this.platform.getDefaultSchemaName() ? `${schema}.${meta.tableName}` : meta.tableName;
452
- if (quote) {
453
- return this.platform.quoteIdentifier(tableName);
454
- }
455
- return tableName;
457
+ return this.platform.getExceptionConverter().convertException(exception);
458
+ }
459
+ rethrow(promise) {
460
+ return promise.catch(e => {
461
+ throw this.convertException(e);
462
+ });
463
+ }
464
+ /**
465
+ * @internal
466
+ */
467
+ getTableName(meta, options, quote = true) {
468
+ const schema = this.getSchemaName(meta, options);
469
+ const tableName =
470
+ schema && schema !== this.platform.getDefaultSchemaName() ? `${schema}.${meta.tableName}` : meta.tableName;
471
+ if (quote) {
472
+ return this.platform.quoteIdentifier(tableName);
456
473
  }
457
- /**
458
- * @internal
459
- */
460
- getSchemaName(meta, options) {
461
- if (meta?.schema && meta.schema !== '*') {
462
- return meta.schema;
463
- }
464
- if (options?.schema === '*') {
465
- return this.config.get('schema');
466
- }
467
- const schemaName = meta?.schema === '*' ? this.config.getSchema() : meta?.schema;
468
- return options?.schema ?? options?.parentSchema ?? schemaName ?? this.config.getSchema();
474
+ return tableName;
475
+ }
476
+ /**
477
+ * @internal
478
+ */
479
+ getSchemaName(meta, options) {
480
+ if (meta?.schema && meta.schema !== '*') {
481
+ return meta.schema;
469
482
  }
470
- /** @internal */
471
- getORMClass() {
472
- return MikroORM;
483
+ if (options?.schema === '*') {
484
+ return this.config.get('schema');
473
485
  }
486
+ const schemaName = meta?.schema === '*' ? this.config.getSchema() : meta?.schema;
487
+ return options?.schema ?? options?.parentSchema ?? schemaName ?? this.config.getSchema();
488
+ }
489
+ /** @internal */
490
+ getORMClass() {
491
+ return MikroORM;
492
+ }
474
493
  }