summary refs log tree commit diff
path: root/src/util/imports/OrmUtils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/imports/OrmUtils.ts')
-rw-r--r--src/util/imports/OrmUtils.ts96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/util/imports/OrmUtils.ts b/src/util/imports/OrmUtils.ts
new file mode 100644
index 00000000..68a1932c
--- /dev/null
+++ b/src/util/imports/OrmUtils.ts
@@ -0,0 +1,96 @@
+//source: https://github.com/typeorm/typeorm/blob/master/src/util/OrmUtils.ts
+export class OrmUtils {
+	// Checks if it's an object made by Object.create(null), {} or new Object()
+	private static isPlainObject(item: any) {
+		if (item === null || item === undefined) {
+			return false;
+		}
+
+		return !item.constructor || item.constructor === Object;
+	}
+
+	private static mergeArrayKey(target: any, key: number, value: any, memo: Map<any, any>) {
+		// Have we seen this before?  Prevent infinite recursion.
+		if (memo.has(value)) {
+			target[key] = memo.get(value);
+			return;
+		}
+
+		if (value instanceof Promise) {
+			// Skip promises entirely.
+			// This is a hold-over from the old code & is because we don't want to pull in
+			// the lazy fields.  Ideally we'd remove these promises via another function first
+			// but for now we have to do it here.
+			return;
+		}
+
+		if (!this.isPlainObject(value) && !Array.isArray(value)) {
+			target[key] = value;
+			return;
+		}
+
+		if (!target[key]) {
+			target[key] = Array.isArray(value) ? [] : {};
+		}
+
+		memo.set(value, target[key]);
+		this.merge(target[key], value, memo);
+		memo.delete(value);
+	}
+
+	private static mergeObjectKey(target: any, key: string, value: any, memo: Map<any, any>) {
+		// Have we seen this before?  Prevent infinite recursion.
+		if (memo.has(value)) {
+			Object.assign(target, { [key]: memo.get(value) });
+			return;
+		}
+
+		if (value instanceof Promise) {
+			// Skip promises entirely.
+			// This is a hold-over from the old code & is because we don't want to pull in
+			// the lazy fields.  Ideally we'd remove these promises via another function first
+			// but for now we have to do it here.
+			return;
+		}
+
+		if (!this.isPlainObject(value) && !Array.isArray(value)) {
+			Object.assign(target, { [key]: value });
+			return;
+		}
+
+		if (!target[key]) {
+			Object.assign(target, { [key]: value });
+		}
+
+		memo.set(value, target[key]);
+		this.merge(target[key], value, memo);
+		memo.delete(value);
+	}
+
+	private static merge(target: any, source: any, memo: Map<any, any> = new Map()): any {
+		if (Array.isArray(target) && Array.isArray(source)) {
+			for (let key = 0; key < source.length; key++) {
+				this.mergeArrayKey(target, key, source[key], memo);
+			}
+		} else {
+			for (const key of Object.keys(source)) {
+				this.mergeObjectKey(target, key, source[key], memo);
+			}
+		}
+	}
+
+	/**
+	 * Deep Object.assign.
+	 */
+	static mergeDeep(target: any, ...sources: any[]): any {
+		if (!sources.length) {
+			return target;
+		}
+
+		for (const source of sources) {
+			OrmUtils.merge(target, source);
+		}
+
+		return target;
+	}
+}
\ No newline at end of file