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

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 (206) hide show
  1. package/EntityManager.d.ts +884 -583
  2. package/EntityManager.js +1922 -1895
  3. package/MikroORM.d.ts +103 -74
  4. package/MikroORM.js +178 -179
  5. package/README.md +1 -1
  6. package/cache/CacheAdapter.d.ts +36 -36
  7. package/cache/FileCacheAdapter.d.ts +30 -24
  8. package/cache/FileCacheAdapter.js +80 -78
  9. package/cache/GeneratedCacheAdapter.d.ts +18 -20
  10. package/cache/GeneratedCacheAdapter.js +30 -30
  11. package/cache/MemoryCacheAdapter.d.ts +18 -20
  12. package/cache/MemoryCacheAdapter.js +35 -36
  13. package/cache/NullCacheAdapter.d.ts +16 -16
  14. package/cache/NullCacheAdapter.js +24 -24
  15. package/connections/Connection.d.ts +95 -84
  16. package/connections/Connection.js +165 -168
  17. package/drivers/DatabaseDriver.d.ts +186 -80
  18. package/drivers/DatabaseDriver.js +450 -443
  19. package/drivers/IDatabaseDriver.d.ts +440 -301
  20. package/entity/BaseEntity.d.ts +120 -83
  21. package/entity/BaseEntity.js +43 -43
  22. package/entity/Collection.d.ts +212 -179
  23. package/entity/Collection.js +727 -721
  24. package/entity/EntityAssigner.d.ts +88 -77
  25. package/entity/EntityAssigner.js +231 -230
  26. package/entity/EntityFactory.d.ts +66 -54
  27. package/entity/EntityFactory.js +425 -383
  28. package/entity/EntityHelper.d.ts +34 -22
  29. package/entity/EntityHelper.js +280 -267
  30. package/entity/EntityIdentifier.d.ts +4 -4
  31. package/entity/EntityIdentifier.js +10 -10
  32. package/entity/EntityLoader.d.ts +98 -72
  33. package/entity/EntityLoader.js +753 -723
  34. package/entity/EntityRepository.d.ts +316 -201
  35. package/entity/EntityRepository.js +213 -213
  36. package/entity/PolymorphicRef.d.ts +5 -5
  37. package/entity/PolymorphicRef.js +10 -10
  38. package/entity/Reference.d.ts +126 -82
  39. package/entity/Reference.js +278 -274
  40. package/entity/WrappedEntity.d.ts +115 -72
  41. package/entity/WrappedEntity.js +168 -166
  42. package/entity/defineEntity.d.ts +1315 -636
  43. package/entity/defineEntity.js +527 -518
  44. package/entity/utils.d.ts +13 -3
  45. package/entity/utils.js +71 -73
  46. package/entity/validators.js +43 -43
  47. package/entity/wrap.js +8 -8
  48. package/enums.d.ts +258 -253
  49. package/enums.js +251 -252
  50. package/errors.d.ts +114 -72
  51. package/errors.js +350 -253
  52. package/events/EventManager.d.ts +26 -14
  53. package/events/EventManager.js +79 -77
  54. package/events/EventSubscriber.d.ts +29 -29
  55. package/events/TransactionEventBroadcaster.d.ts +15 -8
  56. package/events/TransactionEventBroadcaster.js +14 -14
  57. package/exceptions.d.ts +23 -40
  58. package/exceptions.js +35 -52
  59. package/hydration/Hydrator.d.ts +42 -17
  60. package/hydration/Hydrator.js +43 -43
  61. package/hydration/ObjectHydrator.d.ts +50 -17
  62. package/hydration/ObjectHydrator.js +481 -416
  63. package/index.d.ts +116 -2
  64. package/index.js +10 -1
  65. package/logging/DefaultLogger.d.ts +34 -32
  66. package/logging/DefaultLogger.js +86 -86
  67. package/logging/Logger.d.ts +41 -41
  68. package/logging/SimpleLogger.d.ts +13 -11
  69. package/logging/SimpleLogger.js +22 -22
  70. package/logging/colors.d.ts +6 -6
  71. package/logging/colors.js +11 -10
  72. package/logging/inspect.js +7 -7
  73. package/metadata/EntitySchema.d.ts +211 -127
  74. package/metadata/EntitySchema.js +397 -398
  75. package/metadata/MetadataDiscovery.d.ts +114 -114
  76. package/metadata/MetadataDiscovery.js +1951 -1863
  77. package/metadata/MetadataProvider.d.ts +24 -21
  78. package/metadata/MetadataProvider.js +82 -84
  79. package/metadata/MetadataStorage.d.ts +38 -32
  80. package/metadata/MetadataStorage.js +118 -118
  81. package/metadata/MetadataValidator.d.ts +39 -39
  82. package/metadata/MetadataValidator.js +381 -338
  83. package/metadata/discover-entities.d.ts +5 -2
  84. package/metadata/discover-entities.js +35 -27
  85. package/metadata/types.d.ts +615 -531
  86. package/naming-strategy/AbstractNamingStrategy.d.ts +54 -39
  87. package/naming-strategy/AbstractNamingStrategy.js +90 -85
  88. package/naming-strategy/EntityCaseNamingStrategy.d.ts +6 -6
  89. package/naming-strategy/EntityCaseNamingStrategy.js +22 -22
  90. package/naming-strategy/MongoNamingStrategy.d.ts +6 -6
  91. package/naming-strategy/MongoNamingStrategy.js +18 -18
  92. package/naming-strategy/NamingStrategy.d.ts +109 -99
  93. package/naming-strategy/UnderscoreNamingStrategy.d.ts +7 -7
  94. package/naming-strategy/UnderscoreNamingStrategy.js +21 -21
  95. package/not-supported.js +7 -4
  96. package/package.json +1 -1
  97. package/platforms/ExceptionConverter.d.ts +1 -1
  98. package/platforms/ExceptionConverter.js +4 -4
  99. package/platforms/Platform.d.ts +310 -299
  100. package/platforms/Platform.js +663 -636
  101. package/serialization/EntitySerializer.d.ts +49 -26
  102. package/serialization/EntitySerializer.js +224 -218
  103. package/serialization/EntityTransformer.d.ts +10 -6
  104. package/serialization/EntityTransformer.js +219 -217
  105. package/serialization/SerializationContext.d.ts +27 -23
  106. package/serialization/SerializationContext.js +105 -105
  107. package/types/ArrayType.d.ts +8 -8
  108. package/types/ArrayType.js +33 -33
  109. package/types/BigIntType.d.ts +17 -10
  110. package/types/BigIntType.js +37 -37
  111. package/types/BlobType.d.ts +3 -3
  112. package/types/BlobType.js +13 -13
  113. package/types/BooleanType.d.ts +4 -4
  114. package/types/BooleanType.js +12 -12
  115. package/types/CharacterType.d.ts +2 -2
  116. package/types/CharacterType.js +6 -6
  117. package/types/DateTimeType.d.ts +5 -5
  118. package/types/DateTimeType.js +15 -15
  119. package/types/DateType.d.ts +5 -5
  120. package/types/DateType.js +15 -15
  121. package/types/DecimalType.d.ts +7 -7
  122. package/types/DecimalType.js +26 -26
  123. package/types/DoubleType.d.ts +3 -3
  124. package/types/DoubleType.js +12 -12
  125. package/types/EnumArrayType.d.ts +5 -5
  126. package/types/EnumArrayType.js +24 -24
  127. package/types/EnumType.d.ts +3 -3
  128. package/types/EnumType.js +11 -11
  129. package/types/FloatType.d.ts +3 -3
  130. package/types/FloatType.js +9 -9
  131. package/types/IntegerType.d.ts +3 -3
  132. package/types/IntegerType.js +9 -9
  133. package/types/IntervalType.d.ts +4 -4
  134. package/types/IntervalType.js +12 -12
  135. package/types/JsonType.d.ts +8 -8
  136. package/types/JsonType.js +32 -32
  137. package/types/MediumIntType.d.ts +1 -1
  138. package/types/MediumIntType.js +3 -3
  139. package/types/SmallIntType.d.ts +3 -3
  140. package/types/SmallIntType.js +9 -9
  141. package/types/StringType.d.ts +4 -4
  142. package/types/StringType.js +12 -12
  143. package/types/TextType.d.ts +3 -3
  144. package/types/TextType.js +9 -9
  145. package/types/TimeType.d.ts +5 -5
  146. package/types/TimeType.js +17 -17
  147. package/types/TinyIntType.d.ts +3 -3
  148. package/types/TinyIntType.js +10 -10
  149. package/types/Type.d.ts +83 -79
  150. package/types/Type.js +82 -82
  151. package/types/Uint8ArrayType.d.ts +4 -4
  152. package/types/Uint8ArrayType.js +21 -21
  153. package/types/UnknownType.d.ts +4 -4
  154. package/types/UnknownType.js +12 -12
  155. package/types/UuidType.d.ts +5 -5
  156. package/types/UuidType.js +19 -19
  157. package/types/index.d.ts +75 -49
  158. package/types/index.js +52 -26
  159. package/typings.d.ts +1250 -737
  160. package/typings.js +244 -231
  161. package/unit-of-work/ChangeSet.d.ts +26 -26
  162. package/unit-of-work/ChangeSet.js +56 -56
  163. package/unit-of-work/ChangeSetComputer.d.ts +12 -12
  164. package/unit-of-work/ChangeSetComputer.js +178 -170
  165. package/unit-of-work/ChangeSetPersister.d.ts +63 -44
  166. package/unit-of-work/ChangeSetPersister.js +442 -421
  167. package/unit-of-work/CommitOrderCalculator.d.ts +40 -40
  168. package/unit-of-work/CommitOrderCalculator.js +89 -88
  169. package/unit-of-work/IdentityMap.d.ts +31 -31
  170. package/unit-of-work/IdentityMap.js +105 -105
  171. package/unit-of-work/UnitOfWork.d.ts +181 -141
  172. package/unit-of-work/UnitOfWork.js +1200 -1183
  173. package/utils/AbstractMigrator.d.ts +111 -91
  174. package/utils/AbstractMigrator.js +275 -275
  175. package/utils/AbstractSchemaGenerator.d.ts +43 -34
  176. package/utils/AbstractSchemaGenerator.js +121 -122
  177. package/utils/AsyncContext.d.ts +3 -3
  178. package/utils/AsyncContext.js +34 -35
  179. package/utils/Configuration.d.ts +852 -808
  180. package/utils/Configuration.js +359 -344
  181. package/utils/Cursor.d.ts +40 -22
  182. package/utils/Cursor.js +135 -127
  183. package/utils/DataloaderUtils.d.ts +58 -43
  184. package/utils/DataloaderUtils.js +203 -198
  185. package/utils/EntityComparator.d.ts +98 -81
  186. package/utils/EntityComparator.js +828 -728
  187. package/utils/NullHighlighter.d.ts +1 -1
  188. package/utils/NullHighlighter.js +3 -3
  189. package/utils/QueryHelper.d.ts +79 -51
  190. package/utils/QueryHelper.js +372 -361
  191. package/utils/RawQueryFragment.d.ts +50 -34
  192. package/utils/RawQueryFragment.js +107 -105
  193. package/utils/RequestContext.d.ts +32 -32
  194. package/utils/RequestContext.js +52 -53
  195. package/utils/TransactionContext.d.ts +16 -16
  196. package/utils/TransactionContext.js +27 -27
  197. package/utils/TransactionManager.d.ts +58 -58
  198. package/utils/TransactionManager.js +199 -197
  199. package/utils/Utils.d.ts +204 -145
  200. package/utils/Utils.js +812 -810
  201. package/utils/clone.js +104 -113
  202. package/utils/env-vars.js +90 -88
  203. package/utils/fs-utils.d.ts +15 -15
  204. package/utils/fs-utils.js +180 -181
  205. package/utils/upsert-utils.d.ts +20 -5
  206. package/utils/upsert-utils.js +114 -116
