@mikro-orm/core 7.0.0-dev.3 → 7.0.0-dev.300

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/EntityManager.d.ts +114 -63
  2. package/EntityManager.js +385 -310
  3. package/MikroORM.d.ts +44 -35
  4. package/MikroORM.js +109 -143
  5. package/README.md +3 -2
  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 +16 -7
  13. package/connections/Connection.js +23 -14
  14. package/drivers/DatabaseDriver.d.ts +25 -16
  15. package/drivers/DatabaseDriver.js +119 -36
  16. package/drivers/IDatabaseDriver.d.ts +125 -23
  17. package/entity/BaseEntity.d.ts +63 -4
  18. package/entity/BaseEntity.js +0 -3
  19. package/entity/Collection.d.ts +102 -31
  20. package/entity/Collection.js +446 -108
  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 +106 -60
  25. package/entity/EntityHelper.d.ts +2 -2
  26. package/entity/EntityHelper.js +65 -20
  27. package/entity/EntityLoader.d.ts +13 -11
  28. package/entity/EntityLoader.js +257 -107
  29. package/entity/EntityRepository.d.ts +28 -8
  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 +9 -12
  34. package/entity/Reference.js +34 -9
  35. package/entity/WrappedEntity.d.ts +3 -8
  36. package/entity/WrappedEntity.js +3 -8
  37. package/entity/defineEntity.d.ts +753 -0
  38. package/entity/defineEntity.js +537 -0
  39. package/entity/index.d.ts +4 -2
  40. package/entity/index.js +4 -2
  41. package/entity/utils.d.ts +13 -1
  42. package/entity/utils.js +49 -4
  43. package/entity/validators.d.ts +11 -0
  44. package/entity/validators.js +65 -0
  45. package/enums.d.ts +23 -8
  46. package/enums.js +15 -1
  47. package/errors.d.ts +25 -9
  48. package/errors.js +67 -21
  49. package/events/EventManager.d.ts +2 -1
  50. package/events/EventManager.js +19 -11
  51. package/events/EventSubscriber.d.ts +3 -1
  52. package/hydration/Hydrator.js +1 -2
  53. package/hydration/ObjectHydrator.d.ts +4 -4
  54. package/hydration/ObjectHydrator.js +89 -36
  55. package/index.d.ts +2 -2
  56. package/index.js +1 -2
  57. package/logging/DefaultLogger.d.ts +1 -1
  58. package/logging/DefaultLogger.js +1 -0
  59. package/logging/SimpleLogger.d.ts +1 -1
  60. package/logging/colors.d.ts +1 -1
  61. package/logging/colors.js +7 -6
  62. package/logging/index.d.ts +1 -0
  63. package/logging/index.js +1 -0
  64. package/logging/inspect.d.ts +2 -0
  65. package/logging/inspect.js +11 -0
  66. package/metadata/EntitySchema.d.ts +53 -27
  67. package/metadata/EntitySchema.js +125 -52
  68. package/metadata/MetadataDiscovery.d.ts +64 -10
  69. package/metadata/MetadataDiscovery.js +823 -344
  70. package/metadata/MetadataProvider.d.ts +11 -2
  71. package/metadata/MetadataProvider.js +66 -2
  72. package/metadata/MetadataStorage.d.ts +13 -11
  73. package/metadata/MetadataStorage.js +71 -38
  74. package/metadata/MetadataValidator.d.ts +32 -9
  75. package/metadata/MetadataValidator.js +198 -42
  76. package/metadata/discover-entities.d.ts +5 -0
  77. package/metadata/discover-entities.js +40 -0
  78. package/metadata/index.d.ts +1 -1
  79. package/metadata/index.js +1 -1
  80. package/metadata/types.d.ts +577 -0
  81. package/metadata/types.js +1 -0
  82. package/naming-strategy/AbstractNamingStrategy.d.ts +16 -4
  83. package/naming-strategy/AbstractNamingStrategy.js +20 -2
  84. package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
  85. package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
  86. package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
  87. package/naming-strategy/MongoNamingStrategy.js +6 -6
  88. package/naming-strategy/NamingStrategy.d.ts +28 -4
  89. package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
  90. package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
  91. package/not-supported.d.ts +2 -0
  92. package/not-supported.js +4 -0
  93. package/package.json +22 -11
  94. package/platforms/ExceptionConverter.js +1 -1
  95. package/platforms/Platform.d.ts +14 -16
  96. package/platforms/Platform.js +24 -44
  97. package/serialization/EntitySerializer.d.ts +8 -3
  98. package/serialization/EntitySerializer.js +47 -27
  99. package/serialization/EntityTransformer.js +33 -21
  100. package/serialization/SerializationContext.d.ts +6 -6
  101. package/serialization/SerializationContext.js +16 -13
  102. package/types/ArrayType.d.ts +1 -1
  103. package/types/ArrayType.js +2 -3
  104. package/types/BigIntType.d.ts +9 -6
  105. package/types/BigIntType.js +4 -1
  106. package/types/BlobType.d.ts +0 -1
  107. package/types/BlobType.js +0 -3
  108. package/types/BooleanType.d.ts +2 -1
  109. package/types/BooleanType.js +3 -0
  110. package/types/DecimalType.d.ts +6 -4
  111. package/types/DecimalType.js +3 -3
  112. package/types/DoubleType.js +2 -2
  113. package/types/EnumArrayType.js +1 -2
  114. package/types/JsonType.d.ts +1 -1
  115. package/types/JsonType.js +7 -2
  116. package/types/TinyIntType.js +1 -1
  117. package/types/Type.d.ts +2 -4
  118. package/types/Type.js +3 -3
  119. package/types/Uint8ArrayType.d.ts +0 -1
  120. package/types/Uint8ArrayType.js +1 -4
  121. package/types/index.d.ts +1 -1
  122. package/typings.d.ts +469 -175
  123. package/typings.js +120 -45
  124. package/unit-of-work/ChangeSet.d.ts +4 -6
  125. package/unit-of-work/ChangeSet.js +4 -5
  126. package/unit-of-work/ChangeSetComputer.d.ts +3 -8
  127. package/unit-of-work/ChangeSetComputer.js +44 -21
  128. package/unit-of-work/ChangeSetPersister.d.ts +15 -12
  129. package/unit-of-work/ChangeSetPersister.js +113 -45
  130. package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
  131. package/unit-of-work/CommitOrderCalculator.js +13 -13
  132. package/unit-of-work/IdentityMap.d.ts +12 -0
  133. package/unit-of-work/IdentityMap.js +39 -1
  134. package/unit-of-work/UnitOfWork.d.ts +28 -3
  135. package/unit-of-work/UnitOfWork.js +315 -110
  136. package/utils/AbstractMigrator.d.ts +101 -0
  137. package/utils/AbstractMigrator.js +305 -0
  138. package/utils/AbstractSchemaGenerator.d.ts +5 -5
  139. package/utils/AbstractSchemaGenerator.js +32 -18
  140. package/utils/AsyncContext.d.ts +6 -0
  141. package/utils/AsyncContext.js +42 -0
  142. package/utils/Configuration.d.ts +801 -207
  143. package/utils/Configuration.js +150 -191
  144. package/utils/ConfigurationLoader.d.ts +1 -54
  145. package/utils/ConfigurationLoader.js +1 -352
  146. package/utils/Cursor.d.ts +3 -6
  147. package/utils/Cursor.js +27 -11
  148. package/utils/DataloaderUtils.d.ts +15 -5
  149. package/utils/DataloaderUtils.js +65 -17
  150. package/utils/EntityComparator.d.ts +21 -10
  151. package/utils/EntityComparator.js +243 -106
  152. package/utils/QueryHelper.d.ts +24 -6
  153. package/utils/QueryHelper.js +122 -26
  154. package/utils/RawQueryFragment.d.ts +60 -32
  155. package/utils/RawQueryFragment.js +69 -66
  156. package/utils/RequestContext.js +2 -2
  157. package/utils/TransactionContext.js +2 -2
  158. package/utils/TransactionManager.d.ts +65 -0
  159. package/utils/TransactionManager.js +223 -0
  160. package/utils/Utils.d.ts +15 -122
  161. package/utils/Utils.js +108 -376
  162. package/utils/clone.js +8 -23
  163. package/utils/env-vars.d.ts +7 -0
  164. package/utils/env-vars.js +97 -0
  165. package/utils/fs-utils.d.ts +34 -0
  166. package/utils/fs-utils.js +196 -0
  167. package/utils/index.d.ts +2 -3
  168. package/utils/index.js +2 -3
  169. package/utils/upsert-utils.d.ts +9 -4
  170. package/utils/upsert-utils.js +55 -4
  171. package/decorators/Check.d.ts +0 -3
  172. package/decorators/Check.js +0 -13
  173. package/decorators/CreateRequestContext.d.ts +0 -3
  174. package/decorators/CreateRequestContext.js +0 -32
  175. package/decorators/Embeddable.d.ts +0 -8
  176. package/decorators/Embeddable.js +0 -11
  177. package/decorators/Embedded.d.ts +0 -18
  178. package/decorators/Embedded.js +0 -18
  179. package/decorators/Entity.d.ts +0 -18
  180. package/decorators/Entity.js +0 -13
  181. package/decorators/Enum.d.ts +0 -9
  182. package/decorators/Enum.js +0 -16
  183. package/decorators/Filter.d.ts +0 -2
  184. package/decorators/Filter.js +0 -8
  185. package/decorators/Formula.d.ts +0 -5
  186. package/decorators/Formula.js +0 -15
  187. package/decorators/Indexed.d.ts +0 -17
  188. package/decorators/Indexed.js +0 -20
  189. package/decorators/ManyToMany.d.ts +0 -40
  190. package/decorators/ManyToMany.js +0 -14
  191. package/decorators/ManyToOne.d.ts +0 -30
  192. package/decorators/ManyToOne.js +0 -14
  193. package/decorators/OneToMany.d.ts +0 -28
  194. package/decorators/OneToMany.js +0 -17
  195. package/decorators/OneToOne.d.ts +0 -24
  196. package/decorators/OneToOne.js +0 -7
  197. package/decorators/PrimaryKey.d.ts +0 -9
  198. package/decorators/PrimaryKey.js +0 -20
  199. package/decorators/Property.d.ts +0 -250
  200. package/decorators/Property.js +0 -32
  201. package/decorators/Transactional.d.ts +0 -13
  202. package/decorators/Transactional.js +0 -28
  203. package/decorators/hooks.d.ts +0 -16
  204. package/decorators/hooks.js +0 -47
  205. package/decorators/index.d.ts +0 -17
  206. package/decorators/index.js +0 -17
  207. package/entity/ArrayCollection.d.ts +0 -116
  208. package/entity/ArrayCollection.js +0 -395
  209. package/entity/EntityValidator.d.ts +0 -19
  210. package/entity/EntityValidator.js +0 -150
  211. package/metadata/ReflectMetadataProvider.d.ts +0 -8
  212. package/metadata/ReflectMetadataProvider.js +0 -44
  213. package/utils/resolveContextProvider.d.ts +0 -10
  214. package/utils/resolveContextProvider.js +0 -28
