Superdiff provides a complete and readable diff for both arrays and objects. Plus, it supports stream and file inputs for handling large datasets efficiently, is battle-tested, has zero dependencies, and is super fast.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

3 lines
4.7 KiB

var u={ADDED:"added",EQUAL:"equal",DELETED:"deleted",UPDATED:"updated"},d={...u,MOVED:"moved"},y={BASIC:"basic",DEEP:"deep"};function a(e,t,f={ignoreArrayOrder:!1}){return typeof e!=typeof t?!1:Array.isArray(e)?e.length!==t.length?!1:f.ignoreArrayOrder?e.every(i=>t.some(n=>JSON.stringify(n)===JSON.stringify(i))):e.every((i,n)=>JSON.stringify(i)===JSON.stringify(t[n])):typeof e=="object"?JSON.stringify(e)===JSON.stringify(t):e===t}function p(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}function b(e,t={statuses:[],granularity:y.BASIC}){let{statuses:f,granularity:i}=t;return e.reduce((n,r)=>{if(i===y.DEEP&&r.subPropertiesDiff){let s=b(r.subPropertiesDiff,t);if(s.length>0)return [...n,{...r,subPropertiesDiff:s}]}if(i===y.DEEP&&r.subDiff){let s=b(r.subDiff,t);if(s.length>0)return [...n,{...r,subDiff:s}]}return f.includes(r.status)?[...n,r]:n},[])}function A(e){return e.some(t=>t.status!==u.EQUAL)?u.UPDATED:u.EQUAL}function j(e,t,f={ignoreArrayOrder:!1,showOnly:{statuses:[],granularity:y.BASIC}}){if(!e)return {type:"object",status:u.EQUAL,diff:[]};let i=[];return Object.entries(e).forEach(([n,r])=>{if(p(r)){let s=[];return Object.entries(r).forEach(([o,c])=>{s.push({property:o,previousValue:t===u.ADDED?void 0:c,currentValue:t===u.ADDED?c:void 0,status:t});}),i.push({property:n,previousValue:t===u.ADDED?void 0:e[n],currentValue:t===u.ADDED?r:void 0,status:t,subPropertiesDiff:s})}return i.push({property:n,previousValue:t===u.ADDED?void 0:e[n],currentValue:t===u.ADDED?r:void 0,status:t})}),f.showOnly&&f.showOnly.statuses.length>0?{type:"object",status:t,diff:b(i,f.showOnly)}:{type:"object",status:t,diff:i}}function U(e,t,f){if(!e)return;let i=Object.entries(e).find(([n])=>a(n,t,f));return i?i[1]:void 0}function g(e,t,f){return a(e,t,f)?u.EQUAL:u.UPDATED}function m(e){return e.some(t=>t.status!==u.EQUAL)?u.UPDATED:u.EQUAL}function S(e,t){if(!e)return;let f=Object.keys(e),i=Object.keys(t),n=f.filter(r=>!i.includes(r));if(n.length>0)return n.map(r=>({property:r,value:e[r]}))}function h(e,t,f){let i=[],n,r=S(e,t);return r&&r.forEach(s=>{i.push({property:s.property,previousValue:s.value,currentValue:void 0,status:u.DELETED});}),Object.entries(t).forEach(([s,o])=>{let c=U(e,s,f);if(!c)return i.push({property:s,previousValue:c,currentValue:o,status:!e||!(s in e)?u.ADDED:c===o?u.EQUAL:u.UPDATED});if(p(o)){let D=h(c,o,f);D&&D.length>0&&(n=D);}c&&i.push({property:s,previousValue:c,currentValue:o,status:g(c,o,f),...!!n&&{subDiff:n}});}),i}function w(e,t,f={ignoreArrayOrder:!1,showOnly:{statuses:[],granularity:y.BASIC}}){if(!e&&!t)return {type:"object",status:u.EQUAL,diff:[]};if(!e)return j(t,u.ADDED,f);if(!t)return j(e,u.DELETED,f);let i=[];Object.entries(t).forEach(([r,s])=>{let o=e[r];if(!o)return i.push({property:r,previousValue:o,currentValue:s,status:r in e?o===s?u.EQUAL:u.UPDATED:u.ADDED});if(p(s)){let c=h(o,s,f),D=m(c);return i.push({property:r,previousValue:o,currentValue:s,status:D,...D!==u.EQUAL&&{subPropertiesDiff:c}})}return i.push({property:r,previousValue:o,currentValue:s,status:g(o,s,f)})});let n=S(e,t);return n&&n.forEach(r=>{i.push({property:r.property,previousValue:r.value,currentValue:void 0,status:u.DELETED});}),f.showOnly&&f.showOnly.statuses.length>0?{type:"object",status:A(i),diff:b(i,f.showOnly)}:{type:"object",status:A(i),diff:i}}function I(e,t=[]){return e.filter(f=>t?.includes(f.status))}function L(e,t,f={showOnly:[]}){let i=e.map((n,r)=>({value:n,prevIndex:t===d.ADDED?null:r,newIndex:t===d.ADDED?r:null,indexDiff:null,status:t}));return f.showOnly&&f.showOnly.length>0?{type:"list",status:t,diff:i.filter(n=>f.showOnly?.includes(n.status))}:{type:"list",status:t,diff:i}}function T(e){return e.some(t=>t.status!==d.EQUAL)?d.UPDATED:d.EQUAL}function P(e,t){return p(e)&&t?Object.hasOwn(e,t):!1}var R=(e,t,f={showOnly:[],referenceProperty:void 0})=>{if(!e&&!t)return {type:"list",status:d.EQUAL,diff:[]};if(!e)return L(t,d.ADDED,f);if(!t)return L(e,d.DELETED,f);let i=[],n=[];return t.forEach((r,s)=>{let o=e.findIndex((D,E)=>P(D,f.referenceProperty)?p(r)?a(D[f.referenceProperty],r[f.referenceProperty])&&!n.includes(E):!1:a(D,r)&&!n.includes(E));o>-1&&n.push(o);let c=o===-1?null:s-o;if(c===0){let D=d.EQUAL;return P(r,f.referenceProperty)&&(a(e[o],r)||(D=d.UPDATED)),i.push({value:r,prevIndex:o,newIndex:s,indexDiff:c,status:D})}return o===-1?i.push({value:r,prevIndex:null,newIndex:s,indexDiff:c,status:d.ADDED}):i.push({value:r,prevIndex:o,newIndex:s,indexDiff:c,status:d.MOVED})}),e.forEach((r,s)=>{if(!n.includes(s))return i.splice(s,0,{value:r,prevIndex:s,newIndex:null,indexDiff:null,status:d.DELETED})}),f.showOnly&&f?.showOnly?.length>0?{type:"list",status:T(i),diff:I(i,f.showOnly)}:{type:"list",status:T(i),diff:i}};
export { R as getListDiff, w as getObjectDiff, a as isEqual, p as isObject };