@@ -1,33 +1,45 @@
1
- import type { ArrayElement, AutoPath, CleanTypeConfig, ExtractFieldsHint, FromEntityType, SerializeDTO, TypeConfig, UnboxArray } from '../typings.js';
1
+ import type {
2
+ ArrayElement,
3
+ AutoPath,
4
+ CleanTypeConfig,
5
+ ExtractFieldsHint,
6
+ FromEntityType,
7
+ SerializeDTO,
8
+ TypeConfig,
9
+ UnboxArray,
10
+ } from '../typings.js';
2
11
  import { type PopulatePath } from '../enums.js';
3
12
  /** Converts entity instances to plain DTOs via `serialize()`, with fine-grained control over populate, exclude, and serialization groups. */
4
13
  export declare class EntitySerializer {
5
- /** Serializes an entity to a plain DTO, with fine-grained control over population, exclusion, groups, and custom types. */
6
- static serialize<T extends object, P extends string = never, E extends string = never>(entity: T, options?: SerializeOptions<T, P, E>): SerializeDTO<T, P, E>;
7
- private static propertyName;
8
- private static processProperty;
9
- private static processCustomType;
10
- private static extractChildOptions;
11
- private static processEntity;
12
- private static processCollection;
14
+ /** Serializes an entity to a plain DTO, with fine-grained control over population, exclusion, groups, and custom types. */
15
+ static serialize<T extends object, P extends string = never, E extends string = never>(
16
+ entity: T,
17
+ options?: SerializeOptions<T, P, E>,
18
+ ): SerializeDTO<T, P, E>;
19
+ private static propertyName;
20
+ private static processProperty;
21
+ private static processCustomType;
22
+ private static extractChildOptions;
23
+ private static processEntity;
24
+ private static processCollection;
13
25
  }
