
* Add eslint, switch to lint-staged for precommit * Fix all ESLint errors * Update GH workflow to check prettier and eslint
114 lines
2.7 KiB
TypeScript
114 lines
2.7 KiB
TypeScript
// source: https://github.com/typeorm/typeorm/blob/master/src/util/OrmUtils.ts
|
|
// Copyright (c) 2015-2022 TypeORM. http://typeorm.github.io
|
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
// @fc-license-skip
|
|
export class OrmUtils {
|
|
// Checks if it's an object made by Object.create(null), {} or new Object()
|
|
private static isPlainObject(item: unknown) {
|
|
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;
|
|
}
|
|
}
|