@sprucelabs/schema
Version:
Static and dynamic binding plus runtime validation and transformation to ensure your app is sound. 🤓
50 lines (49 loc) • 1.53 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = cloneDeep;
function cloneDeep(obj, transformer) {
const o = obj;
let result = o;
let type = {}.toString.call(o).slice(8, -1);
if (type == 'Set') {
return new Set([...o].map((value) => cloneDeep(value, transformer)));
}
if (type == 'Map') {
const items = [];
[...o.entries()].forEach((kv) => {
if (transformer?.(kv[1], kv[0]) !== false) {
items.push([cloneDeep(kv[0]), cloneDeep(kv[1])]);
}
});
return new Map(items);
}
if (type == 'Date') {
return new Date(o.getTime());
}
if (type == 'RegExp') {
return RegExp(o.source, getRegExpFlags(o));
}
if (type == 'Array' || type == 'Object') {
result = Array.isArray(o) ? [] : {};
for (let key in o) {
result[key] =
transformer?.(o[key], key) ?? cloneDeep(o[key], transformer);
}
}
// primitives and non-supported objects (e.g. functions) land here
return result;
}
function getRegExpFlags(regExp) {
if (typeof regExp.source.flags == 'string') {
return regExp.source.flags;
}
else {
let flags = [];
regExp.global && flags.push('g');
regExp.ignoreCase && flags.push('i');
regExp.multiline && flags.push('m');
regExp.sticky && flags.push('y');
regExp.unicode && flags.push('u');
return flags.join('');
}
}