14
26
  export interface SerializeOptions<T, P extends string = never, E extends string = never> {
15
- /** Specify which relation should be serialized as populated and which as a FK. */
16
- populate?: readonly AutoPath<T, P, `${PopulatePath.ALL}`>[];
17
- /** Specify which properties should be omitted. */
18
- exclude?: readonly AutoPath<T, E>[];
19
- /** Enforce unpopulated references to be returned as objects, e.g. `{ author: { id: 1 } }` instead of `{ author: 1 }`. */
20
- forceObject?: boolean;
21
- /** Ignore custom property serializers. */
22
- ignoreSerializers?: boolean;
23
- /** Include properties marked as `hidden`. */
24
- includeHidden?: boolean;
25
- /** Skip properties with `null` value. */
26
- skipNull?: boolean;
27
- /** 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. */
28
- groups?: string[];
29
- /** Convert custom types to their database representation. By default, the `Type.toJSON` method is invoked instead. */
30
- convertCustomTypes?: boolean;
27
+ /** Specify which relation should be serialized as populated and which as a FK. */
28
+ populate?: readonly AutoPath<T, P, `${PopulatePath.ALL}`>[];
29
+ /** Specify which properties should be omitted. */
30
+ exclude?: readonly AutoPath<T, E>[];
31
+ /** Enforce unpopulated references to be returned as objects, e.g. `{ author: { id: 1 } }` instead of `{ author: 1 }`. */
32
+ forceObject?: boolean;
33
+ /** Ignore custom property serializers. */
34
+ ignoreSerializers?: boolean;
35
+ /** Include properties marked as `hidden`. */
36
+ includeHidden?: boolean;
37
+ /** Skip properties with `null` value. */
38
+ skipNull?: boolean;
39
+ /** 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. */
40
+ groups?: string[];
41
+ /** Convert custom types to their database representation. By default, the `Type.toJSON` method is invoked instead. */
42
+ convertCustomTypes?: boolean;
31
43
  }
