@mikro-orm/core 7.0.0-dev.31 → 7.0.0-dev.311

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 (214) hide show
  1. package/EntityManager.d.ts +69 -61
  2. package/EntityManager.js +365 -283
  3. package/MikroORM.d.ts +44 -35
  4. package/MikroORM.js +109 -142
  5. package/README.md +5 -3
  6. package/cache/FileCacheAdapter.d.ts +1 -2
  7. package/cache/FileCacheAdapter.js +19 -14
  8. package/cache/GeneratedCacheAdapter.d.ts +0 -1
  9. package/cache/GeneratedCacheAdapter.js +0 -2
  10. package/cache/index.d.ts +1 -2
  11. package/cache/index.js +0 -2
  12. package/connections/Connection.d.ts +12 -5
  13. package/connections/Connection.js +37 -15
  14. package/drivers/DatabaseDriver.d.ts +25 -16
  15. package/drivers/DatabaseDriver.js +144 -43
  16. package/drivers/IDatabaseDriver.d.ts +118 -23
  17. package/entity/BaseEntity.d.ts +63 -4
  18. package/entity/BaseEntity.js +0 -3
  19. package/entity/Collection.d.ts +101 -29
  20. package/entity/Collection.js +473 -115
  21. package/entity/EntityAssigner.js +37 -25
  22. package/entity/EntityFactory.d.ts +7 -1
  23. package/entity/EntityFactory.js +116 -64
  24. package/entity/EntityHelper.d.ts +2 -2
  25. package/entity/EntityHelper.js +69 -27
  26. package/entity/EntityLoader.d.ts +11 -10
  27. package/entity/EntityLoader.js +262 -98
  28. package/entity/EntityRepository.d.ts +28 -8
  29. package/entity/EntityRepository.js +8 -2
  30. package/entity/PolymorphicRef.d.ts +12 -0
  31. package/entity/PolymorphicRef.js +18 -0
  32. package/entity/Reference.d.ts +2 -6
  33. package/entity/Reference.js +52 -19
  34. package/entity/WrappedEntity.d.ts +3 -8
  35. package/entity/WrappedEntity.js +6 -7
  36. package/entity/defineEntity.d.ts +525 -311
  37. package/entity/defineEntity.js +134 -290
  38. package/entity/index.d.ts +2 -2
  39. package/entity/index.js +2 -2
  40. package/entity/utils.d.ts +6 -1
  41. package/entity/utils.js +46 -11
  42. package/entity/validators.d.ts +11 -0
  43. package/entity/validators.js +66 -0
  44. package/enums.d.ts +8 -6
  45. package/enums.js +13 -17
  46. package/errors.d.ts +20 -10
  47. package/errors.js +63 -31
  48. package/events/EventManager.d.ts +2 -1
  49. package/events/EventManager.js +24 -13
  50. package/events/index.d.ts +1 -1
  51. package/events/index.js +0 -1
  52. package/exceptions.js +7 -2
  53. package/hydration/Hydrator.js +1 -2
  54. package/hydration/ObjectHydrator.d.ts +4 -4
  55. package/hydration/ObjectHydrator.js +105 -46
  56. package/index.d.ts +2 -2
  57. package/index.js +1 -2
  58. package/logging/DefaultLogger.d.ts +1 -1
  59. package/logging/DefaultLogger.js +3 -4
  60. package/logging/SimpleLogger.d.ts +1 -1
  61. package/logging/colors.d.ts +1 -1
  62. package/logging/colors.js +5 -7
  63. package/logging/index.d.ts +2 -1
  64. package/logging/index.js +1 -1
  65. package/logging/inspect.d.ts +2 -0
  66. package/logging/inspect.js +11 -0
  67. package/metadata/EntitySchema.d.ts +47 -23
  68. package/metadata/EntitySchema.js +103 -34
  69. package/metadata/MetadataDiscovery.d.ts +64 -9
  70. package/metadata/MetadataDiscovery.js +866 -354
  71. package/metadata/MetadataProvider.d.ts +11 -2
  72. package/metadata/MetadataProvider.js +71 -2
  73. package/metadata/MetadataStorage.d.ts +13 -11
  74. package/metadata/MetadataStorage.js +72 -41
  75. package/metadata/MetadataValidator.d.ts +32 -9
  76. package/metadata/MetadataValidator.js +214 -44
  77. package/metadata/discover-entities.d.ts +5 -0
  78. package/metadata/discover-entities.js +40 -0
  79. package/metadata/index.d.ts +1 -1
  80. package/metadata/index.js +0 -1
  81. package/metadata/types.d.ts +577 -0
  82. package/metadata/types.js +1 -0
  83. package/naming-strategy/AbstractNamingStrategy.d.ts +16 -4
  84. package/naming-strategy/AbstractNamingStrategy.js +26 -5
  85. package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
  86. package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
  87. package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
  88. package/naming-strategy/MongoNamingStrategy.js +6 -6
  89. package/naming-strategy/NamingStrategy.d.ts +28 -4
  90. package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
  91. package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
  92. package/naming-strategy/index.d.ts +1 -1
  93. package/naming-strategy/index.js +0 -1
  94. package/not-supported.d.ts +2 -0
  95. package/not-supported.js +8 -0
  96. package/package.json +47 -36
  97. package/platforms/ExceptionConverter.js +1 -1
  98. package/platforms/Platform.d.ts +11 -15
  99. package/platforms/Platform.js +72 -69
  100. package/serialization/EntitySerializer.d.ts +6 -3
  101. package/serialization/EntitySerializer.js +53 -29
  102. package/serialization/EntityTransformer.js +33 -21
  103. package/serialization/SerializationContext.d.ts +6 -6
  104. package/serialization/SerializationContext.js +4 -4
  105. package/types/ArrayType.d.ts +1 -1
  106. package/types/ArrayType.js +2 -3
  107. package/types/BigIntType.js +1 -1
  108. package/types/BlobType.d.ts +0 -1
  109. package/types/BlobType.js +0 -3
  110. package/types/BooleanType.d.ts +1 -0
  111. package/types/BooleanType.js +3 -0
  112. package/types/DecimalType.js +2 -2
  113. package/types/DoubleType.js +1 -1
  114. package/types/EnumArrayType.js +1 -2
  115. package/types/JsonType.d.ts +1 -1
  116. package/types/JsonType.js +7 -2
  117. package/types/TinyIntType.js +1 -1
  118. package/types/Type.d.ts +2 -4
  119. package/types/Type.js +3 -3
  120. package/types/Uint8ArrayType.d.ts +0 -1
  121. package/types/Uint8ArrayType.js +1 -4
  122. package/types/index.d.ts +3 -2
  123. package/typings.d.ts +427 -170
  124. package/typings.js +100 -45
  125. package/unit-of-work/ChangeSet.d.ts +4 -6
  126. package/unit-of-work/ChangeSet.js +8 -9
  127. package/unit-of-work/ChangeSetComputer.d.ts +3 -8
  128. package/unit-of-work/ChangeSetComputer.js +49 -26
  129. package/unit-of-work/ChangeSetPersister.d.ts +13 -12
  130. package/unit-of-work/ChangeSetPersister.js +106 -43
  131. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  132. package/unit-of-work/CommitOrderCalculator.js +17 -15
  133. package/unit-of-work/IdentityMap.d.ts +12 -0
  134. package/unit-of-work/IdentityMap.js +39 -1
  135. package/unit-of-work/UnitOfWork.d.ts +34 -4
  136. package/unit-of-work/UnitOfWork.js +294 -107
  137. package/utils/AbstractMigrator.d.ts +101 -0
  138. package/utils/AbstractMigrator.js +303 -0
  139. package/utils/AbstractSchemaGenerator.d.ts +5 -5
  140. package/utils/AbstractSchemaGenerator.js +30 -18
  141. package/utils/AsyncContext.d.ts +6 -0
  142. package/utils/AsyncContext.js +42 -0
  143. package/utils/Configuration.d.ts +795 -211
  144. package/utils/Configuration.js +160 -197
  145. package/utils/ConfigurationLoader.d.ts +1 -52
  146. package/utils/ConfigurationLoader.js +1 -330
  147. package/utils/Cursor.d.ts +0 -3
  148. package/utils/Cursor.js +29 -14
  149. package/utils/DataloaderUtils.d.ts +10 -5
  150. package/utils/DataloaderUtils.js +42 -22
  151. package/utils/EntityComparator.d.ts +16 -9
  152. package/utils/EntityComparator.js +202 -96
  153. package/utils/QueryHelper.d.ts +34 -6
  154. package/utils/QueryHelper.js +181 -48
  155. package/utils/RawQueryFragment.d.ts +28 -34
  156. package/utils/RawQueryFragment.js +37 -72
  157. package/utils/RequestContext.js +2 -2
  158. package/utils/TransactionContext.js +2 -2
  159. package/utils/TransactionManager.js +11 -7
  160. package/utils/Utils.d.ts +16 -127
  161. package/utils/Utils.js +106 -401
  162. package/utils/clone.js +8 -23
  163. package/utils/env-vars.d.ts +7 -0
  164. package/utils/env-vars.js +98 -0
  165. package/utils/fs-utils.d.ts +34 -0
  166. package/utils/fs-utils.js +193 -0
  167. package/utils/index.d.ts +1 -3
  168. package/utils/index.js +1 -3
  169. package/utils/upsert-utils.d.ts +9 -4
  170. package/utils/upsert-utils.js +51 -5
  171. package/decorators/Check.d.ts +0 -3
  172. package/decorators/Check.js +0 -13
  173. package/decorators/CreateRequestContext.d.ts +0 -3
  174. package/decorators/CreateRequestContext.js +0 -32
  175. package/decorators/Embeddable.d.ts +0 -8
  176. package/decorators/Embeddable.js +0 -11
  177. package/decorators/Embedded.d.ts +0 -12
  178. package/decorators/Embedded.js +0 -18
  179. package/decorators/Entity.d.ts +0 -33
  180. package/decorators/Entity.js +0 -12
  181. package/decorators/Enum.d.ts +0 -9
  182. package/decorators/Enum.js +0 -16
  183. package/decorators/Filter.d.ts +0 -2
  184. package/decorators/Filter.js +0 -8
  185. package/decorators/Formula.d.ts +0 -4
  186. package/decorators/Formula.js +0 -15
  187. package/decorators/Indexed.d.ts +0 -19
  188. package/decorators/Indexed.js +0 -20
  189. package/decorators/ManyToMany.d.ts +0 -42
  190. package/decorators/ManyToMany.js +0 -14
  191. package/decorators/ManyToOne.d.ts +0 -34
  192. package/decorators/ManyToOne.js +0 -14
  193. package/decorators/OneToMany.d.ts +0 -28
  194. package/decorators/OneToMany.js +0 -17
  195. package/decorators/OneToOne.d.ts +0 -28
  196. package/decorators/OneToOne.js +0 -7
  197. package/decorators/PrimaryKey.d.ts +0 -8
  198. package/decorators/PrimaryKey.js +0 -20
  199. package/decorators/Property.d.ts +0 -250
  200. package/decorators/Property.js +0 -32
  201. package/decorators/Transactional.d.ts +0 -14
  202. package/decorators/Transactional.js +0 -28
  203. package/decorators/hooks.d.ts +0 -16
  204. package/decorators/hooks.js +0 -47
  205. package/decorators/index.d.ts +0 -17
  206. package/decorators/index.js +0 -17
  207. package/entity/ArrayCollection.d.ts +0 -118
  208. package/entity/ArrayCollection.js +0 -407
  209. package/entity/EntityValidator.d.ts +0 -19
  210. package/entity/EntityValidator.js +0 -150
  211. package/metadata/ReflectMetadataProvider.d.ts +0 -8
  212. package/metadata/ReflectMetadataProvider.js +0 -44
  213. package/utils/resolveContextProvider.d.ts +0 -10
  214. package/utils/resolveContextProvider.js +0 -28
