@mikro-orm/core 7.0.0-dev.23 → 7.0.0-dev.231

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 (209) hide show
  1. package/EntityManager.d.ts +91 -59
  2. package/EntityManager.js +303 -251
  3. package/MikroORM.d.ts +44 -35
  4. package/MikroORM.js +109 -143
  5. package/README.md +2 -0
  6. package/cache/FileCacheAdapter.d.ts +1 -1
  7. package/cache/FileCacheAdapter.js +17 -8
  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 +12 -5
  13. package/connections/Connection.js +21 -12
  14. package/drivers/DatabaseDriver.d.ts +25 -16
  15. package/drivers/DatabaseDriver.js +118 -35
  16. package/drivers/IDatabaseDriver.d.ts +42 -19
  17. package/entity/BaseEntity.d.ts +61 -2
  18. package/entity/BaseEntity.js +0 -3
  19. package/entity/Collection.d.ts +101 -29
  20. package/entity/Collection.js +436 -104
  21. package/entity/EntityAssigner.d.ts +1 -1
  22. package/entity/EntityAssigner.js +26 -18
  23. package/entity/EntityFactory.d.ts +7 -1
  24. package/entity/EntityFactory.js +83 -54
  25. package/entity/EntityHelper.d.ts +2 -2
  26. package/entity/EntityHelper.js +48 -15
  27. package/entity/EntityLoader.d.ts +7 -6
  28. package/entity/EntityLoader.js +221 -93
  29. package/entity/EntityRepository.d.ts +27 -7
  30. package/entity/EntityRepository.js +8 -2
  31. package/entity/PolymorphicRef.d.ts +12 -0
  32. package/entity/PolymorphicRef.js +18 -0
  33. package/entity/Reference.d.ts +1 -5
  34. package/entity/Reference.js +21 -12
  35. package/entity/WrappedEntity.d.ts +0 -5
  36. package/entity/WrappedEntity.js +2 -7
  37. package/entity/defineEntity.d.ts +380 -310
  38. package/entity/defineEntity.js +124 -273
  39. package/entity/index.d.ts +2 -2
  40. package/entity/index.js +2 -2
  41. package/entity/utils.js +1 -1
  42. package/entity/validators.d.ts +11 -0
  43. package/entity/validators.js +65 -0
  44. package/enums.d.ts +8 -6
  45. package/enums.js +2 -1
  46. package/errors.d.ts +20 -10
  47. package/errors.js +55 -23
  48. package/events/EventManager.d.ts +2 -1
  49. package/events/EventManager.js +19 -11
  50. package/hydration/Hydrator.js +1 -2
  51. package/hydration/ObjectHydrator.d.ts +4 -4
  52. package/hydration/ObjectHydrator.js +87 -35
  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 +47 -23
  65. package/metadata/EntitySchema.js +92 -33
  66. package/metadata/MetadataDiscovery.d.ts +64 -9
  67. package/metadata/MetadataDiscovery.js +778 -325
  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 +32 -9
  73. package/metadata/MetadataValidator.js +196 -41
  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 +526 -0
  79. package/metadata/types.js +1 -0
  80. package/naming-strategy/AbstractNamingStrategy.d.ts +16 -4
  81. package/naming-strategy/AbstractNamingStrategy.js +20 -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 +28 -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 -14
  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 +3 -3
  100. package/types/ArrayType.d.ts +1 -1
  101. package/types/ArrayType.js +2 -3
  102. package/types/BigIntType.d.ts +8 -6
  103. package/types/BigIntType.js +1 -1
  104. package/types/BlobType.d.ts +0 -1
  105. package/types/BlobType.js +0 -3
  106. package/types/BooleanType.d.ts +1 -0
  107. package/types/BooleanType.js +3 -0
  108. package/types/DecimalType.d.ts +6 -4
  109. package/types/DecimalType.js +2 -2
  110. package/types/DoubleType.js +1 -1
  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 +381 -171
  121. package/typings.js +97 -44
  122. package/unit-of-work/ChangeSet.d.ts +4 -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 +35 -14
  126. package/unit-of-work/ChangeSetPersister.d.ts +7 -3
  127. package/unit-of-work/ChangeSetPersister.js +83 -25
  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 +27 -3
  133. package/unit-of-work/UnitOfWork.js +258 -92
  134. package/utils/AbstractSchemaGenerator.d.ts +5 -5
  135. package/utils/AbstractSchemaGenerator.js +28 -17
  136. package/utils/AsyncContext.d.ts +6 -0
  137. package/utils/AsyncContext.js +42 -0
  138. package/utils/Configuration.d.ts +795 -209
  139. package/utils/Configuration.js +150 -192
  140. package/utils/ConfigurationLoader.d.ts +1 -54
  141. package/utils/ConfigurationLoader.js +1 -352
  142. package/utils/Cursor.d.ts +0 -3
  143. package/utils/Cursor.js +24 -11
  144. package/utils/DataloaderUtils.d.ts +10 -5
  145. package/utils/DataloaderUtils.js +29 -12
  146. package/utils/EntityComparator.d.ts +16 -9
  147. package/utils/EntityComparator.js +158 -58
  148. package/utils/QueryHelper.d.ts +18 -6
  149. package/utils/QueryHelper.js +76 -23
  150. package/utils/RawQueryFragment.d.ts +28 -34
  151. package/utils/RawQueryFragment.js +35 -71
  152. package/utils/RequestContext.js +2 -2
  153. package/utils/TransactionContext.js +2 -2
  154. package/utils/TransactionManager.js +28 -4
  155. package/utils/Utils.d.ts +14 -127
  156. package/utils/Utils.js +85 -397
  157. package/utils/clone.js +8 -23
  158. package/utils/env-vars.d.ts +7 -0
  159. package/utils/env-vars.js +97 -0
  160. package/utils/fs-utils.d.ts +33 -0
  161. package/utils/fs-utils.js +192 -0
  162. package/utils/index.d.ts +1 -1
  163. package/utils/index.js +1 -1
  164. package/utils/upsert-utils.d.ts +9 -4
  165. package/utils/upsert-utils.js +46 -3
  166. package/decorators/Check.d.ts +0 -3
  167. package/decorators/Check.js +0 -13
  168. package/decorators/CreateRequestContext.d.ts +0 -3
  169. package/decorators/CreateRequestContext.js +0 -32
  170. package/decorators/Embeddable.d.ts +0 -8
  171. package/decorators/Embeddable.js +0 -11
  172. package/decorators/Embedded.d.ts +0 -12
  173. package/decorators/Embedded.js +0 -18
  174. package/decorators/Entity.d.ts +0 -33
  175. package/decorators/Entity.js +0 -12
  176. package/decorators/Enum.d.ts +0 -9
  177. package/decorators/Enum.js +0 -16
  178. package/decorators/Filter.d.ts +0 -2
  179. package/decorators/Filter.js +0 -8
  180. package/decorators/Formula.d.ts +0 -4
  181. package/decorators/Formula.js +0 -15
  182. package/decorators/Indexed.d.ts +0 -19
  183. package/decorators/Indexed.js +0 -20
  184. package/decorators/ManyToMany.d.ts +0 -42
  185. package/decorators/ManyToMany.js +0 -14
  186. package/decorators/ManyToOne.d.ts +0 -34
  187. package/decorators/ManyToOne.js +0 -14
  188. package/decorators/OneToMany.d.ts +0 -28
  189. package/decorators/OneToMany.js +0 -17
  190. package/decorators/OneToOne.d.ts +0 -28
  191. package/decorators/OneToOne.js +0 -7
  192. package/decorators/PrimaryKey.d.ts +0 -8
  193. package/decorators/PrimaryKey.js +0 -20
  194. package/decorators/Property.d.ts +0 -250
  195. package/decorators/Property.js +0 -32
  196. package/decorators/Transactional.d.ts +0 -14
  197. package/decorators/Transactional.js +0 -28
  198. package/decorators/hooks.d.ts +0 -16
  199. package/decorators/hooks.js +0 -47
  200. package/decorators/index.d.ts +0 -17
  201. package/decorators/index.js +0 -17
  202. package/entity/ArrayCollection.d.ts +0 -118
  203. package/entity/ArrayCollection.js +0 -407
  204. package/entity/EntityValidator.d.ts +0 -19
  205. package/entity/EntityValidator.js +0 -150
  206. package/metadata/ReflectMetadataProvider.d.ts +0 -8
  207. package/metadata/ReflectMetadataProvider.js +0 -44
  208. package/utils/resolveContextProvider.d.ts +0 -10
  209. package/utils/resolveContextProvider.js +0 -28
