@mikro-orm/core 7.0.4 → 7.0.5-dev.0

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 +583 -884
  2. package/EntityManager.js +1895 -1922
  3. package/MikroORM.d.ts +74 -103
  4. package/MikroORM.js +179 -178
  5. package/README.md +1 -1
  6. package/cache/CacheAdapter.d.ts +36 -36
  7. package/cache/FileCacheAdapter.d.ts +24 -30
  8. package/cache/FileCacheAdapter.js +78 -80
  9. package/cache/GeneratedCacheAdapter.d.ts +20 -18
  10. package/cache/GeneratedCacheAdapter.js +30 -30
  11. package/cache/MemoryCacheAdapter.d.ts +20 -18
  12. package/cache/MemoryCacheAdapter.js +36 -35
  13. package/cache/NullCacheAdapter.d.ts +16 -16
  14. package/cache/NullCacheAdapter.js +24 -24
  15. package/connections/Connection.d.ts +84 -95
  16. package/connections/Connection.js +168 -165
  17. package/drivers/DatabaseDriver.d.ts +80 -186
  18. package/drivers/DatabaseDriver.js +443 -450
  19. package/drivers/IDatabaseDriver.d.ts +301 -440
  20. package/entity/BaseEntity.d.ts +83 -120
  21. package/entity/BaseEntity.js +43 -43
  22. package/entity/Collection.d.ts +179 -212
  23. package/entity/Collection.js +721 -727
  24. package/entity/EntityAssigner.d.ts +77 -88
  25. package/entity/EntityAssigner.js +230 -231
  26. package/entity/EntityFactory.d.ts +54 -66
  27. package/entity/EntityFactory.js +383 -425
  28. package/entity/EntityHelper.d.ts +22 -34
  29. package/entity/EntityHelper.js +267 -280
  30. package/entity/EntityIdentifier.d.ts +4 -4
  31. package/entity/EntityIdentifier.js +10 -10
  32. package/entity/EntityLoader.d.ts +72 -98
  33. package/entity/EntityLoader.js +723 -753
  34. package/entity/EntityRepository.d.ts +201 -316
  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 +82 -126
  39. package/entity/Reference.js +274 -278
  40. package/entity/WrappedEntity.d.ts +72 -115
  41. package/entity/WrappedEntity.js +166 -168
  42. package/entity/defineEntity.d.ts +636 -1315
  43. package/entity/defineEntity.js +518 -527
  44. package/entity/utils.d.ts +3 -13
  45. package/entity/utils.js +73 -71
  46. package/entity/validators.js +43 -43
  47. package/entity/wrap.js +8 -8
  48. package/enums.d.ts +253 -258
  49. package/enums.js +252 -251
  50. package/errors.d.ts +72 -114
  51. package/errors.js +253 -350
  52. package/events/EventManager.d.ts +14 -26
  53. package/events/EventManager.js +77 -79
  54. package/events/EventSubscriber.d.ts +29 -29
  55. package/events/TransactionEventBroadcaster.d.ts +8 -15
  56. package/events/TransactionEventBroadcaster.js +14 -14
  57. package/exceptions.d.ts +40 -23
  58. package/exceptions.js +52 -35
  59. package/hydration/Hydrator.d.ts +17 -42
  60. package/hydration/Hydrator.js +43 -43
  61. package/hydration/ObjectHydrator.d.ts +17 -50
  62. package/hydration/ObjectHydrator.js +416 -481
  63. package/index.d.ts +2 -116
  64. package/index.js +1 -10
  65. package/logging/DefaultLogger.d.ts +32 -34
  66. package/logging/DefaultLogger.js +86 -86
  67. package/logging/Logger.d.ts +41 -41
  68. package/logging/SimpleLogger.d.ts +11 -13
  69. package/logging/SimpleLogger.js +22 -22
  70. package/logging/colors.d.ts +6 -6
  71. package/logging/colors.js +10 -11
  72. package/logging/inspect.js +7 -7
  73. package/metadata/EntitySchema.d.ts +127 -211
  74. package/metadata/EntitySchema.js +398 -397
  75. package/metadata/MetadataDiscovery.d.ts +114 -114
  76. package/metadata/MetadataDiscovery.js +1870 -1951
  77. package/metadata/MetadataProvider.d.ts +21 -24
  78. package/metadata/MetadataProvider.js +84 -82
  79. package/metadata/MetadataStorage.d.ts +32 -38
  80. package/metadata/MetadataStorage.js +118 -118
  81. package/metadata/MetadataValidator.d.ts +39 -39
  82. package/metadata/MetadataValidator.js +338 -381
  83. package/metadata/discover-entities.d.ts +2 -5
  84. package/metadata/discover-entities.js +37 -35
  85. package/metadata/types.d.ts +531 -615
  86. package/naming-strategy/AbstractNamingStrategy.d.ts +39 -54
  87. package/naming-strategy/AbstractNamingStrategy.js +85 -90
  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 +99 -109
  93. package/naming-strategy/UnderscoreNamingStrategy.d.ts +7 -7
  94. package/naming-strategy/UnderscoreNamingStrategy.js +21 -21
  95. package/not-supported.js +4 -7
  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 +301 -310
  100. package/platforms/Platform.js +640 -663
  101. package/serialization/EntitySerializer.d.ts +26 -49
  102. package/serialization/EntitySerializer.js +218 -224
  103. package/serialization/EntityTransformer.d.ts +6 -10
  104. package/serialization/EntityTransformer.js +217 -219
  105. package/serialization/SerializationContext.d.ts +23 -27
  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 +10 -17
  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 +79 -83
  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 +49 -75
  158. package/types/index.js +26 -52
  159. package/typings.d.ts +737 -1250
  160. package/typings.js +231 -244
  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 +170 -178
  165. package/unit-of-work/ChangeSetPersister.d.ts +44 -63
  166. package/unit-of-work/ChangeSetPersister.js +421 -442
  167. package/unit-of-work/CommitOrderCalculator.d.ts +40 -40
  168. package/unit-of-work/CommitOrderCalculator.js +88 -89
  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 +141 -181
  172. package/unit-of-work/UnitOfWork.js +1183 -1200
  173. package/utils/AbstractMigrator.d.ts +91 -111
  174. package/utils/AbstractMigrator.js +275 -275
  175. package/utils/AbstractSchemaGenerator.d.ts +34 -43
  176. package/utils/AbstractSchemaGenerator.js +122 -121
  177. package/utils/AsyncContext.d.ts +3 -3
  178. package/utils/AsyncContext.js +35 -34
  179. package/utils/Configuration.d.ts +808 -852
  180. package/utils/Configuration.js +344 -359
  181. package/utils/Cursor.d.ts +22 -40
  182. package/utils/Cursor.js +127 -135
  183. package/utils/DataloaderUtils.d.ts +43 -58
  184. package/utils/DataloaderUtils.js +198 -203
  185. package/utils/EntityComparator.d.ts +81 -98
  186. package/utils/EntityComparator.js +732 -828
  187. package/utils/NullHighlighter.d.ts +1 -1
  188. package/utils/NullHighlighter.js +3 -3
  189. package/utils/QueryHelper.d.ts +51 -79
  190. package/utils/QueryHelper.js +361 -372
  191. package/utils/RawQueryFragment.d.ts +34 -50
  192. package/utils/RawQueryFragment.js +105 -107
  193. package/utils/RequestContext.d.ts +32 -32
  194. package/utils/RequestContext.js +53 -52
  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 +197 -199
  199. package/utils/Utils.d.ts +145 -204
  200. package/utils/Utils.js +812 -812
  201. package/utils/clone.js +113 -104
  202. package/utils/env-vars.js +88 -90
  203. package/utils/fs-utils.d.ts +15 -15
  204. package/utils/fs-utils.js +181 -180
  205. package/utils/upsert-utils.d.ts +5 -20
  206. package/utils/upsert-utils.js +116 -114