@@ -1,12 +1,11 @@
1
- import { inspect } from 'node:util';
2
1
  import { clone } from '../utils/clone.js';
3
2
  import { EntityRepository } from '../entity/EntityRepository.js';
4
3
  import { UnderscoreNamingStrategy } from '../naming-strategy/UnderscoreNamingStrategy.js';
5
4
  import { ExceptionConverter } from './ExceptionConverter.js';
6
- import { ArrayType, BigIntType, BlobType, Uint8ArrayType, BooleanType, CharacterType, DateType, DecimalType, DoubleType, JsonType, SmallIntType, TimeType, TinyIntType, Type, UuidType, StringType, IntegerType, FloatType, DateTimeType, TextType, EnumType, UnknownType, MediumIntType, IntervalType, } from '../types/index.js';
7
- import { parseJsonSafe, Utils } from '../utils/Utils.js';
5
+ import { ArrayType, BigIntType, BlobType, BooleanType, CharacterType, DateTimeType, DateType, DecimalType, DoubleType, EnumType, FloatType, IntegerType, IntervalType, JsonType, MediumIntType, SmallIntType, StringType, TextType, TimeType, TinyIntType, Type, Uint8ArrayType, UnknownType, UuidType, } from '../types/index.js';
6
+ import { parseJsonSafe } from '../utils/Utils.js';
8
7
  import { ReferenceKind } from '../enums.js';
