2021-06-28 04:04:48 +02:00
|
|
|
import { assert } from "tsafe/assert";
|
|
|
|
import { is } from "tsafe/is";
|
2024-06-02 00:24:07 +02:00
|
|
|
import { structuredCloneButFunctions } from "./structuredCloneButFunctions";
|
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.
|
2024-05-20 15:48:51 +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;
|
|
|
|
|
2024-06-02 00:24:07 +02:00
|
|
|
const source = structuredCloneButFunctions(params.source);
|
2021-10-11 21:35:40 +02:00
|
|
|
|
|
|
|
Object.keys(source).forEach(key => {
|
|
|
|
var dereferencedSource = source[key];
|
|
|
|
|
2024-05-20 15:48:51 +02:00
|
|
|
if (
|
|
|
|
target[key] === undefined ||
|
|
|
|
dereferencedSource instanceof Function ||
|
|
|
|
!(dereferencedSource instanceof Object)
|
|
|
|
) {
|
2021-10-11 21:35:40 +02:00
|
|
|
Object.defineProperty(target, key, {
|
2024-05-20 15:48:51 +02:00
|
|
|
enumerable: true,
|
|
|
|
writable: true,
|
|
|
|
configurable: true,
|
|
|
|
value: dereferencedSource
|
2021-10-11 21:35:40 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
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({
|
2024-05-20 15:48:51 +02:00
|
|
|
target: dereferencedTarget,
|
|
|
|
source: dereferencedSource
|
2021-10-11 21:35:40 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|