@@ -1,45 +1,33 @@
1
- import type {
2
- ArrayElement,
3
- AutoPath,
4
- CleanTypeConfig,
5
- ExtractFieldsHint,
6
- FromEntityType,
7
- SerializeDTO,
8
- TypeConfig,
9
- UnboxArray,
10
- } from '../typings.js';
1
+ import type { ArrayElement, AutoPath, CleanTypeConfig, ExtractFieldsHint, FromEntityType, SerializeDTO, TypeConfig, UnboxArray } from '../typings.js';
11
2
  import { type PopulatePath } from '../enums.js';
12
3
  /** Converts entity instances to plain DTOs via `serialize()`, with fine-grained control over populate, exclude, and serialization groups. */
13
4
  export declare class EntitySerializer {
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;
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;
25
13
  }
26
14
  export interface SerializeOptions<T, P extends string = never, E extends string = never> {
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;
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;
43
31
  }
44
32
  /**
45
33
  * Converts entity instance to POJO, converting the `Collection`s to arrays and unwrapping the `Reference` wrapper, while respecting the serialization options.
@@ -53,15 +41,4 @@ export interface SerializeOptions<T, P extends string = never, E extends string
53
41
  * const dto2 = wrap(user).serialize({ exclude: ['id', 'email'], forceObject: true });
54
42
  * ```
55
43
  */
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>>;
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>>;
@@ -5,235 +5,229 @@ 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 (
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;
24
- }
25
- function isPopulated(propName, options) {
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;
36
- }
37
- /** Converts entity instances to plain DTOs via `serialize()`, with fine-grained control over populate, exclude, and serialization groups. */
38
- export class EntitySerializer {
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;
53
- }
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));
61
- }
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
- }
74
- }
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
- }
8
+ const prop = meta.properties[propName];
9
+ if (options.groups && prop?.groups) {
10
+ return prop.groups.some(g => options.groups.includes(g));
122
11
  }
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;
12
+ if (Array.isArray(options.populate) &&
13
+ options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
14
+ return true;
129
15
  }