9
- import { RawQueryFragment } from '../utils/RawQueryFragment.js';
8
+ import { Raw } from '../utils/RawQueryFragment.js';
10
9
  export const JsonProperty = Symbol('JsonProperty');
11
10
  export class Platform {
12
11
  exceptionConverter = new ExceptionConverter();
@@ -42,15 +41,15 @@ export class Platform {
42
41
  usesEnumCheckConstraints() {
43
42
  return false;
44
43
  }
44
+ supportsMaterializedViews() {
45
+ return false;
46
+ }
45
47
  getSchemaHelper() {
46
48
  return undefined;
47
49
  }
48
50
  indexForeignKeys() {
49
51
  return false;
50
52
  }
51
- allowsMultiInsert() {
52
- return true;
53
- }
54
53
  /**
55
54
  * Whether or not the driver supports retuning list of created PKs back when multi-inserting
56
55
  */
@@ -78,15 +77,6 @@ export class Platform {
78
77
  denormalizePrimaryKey(data) {
79
78
  return data;
80
79
  }
81
- /**
82
- * Used when serializing via toObject and toJSON methods, allows to use different PK field name (like `id` instead of `_id`)
83
- */
84
- getSerializedPrimaryKeyField(field) {
85
- return field;
86
- }
87
- usesDifferentSerializedPrimaryKey() {
88
- return false;
89
- }
90
80
  /**
91
81
  * Returns the SQL specific for the platform to get the current timestamp
92
82
  */
@@ -123,7 +113,7 @@ export class Platform {
123
113
  isAllowedTopLevelOperator(operator) {
124
114
  return operator === '$not';
125
115
  }
126
- quoteVersionValue(value, prop) {
116
+ convertVersionValue(value, prop) {
127
117
  return value;
128
118
  }
129
119
  getDefaultVersionLength() {
@@ -133,7 +123,7 @@ export class Platform {
133
123
  return true;
134
124
  }
135
125
  isBigIntProperty(prop) {
136
- return prop.columnTypes && prop.columnTypes[0] === 'bigint';
126
+ return prop.columnTypes?.[0] === 'bigint';
137
127
  }
138
128
  getDefaultSchemaName() {
139
129
  return undefined;
@@ -169,7 +159,7 @@ export class Platform {
169
159
  return `text`;
170
160
  }
171
161
  getEnumTypeDeclarationSQL(column) {
172
- if (column.items?.every(item => Utils.isString(item))) {
162
+ if (column.items?.every(item => typeof item === 'string')) {
173
163
  return `enum('${column.items.join("','")}')`;
174
164
  }
175
165
  return this.getTinyIntTypeDeclarationSQL(column);
@@ -190,7 +180,7 @@ export class Platform {
190
180
  return this.getVarcharTypeDeclarationSQL(column);
191
181
  }
192
182
  extractSimpleType(type) {
193
- return type.toLowerCase().match(/[^(), ]+/)[0];
183
+ return /[^(), ]+/.exec(type.toLowerCase())[0];
194
184
  }
195
185
  /**
196
186
  * This should be used only to compare types, it can strip some information like the length.
@@ -208,35 +198,58 @@ export class Platform {
208
198
  }
209
199
  switch (this.extractSimpleType(type)) {
210
200
  case 'character':
211
- case 'char': return Type.getType(CharacterType);
201
+ case 'char':
202
+ return Type.getType(CharacterType);
212
203
  case 'string':
213
- case 'varchar': return Type.getType(StringType);
214
- case 'interval': return Type.getType(IntervalType);
215
- case 'text': return Type.getType(TextType);
204
+ case 'varchar':
205
+ return Type.getType(StringType);
206
+ case 'interval':
207
+ return Type.getType(IntervalType);
208
+ case 'text':
209
+ return Type.getType(TextType);
216
210
  case 'int':
217
- case 'number': return Type.getType(IntegerType);
218
- case 'bigint': return Type.getType(BigIntType);
219
- case 'smallint': return Type.getType(SmallIntType);
220
- case 'tinyint': return Type.getType(TinyIntType);
221
- case 'mediumint': return Type.getType(MediumIntType);
222
- case 'float': return Type.getType(FloatType);
223
- case 'double': return Type.getType(DoubleType);
224
- case 'integer': return Type.getType(IntegerType);
211
+ case 'number':
212
+ return Type.getType(IntegerType);
213
+ case 'bigint':
214
+ return Type.getType(BigIntType);
215
+ case 'smallint':
216
+ return Type.getType(SmallIntType);
217
+ case 'tinyint':
218
+ return Type.getType(TinyIntType);
219
+ case 'mediumint':
220
+ return Type.getType(MediumIntType);
221
+ case 'float':
222
+ return Type.getType(FloatType);
223
+ case 'double':
224
+ return Type.getType(DoubleType);
225
+ case 'integer':
226
+ return Type.getType(IntegerType);
225
227
  case 'decimal':
226
- case 'numeric': return Type.getType(DecimalType);
227
- case 'boolean': return Type.getType(BooleanType);
228
+ case 'numeric':
229
+ return Type.getType(DecimalType);
230
+ case 'boolean':
231
+ return Type.getType(BooleanType);
228
232
  case 'blob':
229
- case 'buffer': return Type.getType(BlobType);
230
- case 'uint8array': return Type.getType(Uint8ArrayType);
231
- case 'uuid': return Type.getType(UuidType);
232
- case 'date': return Type.getType(DateType);
233
+ case 'buffer':
234
+ return Type.getType(BlobType);
235
+ case 'uint8array':
236
+ return Type.getType(Uint8ArrayType);
237
+ case 'uuid':
238
+ return Type.getType(UuidType);
239
+ case 'date':
240
+ return Type.getType(DateType);
233
241
  case 'datetime':
234
- case 'timestamp': return Type.getType(DateTimeType);
235
- case 'time': return Type.getType(TimeType);
242
+ case 'timestamp':
243
+ return Type.getType(DateTimeType);
244
+ case 'time':
245
+ return Type.getType(TimeType);
236
246
  case 'object':
237
- case 'json': return Type.getType(JsonType);
238
- case 'enum': return Type.getType(EnumType);
239
- default: return Type.getType(UnknownType);
247
+ case 'json':
248
+ return Type.getType(JsonType);
249
+ case 'enum':
250
+ return Type.getType(EnumType);
251
+ default:
252
+ return Type.getType(UnknownType);
240
253
  }
241
254
  }
242
255
  supportsMultipleCascadePaths() {
@@ -245,6 +258,9 @@ export class Platform {
245
258
  supportsMultipleStatements() {
246
259
  return this.config.get('multipleStatements');
247
260
  }
261
+ supportsUnionWhere() {
262
+ return false;
263
+ }
248
264
  getArrayDeclarationSQL() {
249
265
  return 'text';
250
266
  }
@@ -269,7 +285,7 @@ export class Platform {
269
285
  getSearchJsonPropertyKey(path, type, aliased, value) {
270
286
  return path.join('.');
271
287
  }
272
- /* v8 ignore next 3 */
288
+ /* v8 ignore next */
273
289
  getJsonIndexDefinition(index) {
274
290
  return index.columnNames;
275
291
  }
@@ -288,11 +304,7 @@ export class Platform {
288
304
  convertJsonToDatabaseValue(value, context) {
289
305
  return JSON.stringify(value);
290
306
  }
291
- convertJsonToJSValue(value, prop) {
292
- const isObjectEmbedded = prop.embedded && prop.object;
293
- if ((this.convertsJsonAutomatically() || isObjectEmbedded) && ['json', 'jsonb', this.getJsonDeclarationSQL()].includes(prop.columnTypes[0])) {
294
- return value;
295
- }
307
+ convertJsonToJSValue(value, context) {
296
308
  return parseJsonSafe(value);
297
309
  }
298
310
  convertDateToJSValue(value) {
@@ -306,7 +318,7 @@ export class Platform {
306
318
  }
307
319
  parseDate(value) {
308
320
  const date = new Date(value);
309
- /* v8 ignore next 3 */
321
+ /* v8 ignore next */
310
322
  if (isNaN(date.getTime())) {
311
323
  return value;
312
324
  }
@@ -336,19 +348,10 @@ export class Platform {
336
348
  if (extension) {
337
349
  return extension;
338
350
  }
339
- /* v8 ignore next 4 */
340
- const module = Utils.tryRequire({
341
- module: moduleName,
342
- warning: `Please install ${moduleName} package.`,
343
- });
344
- /* v8 ignore next 3 */
345
- if (module) {
346
- return this.config.getCachedService(module[extensionName], em);
347
- }
348
- /* v8 ignore next 2 */
349
- throw new Error(`${extensionName} extension not registered.`);
351
+ /* v8 ignore next */
352
+ throw new Error(`${extensionName} extension not registered. Provide it in the ORM config, or use the async \`MikroORM.init()\` method to load extensions automatically.`);
350
353
  }
351
- /* v8 ignore next 3: kept for type inference only */
354
+ /* v8 ignore next: kept for type inference only */
352
355
  getSchemaGenerator(driver, em) {
353
356
  throw new Error(`${driver.constructor.name} does not support SchemaGenerator`);
354
357
  }
@@ -356,7 +359,7 @@ export class Platform {
356
359
  return value;
357
360
  }
358
361
  quoteIdentifier(id, quote = '`') {
359
- const raw = RawQueryFragment.getKnownFragment(id);
362
+ const raw = Raw.getKnownFragment(id);
360
363
  if (raw) {
361
364
  return this.formatQuery(raw.sql, raw.params);
362
365
  }
@@ -365,7 +368,7 @@ export class Platform {
365
368
  quoteValue(value) {
366
369
  return value;
367
370
  }
368
- /* v8 ignore next 3 */
371
+ /* v8 ignore next */
369
372
  escape(value) {
370
373
  return value;
371
374
  }
@@ -377,7 +380,7 @@ export class Platform {
377
380
  let j = 0;
378
381
  let pos = 0;
379
382
  let ret = '';
380
- if (sql[0] === '?') {
383
+ if (sql.startsWith('?')) {
381
384
  if (sql[1] === '?') {
382
385
  ret += this.quoteIdentifier(params[j++]);
383
386
  pos = 2;
@@ -455,7 +458,7 @@ export class Platform {
455
458
  isPopulated(key, populate) {
456
459
  return populate === true || (populate !== false && populate.some(p => p.field === key || p.all));
457
460
  }
458
- shouldHaveColumn(prop, populate, exclude, includeFormulas = true) {
461
+ shouldHaveColumn(prop, populate, exclude, includeFormulas = true, ignoreInlineEmbeddables = true) {
459
462
  if (exclude?.includes(prop.name)) {
460
463
  return false;
461
464
  }
@@ -475,7 +478,7 @@ export class Platform {
475
478
  return true;
476
479
  }
477
480
  if (prop.kind === ReferenceKind.EMBEDDED) {
478
- return !!prop.object;
481
+ return prop.object || ignoreInlineEmbeddables;
479
482
  }
480
483
  return prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner;
481
484
  }
@@ -522,9 +525,9 @@ export class Platform {
522
525
  clone() {
523
526
  return this;
524
527
  }
525
- /* v8 ignore next 4 */
526
528
  /** @ignore */
527
- [inspect.custom]() {
529
+ /* v8 ignore next */
530
+ [Symbol.for('nodejs.util.inspect.custom')]() {
528
531
  return `[${this.constructor.name}]`;
529
532
  }
530
533
  }
@@ -1,9 +1,10 @@
1
- import type { ArrayElement, AutoPath, CleanTypeConfig, EntityDTO, FromEntityType, Loaded, TypeConfig, UnboxArray } from '../typings.js';
1
+ import type { ArrayElement, AutoPath, CleanTypeConfig, SerializeDTO, FromEntityType, TypeConfig, UnboxArray } from '../typings.js';
2
2
  import { type PopulatePath } from '../enums.js';
3
3
  export declare class EntitySerializer {
4
- static serialize<T extends object, P extends string = never, E extends string = never>(entity: T, options?: SerializeOptions<T, P, E>): EntityDTO<Loaded<T, P>>;
4
+ static serialize<T extends object, P extends string = never, E extends string = never>(entity: T, options?: SerializeOptions<T, P, E>): SerializeDTO<T, P, E>;
5
5
  private static propertyName;
6
6
  private static processProperty;
7
+ private static processCustomType;
7
8
  private static extractChildOptions;
8
9
  private static processEntity;
9
10
  private static processCollection;
@@ -23,6 +24,8 @@ export interface SerializeOptions<T, P extends string = never, E extends string
23
24
  skipNull?: boolean;
24
25
  /** Only include properties for a specific group. If a property does not specify any group, it will be included, otherwise only properties with a matching group are included. */
25
26
  groups?: string[];
27
+ /** Convert custom types to their database representation. By default, the `Type.toJSON` method is invoked instead. */
28
+ convertCustomTypes?: boolean;
26
29
  }
27
30
  /**
28
31
  * Converts entity instance to POJO, converting the `Collection`s to arrays and unwrapping the `Reference` wrapper, while respecting the serialization options.
@@ -36,4 +39,4 @@ export interface SerializeOptions<T, P extends string = never, E extends string
36
39
  * const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true });
37
40
  * ```
38
41
  */
39
- export declare function serialize<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Populate extends string = never, Exclude extends string = never, Config extends TypeConfig = never>(entity: Entity, options?: Config & SerializeOptions<UnboxArray<Entity>, Populate, Exclude>): Naked extends object[] ? EntityDTO<Loaded<ArrayElement<Naked>, Populate>, CleanTypeConfig<Config>>[] : EntityDTO<Loaded<Naked, Populate>, CleanTypeConfig<Config>>;
42
+ export declare function serialize<Entity extends object, Naked extends FromEntityType<Entity> = FromEntityType<Entity>, Populate extends string = never, Exclude extends string = never, Config extends TypeConfig = never>(entity: Entity, options?: Config & SerializeOptions<UnboxArray<Entity>, Populate, Exclude>): Naked extends object[] ? SerializeDTO<ArrayElement<Naked>, Populate, Exclude, CleanTypeConfig<Config>>[] : SerializeDTO<Naked, Populate, Exclude, CleanTypeConfig<Config>>;
@@ -9,18 +9,20 @@ function isVisible(meta, propName, options) {
9
9
  if (options.groups && prop?.groups) {
10
10
  return prop.groups.some(g => options.groups.includes(g));
11
11
  }
12
- if (Array.isArray(options.populate) && options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
12
+ if (Array.isArray(options.populate) &&
13
+ options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
13
14
  return true;
14
15
  }
15
16
  if (options.exclude?.find(item => item === propName)) {
16
17
  return false;
17
18
  }
18
19
  const visible = prop && !(prop.hidden && !options.includeHidden);
19
- const prefixed = prop && !prop.primary && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
20
+ const prefixed = prop && !prop.primary && !prop.accessor && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
20
21
  return visible && !prefixed;
21
22
  }
22
23
  function isPopulated(propName, options) {
23
- if (typeof options.populate !== 'boolean' && options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
24
+ if (typeof options.populate !== 'boolean' &&
25
+ options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
24
26
  return true;
25
27
  }
26
28
  if (typeof options.populate === 'boolean') {
@@ -41,23 +43,41 @@ export class EntitySerializer {
41
43
  }
42
44
  const root = wrapped.__serializationContext.root;
43
45
  const ret = {};
44
- const keys = new Set(meta.primaryKeys);
45
- Utils.keys(entity).forEach(prop => keys.add(prop));
46
+ const props = new Set();
47
+ if (meta.serializedPrimaryKey && !meta.compositePK) {
48
+ props.add(meta.serializedPrimaryKey);
49
+ }
50
+ else {
51
+ meta.primaryKeys.forEach(pk => props.add(pk));
52
+ }
53
+ if (wrapped.isInitialized() || !wrapped.hasPrimaryKey()) {
54
+ const entityKeys = new Set(Object.keys(entity));
55
+ for (const prop of meta.props) {
56
+ if (entityKeys.has(prop.name) || (prop.getter && prop.accessor === prop.name)) {
57
+ props.add(prop.name);
58
+ }
59
+ }
60
+ for (const key of entityKeys) {
61
+ if (!meta.properties[key]) {
62
+ props.add(key);
63
+ }
64
+ }
65
+ }
46
66
  const visited = root.visited.has(entity);
47
67
  if (!visited) {
48
68
  root.visited.add(entity);
49
69
  }
50
- for (const prop of keys) {
70
+ for (const prop of props) {
51
71
  if (!isVisible(meta, prop, options)) {
52
72
  continue;
53
73
  }
54
- const cycle = root.visit(meta.className, prop);
74
+ const cycle = root.visit(meta.class, prop);
55
75
  if (cycle && visited) {
56
76
  continue;
57
77
  }
58
78
  const val = this.processProperty(prop, entity, options);
59
79
  if (!cycle) {
60
- root.leave(meta.className, prop);
80
+ root.leave(meta.class, prop);
61
81
  }
62
82
  if (options.skipNull && Utils.isPlainObject(val)) {
63
83
  Utils.dropUndefinedProperties(val, null);
@@ -67,7 +87,7 @@ export class EntitySerializer {
67
87
  }
68
88
  const visible = typeof val !== 'undefined' && !(val === null && options.skipNull);
69
89
  if (visible) {
70
- ret[this.propertyName(meta, prop, wrapped.__platform)] = val;
90
+ ret[this.propertyName(meta, prop)] = val;
71
91
  }
72
92
  }
73
93
  if (contextCreated) {
@@ -81,26 +101,26 @@ export class EntitySerializer {
81
101
  if (prop.getterName != null) {
82
102
  const visible = entity[prop.getterName] instanceof Function && isVisible(meta, prop.name, options);
83
103
  if (visible) {
84
- ret[this.propertyName(meta, prop.name, wrapped.__platform)] = this.processProperty(prop.getterName, entity, options);
104
+ ret[this.propertyName(meta, prop.name)] = this.processProperty(prop.getterName, entity, options);
85
105
  }
86
106
  }
87
107
  else {
88
108
  // decorated getters
89
109
  const visible = typeof entity[prop.name] !== 'undefined' && isVisible(meta, prop.name, options);
90
110
  if (visible) {
91
- ret[this.propertyName(meta, prop.name, wrapped.__platform)] = this.processProperty(prop.name, entity, options);
111
+ ret[this.propertyName(meta, prop.name)] = this.processProperty(prop.name, entity, options);
92
112
  }
93
113
  }
94
114
  }
95
115
  return ret;
96
116
  }
97
- static propertyName(meta, prop, platform) {
98
- /* v8 ignore next 3 */
117
+ static propertyName(meta, prop) {
118
+ /* v8 ignore next */
99
119
  if (meta.properties[prop]?.serializedName) {
100
120
  return meta.properties[prop].serializedName;
101
121
  }
102
- if (meta.properties[prop]?.primary && platform) {
103
- return platform.getSerializedPrimaryKeyField(prop);
122
+ if (meta.properties[prop]?.primary && meta.serializedPrimaryKey) {
123
+ return meta.serializedPrimaryKey;
104
124
  }
105
125
  return prop;
106
126
  }
@@ -119,7 +139,7 @@ export class EntitySerializer {
119
139
  }
120
140
  return returnValue;
121
141
  }
122
- /* v8 ignore next 3 */
142
+ /* v8 ignore next */
123
143
  if (!options.ignoreSerializers && serializer) {
124
144
  return serializer(value);
125
145
  }
@@ -132,7 +152,7 @@ export class EntitySerializer {
132
152
  if (Utils.isScalarReference(value)) {
133
153
  return value.unwrap();
134
154
  }
135
- /* v8 ignore next 9 */
155
+ /* v8 ignore next */
136
156
  if (property?.kind === ReferenceKind.EMBEDDED) {
137
157
  if (Array.isArray(value)) {
138
158
  return value.map(item => helper(item).toJSON());
@@ -141,16 +161,26 @@ export class EntitySerializer {
141
161
  return helper(value).toJSON();
142
162
  }
143
163
  }
144
- const customType = property?.customType;
145
- if (customType) {
146
- return customType.toJSON(value, wrapped.__platform);
164
+ if (property.customType) {
165
+ return this.processCustomType(value, property, wrapped.__platform, options.convertCustomTypes);
147
166
  }
148
167
  return wrapped.__platform.normalizePrimaryKey(value);
149
168
  }
169
+ static processCustomType(value, prop, platform, convertCustomTypes) {
170
+ if (!prop.customType) {
171
+ return value;
172
+ }
173
+ if (convertCustomTypes) {
174
+ return prop.customType.convertToDatabaseValue(value, platform, { mode: 'serialization' });
175
+ }
176
+ return prop.customType.toJSON(value, platform);
177
+ }
150
178
  static extractChildOptions(options, prop) {
151
179
  return {
152
180
  ...options,
153
- populate: Array.isArray(options.populate) ? Utils.extractChildElements(options.populate, prop, '*') : options.populate,
181
+ populate: Array.isArray(options.populate)
182
+ ? Utils.extractChildElements(options.populate, prop, '*')
183
+ : options.populate,
154
184
  exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop) : options.exclude,
155
185
  };
156
186
  }
@@ -165,10 +195,7 @@ export class EntitySerializer {
165
195
  if (expand) {
166
196
  return this.serialize(child, childOptions);
167
197
  }
168
- let pk = wrapped.getPrimaryKey();
169
- if (prop.customType) {
170
- pk = prop.customType.toJSON(pk, wrapped.__platform);
171
- }
198
+ const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
172
199
  if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
173
200
  return Utils.primaryKeyToObject(meta, pk, visible);
174
201
  }
@@ -192,10 +219,7 @@ export class EntitySerializer {
192
219
  if (populated || !wrapped.__managed) {
193
220
  return this.serialize(item, this.extractChildOptions(options, prop.name));
194
221
  }
195
- let pk = wrapped.getPrimaryKey();
196
- if (prop.customType) {
197
- pk = prop.customType.toJSON(pk, wrapped.__platform);
198
- }
222
+ const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
199
223
  if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
200
224
  return Utils.primaryKeyToObject(wrapped.__meta, pk);
201
225
  }
@@ -6,7 +6,7 @@ import { isRaw } from '../utils/RawQueryFragment.js';
6
6
  function isVisible(meta, propName, ignoreFields = []) {
7
7
  const prop = meta.properties[propName];
8
8
  const visible = prop && !prop.hidden;
9
- const prefixed = prop && !prop.primary && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
9
+ const prefixed = prop && !prop.primary && !prop.accessor && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
10
10
  return visible && !prefixed && !ignoreFields.includes(propName);
11
11
  }
12
12
  export class EntityTransformer {
@@ -27,39 +27,51 @@ export class EntityTransformer {
27
27
  const root = wrapped.__serializationContext.root;
28
28
  const meta = wrapped.__meta;
29
29
  const ret = {};
30
- const keys = new Set();
30
+ const props = new Set();
31
31
  if (meta.serializedPrimaryKey && !meta.compositePK) {
32
- keys.add(meta.serializedPrimaryKey);
32
+ props.add(meta.serializedPrimaryKey);
33
33
  }
34
34
  else {
35
- meta.primaryKeys.forEach(pk => keys.add(pk));
35
+ meta.primaryKeys.forEach(pk => props.add(pk));
36
36
  }
37
37
  if (wrapped.isInitialized() || !wrapped.hasPrimaryKey()) {
38
- Utils.keys(entity).forEach(prop => keys.add(prop));
38
+ const entityKeys = new Set(Object.keys(entity));
39
+ for (const prop of meta.props) {
40
+ if (entityKeys.has(prop.name) || (prop.getter && prop.accessor === prop.name)) {
41
+ props.add(prop.name);
42
+ }
43
+ }
44
+ for (const key of entityKeys) {
45
+ if (!meta.properties[key]) {
46
+ props.add(key);
47
+ }
48
+ }
39
49
  }
40
50
  const visited = root.visited.has(entity);
41
51
  const includePrimaryKeys = wrapped.__config.get('serialization').includePrimaryKeys;
42
52
  if (!visited) {
43
53
  root.visited.add(entity);
44
54
  }
45
- for (const prop of keys) {
55
+ for (const prop of props) {
46
56
  const visible = raw ? meta.properties[prop] : isVisible(meta, prop, ignoreFields);
47
57
  if (!visible) {
48
58
  continue;
49
59
  }
50
- const populated = root.isMarkedAsPopulated(meta.className, prop);
51
- const partiallyLoaded = root.isPartiallyLoaded(meta.className, prop);
52
- const isPrimary = includePrimaryKeys && meta.properties[prop].primary;
53
- if (!partiallyLoaded && !populated && !isPrimary) {
54
- continue;
60
+ const populated = root.isMarkedAsPopulated(meta.class, prop);
61
+ if (!raw) {
62
+ const partiallyLoaded = root.isPartiallyLoaded(meta.class, prop);
63
+ const isPrimary = includePrimaryKeys && meta.properties[prop].primary;
64
+ if (!partiallyLoaded && !populated && !isPrimary) {
65
+ continue;
66
+ }
55
67
  }
56
- const cycle = root.visit(meta.className, prop);
68
+ const cycle = root.visit(meta.class, prop);
57
69
  if (cycle && visited) {
58
70
  continue;
59
71
  }
60
72
  const val = EntityTransformer.processProperty(prop, entity, raw, populated);
61
73
  if (!cycle) {
62
- root.leave(meta.className, prop);
74
+ root.leave(meta.class, prop);
63
75
  }
64
76
  if (isRaw(val)) {
65
77
  throw new Error(`Trying to serialize raw SQL fragment: '${val.sql}'`);
@@ -67,7 +79,7 @@ export class EntityTransformer {
67
79
  if (typeof val === 'undefined') {
68
80
  continue;
69
81
  }
70
- ret[this.propertyName(meta, prop, wrapped.__platform, raw)] = val;
82
+ ret[this.propertyName(meta, prop, raw)] = val;
71
83
  }
72
84
  if (!wrapped.isInitialized() && wrapped.hasPrimaryKey()) {
73
85
  return ret;
@@ -76,17 +88,17 @@ export class EntityTransformer {
76
88
  // decorated get methods
77
89
  if (prop.getterName != null) {
78
90
  const visible = !prop.hidden && entity[prop.getterName] instanceof Function;
79
- const populated = root.isMarkedAsPopulated(meta.className, prop.name);
91
+ const populated = root.isMarkedAsPopulated(meta.class, prop.name);
80
92
  if (visible) {
81
- ret[this.propertyName(meta, prop.name, wrapped.__platform, raw)] = this.processProperty(prop.getterName, entity, raw, populated);
93
+ ret[this.propertyName(meta, prop.name, raw)] = this.processProperty(prop.getterName, entity, raw, populated);
82
94
  }
83
95
  }
84
96
  else {
85
97
  // decorated getters
86
98
  const visible = !prop.hidden && typeof entity[prop.name] !== 'undefined';
87
- const populated = root.isMarkedAsPopulated(meta.className, prop.name);
99
+ const populated = root.isMarkedAsPopulated(meta.class, prop.name);
88
100
  if (visible) {
89
- ret[this.propertyName(meta, prop.name, wrapped.__platform, raw)] = this.processProperty(prop.name, entity, raw, populated);
101
+ ret[this.propertyName(meta, prop.name, raw)] = this.processProperty(prop.name, entity, raw, populated);
90
102
  }
91
103
  }
92
104
  }
@@ -95,15 +107,15 @@ export class EntityTransformer {
95
107
  }
96
108
  return ret;
97
109
  }
98
- static propertyName(meta, prop, platform, raw) {
110
+ static propertyName(meta, prop, raw) {
99
111
  if (raw) {
100
112
  return prop;
101
113
  }
102
114
  if (meta.properties[prop].serializedName) {
103
115
  return meta.properties[prop].serializedName;
104
116
  }
105
- if (meta.properties[prop].primary && platform) {
106
- return platform.getSerializedPrimaryKeyField(prop);
117
+ if (meta.properties[prop].primary && meta.serializedPrimaryKey) {
118
+ return meta.serializedPrimaryKey;
107
119
  }
108
120
  return prop;
109
121
  }
@@ -1,4 +1,4 @@
1
- import type { AnyEntity, EntityMetadata, PopulateOptions } from '../typings.js';
1
+ import type { AnyEntity, EntityMetadata, EntityName, PopulateOptions } from '../typings.js';
2
2
  import type { Configuration } from '../utils/Configuration.js';
3
3
  /**
4
4
  * Helper that allows to keep track of where we are currently at when serializing complex entity graph with cycles.
@@ -10,21 +10,21 @@ export declare class SerializationContext<T extends object> {
10
10
  private readonly populate;
11
11
  private readonly fields?;
12
12
  private readonly exclude?;
13
- readonly path: [string, string][];
13
+ readonly path: [EntityName, string][];
14
14
  readonly visited: Set<Partial<any>>;
15
15
  private entities;
16
16
  constructor(config: Configuration, populate?: PopulateOptions<T>[], fields?: Set<string> | undefined, exclude?: string[] | undefined);
17
17
  /**
18
18
  * Returns true when there is a cycle detected.
19
19
  */
20
- visit(entityName: string, prop: string): boolean;
21
- leave<U>(entityName: string, prop: string): void;
20
+ visit(entityName: EntityName, prop: string): boolean;
21
+ leave(entityName: EntityName, prop: string): void;
22
22
  close(): void;
23
23
  /**
24
24
  * When initializing new context, we need to propagate it to the whole entity graph recursively.
25
25
  */
26
26
  static propagate(root: SerializationContext<any>, entity: AnyEntity, isVisible: (meta: EntityMetadata, prop: string) => boolean): void;
27
- isMarkedAsPopulated(entityName: string, prop: string): boolean;
28
- isPartiallyLoaded(entityName: string, prop: string): boolean;
27
+ isMarkedAsPopulated(entityName: EntityName, prop: string): boolean;
28
+ isPartiallyLoaded(entityName: EntityName, prop: string): boolean;
29
29
  private register;
30
30
  }