@mikro-orm/core 7.0.0-dev.2 → 7.0.0-dev.200

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 (210) hide show
  1. package/EntityManager.d.ts +111 -61
  2. package/EntityManager.js +346 -300
  3. package/MikroORM.d.ts +44 -35
  4. package/MikroORM.js +103 -143
  5. package/README.md +3 -2
  6. package/cache/FileCacheAdapter.d.ts +1 -1
  7. package/cache/FileCacheAdapter.js +8 -7
  8. package/cache/GeneratedCacheAdapter.d.ts +0 -1
  9. package/cache/GeneratedCacheAdapter.js +0 -2
  10. package/cache/index.d.ts +0 -1
  11. package/cache/index.js +0 -1
  12. package/connections/Connection.d.ts +16 -7
  13. package/connections/Connection.js +23 -14
  14. package/drivers/DatabaseDriver.d.ts +25 -16
  15. package/drivers/DatabaseDriver.js +80 -35
  16. package/drivers/IDatabaseDriver.d.ts +47 -17
  17. package/entity/BaseEntity.d.ts +2 -2
  18. package/entity/BaseEntity.js +0 -3
  19. package/entity/Collection.d.ts +95 -31
  20. package/entity/Collection.js +444 -102
  21. package/entity/EntityAssigner.d.ts +1 -1
  22. package/entity/EntityAssigner.js +26 -18
  23. package/entity/EntityFactory.d.ts +13 -1
  24. package/entity/EntityFactory.js +88 -54
  25. package/entity/EntityHelper.d.ts +2 -2
  26. package/entity/EntityHelper.js +38 -15
  27. package/entity/EntityLoader.d.ts +8 -7
  28. package/entity/EntityLoader.js +134 -80
  29. package/entity/EntityRepository.d.ts +24 -4
  30. package/entity/EntityRepository.js +8 -2
  31. package/entity/Reference.d.ts +9 -12
  32. package/entity/Reference.js +34 -9
  33. package/entity/WrappedEntity.d.ts +2 -7
  34. package/entity/WrappedEntity.js +3 -8
  35. package/entity/defineEntity.d.ts +585 -0
  36. package/entity/defineEntity.js +533 -0
  37. package/entity/index.d.ts +3 -2
  38. package/entity/index.js +3 -2
  39. package/entity/utils.d.ts +7 -0
  40. package/entity/utils.js +16 -4
  41. package/entity/validators.d.ts +11 -0
  42. package/entity/validators.js +65 -0
  43. package/enums.d.ts +22 -6
  44. package/enums.js +15 -1
  45. package/errors.d.ts +23 -9
  46. package/errors.js +59 -21
  47. package/events/EventManager.d.ts +2 -1
  48. package/events/EventManager.js +19 -11
  49. package/events/EventSubscriber.d.ts +3 -1
  50. package/hydration/Hydrator.js +1 -2
  51. package/hydration/ObjectHydrator.d.ts +4 -4
  52. package/hydration/ObjectHydrator.js +53 -33
  53. package/index.d.ts +2 -2
  54. package/index.js +1 -2
  55. package/logging/DefaultLogger.d.ts +1 -1
  56. package/logging/DefaultLogger.js +1 -0
  57. package/logging/SimpleLogger.d.ts +1 -1
  58. package/logging/colors.d.ts +1 -1
  59. package/logging/colors.js +7 -6
  60. package/logging/index.d.ts +1 -0
  61. package/logging/index.js +1 -0
  62. package/logging/inspect.d.ts +2 -0
  63. package/logging/inspect.js +11 -0
  64. package/metadata/EntitySchema.d.ts +26 -26
  65. package/metadata/EntitySchema.js +82 -51
  66. package/metadata/MetadataDiscovery.d.ts +7 -10
  67. package/metadata/MetadataDiscovery.js +408 -335
  68. package/metadata/MetadataProvider.d.ts +11 -2
  69. package/metadata/MetadataProvider.js +46 -2
  70. package/metadata/MetadataStorage.d.ts +13 -11
  71. package/metadata/MetadataStorage.js +70 -37
  72. package/metadata/MetadataValidator.d.ts +17 -9
  73. package/metadata/MetadataValidator.js +100 -42
  74. package/metadata/discover-entities.d.ts +5 -0
  75. package/metadata/discover-entities.js +40 -0
  76. package/metadata/index.d.ts +1 -1
  77. package/metadata/index.js +1 -1
  78. package/metadata/types.d.ts +502 -0
  79. package/metadata/types.js +1 -0
  80. package/naming-strategy/AbstractNamingStrategy.d.ts +12 -4
  81. package/naming-strategy/AbstractNamingStrategy.js +14 -2
  82. package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
  83. package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
  84. package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
  85. package/naming-strategy/MongoNamingStrategy.js +6 -6
  86. package/naming-strategy/NamingStrategy.d.ts +24 -4
  87. package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
  88. package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
  89. package/not-supported.d.ts +2 -0
  90. package/not-supported.js +4 -0
  91. package/package.json +19 -11
  92. package/platforms/ExceptionConverter.js +1 -1
  93. package/platforms/Platform.d.ts +7 -13
  94. package/platforms/Platform.js +20 -43
  95. package/serialization/EntitySerializer.d.ts +5 -0
  96. package/serialization/EntitySerializer.js +47 -27
  97. package/serialization/EntityTransformer.js +28 -18
  98. package/serialization/SerializationContext.d.ts +6 -6
  99. package/serialization/SerializationContext.js +16 -13
  100. package/types/ArrayType.d.ts +1 -1
  101. package/types/ArrayType.js +2 -3
  102. package/types/BigIntType.d.ts +9 -6
  103. package/types/BigIntType.js +4 -1
  104. package/types/BlobType.d.ts +0 -1
  105. package/types/BlobType.js +0 -3
  106. package/types/BooleanType.d.ts +2 -1
  107. package/types/BooleanType.js +3 -0
  108. package/types/DecimalType.d.ts +6 -4
  109. package/types/DecimalType.js +3 -3
  110. package/types/DoubleType.js +2 -2
  111. package/types/EnumArrayType.js +1 -2
  112. package/types/JsonType.d.ts +1 -1
  113. package/types/JsonType.js +7 -2
  114. package/types/TinyIntType.js +1 -1
  115. package/types/Type.d.ts +2 -4
  116. package/types/Type.js +3 -3
  117. package/types/Uint8ArrayType.d.ts +0 -1
  118. package/types/Uint8ArrayType.js +1 -4
  119. package/types/index.d.ts +1 -1
  120. package/typings.d.ts +300 -140
  121. package/typings.js +62 -44
  122. package/unit-of-work/ChangeSet.d.ts +2 -6
  123. package/unit-of-work/ChangeSet.js +4 -5
  124. package/unit-of-work/ChangeSetComputer.d.ts +1 -3
  125. package/unit-of-work/ChangeSetComputer.js +26 -13
  126. package/unit-of-work/ChangeSetPersister.d.ts +5 -4
  127. package/unit-of-work/ChangeSetPersister.js +77 -35
  128. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  129. package/unit-of-work/CommitOrderCalculator.js +13 -13
  130. package/unit-of-work/IdentityMap.d.ts +12 -0
  131. package/unit-of-work/IdentityMap.js +39 -1
  132. package/unit-of-work/UnitOfWork.d.ts +23 -3
  133. package/unit-of-work/UnitOfWork.js +199 -106
  134. package/utils/AbstractSchemaGenerator.d.ts +5 -5
  135. package/utils/AbstractSchemaGenerator.js +22 -17
  136. package/utils/AsyncContext.d.ts +6 -0
  137. package/utils/AsyncContext.js +42 -0
  138. package/utils/Configuration.d.ts +779 -207
  139. package/utils/Configuration.js +146 -190
  140. package/utils/ConfigurationLoader.d.ts +1 -54
  141. package/utils/ConfigurationLoader.js +1 -352
  142. package/utils/Cursor.d.ts +3 -6
  143. package/utils/Cursor.js +27 -11
  144. package/utils/DataloaderUtils.d.ts +15 -5
  145. package/utils/DataloaderUtils.js +65 -17
  146. package/utils/EntityComparator.d.ts +13 -9
  147. package/utils/EntityComparator.js +164 -89
  148. package/utils/QueryHelper.d.ts +14 -6
  149. package/utils/QueryHelper.js +88 -26
  150. package/utils/RawQueryFragment.d.ts +48 -25
  151. package/utils/RawQueryFragment.js +67 -66
  152. package/utils/RequestContext.js +2 -2
  153. package/utils/TransactionContext.js +2 -2
  154. package/utils/TransactionManager.d.ts +65 -0
  155. package/utils/TransactionManager.js +223 -0
  156. package/utils/Utils.d.ts +13 -120
  157. package/utils/Utils.js +104 -375
  158. package/utils/clone.js +8 -23
  159. package/utils/env-vars.d.ts +7 -0
  160. package/utils/env-vars.js +97 -0
  161. package/utils/fs-utils.d.ts +32 -0
  162. package/utils/fs-utils.js +178 -0
  163. package/utils/index.d.ts +2 -1
  164. package/utils/index.js +2 -1
  165. package/utils/upsert-utils.d.ts +9 -4
  166. package/utils/upsert-utils.js +55 -4
  167. package/decorators/Check.d.ts +0 -3
  168. package/decorators/Check.js +0 -13
  169. package/decorators/CreateRequestContext.d.ts +0 -3
  170. package/decorators/CreateRequestContext.js +0 -29
  171. package/decorators/Embeddable.d.ts +0 -8
  172. package/decorators/Embeddable.js +0 -11
  173. package/decorators/Embedded.d.ts +0 -18
  174. package/decorators/Embedded.js +0 -18
  175. package/decorators/Entity.d.ts +0 -18
  176. package/decorators/Entity.js +0 -13
  177. package/decorators/Enum.d.ts +0 -9
  178. package/decorators/Enum.js +0 -16
  179. package/decorators/Filter.d.ts +0 -2
  180. package/decorators/Filter.js +0 -8
  181. package/decorators/Formula.d.ts +0 -5
  182. package/decorators/Formula.js +0 -15
  183. package/decorators/Indexed.d.ts +0 -17
  184. package/decorators/Indexed.js +0 -20
  185. package/decorators/ManyToMany.d.ts +0 -40
  186. package/decorators/ManyToMany.js +0 -14
  187. package/decorators/ManyToOne.d.ts +0 -30
  188. package/decorators/ManyToOne.js +0 -14
  189. package/decorators/OneToMany.d.ts +0 -28
  190. package/decorators/OneToMany.js +0 -17
  191. package/decorators/OneToOne.d.ts +0 -24
  192. package/decorators/OneToOne.js +0 -7
  193. package/decorators/PrimaryKey.d.ts +0 -9
  194. package/decorators/PrimaryKey.js +0 -20
  195. package/decorators/Property.d.ts +0 -250
  196. package/decorators/Property.js +0 -32
  197. package/decorators/Transactional.d.ts +0 -13
  198. package/decorators/Transactional.js +0 -28
  199. package/decorators/hooks.d.ts +0 -16
  200. package/decorators/hooks.js +0 -47
  201. package/decorators/index.d.ts +0 -17
  202. package/decorators/index.js +0 -17
  203. package/entity/ArrayCollection.d.ts +0 -116
  204. package/entity/ArrayCollection.js +0 -395
  205. package/entity/EntityValidator.d.ts +0 -19
  206. package/entity/EntityValidator.js +0 -150
  207. package/metadata/ReflectMetadataProvider.d.ts +0 -8
  208. package/metadata/ReflectMetadataProvider.js +0 -44
  209. package/utils/resolveContextProvider.d.ts +0 -10
  210. package/utils/resolveContextProvider.js +0 -28