package/typings.js CHANGED
@@ -1,14 +1,18 @@
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');
9
11
  export const EagerProps = Symbol('EagerProps');
10
12
  export const HiddenProps = Symbol('HiddenProps');
11
13
  export const Config = Symbol('Config');
14
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
15
+ export const EntityName = Symbol('EntityName');
12
16
  export class EntityMetadata {
13
17
  static counter = 0;
14
18
  _id = 1000 * EntityMetadata.counter++; // keep the id >= 1000 to allow computing cache keys by simple addition
@@ -25,38 +29,104 @@ export class EntityMetadata {
25
29
  this.referencingProperties = [];
26
30
  this.concurrencyCheckKeys = new Set();
27
31
  Object.assign(this, meta);
28
- }
29
- addProperty(prop, sync = true) {
30
- if (prop.pivotTable && !prop.pivotEntity) {
31
- prop.pivotEntity = prop.pivotTable;
32
+ const name = meta.className ?? meta.name;
33
+ if (!this.class && name) {
34
+ const Class = this.extends === BaseEntity
35
+ ? ({ [name]: class extends BaseEntity {
36
+ } })[name]
37
+ : ({ [name]: class {
38
+ } })[name];
39
+ this.class = Class;
32
40
  }
41
+ }
42
+ addProperty(prop) {
33
43
  this.properties[prop.name] = prop;
34
44
  this.propertyOrder.set(prop.name, this.props.length);
35
- /* v8 ignore next 3 */
36
- if (sync) {
37
- this.sync();
38
- }
45
+ this.sync();
39
46
  }
40
47
  removeProperty(name, sync = true) {
41
48
  delete this.properties[name];
42
49
  this.propertyOrder.delete(name);
43
- /* v8 ignore next 3 */
44
50
  if (sync) {
45
51
  this.sync();
46
52
  }
47
53
  }
48
- getPrimaryProps() {
49
- return this.primaryKeys.map(pk => this.properties[pk]);
54
+ getPrimaryProps(flatten = false) {
55
+ const pks = this.primaryKeys.map(pk => this.properties[pk]);
56
+ if (flatten) {
57
+ return pks.flatMap(pk => {
58
+ if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(pk.kind)) {
59
+ return pk.targetMeta.getPrimaryProps(true);
60
+ }
61
+ return [pk];
62
+ });
63
+ }
64
+ return pks;
50
65
  }
51
66
  getPrimaryProp() {
52
67
  return this.properties[this.primaryKeys[0]];
53
68
  }
69
+ /**
70
+ * Creates a mapping from property names to field names.
71
+ * @param alias - Optional alias to prefix field names. Can be a string (same for all) or a function (per-property).
72
+ * When provided, also adds toString() returning the alias for backwards compatibility with formulas.
73
+ * @param toStringAlias - Optional alias to return from toString(). Defaults to `alias` when it's a string.
74
+ */
75
+ createColumnMappingObject(alias, toStringAlias) {
76
+ const resolveAlias = typeof alias === 'function' ? alias : () => alias;
77
+ const defaultAlias = toStringAlias ?? (typeof alias === 'string' ? alias : undefined);
78
+ const result = Object.values(this.properties).reduce((o, prop) => {
79
+ if (prop.fieldNames) {
80
+ const propAlias = resolveAlias(prop);
81
+ o[prop.name] = propAlias ? `${propAlias}.${prop.fieldNames[0]}` : prop.fieldNames[0];
82
+ }
83
+ return o;
84
+ }, {});
85
+ // Add toString() for backwards compatibility when alias is provided
86
+ Object.defineProperty(result, 'toString', {
87
+ value: () => defaultAlias ?? '',
88
+ enumerable: false,
89
+ });
90
+ // Wrap in Proxy to detect old formula signature usage where the first param was FormulaTable.
91
+ // If user accesses `.alias` or `.qualifiedName` (FormulaTable-only properties), warn them.
92
+ const warnedProps = new Set(['alias', 'qualifiedName']);
93
+ return new Proxy(result, {
94
+ get(target, prop, receiver) {
95
+ if (typeof prop === 'string' && warnedProps.has(prop) && !(prop in target)) {
96
+ // eslint-disable-next-line no-console
97
+ console.warn(`[MikroORM] Detected old formula callback signature. The first parameter is now 'columns', not 'table'. ` +
98
+ `Accessing '.${prop}' on the columns object will return undefined. ` +
99
+ `Update your formula: formula(cols => quote\`\${cols.propName} ...\`). See the v7 upgrade guide.`);
100
+ }
101
+ return Reflect.get(target, prop, receiver);
102
+ },
103
+ });
104
+ }
105
+ /**
106
+ * Creates a column mapping for schema callbacks (indexes, checks, generated columns).
107
+ * For TPT entities, only includes properties that belong to the current table (ownProps).
108
+ */
109
+ createSchemaColumnMappingObject() {
110
+ // For TPT entities, only include properties that belong to this entity's table
111
+ const props = this.inheritanceType === 'tpt' && this.ownProps
112
+ ? this.ownProps
113
+ : Object.values(this.properties);
114
+ return props.reduce((o, prop) => {
115
+ if (prop.fieldNames) {
116
+ o[prop.name] = prop.fieldNames[0];
117
+ }
118
+ return o;
119
+ }, {});
120
+ }
54
121
  get tableName() {
55
122
  return this.collection;
56
123
  }
57
124
  set tableName(name) {
58
125
  this.collection = name;
59
126
  }
127
+ get uniqueName() {
128
+ return this.tableName + '_' + this._id;
129
+ }
60
130
  sync(initIndexes = false, config) {
61
131
  this.root ??= this;
62
132
  const props = Object.values(this.properties).sort((a, b) => this.propertyOrder.get(a.name) - this.propertyOrder.get(b.name));
@@ -66,23 +136,39 @@ export class EntityMetadata {
66
136
  this.uniqueProps = this.props.filter(prop => prop.unique);
67
137
  this.getterProps = this.props.filter(prop => prop.getter);
68
138
  this.comparableProps = this.props.filter(prop => EntityComparator.isComparable(prop, this));
139
+ this.validateProps = this.props.filter(prop => {
140
+ if (prop.inherited || (prop.persist === false && prop.userDefined !== false)) {
141
+ return false;
142
+ }
143
+ return prop.kind === ReferenceKind.SCALAR && ['string', 'number', 'boolean', 'Date'].includes(prop.type);
144
+ });
69
145
  this.hydrateProps = this.props.filter(prop => {
70
146
  // `prop.userDefined` is either `undefined` or `false`
71
147
  const discriminator = this.root.discriminatorColumn === prop.name && prop.userDefined === false;
72
148
  // even if we don't have a setter, do not ignore value from database!
73
- const onlyGetter = prop.getter && !prop.setter;
149
+ const onlyGetter = prop.getter && !prop.setter && prop.persist === false;
74
150
  return !prop.inherited && prop.hydrate !== false && !discriminator && !prop.embedded && !onlyGetter;
75
151
  });
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));
152
+ this.trackingProps = this.hydrateProps.filter(prop => {
153
+ return !prop.getter && !prop.setter && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind);
154
+ });
155
+ this.selfReferencing = this.relations.some(prop => {
156
+ return this.root.uniqueName === prop.targetMeta?.root.uniqueName;
157
+ });
81
158
  this.hasUniqueProps = this.uniques.length + this.uniqueProps.length > 0;
82
- this.virtual = !!this.expression;
159
+ // Normalize object-form `view` option: `view: { materialized: true, withData: false }`
160
+ // into flat metadata fields (`view: true`, `materialized: true`, `withData: false`).
161
+ if (typeof this.view === 'object') {
162
+ this.materialized = this.view.materialized;
163
+ this.withData = this.view.withData;
164
+ this.view = true;
165
+ }
166
+ // If `view` is set, this is a database view entity (not a virtual entity).
167
+ // Virtual entities evaluate expressions at query time, view entities create actual database views.
168
+ this.virtual = !!this.expression && !this.view;
83
169
  if (config) {
84
170
  for (const prop of this.props) {
85
- if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => Utils.isString(item))) {
171
+ if (prop.enum && !prop.nativeEnumName && prop.items?.every(item => typeof item === 'string')) {
86
172
  const name = config.getNamingStrategy().indexName(this.tableName, prop.fieldNames, 'check');
87
173
  const exists = this.checks.findIndex(check => check.name === name);
88
174
  if (exists !== -1) {
@@ -102,16 +188,15 @@ export class EntityMetadata {
102
188
  for (const hook of Utils.keys(this.hooks)) {
103
189
  this.hooks[hook] = Utils.removeDuplicates(this.hooks[hook]);
104
190
  }
105
- if (this.virtual) {
191
+ if (this.virtual || this.view) {
106
192
  this.readonly = true;
107
193
  }
108
194
  if (initIndexes && this.name) {
109
195
  this.props.forEach(prop => this.initIndexes(prop));
110
196
  }
111
197
  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;
114
- if (isReference) {
198
+ const hasInverse = (prop.inversedBy || prop.mappedBy) && !prop.mapToPk;
199
+ if (hasInverse) {
115
200
  // eslint-disable-next-line @typescript-eslint/no-this-alias
116
201
  const meta = this;
117
202
  o[prop.name] = {
@@ -123,13 +208,16 @@ export class EntityMetadata {
123
208
  const hydrator = wrapped.hydrator;
124
209
  const entity = Reference.unwrapReference(val ?? wrapped.__data[prop.name]);
125
210
  const old = Reference.unwrapReference(wrapped.__data[prop.name]);
211
+ if (old && old !== entity && prop.kind === ReferenceKind.MANY_TO_ONE && prop.inversedBy && old[prop.inversedBy]) {
212
+ old[prop.inversedBy].removeWithoutPropagation(this);
213
+ }
126
214
  wrapped.__data[prop.name] = Reference.wrapReference(val, prop);
127
215
  // when propagation from inside hydration, we set the FK to the entity data immediately
128
216
  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();
217
+ const targetMeta = prop.targetMeta ?? helper(entity)?.__meta;
218
+ if (targetMeta) {
219
+ wrapped.__originalEntityData[prop.name] = Utils.getPrimaryKeyValues(val, targetMeta, true);
220
+ }
133
221
  }
134
222
  EntityHelper.propagate(meta, entity, this, prop, Reference.unwrapReference(val), old);
135
223
  },
@@ -137,23 +225,6 @@ export class EntityMetadata {
137
225
  configurable: true,
138
226
  };
139
227
  }
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
228
  return o;
158
229
  }, { __gettersDefined: { value: true, enumerable: false } });
159
230
  }
@@ -175,7 +246,7 @@ export class EntityMetadata {
175
246
  this.indexes.push({ properties: prop.name });
176
247
  prop.index = false;
177
248
  }
178
- /* v8 ignore next 4 */
249
+ /* v8 ignore next */
179
250
  if (owner && prop.fieldNames.length > 1 && prop.unique) {
180
251
  this.uniques.push({ properties: prop.name });
181
252
  prop.unique = false;
@@ -185,4 +256,8 @@ export class EntityMetadata {
185
256
  clone() {
186
257
  return this;
187
258
  }
259
+ /** @ignore */
260
+ [Symbol.for('nodejs.util.inspect.custom')]() {
261
+ return `[${this.constructor.name}<${this.className}>]`;
262
+ }
188
263
  }
@@ -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]);
@@ -1,20 +1,15 @@
1
- import { type Configuration } from '../utils/Configuration.js';
2
- import type { MetadataStorage } from '../metadata/MetadataStorage.js';
3
1
  import type { AnyEntity } from '../typings.js';
4
2
  import { ChangeSet } from './ChangeSet.js';
5
- import { type EntityValidator } from '../entity/EntityValidator.js';
6
3
  import { type Collection } from '../entity/Collection.js';
7
- import type { Platform } from '../platforms/Platform.js';
8
4
  import type { EntityManager } from '../EntityManager.js';
9
5
  export declare class ChangeSetComputer {
10
- private readonly validator;
6
+ private readonly em;
11
7
  private readonly collectionUpdates;
8
+ private readonly comparator;
12
9
  private readonly metadata;
13
10
  private readonly platform;
14
11
  private readonly config;
15
- private readonly em;
16
- private readonly comparator;
17
- constructor(validator: EntityValidator, collectionUpdates: Set<Collection<AnyEntity>>, metadata: MetadataStorage, platform: Platform, config: Configuration, em: EntityManager);
12
+ constructor(em: EntityManager, collectionUpdates: Set<Collection<AnyEntity>>);
18
13
  computeChangeSet<T extends object>(entity: T): ChangeSet<T> | null;
19
14
  /**
20
15
  * Traverses entity graph and executes `onCreate` and `onUpdate` methods, assigning the values to given properties.
@@ -1,26 +1,28 @@
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;
10
+ em;
7
11
  collectionUpdates;
12
+ comparator;
8
13
  metadata;
9
14
  platform;
10
15
  config;
11
- em;
12
- comparator;
13
- constructor(validator, collectionUpdates, metadata, platform, config, em) {
14
- this.validator = validator;
15
- this.collectionUpdates = collectionUpdates;
16
- this.metadata = metadata;
17
- this.platform = platform;
18
- this.config = config;
16
+ constructor(em, collectionUpdates) {
19
17
  this.em = em;
18
+ this.collectionUpdates = collectionUpdates;
19
+ this.config = this.em.config;
20
+ this.metadata = this.em.getMetadata();
21
+ this.platform = this.em.getPlatform();
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
  }
@@ -141,9 +160,13 @@ export class ChangeSetComputer {
141
160
  if (!target.isDirty() && changeSet.type !== ChangeSetType.CREATE) {
142
161
  return;
143
162
  }
144
- this.collectionUpdates.add(target);
163
+ if (target.isDirty()) {
164
+ this.collectionUpdates.add(target);
165
+ }
145
166
  if (prop.owner && !this.platform.usesPivotTable()) {
146
- 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
+ });
147
170
  }
148
171
  }
149
172
  }
@@ -1,29 +1,27 @@
1
- import type { MetadataStorage } from '../metadata/MetadataStorage.js';
2
- import type { Dictionary, EntityDictionary, EntityMetadata, IHydrator } from '../typings.js';
3
- import { type EntityFactory } from '../entity/EntityFactory.js';
4
- import { type EntityValidator } from '../entity/EntityValidator.js';
1
+ import type { Dictionary, EntityDictionary, EntityMetadata } from '../typings.js';
5
2
  import { type ChangeSet } from './ChangeSet.js';
6
- import { type Configuration } from '../utils/Configuration.js';
7
- import type { DriverMethodOptions, IDatabaseDriver } from '../drivers/IDatabaseDriver.js';
3
+ import type { DriverMethodOptions } from '../drivers/IDatabaseDriver.js';
4
+ import type { EntityManager } from '../EntityManager.js';
8
5
  export declare class ChangeSetPersister {
6
+ private readonly em;
7
+ private readonly platform;
8
+ private readonly comparator;
9
+ private readonly usesReturningStatement;
9
10
  private readonly driver;
10
11
  private readonly metadata;
11
12
  private readonly hydrator;
12
13
  private readonly factory;
13
- private readonly validator;
14
14
  private readonly config;
15
- private readonly platform;
16
- private readonly comparator;
17
- private readonly usesReturningStatement;
18
- constructor(driver: IDatabaseDriver, metadata: MetadataStorage, hydrator: IHydrator, factory: EntityFactory, validator: EntityValidator, config: Configuration);
15
+ constructor(em: EntityManager);
19
16
  executeInserts<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
20
17
  executeUpdates<T extends object>(changeSets: ChangeSet<T>[], batched: boolean, options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
21
18
  executeDeletes<T extends object>(changeSets: ChangeSet<T>[], options?: DriverMethodOptions, withSchema?: boolean): Promise<void>;
22
19
  private runForEachSchema;
20
+ private validateRequired;
23
21
  private processProperties;
24
22
  private persistNewEntity;
25
23
  private persistNewEntities;
26
- private propagateSchemaFromMetadata;
24
+ private prepareOptions;
27
25
  private persistNewEntitiesBatch;
28
26
  private persistManagedEntity;
29
27
  private persistManagedEntities;
@@ -42,6 +40,11 @@ export declare class ChangeSetPersister {
42
40
  * so we use a single query in case of both versioning and default values is used.
43
41
  */
44
42
  private reloadVersionValues;
43
+ /**
44
+ * For TPT child tables, resolve EntityIdentifier values in PK fields.
45
+ * The parent table insert assigns the actual PK value, which the child table references.
46
+ */
47
+ private resolveTPTIdentifiers;
45
48
  private processProperty;
46
49
  /**
47
50
  * Maps values returned via `returning` statement (postgres) or the inserted id (other sql drivers).