package/typings.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import { ReferenceKind, } from './enums.js';
2
2
  import { Reference } from './entity/Reference.js';
3
3
  import { EntityHelper } from './entity/EntityHelper.js';
4
+ import { helper } from './entity/wrap.js';
4
5
  import { Utils } from './utils/Utils.js';
5
6
  import { EntityComparator } from './utils/EntityComparator.js';
7
+ import { BaseEntity } from './entity/BaseEntity.js';
6
8
  export const EntityRepositoryType = Symbol('EntityRepositoryType');
7
9
  export const PrimaryKeyProp = Symbol('PrimaryKeyProp');
8
10
  export const OptionalProps = Symbol('OptionalProps');
@@ -25,22 +27,24 @@ export class EntityMetadata {
25
27
  this.referencingProperties = [];
26
28
  this.concurrencyCheckKeys = new Set();
27
29
  Object.assign(this, meta);
28
- }
29
- addProperty(prop, sync = true) {
30
- if (prop.pivotTable && !prop.pivotEntity) {
31
- prop.pivotEntity = prop.pivotTable;
30
+ const name = meta.className ?? meta.name;
31
+ if (!this.class && name) {
32
+ const Class = this.extends === BaseEntity
33
+ ? ({ [name]: class extends BaseEntity {
34
+ } })[name]
35
+ : ({ [name]: class {
36
+ } })[name];
37
+ this.class = Class;
32
38
  }
39
+ }
40
+ addProperty(prop) {
33
41
  this.properties[prop.name] = prop;
34
42
  this.propertyOrder.set(prop.name, this.props.length);
35
- /* v8 ignore next 3 */
36
- if (sync) {
37
- this.sync();
38
- }
43
+ this.sync();
39
44
  }
40
45
  removeProperty(name, sync = true) {
41
46
  delete this.properties[name];
42
47
  this.propertyOrder.delete(name);
43
- /* v8 ignore next 3 */
44
48
  if (sync) {
45
49
  this.sync();
46
50
  }
@@ -60,8 +64,52 @@ export class EntityMetadata {
60
64
  getPrimaryProp() {
61
65
  return this.properties[this.primaryKeys[0]];
62
66
  }
63
- createColumnMappingObject() {
64
- return Object.values(this.properties).reduce((o, prop) => {
67
+ /**
68
+ * Creates a mapping from property names to field names.
69
+ * @param alias - Optional alias to prefix field names. Can be a string (same for all) or a function (per-property).
70
+ * When provided, also adds toString() returning the alias for backwards compatibility with formulas.
71
+ * @param toStringAlias - Optional alias to return from toString(). Defaults to `alias` when it's a string.
72
+ */
73
+ createColumnMappingObject(alias, toStringAlias) {
74
+ const resolveAlias = typeof alias === 'function' ? alias : () => alias;
75
+ const defaultAlias = toStringAlias ?? (typeof alias === 'string' ? alias : undefined);
76
+ const result = Object.values(this.properties).reduce((o, prop) => {
77
+ if (prop.fieldNames) {
78
+ const propAlias = resolveAlias(prop);
79
+ o[prop.name] = propAlias ? `${propAlias}.${prop.fieldNames[0]}` : prop.fieldNames[0];
80
+ }
81
+ return o;
82
+ }, {});
83
+ // Add toString() for backwards compatibility when alias is provided
84
+ Object.defineProperty(result, 'toString', {
85
+ value: () => defaultAlias ?? '',
86
+ enumerable: false,
87
+ });
88
+ // Wrap in Proxy to detect old formula signature usage where the first param was FormulaTable.
89
+ // If user accesses `.alias` or `.qualifiedName` (FormulaTable-only properties), warn them.
90
+ const warnedProps = new Set(['alias', 'qualifiedName']);
91
+ return new Proxy(result, {
92
+ get(target, prop, receiver) {
93
+ if (typeof prop === 'string' && warnedProps.has(prop) && !(prop in target)) {
94
+ // eslint-disable-next-line no-console
95
+ console.warn(`[MikroORM] Detected old formula callback signature. The first parameter is now 'columns', not 'table'. ` +
96
+ `Accessing '.${prop}' on the columns object will return undefined. ` +
97
+ `Update your formula: formula(cols => quote\`\${cols.propName} ...\`). See the v7 upgrade guide.`);
98
+ }
99
+ return Reflect.get(target, prop, receiver);
100
+ },
101
+ });
102
+ }
103
+ /**
104
+ * Creates a column mapping for schema callbacks (indexes, checks, generated columns).
105
+ * For TPT entities, only includes properties that belong to the current table (ownProps).
106
+ */
107
+ createSchemaColumnMappingObject() {
108
+ // For TPT entities, only include properties that belong to this entity's table
109
+ const props = this.inheritanceType === 'tpt' && this.ownProps
110
+ ? this.ownProps
111
+ : Object.values(this.properties);
112
+ return props.reduce((o, prop) => {
65
113
  if (prop.fieldNames) {
66
114
  o[prop.name] = prop.fieldNames[0];
67
115
  }
@@ -74,6 +122,9 @@ export class EntityMetadata {
74
122
  set tableName(name) {
75
123
  this.collection = name;
76
124
  }
125
+ get uniqueName() {
126
+ return this.tableName + '_' + this._id;
127
+ }
77
128
  sync(initIndexes = false, config) {
78
129
  this.root ??= this;
79
130
  const props = Object.values(this.properties).sort((a, b) => this.propertyOrder.get(a.name) - this.propertyOrder.get(b.name));
@@ -83,6 +134,12 @@ export class EntityMetadata {
83
134
  this.uniqueProps = this.props.filter(prop => prop.unique);
84
135
  this.getterProps = this.props.filter(prop => prop.getter);
85
136
  this.comparableProps = this.props.filter(prop => EntityComparator.isComparable(prop, this));
137
+ this.validateProps = this.props.filter(prop => {
138
+ if (prop.inherited || (prop.persist === false && prop.userDefined !== false)) {
139
+ return false;
140
+ }
141
+ return prop.kind === ReferenceKind.SCALAR && ['string', 'number', 'boolean', 'Date'].includes(prop.type);
142
+ });
86
143
  this.hydrateProps = this.props.filter(prop => {
87
144
  // `prop.userDefined` is either `undefined` or `false`
88
145
  const discriminator = this.root.discriminatorColumn === prop.name && prop.userDefined === false;
@@ -90,16 +147,26 @@ export class EntityMetadata {
90
147
  const onlyGetter = prop.getter && !prop.setter && prop.persist === false;
91
148
  return !prop.inherited && prop.hydrate !== false && !discriminator && !prop.embedded && !onlyGetter;
92
149
  });
93
- this.trackingProps = this.hydrateProps
94
- .filter(prop => !prop.getter && !prop.setter && prop.trackChanges !== false)
95
- .filter(prop => ![ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind))
96
- .filter(prop => !prop.serializedPrimaryKey);
97
- this.selfReferencing = this.relations.some(prop => [this.className, this.root.className].includes(prop.targetMeta?.root.className ?? prop.type));
150
+ this.trackingProps = this.hydrateProps.filter(prop => {
151
+ return !prop.getter && !prop.setter && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind);
152
+ });
153
+ this.selfReferencing = this.relations.some(prop => {
154
+ return this.root.uniqueName === prop.targetMeta?.root.uniqueName;
155
+ });
98
156
  this.hasUniqueProps = this.uniques.length + this.uniqueProps.length > 0;
99
- this.virtual = !!this.expression;
157
+ // Normalize object-form `view` option: `view: { materialized: true, withData: false }`
158
+ // into flat metadata fields (`view: true`, `materialized: true`, `withData: false`).
159
+ if (typeof this.view === 'object') {
160
+ this.materialized = this.view.materialized;
161
+ this.withData = this.view.withData;
162
+ this.view = true;
163
+ }
164
+ // If `view` is set, this is a database view entity (not a virtual entity).
165
+ // Virtual entities evaluate expressions at query time, view entities create actual database views.
166
+ this.virtual = !!this.expression && !this.view;
100
167
  if (config) {
101
168
  for (const prop of this.props) {
102
- if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => Utils.isString(item))) {
169
+ if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
103
170
  const name = config.getNamingStrategy().indexName(this.tableName, prop.fieldNames, 'check');
104
171
  const exists = this.checks.findIndex(check => check.name === name);
105
172
  if (exists !== -1) {
@@ -119,16 +186,15 @@ export class EntityMetadata {
119
186
  for (const hook of Utils.keys(this.hooks)) {
120
187
  this.hooks[hook] = Utils.removeDuplicates(this.hooks[hook]);
121
188
  }
122
- if (this.virtual) {
189
+ if (this.virtual || this.view) {
123
190
  this.readonly = true;
124
191
  }
125
192
  if (initIndexes && this.name) {
126
193
  this.props.forEach(prop => this.initIndexes(prop));
127
194
  }
128
195
  this.definedProperties = this.trackingProps.reduce((o, prop) => {
129
- const isCollection = [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(prop.kind);
130
- const isReference = [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(prop.kind) && (prop.inversedBy || prop.mappedBy) && !prop.mapToPk;
131
- if (isReference) {
196
+ const hasInverse = (prop.inversedBy || prop.mappedBy) && !prop.mapToPk;
197
+ if (hasInverse) {
132
198
  // eslint-disable-next-line @typescript-eslint/no-this-alias
133
199
  const meta = this;
134
200
  o[prop.name] = {
@@ -146,10 +212,10 @@ export class EntityMetadata {
146
212
  wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
147
213
  // when propagation from inside hydration, we set the FK to the entity data immediately
148
214
  if (val && hydrator.isRunning() && wrapped.__originalEntityData && prop.owner) {
149
- wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(val, prop.targetMeta, true);
150
- }
151
- else {
152
- wrapped.__touched = !hydrator.isRunning();
215
+ const targetMeta = prop.targetMeta ?? helper(entity)?.__meta;
216
+ if (targetMeta) {
217
+ wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(val, targetMeta, true);
218
+ }
153
219
  }
154
220
  EntityHelper.propagate(meta, entity, this, prop, Reference.unwrapReference(val), old);
155
221
  },
@@ -157,23 +223,6 @@ export class EntityMetadata {
157
223
  configurable: true,
158
224
  };
159
225
  }
160
- if (prop.inherited || prop.primary || isCollection || prop.persist === false || prop.trackChanges === false || isReference || prop.embedded) {
161
- return o;
162
- }
163
- o[prop.name] = {
164
- get() {
165
- return this.__helper.__data[prop.name];
166
- },
167
- set(val) {
168
- if (typeof val === 'object' && !!val && '__raw' in val) {
169
- val.assign();
170
- }
171
- this.__helper.__data[prop.name] = val;
172
- this.__helper.__touched = !this.__helper.hydrator.isRunning();
173
- },
174
- enumerable: true,
175
- configurable: true,
176
- };
177
226
  return o;
178
227
  }, { __gettersDefined: { value: true, enumerable: false } });
179
228
  }
@@ -195,7 +244,7 @@ export class EntityMetadata {
195
244
  this.indexes.push({ properties: prop.name });
196
245
  prop.index = false;
197
246
  }
198
- /* v8 ignore next 4 */
247
+ /* v8 ignore next */
199
248
  if (owner && prop.fieldNames.length > 1 && prop.unique) {
200
249
  this.uniques.push({ properties: prop.name });
201
250
  prop.unique = false;
@@ -205,4 +254,8 @@ export class EntityMetadata {
205
254
  clone() {
206
255
  return this;
207
256
  }
257
+ /** @ignore */
258
+ [Symbol.for('nodejs.util.inspect.custom')]() {
259
+ return `[${this.constructor.name}<${this.className}>]`;
260
+ }
208
261
  }
@@ -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,19 +9,18 @@ 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;
23
19
  payload: EntityDictionary<T>;
24
20
  persisted: boolean;
25
21
  originalEntity?: EntityData<T>;
22
+ /** For TPT: changesets for parent tables, ordered from immediate parent to root */
23
+ tptChangeSets?: ChangeSet<T>[];
26
24
  }
27
25
  export declare enum ChangeSetType {
28
26
  CREATE = "create",
@@ -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,19 @@
1
1
  import { Utils } from '../utils/Utils.js';
2
+ import { QueryHelper } from '../utils/QueryHelper.js';
2
3
  import { ChangeSet, ChangeSetType } from './ChangeSet.js';
3
4
  import { helper } from '../entity/wrap.js';
5
+ import { validateEntity } from '../entity/validators.js';
6
+ import { Reference } from '../entity/Reference.js';
7
+ import { PolymorphicRef } from '../entity/PolymorphicRef.js';
4
8
  import { ReferenceKind } from '../enums.js';
5
9
  export class ChangeSetComputer {
6
- validator;
7
10
  collectionUpdates;
8
11
  metadata;
9
12
  platform;
10
13
  config;
11
14
  em;
12
15
  comparator;
13
- constructor(validator, collectionUpdates, metadata, platform, config, em) {
14
- this.validator = validator;
16
+ constructor(collectionUpdates, metadata, platform, config, em) {
15
17
  this.collectionUpdates = collectionUpdates;
16
18
  this.metadata = metadata;
17
19
  this.platform = platform;
@@ -20,7 +22,7 @@ export class ChangeSetComputer {
20
22
  this.comparator = this.config.getComparator(this.metadata);
21
23
  }
22
24
  computeChangeSet(entity) {
23
- const meta = this.metadata.get(entity.constructor.name);
25
+ const meta = this.metadata.get(entity.constructor);
24
26
  if (meta.readonly) {
25
27
  return null;
26
28
  }
@@ -34,20 +36,21 @@ export class ChangeSetComputer {
34
36
  this.processPropertyInitializers(entity, prop, type, map);
35
37
  }
36
38
  }
37
- if (type === ChangeSetType.UPDATE && !wrapped.__initialized && !wrapped.isTouched()) {
38
- return null;
39
+ if (type === ChangeSetType.UPDATE && !wrapped.__initialized) {
40
+ const data = this.comparator.prepareEntity(entity);
41
+ if (Utils.equals(data, wrapped.__originalEntityData)) {
42
+ return null;
43
+ }
39
44
  }
40
45
  const changeSet = new ChangeSet(entity, type, this.computePayload(entity), meta);
41
46
  changeSet.originalEntity = wrapped.__originalEntityData;
42
- if (this.config.get('validate')) {
43
- this.validator.validate(changeSet.entity, changeSet.payload, meta);
44
- }
45
47
  for (const prop of meta.relations.filter(prop => prop.persist !== false || prop.userDefined === false)) {
46
48
  this.processProperty(changeSet, prop);
47
49
  }
48
50
  if (changeSet.type === ChangeSetType.UPDATE && !Utils.hasObjectKeys(changeSet.payload)) {
49
51
  return null;
50
52
  }
53
+ validateEntity(changeSet.entity, meta);
51
54
  // Execute `onCreate` and `onUpdate` on properties recursively, saves `onUpdate` results
52
55
  // to the `map` as we want to apply those only if something else changed.
53
56
  if (type === ChangeSetType.UPDATE) {
@@ -91,7 +94,7 @@ export class ChangeSetComputer {
91
94
  computePayload(entity, ignoreUndefined = false) {
92
95
  const data = this.comparator.prepareEntity(entity);
93
96
  const wrapped = helper(entity);
94
- const entityName = wrapped.__meta.className;
97
+ const entityName = wrapped.__meta.class;
95
98
  const originalEntityData = wrapped.__originalEntityData;
96
99
  if (!wrapped.__initialized) {
97
100
  for (const prop of wrapped.__meta.primaryKeys) {
@@ -130,9 +133,25 @@ export class ChangeSetComputer {
130
133
  return;
131
134
  }
132
135
  const targets = Utils.unwrapProperty(changeSet.entity, changeSet.meta, prop);
133
- targets.forEach(([target, idx]) => {
134
- if (!target.__helper.hasPrimaryKey()) {
135
- Utils.setPayloadProperty(changeSet.payload, this.metadata.find(changeSet.name), prop, target.__helper.__identifier, idx);
136
+ targets.forEach(([rawTarget, idx]) => {
137
+ const target = Reference.unwrapReference(rawTarget);
138
+ const needsProcessing = target != null && (prop.targetKey != null || !target.__helper.hasPrimaryKey());
139
+ if (needsProcessing) {
140
+ let value = prop.targetKey ? target[prop.targetKey] : target.__helper.__identifier;
141
+ /* v8 ignore next */
142
+ if (prop.targetKey && prop.targetMeta) {
143
+ const targetProp = prop.targetMeta.properties[prop.targetKey];
144
+ if (targetProp?.customType) {
145
+ value = targetProp.customType.convertToDatabaseValue(value, this.platform, { mode: 'serialization' });
146
+ }
147
+ }
148
+ if (prop.polymorphic) {
149
+ const discriminator = QueryHelper.findDiscriminatorValue(prop.discriminatorMap, target.constructor);
150
+ Utils.setPayloadProperty(changeSet.payload, changeSet.meta, prop, new PolymorphicRef(discriminator, value), idx);
151
+ }
152
+ else {
153
+ Utils.setPayloadProperty(changeSet.payload, changeSet.meta, prop, value, idx);
154
+ }
136
155
  }
137
156
  });
138
157
  }
@@ -145,7 +164,9 @@ export class ChangeSetComputer {
145
164
  this.collectionUpdates.add(target);
146
165
  }
147
166
  if (prop.owner && !this.platform.usesPivotTable()) {
148
- changeSet.payload[prop.name] = target.getItems(false).map((item) => item.__helper.__identifier ?? item.__helper.getPrimaryKey());
167
+ changeSet.payload[prop.name] = target.getItems(false).map((item) => {
168
+ return item.__helper.__identifier ?? item.__helper.getPrimaryKey();
169
+ });
149
170
  }
150
171
  }
151
172
  }
@@ -1,7 +1,6 @@
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';
@@ -11,17 +10,17 @@ export declare class ChangeSetPersister {
11
10
  private readonly metadata;
12
11
  private readonly hydrator;
13
12
  private readonly factory;
14
- private readonly validator;
15
13
  private readonly config;
16
14
  private readonly em;
17
15
  private readonly platform;
18
16
  private readonly comparator;
19
17
  private readonly usesReturningStatement;
20
- constructor(driver: IDatabaseDriver, metadata: MetadataStorage, hydrator: IHydrator, factory: EntityFactory, validator: EntityValidator, config: Configuration, em: EntityManager);
18
+ constructor(driver: IDatabaseDriver, metadata: MetadataStorage, hydrator: IHydrator, factory: EntityFactory, config: Configuration, em: EntityManager);
21
19
  executeInserts<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
22
20
  executeUpdates<T extends object>(changeSets: ChangeSet<T>[], batched: boolean, options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
23
21
  executeDeletes<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
24
22
  private runForEachSchema;
23
+ private validateRequired;
25
24
  private processProperties;
26
25
  private persistNewEntity;
27
26
  private persistNewEntities;
@@ -44,6 +43,11 @@ export declare class ChangeSetPersister {
44
43
  * so we use a single query in case of both versioning and default values is used.
45
44
  */
46
45
  private reloadVersionValues;
46
+ /**
47
+ * For TPT child tables, resolve EntityIdentifier values in PK fields.
48
+ * The parent table insert assigns the actual PK value, which the child table references.
49
+ */
50
+ private resolveTPTIdentifiers;
47
51
  private processProperty;
48
52
  /**
49
53
  * Maps values returned via `returning` statement (postgres) or the inserted id (other sql drivers).