|
|
@@ -1,5 +1,6 @@
|
|
|
import { Injectable } from '@nestjs/common';
|
|
|
import { Type } from '@vendure/common/lib/shared-types';
|
|
|
+import { isObject } from '@vendure/common/lib/shared-utils';
|
|
|
import { unique } from '@vendure/common/lib/unique';
|
|
|
|
|
|
import { RequestContext } from '../../../api/common/request-context';
|
|
|
@@ -89,7 +90,7 @@ export class EntityHydrator {
|
|
|
});
|
|
|
const propertiesToAdd = unique(missingRelations.map(relation => relation.split('.')[0]));
|
|
|
for (const prop of propertiesToAdd) {
|
|
|
- (target as any)[prop] = (hydrated as any)[prop];
|
|
|
+ (target as any)[prop] = this.mergeDeep((target as any)[prop], (hydrated as any)[prop]);
|
|
|
}
|
|
|
|
|
|
const relationsWithEntities = missingRelations.map(relation => ({
|
|
|
@@ -241,4 +242,30 @@ export class EntityHydrator {
|
|
|
? input[0]?.hasOwnProperty('translations') ?? false
|
|
|
: input?.hasOwnProperty('translations') ?? false;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Merges properties into a target entity. This is needed for the cases in which a
|
|
|
+ * property already exists on the target, but the hydrated version also contains that
|
|
|
+ * property with a different set of properties. This prevents the original target
|
|
|
+ * entity from having data overwritten.
|
|
|
+ */
|
|
|
+ private mergeDeep<T extends { [key: string]: any }>(a: T | undefined, b: T): T {
|
|
|
+ if (!a) {
|
|
|
+ return b;
|
|
|
+ }
|
|
|
+ for (const [key, value] of Object.entries(b)) {
|
|
|
+ if (Object.getOwnPropertyDescriptor(b, key)?.writable) {
|
|
|
+ if (Array.isArray(value)) {
|
|
|
+ (a as any)[key] = value.map((v, index) =>
|
|
|
+ this.mergeDeep(a?.[key]?.[index], b[key][index]),
|
|
|
+ );
|
|
|
+ } else if (isObject(value)) {
|
|
|
+ (a as any)[key] = this.mergeDeep(a?.[key], b[key]);
|
|
|
+ } else {
|
|
|
+ (a as any)[key] = b[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return a ?? b;
|
|
|
+ }
|
|
|
}
|