32
44
  /**
33
45
  * Converts entity instance to POJO, converting the `Collection`s to arrays and unwrapping the `Reference` wrapper, while respecting the serialization options.
@@ -41,4 +53,15 @@ export interface SerializeOptions<T, P extends string = never, E extends string
41
53
  * const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true });
42
54
  * ```
43
55
  */
44
- 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>, ExtractFieldsHint<Entity>>;
56
+ export declare function serialize<
57
+ Entity extends object,
58
+ Naked extends FromEntityType<Entity> = FromEntityType<Entity>,
59
+ Populate extends string = never,
60
+ Exclude extends string = never,
61
+ Config extends TypeConfig = never,
62
+ >(
63
+ entity: Entity,
64
+ options?: Config & SerializeOptions<UnboxArray<Entity>, Populate, Exclude>,
65
+ ): Naked extends object[]
66
+ ? SerializeDTO<ArrayElement<Naked>, Populate, Exclude, CleanTypeConfig<Config>>[]
67
+ : SerializeDTO<Naked, Populate, Exclude, CleanTypeConfig<Config>, ExtractFieldsHint<Entity>>;
@@ -5,229 +5,235 @@ import { Reference } from '../entity/Reference.js';
5
5
  import { SerializationContext } from './SerializationContext.js';
6
6
  import { isRaw } from '../utils/RawQueryFragment.js';
7
7
  function isVisible(meta, propName, options) {
8
- const prop = meta.properties[propName];
9
- if (options.groups && prop?.groups) {
10
- return prop.groups.some(g => options.groups.includes(g));
11
- }
12
- if (Array.isArray(options.populate) &&
13
- options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
14
- return true;
15
- }
16
- if (options.exclude?.find(item => item === propName)) {
17
- return false;
18
- }
19
- const visible = prop && !(prop.hidden && !options.includeHidden);
20
- const prefixed = prop && !prop.primary && !prop.accessor && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
21
- return visible && !prefixed;
8
+ const prop = meta.properties[propName];
9
+ if (options.groups && prop?.groups) {
10
+ return prop.groups.some(g => options.groups.includes(g));
11
+ }
12
+ if (
13
+ Array.isArray(options.populate) &&
14
+ options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')
15
+ ) {
16
+ return true;
17
+ }
18
+ if (options.exclude?.find(item => item === propName)) {
19
+ return false;
20
+ }
21
+ const visible = prop && !(prop.hidden && !options.includeHidden);
22
+ const prefixed = prop && !prop.primary && !prop.accessor && propName.startsWith('_'); // ignore prefixed properties, if it's not a PK
23
+ return visible && !prefixed;
22
24
  }