package/typings.js CHANGED
@@ -3,6 +3,7 @@ import { Reference } from './entity/Reference.js';
3
3
  import { EntityHelper } from './entity/EntityHelper.js';
4
4
  import { Utils } from './utils/Utils.js';
5
5
  import { EntityComparator } from './utils/EntityComparator.js';
6
+ import { BaseEntity } from './entity/BaseEntity.js';
6
7
  export const EntityRepositoryType = Symbol('EntityRepositoryType');
7
8
  export const PrimaryKeyProp = Symbol('PrimaryKeyProp');
8
9
  export const OptionalProps = Symbol('OptionalProps');
@@ -25,38 +26,60 @@ export class EntityMetadata {
25
26
  this.referencingProperties = [];
26
27
  this.concurrencyCheckKeys = new Set();
27
28
  Object.assign(this, meta);
28
- }
29
- addProperty(prop, sync = true) {
30
- if (prop.pivotTable && !prop.pivotEntity) {
31
- prop.pivotEntity = prop.pivotTable;
29
+ const name = meta.className ?? meta.name;
30
+ if (!this.class && name) {
31
+ const Class = this.extends === BaseEntity
32
+ ? ({ [name]: class extends BaseEntity {
33
+ } })[name]
34
+ : ({ [name]: class {
35
+ } })[name];
36
+ this.class = Class;
32
37
  }
38
+ }
39
+ addProperty(prop) {
33
40
  this.properties[prop.name] = prop;
34
41
  this.propertyOrder.set(prop.name, this.props.length);
35
- /* v8 ignore next 3 */
36
- if (sync) {
37
- this.sync();
38
- }
42
+ this.sync();
39
43
  }
40
44
  removeProperty(name, sync = true) {
41
45
  delete this.properties[name];
42
46
  this.propertyOrder.delete(name);
43
- /* v8 ignore next 3 */
44
47
  if (sync) {
45
48
  this.sync();
46
49
  }
47
50
  }
48
- getPrimaryProps() {
49
- return this.primaryKeys.map(pk => this.properties[pk]);
51
+ getPrimaryProps(flatten = false) {
52
+ const pks = this.primaryKeys.map(pk => this.properties[pk]);
53
+ if (flatten) {
54
+ return pks.flatMap(pk => {
55
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(pk.kind)) {
56
+ return pk.targetMeta.getPrimaryProps(true);
57
+ }
58
+ return [pk];
59
+ });
60
+ }
61
+ return pks;
50
62
  }
51
63
  getPrimaryProp() {
52
64
  return this.properties[this.primaryKeys[0]];
53
65
  }
66
+ createColumnMappingObject() {
67
+ return Object.values(this.properties).reduce((o, prop) => {
68
+ if (prop.fieldNames) {
69
+ o[prop.name] = prop.fieldNames[0];
70
+ }
71
+ return o;
72
+ }, {});
73
+ }
54
74
  get tableName() {
55
75
  return this.collection;
56
76
  }
57
77
  set tableName(name) {
58
78
  this.collection = name;
59
79
  }
80
+ get uniqueName() {
81
+ return this.tableName + '_' + this._id;
82
+ }
60
83
  sync(initIndexes = false, config) {
61
84
  this.root ??= this;
62
85
  const props = Object.values(this.properties).sort((a, b) => this.propertyOrder.get(a.name) - this.propertyOrder.get(b.name));
@@ -66,23 +89,32 @@ export class EntityMetadata {
66
89
  this.uniqueProps = this.props.filter(prop => prop.unique);
67
90
  this.getterProps = this.props.filter(prop => prop.getter);
68
91
  this.comparableProps = this.props.filter(prop => EntityComparator.isComparable(prop, this));
92
+ this.validateProps = this.props.filter(prop => {
93
+ if (prop.inherited || (prop.persist === false && prop.userDefined !== false)) {
94
+ return false;
95
+ }
96
+ return prop.kind === ReferenceKind.SCALAR && ['string', 'number', 'boolean', 'Date'].includes(prop.type);
97
+ });
69
98
  this.hydrateProps = this.props.filter(prop => {
70
99
  // `prop.userDefined` is either `undefined` or `false`
71
100
  const discriminator = this.root.discriminatorColumn === prop.name && prop.userDefined === false;
72
101
  // even if we don't have a setter, do not ignore value from database!
73
- const onlyGetter = prop.getter && !prop.setter;
102
+ const onlyGetter = prop.getter && !prop.setter && prop.persist === false;
74
103
  return !prop.inherited && prop.hydrate !== false && !discriminator && !prop.embedded && !onlyGetter;
75
104
  });
76
- this.trackingProps = this.hydrateProps
77
- .filter(prop => !prop.getter && !prop.setter && prop.trackChanges !== false)
78
- .filter(prop => ![ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind))
79
- .filter(prop => !prop.serializedPrimaryKey);
80
- this.selfReferencing = this.relations.some(prop => [this.className, this.root.className].includes(prop.targetMeta?.root.className ?? prop.type));
105
+ this.trackingProps = this.hydrateProps.filter(prop => {
106
+ return !prop.getter && !prop.setter && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind);
107
+ });
108
+ this.selfReferencing = this.relations.some(prop => {
109
+ return this.root.uniqueName === prop.targetMeta?.root.uniqueName;
110
+ });
81
111
  this.hasUniqueProps = this.uniques.length + this.uniqueProps.length > 0;
82
- this.virtual = !!this.expression;
112
+ // If `view` is set, this is a database view entity (not a virtual entity).
113
+ // Virtual entities evaluate expressions at query time, view entities create actual database views.
114
+ this.virtual = !!this.expression && !this.view;
83
115
  if (config) {
84
116
  for (const prop of this.props) {
85
- if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => Utils.isString(item))) {
117
+ if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
86
118
  const name = config.getNamingStrategy().indexName(this.tableName, prop.fieldNames, 'check');
87
119
  const exists = this.checks.findIndex(check => check.name === name);
88
120
  if (exists !== -1) {
@@ -102,15 +134,14 @@ export class EntityMetadata {
102
134
  for (const hook of Utils.keys(this.hooks)) {
103
135
  this.hooks[hook] = Utils.removeDuplicates(this.hooks[hook]);
104
136
  }
105
- if (this.virtual) {
137
+ if (this.virtual || this.view) {
106
138
  this.readonly = true;
107
139
  }
108
140
  if (initIndexes && this.name) {
109
141
  this.props.forEach(prop => this.initIndexes(prop));
110
142
  }
111
143
  this.definedProperties = this.trackingProps.reduce((o, prop) => {
112
- const isCollection = [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind);
113
- const isReference = [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && (prop.inversedBy || prop.mappedBy) && !prop.mapToPk;
144
+ const isReference = (prop.inversedBy || prop.mappedBy) && !prop.mapToPk;
114
145
  if (isReference) {
115
146
  // eslint-disable-next-line @typescript-eslint/no-this-alias
116
147
  const meta = this;
@@ -123,13 +154,13 @@ export class EntityMetadata {
123
154
  const hydrator = wrapped.hydrator;
124
155
  const entity = Reference.unwrapReference(val ?? wrapped.__data[prop.name]);
125
156
  const old = Reference.unwrapReference(wrapped.__data[prop.name]);
157
+ if (old && old !== entity && prop.kind === ReferenceKind.MANY_TO_ONE && prop.inversedBy && old[prop.inversedBy]) {
158
+ old[prop.inversedBy].removeWithoutPropagation(this);
159
+ }
126
160
  wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
127
161
  // when propagation from inside hydration, we set the FK to the entity data immediately
128
162
  if (val && hydrator.isRunning() && wrapped.__originalEntityData && prop.owner) {
129
- wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(val, prop.targetMeta.primaryKeys, true);
130
- }
131
- else {
132
- wrapped.__touched = !hydrator.isRunning();
163
+ wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(val, prop.targetMeta, true);
133
164
  }
134
165
  EntityHelper.propagate(meta, entity, this, prop, Reference.unwrapReference(val), old);
135
166
  },
@@ -137,23 +168,6 @@ export class EntityMetadata {
137
168
  configurable: true,
138
169
  };
139
170
  }
140
- if (prop.inherited || prop.primary || isCollection || prop.persist === false || prop.trackChanges === false || isReference || prop.embedded) {
141
- return o;
142
- }
143
- o[prop.name] = {
144
- get() {
145
- return this.__helper.__data[prop.name];
146
- },
147
- set(val) {
148
- if (typeof val === 'object' && !!val && '__raw' in val) {
149
- val.assign();
150
- }
151
- this.__helper.__data[prop.name] = val;
152
- this.__helper.__touched = !this.__helper.hydrator.isRunning();
153
- },
154
- enumerable: true,
155
- configurable: true,
156
- };
157
171
  return o;
158
172
  }, { __gettersDefined: { value: true, enumerable: false } });
159
173
  }
@@ -175,7 +189,7 @@ export class EntityMetadata {
175
189
  this.indexes.push({ properties: prop.name });
176
190
  prop.index = false;
177
191
  }
178
- /* v8 ignore next 4 */
192
+ /* v8 ignore next */
179
193
  if (owner && prop.fieldNames.length > 1 && prop.unique) {
180
194
  this.uniques.push({ properties: prop.name });
181
195
  prop.unique = false;
@@ -185,4 +199,8 @@ export class EntityMetadata {
185
199
  clone() {
186
200
  return this;
187
201
  }
202
+ /** @ignore */
203
+ [Symbol.for('nodejs.util.inspect.custom')]() {
204
+ return `[${this.constructor.name}<${this.className}>]`;
205
+ }
188
206
  }
@@ -1,4 +1,3 @@
1
- import { inspect } from 'node:util';
2
1
  import type { EntityData, EntityMetadata, EntityDictionary, Primary } from '../typings.js';
3
2
  export declare class ChangeSet<T extends object> {
4
3
  entity: T;
@@ -10,13 +9,10 @@ export declare class ChangeSet<T extends object> {
10
9
  constructor(entity: T, type: ChangeSetType, payload: EntityDictionary<T>, meta: EntityMetadata<T>);
11
10
  getPrimaryKey(object?: boolean): Primary<T> | null;
12
11
  getSerializedPrimaryKey(): string | null;
13
- /** @ignore */
14
- [inspect.custom](depth?: number): string;
15
12
  }
16
13
  export interface ChangeSet<T> {
17
- name: string;
18
- rootName: string;
19
- collection: string;
14
+ meta: EntityMetadata<T>;
15
+ rootMeta: EntityMetadata<T>;
20
16
  schema?: string;
21
17
  type: ChangeSetType;
22
18
  entity: T;
@@ -1,6 +1,6 @@
1
- import { inspect } from 'node:util';
2
1
  import { helper } from '../entity/wrap.js';
3
2
  import { Utils } from '../utils/Utils.js';
3
+ import { inspect } from '../logging/inspect.js';
4
4
  export class ChangeSet {
5
5
  entity;
6
6
  type;
@@ -13,9 +13,8 @@ export class ChangeSet {
13
13
  this.type = type;
14
14
  this.payload = payload;
15
15
  this.meta = meta;
16
- this.name = meta.className;
17
- this.rootName = meta.root.className;
18
- this.collection = meta.root.collection;
16
+ this.meta = meta;
17
+ this.rootMeta = meta.root;
19
18
  this.schema = helper(entity).__schema ?? meta.root.schema;
20
19
  }
21
20
  getPrimaryKey(object = false) {
@@ -46,7 +45,7 @@ export class ChangeSet {
46
45
  return this.serializedPrimaryKey;
47
46
  }
48
47
  /** @ignore */
49
- [inspect.custom](depth = 2) {
48
+ [Symbol.for('nodejs.util.inspect.custom')](depth = 2) {
50
49
  const object = { ...this };
51
50
  const hidden = ['meta', 'serializedPrimaryKey'];
52
51
  hidden.forEach(k => delete object[k]);
@@ -2,19 +2,17 @@ import { type Configuration } from '../utils/Configuration.js';
2
2
  import type { MetadataStorage } from '../metadata/MetadataStorage.js';
3
3
  import type { AnyEntity } from '../typings.js';
4
4
  import { ChangeSet } from './ChangeSet.js';
5
- import { type EntityValidator } from '../entity/EntityValidator.js';
6
5
  import { type Collection } from '../entity/Collection.js';
7
6
  import type { Platform } from '../platforms/Platform.js';
8
7
  import type { EntityManager } from '../EntityManager.js';
9
8
  export declare class ChangeSetComputer {
10
- private readonly validator;
11
9
  private readonly collectionUpdates;
12
10
  private readonly metadata;
13
11
  private readonly platform;
14
12
  private readonly config;
15
13
  private readonly em;
16
14
  private readonly comparator;
17
- constructor(validator: EntityValidator, collectionUpdates: Set<Collection<AnyEntity>>, metadata: MetadataStorage, platform: Platform, config: Configuration, em: EntityManager);
15
+ constructor(collectionUpdates: Set<Collection<AnyEntity>>, metadata: MetadataStorage, platform: Platform, config: Configuration, em: EntityManager);
18
16
  computeChangeSet<T extends object>(entity: T): ChangeSet<T> | null;
19
17
  /**
20
18
  * Traverses entity graph and executes `onCreate` and `onUpdate` methods, assigning the values to given properties.
@@ -1,17 +1,16 @@
1
1
  import { Utils } from '../utils/Utils.js';
2
2
  import { ChangeSet, ChangeSetType } from './ChangeSet.js';
3
3
  import { helper } from '../entity/wrap.js';
4
+ import { validateEntity } from '../entity/validators.js';
4
5
  import { ReferenceKind } from '../enums.js';
5
6
  export class ChangeSetComputer {
6
- validator;
7
7
  collectionUpdates;
8
8
  metadata;
9
9
  platform;
10
10
  config;
11
11
  em;
12
12
  comparator;
13
- constructor(validator, collectionUpdates, metadata, platform, config, em) {
14
- this.validator = validator;
13
+ constructor(collectionUpdates, metadata, platform, config, em) {
15
14
  this.collectionUpdates = collectionUpdates;
16
15
  this.metadata = metadata;
17
16
  this.platform = platform;
@@ -20,7 +19,7 @@ export class ChangeSetComputer {
20
19
  this.comparator = this.config.getComparator(this.metadata);
21
20
  }
22
21
  computeChangeSet(entity) {
23
- const meta = this.metadata.get(entity.constructor.name);
22
+ const meta = this.metadata.get(entity.constructor);
24
23
  if (meta.readonly) {
25
24
  return null;
26
25
  }
@@ -34,20 +33,21 @@ export class ChangeSetComputer {
34
33
  this.processPropertyInitializers(entity, prop, type, map);
35
34
  }
36
35
  }
37
- if (type === ChangeSetType.UPDATE && !wrapped.__initialized && !wrapped.isTouched()) {
38
- return null;
36
+ if (type === ChangeSetType.UPDATE && !wrapped.__initialized) {
37
+ const data = this.comparator.prepareEntity(entity);
38
+ if (Utils.equals(data, wrapped.__originalEntityData)) {
39
+ return null;
40
+ }
39
41
  }
40
42
  const changeSet = new ChangeSet(entity, type, this.computePayload(entity), meta);
41
43
  changeSet.originalEntity = wrapped.__originalEntityData;
42
- if (this.config.get('validate')) {
43
- this.validator.validate(changeSet.entity, changeSet.payload, meta);
44
- }
45
44
  for (const prop of meta.relations.filter(prop => prop.persist !== false || prop.userDefined === false)) {
46
45
  this.processProperty(changeSet, prop);
47
46
  }
48
47
  if (changeSet.type === ChangeSetType.UPDATE && !Utils.hasObjectKeys(changeSet.payload)) {
49
48
  return null;
50
49
  }
50
+ validateEntity(changeSet.entity, meta);
51
51
  // Execute `onCreate` and `onUpdate` on properties recursively, saves `onUpdate` results
52
52
  // to the `map` as we want to apply those only if something else changed.
53
53
  if (type === ChangeSetType.UPDATE) {
@@ -91,7 +91,7 @@ export class ChangeSetComputer {
91
91
  computePayload(entity, ignoreUndefined = false) {
92
92
  const data = this.comparator.prepareEntity(entity);
93
93
  const wrapped = helper(entity);
94
- const entityName = wrapped.__meta.className;
94
+ const entityName = wrapped.__meta.class;
95
95
  const originalEntityData = wrapped.__originalEntityData;
96
96
  if (!wrapped.__initialized) {
97
97
  for (const prop of wrapped.__meta.primaryKeys) {
@@ -132,7 +132,16 @@ export class ChangeSetComputer {
132
132
  const targets = Utils.unwrapProperty(changeSet.entity, changeSet.meta, prop);
133
133
  targets.forEach(([target, idx]) => {
134
134
  if (!target.__helper.hasPrimaryKey()) {
135
- Utils.setPayloadProperty(changeSet.payload, this.metadata.find(changeSet.name), prop, target.__helper.__identifier, idx);
135
+ // When targetKey is set, use that property value instead of the PK identifier
136
+ let value = prop.targetKey ? target[prop.targetKey] : target.__helper.__identifier;
137
+ /* v8 ignore next */
138
+ if (prop.targetKey && prop.targetMeta) {
139
+ const targetProp = prop.targetMeta.properties[prop.targetKey];
140
+ if (targetProp?.customType) {
141
+ value = targetProp.customType.convertToDatabaseValue(value, this.platform, { mode: 'serialization' });
142
+ }
143
+ }
144
+ Utils.setPayloadProperty(changeSet.payload, changeSet.meta, prop, value, idx);
136
145
  }
137
146
  });
138
147
  }
@@ -141,9 +150,13 @@ export class ChangeSetComputer {
141
150
  if (!target.isDirty() && changeSet.type !== ChangeSetType.CREATE) {
142
151
  return;
143
152
  }
144
- this.collectionUpdates.add(target);
153
+ if (target.isDirty()) {
154
+ this.collectionUpdates.add(target);
155
+ }
145
156
  if (prop.owner && !this.platform.usesPivotTable()) {
146
- changeSet.payload[prop.name] = target.getItems(false).map((item) => item.__helper.__identifier ?? item.__helper.getPrimaryKey());
157
+ changeSet.payload[prop.name] = target.getItems(false).map((item) => {
158
+ return item.__helper.__identifier ?? item.__helper.getPrimaryKey();
159
+ });
147
160
  }
148
161
  }
149
162
  }
@@ -1,29 +1,30 @@
1
1
  import type { MetadataStorage } from '../metadata/MetadataStorage.js';
2
2
  import type { Dictionary, EntityDictionary, EntityMetadata, IHydrator } from '../typings.js';
3
3
  import { type EntityFactory } from '../entity/EntityFactory.js';
4
- import { type EntityValidator } from '../entity/EntityValidator.js';
5
4
  import { type ChangeSet } from './ChangeSet.js';
6
5
  import { type Configuration } from '../utils/Configuration.js';
7
6
  import type { DriverMethodOptions, IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
7
+ import type { EntityManager } from '../EntityManager.js';
8
8
  export declare class ChangeSetPersister {
9
9
  private readonly driver;
10
10
  private readonly metadata;
11
11
  private readonly hydrator;
12
12
  private readonly factory;
13
- private readonly validator;
14
13
  private readonly config;
14
+ private readonly em;
15
15
  private readonly platform;
16
16
  private readonly comparator;
17
17
  private readonly usesReturningStatement;
18
- constructor(driver: IDatabaseDriver, metadata: MetadataStorage, hydrator: IHydrator, factory: EntityFactory, validator: EntityValidator, config: Configuration);
18
+ constructor(driver: IDatabaseDriver, metadata: MetadataStorage, hydrator: IHydrator, factory: EntityFactory, config: Configuration, em: EntityManager);
19
19
  executeInserts<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
20
20
  executeUpdates<T extends object>(changeSets: ChangeSet<T>[], batched: boolean, options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
21
21
  executeDeletes<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
22
22
  private runForEachSchema;
23
+ private validateRequired;
23
24
  private processProperties;
24
25
  private persistNewEntity;
25
26
  private persistNewEntities;
26
- private propagateSchemaFromMetadata;
27
+ private prepareOptions;
27
28
  private persistNewEntitiesBatch;
28
29
  private persistManagedEntity;
29
30
  private persistManagedEntities;