UNPKG

deep-compare-by

Version:

Deep compare with a function

71 lines (70 loc) 2.29 kB
const sNoDefault = Symbol("No default"); const sFailPath = Symbol("Fail path"); const err = msg=>{ throw new Error(msg); }; const configSymbols = new Set([ sNoDefault, sFailPath ]); const cleanTests = tests=> Array.isArray(tests) ? tests : tests===null ? [] : typeof tests === "function" ? [tests] : err("Tests invalid"); const compare = ({ tests, a, b, failPath, noDefault }, path = []) => { tests = cleanTests(tests); const testsAdj = noDefault ? tests : [(a, b) => a === b, ...tests]; if (typeof a !== "object" || typeof b !== "object") { if (testsAdj.some(i => i(a, b))) { return true; } else { return failPath ? path : false; } } else if (testsAdj.some(i => i(a, b))) { return true; } else if (Object.keys(a) .length !== Object.keys(b) .length) { return failPath ? path : false; } else if (Object.keys(a) .length === 0) { return failPath ? path : false; } else { for (const k of Object.keys(a)) { if (k in b) { let res; if ((res = compare({ tests, a:a[k], b:b[k], failPath, noDefault }, path.concat([k]))) !== true) { return res; } } else { return failPath ? path : false; } } return true; } }; const makeCompare = (...args) => { const properArgs = args.filter(i => !configSymbols.has(i)); if (properArgs.length >= 3) { const configs = { tests: properArgs[0], a: properArgs[1], b: properArgs[2], failPath: args.includes(sFailPath), noDefault: args.includes(sNoDefault), }; return compare(configs); } else { const retFunc = (...newArgs) => makeCompare(...args, ...newArgs); retFunc.noDefault = (...newArgs) => makeCompare(...args, ...newArgs, sNoDefault); retFunc.failPath = (...newArgs) => makeCompare(...args, ...newArgs, sFailPath); retFunc.tests = () => cleanTests(properArgs[0]); retFunc.lhs = () => properArgs[1]; return retFunc; } }; module.exports = makeCompare();