23
25
  function isPopulated(propName, options) {
24
- if (typeof options.populate !== 'boolean' &&
25
- options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
26
- return true;
27
- }
28
- if (typeof options.populate === 'boolean') {
29
- return options.populate;
30
- }
31
- return false;
26
+ if (
27
+ typeof options.populate !== 'boolean' &&
28
+ options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')
29
+ ) {
30
+ return true;
31
+ }
32
+ if (typeof options.populate === 'boolean') {
33
+ return options.populate;
34
+ }
35
+ return false;
32
36
  }
33
37
  /** Converts entity instances to plain DTOs via `serialize()`, with fine-grained control over populate, exclude, and serialization groups. */
34
38
  export class EntitySerializer {
35
- /** Serializes an entity to a plain DTO, with fine-grained control over population, exclusion, groups, and custom types. */
36
- static serialize(entity, options = {}) {
37
- const wrapped = helper(entity);
38
- const meta = wrapped.__meta;
39
- let contextCreated = false;
40
- if (!wrapped.__serializationContext.root) {
41
- const root = new SerializationContext();
42
- SerializationContext.propagate(root, entity, (meta, prop) => meta.properties[prop]?.kind !== ReferenceKind.SCALAR);
43
- options.populate = (options.populate ? Utils.asArray(options.populate) : options.populate);
44
- contextCreated = true;
45
- }
46
- const root = wrapped.__serializationContext.root;
47
- const ret = {};
48
- const props = new Set();
49
- if (meta.serializedPrimaryKey && !meta.compositePK) {
50
- props.add(meta.serializedPrimaryKey);
51
- }
52
- else {
53
- meta.primaryKeys.forEach(pk => props.add(pk));
54
- }
55
- if (wrapped.isInitialized() || !wrapped.hasPrimaryKey()) {
56
- const entityKeys = new Set(Object.keys(entity));
57
- for (const prop of meta.props) {
58
- if (entityKeys.has(prop.name) || (prop.getter && prop.accessor === prop.name)) {
59
- props.add(prop.name);
60
- }
61
- }
62
- for (const key of entityKeys) {
63
- if (!meta.properties[key]) {
64
- props.add(key);
65
- }
66
- }
67
- }
68
- const visited = root.visited.has(entity);
69
- if (!visited) {
70
- root.visited.add(entity);
71
- }
72
- for (const prop of props) {
73
- if (!isVisible(meta, prop, options)) {
74
- continue;
75
- }
76
- const cycle = root.visit(meta.class, prop);
77
- if (cycle && visited) {
78
- continue;
79
- }
80
- const val = this.processProperty(prop, entity, options);
81
- if (!cycle) {
82
- root.leave(meta.class, prop);
83
- }
84
- if (options.skipNull && Utils.isPlainObject(val)) {
85
- Utils.dropUndefinedProperties(val, null);
86
- }
87
- if (isRaw(val)) {
88
- throw new Error(`Trying to serialize raw SQL fragment: '${val.sql}'`);
89
- }
90
- const visible = typeof val !== 'undefined' && !(val === null && options.skipNull);
91
- if (visible) {
92
- ret[this.propertyName(meta, prop)] = val;
93
- }
94
- }
95
- if (contextCreated) {
96
- root.close();
97
- }
98
- if (!wrapped.isInitialized()) {
99
- return ret;
100
- }
101
- for (const prop of meta.getterProps) {
102
- // decorated get methods
103
- if (prop.getterName != null) {
104
- const visible = entity[prop.getterName] instanceof Function && isVisible(meta, prop.name, options);
105
- if (visible) {
106
- ret[this.propertyName(meta, prop.name)] = this.processProperty(prop.getterName, entity, options);
107
- }
108
- }
109
- else {
110
- // decorated getters
111
- const visible = typeof entity[prop.name] !== 'undefined' && isVisible(meta, prop.name, options);
112
- if (visible) {
113
- ret[this.propertyName(meta, prop.name)] = this.processProperty(prop.name, entity, options);
114
- }
115
- }
116
- }
117
- return ret;
39
+ /** Serializes an entity to a plain DTO, with fine-grained control over population, exclusion, groups, and custom types. */
40
+ static serialize(entity, options = {}) {
41
+ const wrapped = helper(entity);
42
+ const meta = wrapped.__meta;
43
+ let contextCreated = false;
44
+ if (!wrapped.__serializationContext.root) {
45
+ const root = new SerializationContext();
46
+ SerializationContext.propagate(
47
+ root,
48
+ entity,
49
+ (meta, prop) => meta.properties[prop]?.kind !== ReferenceKind.SCALAR,
50
+ );
51
+ options.populate = options.populate ? Utils.asArray(options.populate) : options.populate;
52
+ contextCreated = true;
118
53
  }
119
- static propertyName(meta, prop) {
120
- /* v8 ignore next */
121
- if (meta.properties[prop]?.serializedName) {
122
- return meta.properties[prop].serializedName;
123
- }
124
- if (meta.properties[prop]?.primary && meta.serializedPrimaryKey) {
125
- return meta.serializedPrimaryKey;
126
- }
127
- return prop;
128
- }
129
- static processProperty(prop, entity, options) {
130
- const parts = prop.split('.');
131
- prop = parts[0];
132
- const wrapped = helper(entity);
133
- const property = wrapped.__meta.properties[prop] ?? { name: prop };
134
- const serializer = property?.serializer;
135
- const value = entity[prop];
136
- // getter method
137
- if (entity[prop] instanceof Function) {
138
- const returnValue = entity[prop]();
139
- if (!options.ignoreSerializers && serializer) {
140
- return serializer(returnValue, this.extractChildOptions(options, prop));
141
- }
142
- return returnValue;
143
- }
144
- /* v8 ignore next */
145
- if (!options.ignoreSerializers && serializer) {
146
- return serializer(value);
147
- }
148
- if (Utils.isCollection(value)) {
149
- return this.processCollection(property, entity, options);
150
- }
151
- if (Utils.isEntity(value, true)) {
152
- return this.processEntity(property, entity, wrapped.__platform, options);
153
- }
154
- if (Utils.isScalarReference(value)) {
155
- return value.unwrap();
156
- }
157
- /* v8 ignore next */
158
- if (property?.kind === ReferenceKind.EMBEDDED) {
159
- if (Array.isArray(value)) {
160
- return value.map(item => helper(item).toJSON());
161
- }
162
- if (Utils.isObject(value)) {
163
- return helper(value).toJSON();
164
- }
165
- }
166
- if (property.customType) {
167
- return this.processCustomType(value, property, wrapped.__platform, options.convertCustomTypes);
168
- }
169
- return wrapped.__platform.normalizePrimaryKey(value);
54
+ const root = wrapped.__serializationContext.root;
55
+ const ret = {};
56
+ const props = new Set();
57
+ if (meta.serializedPrimaryKey && !meta.compositePK) {
58
+ props.add(meta.serializedPrimaryKey);
59
+ } else {
60
+ meta.primaryKeys.forEach(pk => props.add(pk));
170
61
  }
171
- static processCustomType(value, prop, platform, convertCustomTypes) {
172
- if (!prop.customType) {
173
- return value;
174
- }
175
- if (convertCustomTypes) {
176
- return prop.customType.convertToDatabaseValue(value, platform, { mode: 'serialization' });
177
- }
178
- return prop.customType.toJSON(value, platform);
179
- }
180
- static extractChildOptions(options, prop) {
181
- return {
182
- ...options,
183
- populate: Array.isArray(options.populate)
184
- ? Utils.extractChildElements(options.populate, prop, '*')
185
- : options.populate,
186
- exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop) : options.exclude,
187
- };
188
- }
189
- static processEntity(prop, entity, platform, options) {
190
- const child = Reference.unwrapReference(entity[prop.name]);
191
- const wrapped = helper(child);
192
- const populated = isPopulated(prop.name, options) && wrapped.isInitialized();
193
- const expand = populated || !wrapped.__managed;
194
- const meta = wrapped.__meta;
195
- const childOptions = this.extractChildOptions(options, prop.name);
196
- const visible = meta.primaryKeys.filter(prop => isVisible(meta, prop, childOptions));
197
- if (expand) {
198
- return this.serialize(child, childOptions);
199
- }
200
- const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
201
- if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
202
- return Utils.primaryKeyToObject(meta, pk, visible);
203
- }
204
- if (Utils.isPlainObject(pk)) {
205
- const pruned = Utils.primaryKeyToObject(meta, pk, visible);
206
- if (visible.length === 1) {
207
- return platform.normalizePrimaryKey(pruned[visible[0]]);
208
- }
209
- return pruned;
210
- }
211
- return platform.normalizePrimaryKey(pk);
62
+ if (wrapped.isInitialized() || !wrapped.hasPrimaryKey()) {
63
+ const entityKeys = new Set(Object.keys(entity));
64
+ for (const prop of meta.props) {
65
+ if (entityKeys.has(prop.name) || (prop.getter && prop.accessor === prop.name)) {
66
+ props.add(prop.name);
67
+ }
68
+ }
69
+ for (const key of entityKeys) {
70
+ if (!meta.properties[key]) {
71
+ props.add(key);
72
+ }
73
+ }
212
74
  }
213
- static processCollection(prop, entity, options) {
214
- const col = entity[prop.name];
215
- if (!col.isInitialized()) {
216
- return undefined;
217
- }
218
- return col.getItems(false).map(item => {
219
- const populated = isPopulated(prop.name, options);
220
- const wrapped = helper(item);
221
- if (populated || !wrapped.__managed) {
222
- return this.serialize(item, this.extractChildOptions(options, prop.name));
223
- }
224
- const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
225
- if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
226
- return Utils.primaryKeyToObject(wrapped.__meta, pk);
227
- }
228
- return pk;
229
- });
75
+ const visited = root.visited.has(entity);
76
+ if (!visited) {
77
+ root.visited.add(entity);
78
+ }
79
+ for (const prop of props) {
80
+ if (!isVisible(meta, prop, options)) {
81
+ continue;
82
+ }
83
+ const cycle = root.visit(meta.class, prop);
84
+ if (cycle && visited) {
85
+ continue;
86
+ }
87
+ const val = this.processProperty(prop, entity, options);
88
+ if (!cycle) {
89
+ root.leave(meta.class, prop);
90
+ }
91
+ if (options.skipNull && Utils.isPlainObject(val)) {
92
+ Utils.dropUndefinedProperties(val, null);
93
+ }
94
+ if (isRaw(val)) {
95
+ throw new Error(`Trying to serialize raw SQL fragment: '${val.sql}'`);
96
+ }
97
+ const visible = typeof val !== 'undefined' && !(val === null && options.skipNull);
98
+ if (visible) {
99
+ ret[this.propertyName(meta, prop)] = val;
100
+ }
101
+ }
102
+ if (contextCreated) {
103
+ root.close();
104
+ }
105
+ if (!wrapped.isInitialized()) {
106
+ return ret;
107
+ }
108
+ for (const prop of meta.getterProps) {
109
+ // decorated get methods
110
+ if (prop.getterName != null) {
111
+ const visible = entity[prop.getterName] instanceof Function && isVisible(meta, prop.name, options);
112
+ if (visible) {
113
+ ret[this.propertyName(meta, prop.name)] = this.processProperty(prop.getterName, entity, options);
114
+ }
115
+ } else {
116
+ // decorated getters
117
+ const visible = typeof entity[prop.name] !== 'undefined' && isVisible(meta, prop.name, options);
118
+ if (visible) {
119
+ ret[this.propertyName(meta, prop.name)] = this.processProperty(prop.name, entity, options);
120
+ }
121
+ }
122
+ }
123
+ return ret;
124
+ }
125
+ static propertyName(meta, prop) {
126
+ /* v8 ignore next */
127
+ if (meta.properties[prop]?.serializedName) {
128
+ return meta.properties[prop].serializedName;
129
+ }
130
+ if (meta.properties[prop]?.primary && meta.serializedPrimaryKey) {
131
+ return meta.serializedPrimaryKey;
132
+ }
133
+ return prop;
134
+ }
135
+ static processProperty(prop, entity, options) {
136
+ const parts = prop.split('.');
137
+ prop = parts[0];
138
+ const wrapped = helper(entity);
139
+ const property = wrapped.__meta.properties[prop] ?? { name: prop };
140
+ const serializer = property?.serializer;
141
+ const value = entity[prop];
142
+ // getter method
143
+ if (entity[prop] instanceof Function) {
144
+ const returnValue = entity[prop]();
145
+ if (!options.ignoreSerializers && serializer) {
146
+ return serializer(returnValue, this.extractChildOptions(options, prop));
147
+ }
148
+ return returnValue;
149
+ }
150
+ /* v8 ignore next */
151
+ if (!options.ignoreSerializers && serializer) {
152
+ return serializer(value);
230
153
  }
154
+ if (Utils.isCollection(value)) {
155
+ return this.processCollection(property, entity, options);
156
+ }
157
+ if (Utils.isEntity(value, true)) {
158
+ return this.processEntity(property, entity, wrapped.__platform, options);
159
+ }
160
+ if (Utils.isScalarReference(value)) {
161
+ return value.unwrap();
162
+ }
163
+ /* v8 ignore next */
164
+ if (property?.kind === ReferenceKind.EMBEDDED) {
165
+ if (Array.isArray(value)) {
166
+ return value.map(item => helper(item).toJSON());
167
+ }
168
+ if (Utils.isObject(value)) {
169
+ return helper(value).toJSON();
170
+ }
171
+ }
172
+ if (property.customType) {
173
+ return this.processCustomType(value, property, wrapped.__platform, options.convertCustomTypes);
174
+ }
175
+ return wrapped.__platform.normalizePrimaryKey(value);
176
+ }
177
+ static processCustomType(value, prop, platform, convertCustomTypes) {
178
+ if (!prop.customType) {
179
+ return value;
180
+ }
181
+ if (convertCustomTypes) {
182
+ return prop.customType.convertToDatabaseValue(value, platform, { mode: 'serialization' });
183
+ }
184
+ return prop.customType.toJSON(value, platform);
185
+ }
186
+ static extractChildOptions(options, prop) {
187
+ return {
188
+ ...options,
189
+ populate: Array.isArray(options.populate)
190
+ ? Utils.extractChildElements(options.populate, prop, '*')
191
+ : options.populate,
192
+ exclude: Array.isArray(options.exclude) ? Utils.extractChildElements(options.exclude, prop) : options.exclude,
193
+ };
194
+ }
195
+ static processEntity(prop, entity, platform, options) {
196
+ const child = Reference.unwrapReference(entity[prop.name]);
197
+ const wrapped = helper(child);
198
+ const populated = isPopulated(prop.name, options) && wrapped.isInitialized();
199
+ const expand = populated || !wrapped.__managed;
200
+ const meta = wrapped.__meta;
201
+ const childOptions = this.extractChildOptions(options, prop.name);
202
+ const visible = meta.primaryKeys.filter(prop => isVisible(meta, prop, childOptions));
203
+ if (expand) {
204
+ return this.serialize(child, childOptions);
205
+ }
206
+ const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
207
+ if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
208
+ return Utils.primaryKeyToObject(meta, pk, visible);
209
+ }
210
+ if (Utils.isPlainObject(pk)) {
211
+ const pruned = Utils.primaryKeyToObject(meta, pk, visible);
212
+ if (visible.length === 1) {
213
+ return platform.normalizePrimaryKey(pruned[visible[0]]);
214
+ }
215
+ return pruned;
216
+ }
217
+ return platform.normalizePrimaryKey(pk);
218
+ }
219
+ static processCollection(prop, entity, options) {
220
+ const col = entity[prop.name];
221
+ if (!col.isInitialized()) {
222
+ return undefined;
223
+ }
224
+ return col.getItems(false).map(item => {
225
+ const populated = isPopulated(prop.name, options);
226
+ const wrapped = helper(item);
227
+ if (populated || !wrapped.__managed) {
228
+ return this.serialize(item, this.extractChildOptions(options, prop.name));
229
+ }
230
+ const pk = this.processCustomType(wrapped.getPrimaryKey(), prop, wrapped.__platform, options.convertCustomTypes);
231
+ if (options.forceObject || wrapped.__config.get('serialization').forceObject) {
232
+ return Utils.primaryKeyToObject(wrapped.__meta, pk);
233
+ }
234
+ return pk;
235
+ });
236
+ }
231
237
  }
