@sprucelabs/schema
Version:
Static and dynamic binding plus runtime validation and transformation to ensure your app is sound. 🤓
48 lines (47 loc) • 1.6 kB
JavaScript
export default function cloneDeep(obj, transformer) {
var _a;
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 === null || transformer === void 0 ? void 0 : 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] =
(_a = transformer === null || transformer === void 0 ? void 0 : transformer(o[key], key)) !== null && _a !== void 0 ? _a : 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('');
}
}