130
- if (meta.properties[prop]?.primary && meta.serializedPrimaryKey) {
131
- return meta.serializedPrimaryKey;
16
+ if (options.exclude?.find(item => item === propName)) {
17
+ return false;
132
18
  }
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);
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;
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;
22
+ }
23
+ function isPopulated(propName, options) {
24
+ if (typeof options.populate !== 'boolean' &&
25
+ options.populate?.find(item => item === propName || item.startsWith(propName + '.') || item === '*')) {
26
+ return true;
180
27
  }
181
- if (convertCustomTypes) {
182
- return prop.customType.convertToDatabaseValue(value, platform, { mode: 'serialization' });
28
+ if (typeof options.populate === 'boolean') {
29
+ return options.populate;
183
30
  }
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);
31
+ return false;
32
+ }
33
+ /** Converts entity instances to plain DTOs via `serialize()`, with fine-grained control over populate, exclude, and serialization groups. */
34
+ 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;
205
118
  }
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);
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);
209
170
  }
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;
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);
216
212
  }
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;
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
+ });
223
230
  }
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
- }
237
231
  }
238
232
  /**
239
233
  * Converts entity instance to POJO, converting the `Collection`s to arrays and unwrapping the `Reference` wrapper, while respecting the serialization options.
@@ -248,8 +242,8 @@ export class EntitySerializer {
248
242
  * ```
249
243
  */
250
244
  export function serialize(entities, options) {
251
- if (Array.isArray(entities)) {
252
- return entities.map(e => EntitySerializer.serialize(e, options));
253
- }
254
- return EntitySerializer.serialize(entities, options);
245
+ if (Array.isArray(entities)) {
246
+ return entities.map(e => EntitySerializer.serialize(e, options));
247
+ }
248
+ return EntitySerializer.serialize(entities, options);
255
249
  }
@@ -1,14 +1,10 @@
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>(
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;
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;
14
10
  }