232
238
  /**
233
239
  * Converts entity instance to POJO, converting the `Collection`s to arrays and unwrapping the `Reference` wrapper, while respecting the serialization options.
@@ -242,8 +248,8 @@ export class EntitySerializer {
242
248
  * ```
243
249
  */
244
250
  export function serialize(entities, options) {
245
- if (Array.isArray(entities)) {
246
- return entities.map(e => EntitySerializer.serialize(e, options));
247
- }
248
- return EntitySerializer.serialize(entities, options);
251
+ if (Array.isArray(entities)) {
252
+ return entities.map(e => EntitySerializer.serialize(e, options));
253
+ }
254
+ return EntitySerializer.serialize(entities, options);
249
255
  }
@@ -1,10 +1,14 @@
1
1
  import type { EntityDTO, EntityKey } from '../typings.js';
2
2
  /** Converts entity instances to plain objects via `toObject()`, respecting populate hints, hidden fields, and serialization context. */
3
3
  export declare class EntityTransformer {
4
- /** Converts an entity to a plain object, respecting populate hints, hidden fields, and custom serializers. */
5
- static toObject<Entity extends object, Ignored extends EntityKey<Entity> = never>(entity: Entity, ignoreFields?: Ignored[], raw?: boolean): Omit<EntityDTO<Entity>, Ignored>;
6
- private static propertyName;
7
- private static processProperty;
8
- private static processEntity;
9
- private static processCollection;
4
+ /** Converts an entity to a plain object, respecting populate hints, hidden fields, and custom serializers. */
5
+ static toObject<Entity extends object, Ignored extends EntityKey<Entity> = never>(
6
+ entity: Entity,
7
+ ignoreFields?: Ignored[],
8
+ raw?: boolean,
9
+ ): Omit<EntityDTO<Entity>, Ignored>;
10
+ private static propertyName;
11
+ private static processProperty;
12
+ private static processEntity;
13
+ private static processCollection;
10
14
  }