2021-06-28 04:04:48 +02:00
|
|
|
import { assert } from "tsafe/assert";
|
|
|
|
import { is } from "tsafe/is";
|
2021-11-08 19:33:06 +01:00
|
|
|
import { deepClone } from "./deepClone";
|
2021-11-07 20:17:14 +01:00
|
|
|
|
2021-07-03 02:39:39 +02:00
|
|
|
//Warning: Be mindful that because of array this is not idempotent.
|
2021-10-12 00:26:29 +02:00
|
|
|
export function deepAssign(params: { target: Record<string, unknown>; source: Record<string, unknown> }) {
|
2021-11-07 20:17:14 +01:00
|
|
|
const { target } = params;
|
|
|
|
|
|
|
|
const source = deepClone(params.source);
|
2021-10-11 21:35:40 +02:00
|
|
|
|
|
|
|
Object.keys(source).forEach(key => {
|
|
|
|
var dereferencedSource = source[key];
|
|
|
|
|
2021-10-12 00:26:29 +02:00
|
|
|
if (target[key] === undefined || !(dereferencedSource instanceof Object)) {
|
2021-10-11 21:35:40 +02:00
|
|
|
Object.defineProperty(target, key, {
|
|
|
|
"enumerable": true,
|
|
|
|
"writable": true,
|
|
|
|
"configurable": true,
|
|
|
|
"value": dereferencedSource,
|
|
|
|
});
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const dereferencedTarget = target[key];
|
|
|
|
|
|
|
|
if (dereferencedSource instanceof Array) {
|
|
|
|
assert(is<unknown[]>(dereferencedTarget));
|
|
|
|
assert(is<unknown[]>(dereferencedSource));
|
|
|
|
|
|
|
|
dereferencedSource.forEach(entry => dereferencedTarget.push(entry));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(is<Record<string, unknown>>(dereferencedTarget));
|
|
|
|
assert(is<Record<string, unknown>>(dereferencedSource));
|
|
|
|
|
|
|
|
deepAssign({
|
|
|
|
"target": dereferencedTarget,
|
|
|
|
"source": dereferencedSource,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|