UNPKG

differrer

Version:

> Utility to perform deep diff on any data types with smart order detection in arrays and different views implemented for convenience

292 lines (291 loc) 10.9 kB
const se = (e) => " ".repeat(e * 2), M = (e) => { const t = w(e); return t === "string" ? `'${e.replace(/'/g, "\\'")}'` : ["array", "object"].includes(t) ? JSON.stringify(e) : `${e}`; }, oe = (e) => typeof e == "number" || !e && e !== "" || typeof e != "string" ? "" : /[- ]/.test(e) || e === "" ? `'${e}': ` : `${e}: `, $e = (e) => { const t = (r, n, s = 0, c) => { let o = ""; const u = se(s), i = r || r === 0 ? "," : "", j = w(c); return n.children && (["object", "array"].includes(n.sourceType) || n.added) ? (Array.isArray(n.children) ? o += `[ ${n.children.map((y, h) => t(h, y, s + 1, n)).join(` `)} ${u}]${i}` : o += `{ ${Object.entries(n.children).map(([y, h]) => t(y, h, s + 1, n)).join(` `)} ${u}}${i}`, n.added ? o += " // +" : n.removed ? o += " // -" : n.changed && (o += n.targetType !== n.sourceType ? ` // ~ ${M(n.targetValue)}` : " // ~")) : (n.added ? o += j === "object" ? `${M(n.targetValue)}, // +` : `// + ${M(n.targetValue)}` : o += `${M(n.sourceValue)}${i}`, n.removed && (o += " // -"), !n.removed && !n.added && n.changed && (o += ` // ~ ${M(n.targetValue)}`)), `${u}${oe(r)}${o}`; }; return t(null, e, 0); }; const ce = (e) => " ".repeat(e * 2), le = (e) => { const t = w(e); return t === "string" ? `'${e.replace(/'/g, "\\'")}'` : ["array", "object"].includes(t) ? JSON.stringify(e) : `${e}`; }, ue = (e) => typeof e == "number" || !e && e !== "" || typeof e != "string" ? "" : /[- ]/.test(e) || e === "" ? `'${e}': ` : `${e}: `, ye = (e) => { const t = (r, n, s, c = 0, o, u) => { const i = r === "source" ? "added" : "removed", j = r === "source" ? "sourceValue" : "targetValue", y = r === "source" ? "sourceType" : "targetType", h = ce(c), E = n || n === 0 ? "," : ""; let p = ""; if (s[i] || u || s.children && !["array", "object"].includes(s[y])) { const g = s.children && !["array", "object", "undefined"].includes(s[y]) ? `${h}${s[j]}${E}` : ""; return s.children && (Array.isArray(s.children) ? p += `${g} ${s.children.map((m, V) => t(r, V, m, c + 1, s, u)).join(` `)} ` : p += `${g} ${Object.entries(s.children).map(([m, V]) => t(r, m, V, c + 1, s, u)).join(` `)} `), p; } return s.children ? Array.isArray(s.children) ? p += `[ ${s.children.map((g, m) => t(r, m, g, c + 1)).join(` `)} ${h}]${E}` : p += `{ ${Object.entries(s.children).map(([g, m]) => t(r, g, m, c + 1)).join(` `)} ${h}}${E}` : p += `${le(s[j])}${E}`, `${h}${ue(n)}${p}`; }; return { source: t("source", null, e, 0), target: t("target", null, e, 0) }; }, k = Symbol("CustomString"), I = (e, t, r) => { const n = t === void 0 ? e : t; return { length: e.length, rawValue: e, pretty: n, toString: () => n, search: (s) => e.search(s), padEnd: (s, c = " ") => { const o = e.padEnd(s, c), u = o.length - e.length, i = n.padEnd(n.length + u, c); return I(o, i, r); }, trimStart: () => { const s = e.trimStart(), c = n.trimStart(); return I(s, c, r); }, representedValue: r, type: k }; }, F = (e, t = "") => { const r = e.map((s) => typeof s == "string" ? s : s.rawValue).join(t), n = e.map((s) => typeof s == "string" ? s : s.pretty).join(t); return I(r, n); }, L = (e) => (e == null ? void 0 : e.type) === k, ee = 2, te = 0, U = 0, ae = typeof process < "u" && process.versions != null && process.versions.node != null, J = (e) => { if (ae && typeof require < "u") return I( require("util").inspect(e, { colors: !1 }), require("util").inspect(e, { colors: !0 }), e ); const t = typeof e == "string" ? `'${e.replace(/'/g, "\\'")}'` : `${e}`; return I( t, t, e ); }, z = (e, t = "") => { if (typeof e == "number") { const r = J(e); return F(["[", r, "]"]); } return !e && e !== "" || typeof e != "string" ? I("") : /[- ]/.test(e) || e === "" ? I(`${t}'${e}'`) : I(`${t}${e}`); }, ie = (e) => { let t = !1; return F(e.map((r) => typeof r == "number" ? (t = !1, z(r)) : t ? z(r, ".") : (t = !0, z(r)))); }, Q = (e) => " ".repeat((e && e - 1) * ee), x = (e) => e ? e[e.length - 1] : null, H = (e, t, r = 0) => e.reduce((n, s) => { let c; if (L(s)) c = t === null ? s.length : 0; else { const o = t !== null ? s[t] : null; c = t !== null && L(o) ? o.length : 0; } return c > n ? c : n; }, 0) + r, de = (e, t, r = 0) => { const n = /\S|$/; return e.reduce((s, c) => { let o; return L(c) ? o = t === null ? c.search(n) : 0 : o = t === null ? 0 : J(c[t]).search(n), o > s ? o : s; }, 0) + r; }, X = (e, t = 0) => { if (e.sameValue) return []; if (e.children) { const r = (Array.isArray(e.children) ? e.children.map((n, s) => [s, n]) : Object.entries(e.children)).flatMap(([, n]) => X(n, t + 1)); if (r.length > 0) { const n = e.retrievedId || x(e.sourcePath) || x(e.targetPath), s = H(r, 0, U + te * ee), c = H(r, 1, U), o = H(r, 2, U); return [ I(n ? `${Q(t)}${n}` : ""), ...r.map((u) => L(u) ? u : [u[0], u[1], u[2], s, c, o]) ]; } return []; } return [[ F([Q(t), ie(e.sourcePath || e.targetPath || [])]), J(e.sourceValue), J(e.targetValue) ]]; }, be = (e) => { const t = X(e), r = de(t, null, te); return t.map((n) => { if (L(n)) return n.pretty; { const [s, c, o, u, i, j] = n, y = F([Q(r + 1), s.trimStart()]).padEnd(u || 0), h = c.padEnd(i || 0), E = o.padEnd(j || 0); return `${y}: ${h} -> ${E}`; } }).join(` `); }, Ie = (e) => X(e).map((r) => { if (L(r)) return r.rawValue; { const [n, s, c] = r; return [n.rawValue, s.rawValue, c.rawValue]; } }).filter((r) => r), pe = (e) => e.sort( (t, r) => `${t}`.localeCompare(`${r}`, void 0, { numeric: !0 }) ), ge = (e) => ({ number: e.filter((t) => typeof t[1] == "number"), string: e.filter((t) => typeof t[1] == "string"), booleanTrue: e.filter((t) => t[1] === !0), booleanFalse: e.filter((t) => t[1] === !1), null: e.filter((t) => t[1] === null), undefined: e.filter((t) => t[1] === void 0), object: e.filter((t) => ne(t[1])), array: e.filter((t) => Array.isArray(t[1])) }), v = (e) => { const t = ge(e); return [ ...t.number.sort((r, n) => r[1] - n[1]), ...t.string.sort((r, n) => r[1].localeCompare(n[1], void 0, { numeric: !0 })), ...t.booleanTrue, ...t.booleanFalse, ...t.null, ...t.undefined, ...t.object, ...t.array ]; }, P = (e) => e.filter((t, r) => r === e.indexOf(t)), me = (e, t) => typeof e == "number" && typeof t == "number" ? e === t || e !== e && t !== t : e === t, ne = (e) => Object.prototype.toString.call(e) === "[object Object]" && (e.constructor === void 0 || Object.prototype.toString.call(e.constructor.prototype) === "[object Object]" && e.constructor.prototype.hasOwnProperty("isPrototypeOf")), w = (e) => { switch (!0) { case ne(e): return "object"; case Array.isArray(e): return "array"; case typeof e == "string": return "string"; case typeof e == "number": return "number"; case typeof e == "boolean": return "boolean"; case e === null: return "null"; case e === void 0: return "undefined"; default: return "unknown"; } }, he = (e) => (t, r, n) => { const s = e(t, r, n); return typeof s == "string" || typeof s == "number" ? s : null; }, je = ({ sortArrayItems: e = !1, getArrayElementId: t, getValue: r }) => (n, s) => { const c = he(t), o = (u = [], i = [], j = null, y = null, h, E) => { const p = r ? r(h, u) : h, g = r ? r(E, i) : E, m = w(p), V = w(g), $ = { sourcePath: u, targetPath: i, sourceValue: p, targetValue: g, sameValue: !0, sameValueZero: !0, retrievedId: null, sourceOrder: j, targetOrder: y, sameOrder: j === null && y === null ? null : j === y, sourceType: m, targetType: V, sameType: m === V, added: !1, removed: !1, changed: !1, children: null }; if (m === "object" || V === "object") { const Z = m === "object", q = V === "object", S = Z ? Object.keys(p) : null, f = q ? Object.keys(g) : null, D = P([...S || [], ...f || []]).reduce((G, N) => { const T = Z ? p[N] : void 0, C = q ? g[N] : void 0, _ = S ? S.indexOf(N) : -1, K = f ? f.indexOf(N) : -1, R = o( u ? [...u, N] : null, i ? [...i, N] : null, _ === -1 ? null : _, K === -1 ? null : K, T, C ); return $.sameValue = $.sameValue && R.sameValue, R.added = _ === -1, R.removed = K === -1, G[N] = R, G; }, {}); $.children = D; } else if (m === "array" || V === "array") { const Z = m === "array", q = V === "array", S = [], f = {}; (Z ? p : []).forEach((l, d) => { const a = ["object", "array"].includes(w(l)) ? c(l, u ? [...u, d] : null) : null; a || a === 0 || a === "" ? f[a] = [d, l] : S.push([d, l]); }); const W = [], D = {}; (q ? g : []).forEach((l, d) => { const a = ["object", "array"].includes(w(l)) ? c(l, i ? [...i, d] : null) : null; a || a === 0 || a === "" ? D[a] = [d, l] : W.push([d, l]); }); const N = pe(P([...Object.keys(f), ...Object.keys(D)])).map((l) => { const [d, a] = f[l] || [null, void 0], [O, A] = D[l] || [null, void 0], b = o( d === null || !u ? null : [...u, d], O === null || !i ? null : [...i, O], d, O, a, A ); return b.retrievedId = l, $.sameValue = $.sameValue && b.sameValue, b.added = Boolean(!f[l] && D[l]), b.removed = Boolean(f[l] && !D[l]), b; }), T = e ? v(S) : S, C = e ? v(W) : W, _ = T.reduce((l, [d], a) => ({ ...l, [d]: a }), {}), K = C.reduce((l, [d], a) => ({ ...l, [d]: a }), {}), R = Math.max(T.length, C.length), Y = [], re = (l, d, a, O) => d ? [l, l] : a[l] ? [l, K[a[l][0]]] : [_[O[l][0]], l]; Array(R).fill(null).forEach((l, d) => { const [a, O] = re(d, e, T, C), A = (a || a === 0) && T[a] || [null, void 0], b = (O || O === 0) && C[O] || [null, void 0], B = o( A[0] === null || !u ? null : [...u, A[0]], b[0] === null || !i ? null : [...i, b[0]], A[0], b[0], A[1], b[1] ); $.sameValue = $.sameValue && B.sameValue, B.added = A[0] === null && b[0] !== null, B.removed = A[0] !== null && b[0] === null, Y.push(B); }), $.children = [ ...N, ...Y ]; } else $.sameValue = p === g; return $.sameValueZero = me(p, g), $.changed = !$.sameValue, $; }; return o( [], [], null, null, n, s ); }; export { je as default, je as diff, be as diffChangesViewConsole, Ie as diffChangesViewRaw, $e as diffJsView, ye as diffSortedView, he as getArrayElementIdWrapper, w as getType, ne as isPlainObject };