MCPcopy Create free account
hub / github.com/mikro-orm/mikro-orm / mergeData

Method mergeData

packages/core/src/entity/EntityFactory.ts:220–330  ·  view source on GitHub ↗

Merges new data into an existing entity, preserving user-modified properties.

(
    meta: EntityMetadata<T>,
    entity: T,
    data: EntityData<T>,
    options: FactoryOptions = {},
  )

Source from the content-addressed store, hash-verified

218
219 /** Merges new data into an existing entity, preserving user-modified properties. */
220 mergeData<T extends object>(
221 meta: EntityMetadata<T>,
222 entity: T,
223 data: EntityData<T>,
224 options: FactoryOptions = {},
225 ): void {
226 // merge unchanged properties automatically
227 data = QueryHelper.processParams(data);
228 const existsData = this.#comparator.prepareEntity(entity);
229 const originalEntityData = helper(entity).__originalEntityData ?? ({} as EntityData<T>);
230 const diff = this.#comparator.diffEntities(meta.class, originalEntityData, existsData);
231
232 const diff2 = this.#comparator.diffEntities(meta.class, existsData, data, { includeInverseSides: true });
233
234 // do not override values changed by user; for uninitialized entities,
235 // the diff may include stale snapshot entries (value is undefined) — skip those
236 if (helper(entity).__initialized) {
237 Utils.keys(diff).forEach(key => delete diff2[key]);
238 } else {
239 Utils.keys(diff).forEach(key => {
240 if (diff[key] !== undefined) {
241 delete diff2[key];
242 }
243 });
244 }
245
246 Utils.keys(diff2)
247 .filter(key => {
248 // ignore null values if there is already present non-null value
249 if (existsData[key] != null) {
250 return diff2[key] == null;
251 }
252
253 return diff2[key] === undefined;
254 })
255 .forEach(key => delete diff2[key]);
256
257 // but always add collection properties, formulas, generated columns, version properties, and the
258 // user-declared STI discriminator if they are part of the `data`, as these are excluded from
259 // `comparableProps` and won't appear in the diff
260 Utils.keys(data)
261 .filter(
262 key =>
263 meta.properties[key]?.formula ||
264 meta.properties[key]?.version ||
265 (meta.properties[key]?.generated && !meta.properties[key]?.primary) ||
266 [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(meta.properties[key]?.kind) ||
267 (key === meta.root.discriminatorColumn && meta.properties[key]?.userDefined !== false),
268 )
269 .forEach(key => (diff2[key] = data[key]));
270
271 // rehydrated with the new values, skip those changed by user
272 // use full hydration if the entity is already initialized, even if the caller used `initialized: false`
273 // (e.g. from createReference), otherwise scalar properties in diff2 won't be applied
274 const initialized = options.initialized || helper(entity).__initialized;
275 this.hydrate(entity, meta, diff2, initialized ? { ...options, initialized } : options);
276
277 // we need to update the entity data only with keys that were not present before

Callers 3

createMethod · 0.95
upsertMethod · 0.80
upsertManyMethod · 0.80

Calls 15

hydrateMethod · 0.95
createMethod · 0.95
helperFunction · 0.85
processParamsMethod · 0.80
prepareEntityMethod · 0.80
diffEntitiesMethod · 0.80
filterMethod · 0.80
isPlainObjectMethod · 0.80
addMethod · 0.80
normalizeEntityDataMethod · 0.80
getMethod · 0.65
getPrimaryKeyMethod · 0.65

Tested by

no test coverage detected