UNPKG

differrer

Version:

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

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