5 changed files with 69 additions and 620 deletions
@ -1,314 +1,8 @@ |
|||||||
'use strict'; |
'use strict'; |
||||||
|
|
||||||
// src/model.ts
|
var i={ADDED:"added",EQUAL:"equal",MOVED:"moved",DELETED:"deleted",UPDATED:"updated"};function a(e,t,n={discardArrayOrder:!1}){return typeof e!=typeof t?!1:Array.isArray(e)?e.length!==t.length?!1:n.discardArrayOrder?e.every(r=>t.some(f=>JSON.stringify(f)===JSON.stringify(r))):e.every((r,f)=>JSON.stringify(r)===JSON.stringify(t[f])):typeof e=="object"?JSON.stringify(e)===JSON.stringify(t):e===t}function d(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}function A(e){return e.some(t=>t.status!==i.EQUAL)?i.UPDATED:i.EQUAL}function l(e,t){if(!e)return {type:"object",status:i.isEqual,diff:[]};let n=[];return Object.entries(e).forEach(([r,f])=>{if(d(f)){let u=[];return Object.entries(f).forEach(([s,o])=>{u.push({name:s,previousValue:t===i.ADDED?void 0:o,currentValue:t===i.ADDED?o:void 0,status:t});}),n.push({property:r,previousValue:t===i.ADDED?void 0:e[r],currentValue:t===i.ADDED?f:void 0,status:t,subPropertiesDiff:u})}return n.push({property:r,previousValue:t===i.ADDED?void 0:e[r],currentValue:t===i.ADDED?f:void 0,status:t})}),{type:"object",status:t,diff:n}}function S(e,t,n){if(!e)return;let r=Object.entries(e).find(([f])=>a(f,t,n));return r?r[1]:void 0}function E(e,t,n){return a(e,t,n)?i.EQUAL:i.UPDATED}function j(e){return e.some(t=>t.status!==i.EQUAL)?i.UPDATED:i.EQUAL}function y(e,t){if(!e)return;let n=Object.keys(e),r=Object.keys(t),f=n.filter(u=>!r.includes(u));if(f.length>0)return f.map(u=>({property:u,value:e[u]}))}function O(e,t,n){let r=[],f,u=y(e,t);return u&&u.forEach(s=>{r.push({name:s.property,previousValue:s.value,currentValue:void 0,status:i.DELETED});}),Object.entries(t).forEach(([s,o])=>{let D=S(e,s,n);if(!D&&!!s)return r.push({name:s,previousValue:void 0,currentValue:o,status:i.ADDED});if(d(o)){let c=O(D,o,n);c&&c.length>0&&(f=c);}D&&r.push({name:s,previousValue:D,currentValue:o,status:E(D,o,n),...!!f&&{subDiff:f}});}),r}function g(e,t,n){if(!e&&!t)return {type:"object",status:i.EQUAL,diff:[]};if(!e)return l(t,i.ADDED);if(!t)return l(e,i.DELETED);let r=[];Object.entries(t).forEach(([u,s])=>{let o=e[u];if(!o)return r.push({property:u,previousValue:void 0,currentValue:s,status:i.ADDED});if(d(s)){let D=O(o,s,n);return r.push({property:u,previousValue:o,currentValue:s,status:j(D),subPropertiesDiff:D})}return r.push({property:u,previousValue:o,currentValue:s,status:E(o,s,n)})});let f=y(e,t);return f&&f.forEach(u=>{r.push({property:u.property,previousValue:u.value,currentValue:void 0,status:i.DELETED});}),{type:"object",status:A(r),diff:r}}function b(e,t){return {type:"list",status:t,diff:e.map((n,r)=>({value:n,prevIndex:t===i.ADDED?null:r,newIndex:t===i.ADDED?r:null,indexDiff:null,status:t}))}}function m(e){return e.some(t=>t.status!==i.EQUAL)?i.UPDATED:i.EQUAL}var L=(e,t)=>{if(!e&&!t)return {type:"list",status:i.EQUAL,diff:[]};if(!e)return b(t,i.ADDED);if(!t)return b(e,i.DELETED);let n=[];return t.forEach((r,f)=>{let u=e.findIndex(o=>a(o,r)),s=u===-1?null:f-u;return s===0?n.push({value:r,prevIndex:u,newIndex:f,indexDiff:s,status:i.EQUAL}):u===-1?n.push({value:r,prevIndex:null,newIndex:f,indexDiff:s,status:i.ADDED}):n.push({value:r,prevIndex:u,newIndex:f,indexDiff:s,status:i.MOVED})}),e.forEach((r,f)=>{if(!t.some(u=>a(u,r)))return n.splice(f,0,{value:r,prevIndex:f,newIndex:null,indexDiff:null,status:i.DELETED})}),{type:"list",status:m(n),diff:n}}; |
||||||
var STATUS = { |
|
||||||
ADDED: "added", |
|
||||||
EQUAL: "equal", |
|
||||||
MOVED: "moved", |
|
||||||
DELETED: "deleted", |
|
||||||
UPDATED: "updated" |
|
||||||
}; |
|
||||||
|
|
||||||
// src/utils.ts
|
exports.getListDiff = L; |
||||||
function isEqual(a, b, options = { discardArrayOrder: false }) { |
exports.getObjectDiff = g; |
||||||
if (typeof a !== typeof b) |
exports.isEqual = a; |
||||||
return false; |
exports.isObject = d; |
||||||
if (Array.isArray(a)) { |
|
||||||
if (a.length !== b.length) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
if (options.discardArrayOrder) { |
|
||||||
return a.every( |
|
||||||
(v) => b.some((nextV) => JSON.stringify(nextV) === JSON.stringify(v)) |
|
||||||
); |
|
||||||
} |
|
||||||
return a.every((v, i) => JSON.stringify(v) === JSON.stringify(b[i])); |
|
||||||
} |
|
||||||
if (typeof a === "object") { |
|
||||||
return JSON.stringify(a) === JSON.stringify(b); |
|
||||||
} |
|
||||||
return a === b; |
|
||||||
} |
|
||||||
function isObject(value) { |
|
||||||
return !!value && typeof value === "object" && !Array.isArray(value); |
|
||||||
} |
|
||||||
|
|
||||||
// src/object-diff.ts
|
|
||||||
function getObjectStatus(diff) { |
|
||||||
return diff.some((property) => property.status !== STATUS.EQUAL) ? STATUS.UPDATED : STATUS.EQUAL; |
|
||||||
} |
|
||||||
function formatSingleObjectDiff(data, status) { |
|
||||||
if (!data) { |
|
||||||
return { |
|
||||||
type: "object", |
|
||||||
status: STATUS.isEqual, |
|
||||||
diff: [] |
|
||||||
}; |
|
||||||
} |
|
||||||
const diff = []; |
|
||||||
Object.entries(data).forEach(([property, value]) => { |
|
||||||
if (isObject(value)) { |
|
||||||
const subPropertiesDiff = []; |
|
||||||
Object.entries(value).forEach(([subProperty, subValue]) => { |
|
||||||
subPropertiesDiff.push({ |
|
||||||
name: subProperty, |
|
||||||
previousValue: status === STATUS.ADDED ? void 0 : subValue, |
|
||||||
currentValue: status === STATUS.ADDED ? subValue : void 0, |
|
||||||
status |
|
||||||
}); |
|
||||||
}); |
|
||||||
return diff.push({ |
|
||||||
property, |
|
||||||
previousValue: status === STATUS.ADDED ? void 0 : data[property], |
|
||||||
currentValue: status === STATUS.ADDED ? value : void 0, |
|
||||||
status, |
|
||||||
subPropertiesDiff |
|
||||||
}); |
|
||||||
} |
|
||||||
return diff.push({ |
|
||||||
property, |
|
||||||
previousValue: status === STATUS.ADDED ? void 0 : data[property], |
|
||||||
currentValue: status === STATUS.ADDED ? value : void 0, |
|
||||||
status |
|
||||||
}); |
|
||||||
}); |
|
||||||
return { |
|
||||||
type: "object", |
|
||||||
status, |
|
||||||
diff |
|
||||||
}; |
|
||||||
} |
|
||||||
function getPreviousMatch(previousValue, nextSubProperty, options) { |
|
||||||
if (!previousValue) { |
|
||||||
return void 0; |
|
||||||
} |
|
||||||
const previousMatch = Object.entries(previousValue).find( |
|
||||||
([subPreviousKey]) => isEqual(subPreviousKey, nextSubProperty, options) |
|
||||||
); |
|
||||||
return previousMatch ? previousMatch[1] : void 0; |
|
||||||
} |
|
||||||
function getValueStatus(previousValue, nextValue, options) { |
|
||||||
if (isEqual(previousValue, nextValue, options)) { |
|
||||||
return STATUS.EQUAL; |
|
||||||
} |
|
||||||
return STATUS.UPDATED; |
|
||||||
} |
|
||||||
function getPropertyStatus(subPropertiesDiff) { |
|
||||||
return subPropertiesDiff.some((property) => property.status !== STATUS.EQUAL) ? STATUS.UPDATED : STATUS.EQUAL; |
|
||||||
} |
|
||||||
function getDeletedProperties(previousValue, nextValue) { |
|
||||||
if (!previousValue) |
|
||||||
return void 0; |
|
||||||
const prevKeys = Object.keys(previousValue); |
|
||||||
const nextKeys = Object.keys(nextValue); |
|
||||||
const deletedKeys = prevKeys.filter((prevKey) => !nextKeys.includes(prevKey)); |
|
||||||
if (deletedKeys.length > 0) { |
|
||||||
return deletedKeys.map((deletedKey) => ({ |
|
||||||
property: deletedKey, |
|
||||||
value: previousValue[deletedKey] |
|
||||||
})); |
|
||||||
} |
|
||||||
return void 0; |
|
||||||
} |
|
||||||
function getSubPropertiesDiff(previousValue, nextValue, options) { |
|
||||||
const subPropertiesDiff = []; |
|
||||||
let subDiff; |
|
||||||
const deletedMainSubProperties = getDeletedProperties( |
|
||||||
previousValue, |
|
||||||
nextValue |
|
||||||
); |
|
||||||
if (deletedMainSubProperties) { |
|
||||||
deletedMainSubProperties.forEach((deletedProperty) => { |
|
||||||
subPropertiesDiff.push({ |
|
||||||
name: deletedProperty.property, |
|
||||||
previousValue: deletedProperty.value, |
|
||||||
currentValue: void 0, |
|
||||||
status: STATUS.DELETED |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
Object.entries(nextValue).forEach(([nextSubProperty, nextSubValue]) => { |
|
||||||
const previousMatch = getPreviousMatch( |
|
||||||
previousValue, |
|
||||||
nextSubProperty, |
|
||||||
options |
|
||||||
); |
|
||||||
if (!!!previousMatch && !!nextSubProperty) { |
|
||||||
return subPropertiesDiff.push({ |
|
||||||
name: nextSubProperty, |
|
||||||
previousValue: void 0, |
|
||||||
currentValue: nextSubValue, |
|
||||||
status: STATUS.ADDED |
|
||||||
}); |
|
||||||
} |
|
||||||
if (isObject(nextSubValue)) { |
|
||||||
const data = getSubPropertiesDiff( |
|
||||||
previousMatch, |
|
||||||
nextSubValue, |
|
||||||
options |
|
||||||
); |
|
||||||
if (data && data.length > 0) { |
|
||||||
subDiff = data; |
|
||||||
} |
|
||||||
} |
|
||||||
if (previousMatch) { |
|
||||||
subPropertiesDiff.push({ |
|
||||||
name: nextSubProperty, |
|
||||||
previousValue: previousMatch, |
|
||||||
currentValue: nextSubValue, |
|
||||||
status: getValueStatus(previousMatch, nextSubValue, options), |
|
||||||
...!!subDiff && { subDiff } |
|
||||||
}); |
|
||||||
} |
|
||||||
}); |
|
||||||
return subPropertiesDiff; |
|
||||||
} |
|
||||||
function getObjectDiff(prevData, nextData, options) { |
|
||||||
if (!prevData && !nextData) { |
|
||||||
return { |
|
||||||
type: "object", |
|
||||||
status: STATUS.EQUAL, |
|
||||||
diff: [] |
|
||||||
}; |
|
||||||
} |
|
||||||
if (!prevData) { |
|
||||||
return formatSingleObjectDiff(nextData, STATUS.ADDED); |
|
||||||
} |
|
||||||
if (!nextData) { |
|
||||||
return formatSingleObjectDiff(prevData, STATUS.DELETED); |
|
||||||
} |
|
||||||
const diff = []; |
|
||||||
Object.entries(nextData).forEach(([nextProperty, nextValue]) => { |
|
||||||
const previousValue = prevData[nextProperty]; |
|
||||||
if (!!!previousValue) { |
|
||||||
return diff.push({ |
|
||||||
property: nextProperty, |
|
||||||
previousValue: void 0, |
|
||||||
currentValue: nextValue, |
|
||||||
status: STATUS.ADDED |
|
||||||
}); |
|
||||||
} |
|
||||||
if (isObject(nextValue)) { |
|
||||||
const subPropertiesDiff = getSubPropertiesDiff( |
|
||||||
previousValue, |
|
||||||
nextValue, |
|
||||||
options |
|
||||||
); |
|
||||||
return diff.push({ |
|
||||||
property: nextProperty, |
|
||||||
previousValue, |
|
||||||
currentValue: nextValue, |
|
||||||
status: getPropertyStatus(subPropertiesDiff), |
|
||||||
subPropertiesDiff |
|
||||||
}); |
|
||||||
} |
|
||||||
return diff.push({ |
|
||||||
property: nextProperty, |
|
||||||
previousValue, |
|
||||||
currentValue: nextValue, |
|
||||||
status: getValueStatus(previousValue, nextValue, options) |
|
||||||
}); |
|
||||||
}); |
|
||||||
const deletedProperties = getDeletedProperties(prevData, nextData); |
|
||||||
if (deletedProperties) { |
|
||||||
deletedProperties.forEach((deletedProperty) => { |
|
||||||
diff.push({ |
|
||||||
property: deletedProperty.property, |
|
||||||
previousValue: deletedProperty.value, |
|
||||||
currentValue: void 0, |
|
||||||
status: STATUS.DELETED |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
return { |
|
||||||
type: "object", |
|
||||||
status: getObjectStatus(diff), |
|
||||||
diff |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
// src/list-diff.ts
|
|
||||||
function formatSingleListDiff(listData, status) { |
|
||||||
return { |
|
||||||
type: "list", |
|
||||||
status, |
|
||||||
diff: listData.map((data, i) => ({ |
|
||||||
value: data, |
|
||||||
prevIndex: status === STATUS.ADDED ? null : i, |
|
||||||
newIndex: status === STATUS.ADDED ? i : null, |
|
||||||
indexDiff: null, |
|
||||||
status |
|
||||||
})) |
|
||||||
}; |
|
||||||
} |
|
||||||
function getListStatus(listDiff) { |
|
||||||
return listDiff.some((value) => value.status !== STATUS.EQUAL) ? STATUS.UPDATED : STATUS.EQUAL; |
|
||||||
} |
|
||||||
var getListDiff = (prevList, nextList) => { |
|
||||||
if (!prevList && !nextList) { |
|
||||||
return { |
|
||||||
type: "list", |
|
||||||
status: STATUS.EQUAL, |
|
||||||
diff: [] |
|
||||||
}; |
|
||||||
} |
|
||||||
if (!prevList) { |
|
||||||
return formatSingleListDiff(nextList, STATUS.ADDED); |
|
||||||
} |
|
||||||
if (!nextList) { |
|
||||||
return formatSingleListDiff(prevList, STATUS.DELETED); |
|
||||||
} |
|
||||||
const diff = []; |
|
||||||
nextList.forEach((nextValue, i) => { |
|
||||||
const prevIndex = prevList.findIndex( |
|
||||||
(prevValue) => isEqual(prevValue, nextValue) |
|
||||||
); |
|
||||||
const indexDiff = prevIndex === -1 ? null : i - prevIndex; |
|
||||||
if (indexDiff === 0) { |
|
||||||
return diff.push({ |
|
||||||
value: nextValue, |
|
||||||
prevIndex, |
|
||||||
newIndex: i, |
|
||||||
indexDiff, |
|
||||||
status: STATUS.EQUAL |
|
||||||
}); |
|
||||||
} |
|
||||||
if (prevIndex === -1) { |
|
||||||
return diff.push({ |
|
||||||
value: nextValue, |
|
||||||
prevIndex: null, |
|
||||||
newIndex: i, |
|
||||||
indexDiff, |
|
||||||
status: STATUS.ADDED |
|
||||||
}); |
|
||||||
} |
|
||||||
return diff.push({ |
|
||||||
value: nextValue, |
|
||||||
prevIndex, |
|
||||||
newIndex: i, |
|
||||||
indexDiff, |
|
||||||
status: STATUS.MOVED |
|
||||||
}); |
|
||||||
}); |
|
||||||
prevList.forEach((prevValue, i) => { |
|
||||||
if (!nextList.some((nextValue) => isEqual(nextValue, prevValue))) { |
|
||||||
return diff.splice(i, 0, { |
|
||||||
value: prevValue, |
|
||||||
prevIndex: i, |
|
||||||
newIndex: null, |
|
||||||
indexDiff: null, |
|
||||||
status: STATUS.DELETED |
|
||||||
}); |
|
||||||
} |
|
||||||
}); |
|
||||||
return { |
|
||||||
type: "list", |
|
||||||
status: getListStatus(diff), |
|
||||||
diff |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
exports.getListDiff = getListDiff; |
|
||||||
exports.getObjectDiff = getObjectDiff; |
|
||||||
exports.isEqual = isEqual; |
|
||||||
exports.isObject = isObject; |
|
||||||
|
@ -1,309 +1,3 @@ |
|||||||
// src/model.ts
|
var i={ADDED:"added",EQUAL:"equal",MOVED:"moved",DELETED:"deleted",UPDATED:"updated"};function a(e,t,n={discardArrayOrder:!1}){return typeof e!=typeof t?!1:Array.isArray(e)?e.length!==t.length?!1:n.discardArrayOrder?e.every(r=>t.some(f=>JSON.stringify(f)===JSON.stringify(r))):e.every((r,f)=>JSON.stringify(r)===JSON.stringify(t[f])):typeof e=="object"?JSON.stringify(e)===JSON.stringify(t):e===t}function d(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}function S(e){return e.some(t=>t.status!==i.EQUAL)?i.UPDATED:i.EQUAL}function E(e,t){if(!e)return {type:"object",status:i.isEqual,diff:[]};let n=[];return Object.entries(e).forEach(([r,f])=>{if(d(f)){let u=[];return Object.entries(f).forEach(([s,o])=>{u.push({name:s,previousValue:t===i.ADDED?void 0:o,currentValue:t===i.ADDED?o:void 0,status:t});}),n.push({property:r,previousValue:t===i.ADDED?void 0:e[r],currentValue:t===i.ADDED?f:void 0,status:t,subPropertiesDiff:u})}return n.push({property:r,previousValue:t===i.ADDED?void 0:e[r],currentValue:t===i.ADDED?f:void 0,status:t})}),{type:"object",status:t,diff:n}}function j(e,t,n){if(!e)return;let r=Object.entries(e).find(([f])=>a(f,t,n));return r?r[1]:void 0}function y(e,t,n){return a(e,t,n)?i.EQUAL:i.UPDATED}function g(e){return e.some(t=>t.status!==i.EQUAL)?i.UPDATED:i.EQUAL}function O(e,t){if(!e)return;let n=Object.keys(e),r=Object.keys(t),f=n.filter(u=>!r.includes(u));if(f.length>0)return f.map(u=>({property:u,value:e[u]}))}function b(e,t,n){let r=[],f,u=O(e,t);return u&&u.forEach(s=>{r.push({name:s.property,previousValue:s.value,currentValue:void 0,status:i.DELETED});}),Object.entries(t).forEach(([s,o])=>{let D=j(e,s,n);if(!D&&!!s)return r.push({name:s,previousValue:void 0,currentValue:o,status:i.ADDED});if(d(o)){let l=b(D,o,n);l&&l.length>0&&(f=l);}D&&r.push({name:s,previousValue:D,currentValue:o,status:y(D,o,n),...!!f&&{subDiff:f}});}),r}function m(e,t,n){if(!e&&!t)return {type:"object",status:i.EQUAL,diff:[]};if(!e)return E(t,i.ADDED);if(!t)return E(e,i.DELETED);let r=[];Object.entries(t).forEach(([u,s])=>{let o=e[u];if(!o)return r.push({property:u,previousValue:void 0,currentValue:s,status:i.ADDED});if(d(s)){let D=b(o,s,n);return r.push({property:u,previousValue:o,currentValue:s,status:g(D),subPropertiesDiff:D})}return r.push({property:u,previousValue:o,currentValue:s,status:y(o,s,n)})});let f=O(e,t);return f&&f.forEach(u=>{r.push({property:u.property,previousValue:u.value,currentValue:void 0,status:i.DELETED});}),{type:"object",status:S(r),diff:r}}function A(e,t){return {type:"list",status:t,diff:e.map((n,r)=>({value:n,prevIndex:t===i.ADDED?null:r,newIndex:t===i.ADDED?r:null,indexDiff:null,status:t}))}}function L(e){return e.some(t=>t.status!==i.EQUAL)?i.UPDATED:i.EQUAL}var h=(e,t)=>{if(!e&&!t)return {type:"list",status:i.EQUAL,diff:[]};if(!e)return A(t,i.ADDED);if(!t)return A(e,i.DELETED);let n=[];return t.forEach((r,f)=>{let u=e.findIndex(o=>a(o,r)),s=u===-1?null:f-u;return s===0?n.push({value:r,prevIndex:u,newIndex:f,indexDiff:s,status:i.EQUAL}):u===-1?n.push({value:r,prevIndex:null,newIndex:f,indexDiff:s,status:i.ADDED}):n.push({value:r,prevIndex:u,newIndex:f,indexDiff:s,status:i.MOVED})}),e.forEach((r,f)=>{if(!t.some(u=>a(u,r)))return n.splice(f,0,{value:r,prevIndex:f,newIndex:null,indexDiff:null,status:i.DELETED})}),{type:"list",status:L(n),diff:n}}; |
||||||
var STATUS = { |
|
||||||
ADDED: "added", |
|
||||||
EQUAL: "equal", |
|
||||||
MOVED: "moved", |
|
||||||
DELETED: "deleted", |
|
||||||
UPDATED: "updated" |
|
||||||
}; |
|
||||||
|
|
||||||
// src/utils.ts
|
export { h as getListDiff, m as getObjectDiff, a as isEqual, d as isObject }; |
||||||
function isEqual(a, b, options = { discardArrayOrder: false }) { |
|
||||||
if (typeof a !== typeof b) |
|
||||||
return false; |
|
||||||
if (Array.isArray(a)) { |
|
||||||
if (a.length !== b.length) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
if (options.discardArrayOrder) { |
|
||||||
return a.every( |
|
||||||
(v) => b.some((nextV) => JSON.stringify(nextV) === JSON.stringify(v)) |
|
||||||
); |
|
||||||
} |
|
||||||
return a.every((v, i) => JSON.stringify(v) === JSON.stringify(b[i])); |
|
||||||
} |
|
||||||
if (typeof a === "object") { |
|
||||||
return JSON.stringify(a) === JSON.stringify(b); |
|
||||||
} |
|
||||||
return a === b; |
|
||||||
} |
|
||||||
function isObject(value) { |
|
||||||
return !!value && typeof value === "object" && !Array.isArray(value); |
|
||||||
} |
|
||||||
|
|
||||||
// src/object-diff.ts
|
|
||||||
function getObjectStatus(diff) { |
|
||||||
return diff.some((property) => property.status !== STATUS.EQUAL) ? STATUS.UPDATED : STATUS.EQUAL; |
|
||||||
} |
|
||||||
function formatSingleObjectDiff(data, status) { |
|
||||||
if (!data) { |
|
||||||
return { |
|
||||||
type: "object", |
|
||||||
status: STATUS.isEqual, |
|
||||||
diff: [] |
|
||||||
}; |
|
||||||
} |
|
||||||
const diff = []; |
|
||||||
Object.entries(data).forEach(([property, value]) => { |
|
||||||
if (isObject(value)) { |
|
||||||
const subPropertiesDiff = []; |
|
||||||
Object.entries(value).forEach(([subProperty, subValue]) => { |
|
||||||
subPropertiesDiff.push({ |
|
||||||
name: subProperty, |
|
||||||
previousValue: status === STATUS.ADDED ? void 0 : subValue, |
|
||||||
currentValue: status === STATUS.ADDED ? subValue : void 0, |
|
||||||
status |
|
||||||
}); |
|
||||||
}); |
|
||||||
return diff.push({ |
|
||||||
property, |
|
||||||
previousValue: status === STATUS.ADDED ? void 0 : data[property], |
|
||||||
currentValue: status === STATUS.ADDED ? value : void 0, |
|
||||||
status, |
|
||||||
subPropertiesDiff |
|
||||||
}); |
|
||||||
} |
|
||||||
return diff.push({ |
|
||||||
property, |
|
||||||
previousValue: status === STATUS.ADDED ? void 0 : data[property], |
|
||||||
currentValue: status === STATUS.ADDED ? value : void 0, |
|
||||||
status |
|
||||||
}); |
|
||||||
}); |
|
||||||
return { |
|
||||||
type: "object", |
|
||||||
status, |
|
||||||
diff |
|
||||||
}; |
|
||||||
} |
|
||||||
function getPreviousMatch(previousValue, nextSubProperty, options) { |
|
||||||
if (!previousValue) { |
|
||||||
return void 0; |
|
||||||
} |
|
||||||
const previousMatch = Object.entries(previousValue).find( |
|
||||||
([subPreviousKey]) => isEqual(subPreviousKey, nextSubProperty, options) |
|
||||||
); |
|
||||||
return previousMatch ? previousMatch[1] : void 0; |
|
||||||
} |
|
||||||
function getValueStatus(previousValue, nextValue, options) { |
|
||||||
if (isEqual(previousValue, nextValue, options)) { |
|
||||||
return STATUS.EQUAL; |
|
||||||
} |
|
||||||
return STATUS.UPDATED; |
|
||||||
} |
|
||||||
function getPropertyStatus(subPropertiesDiff) { |
|
||||||
return subPropertiesDiff.some((property) => property.status !== STATUS.EQUAL) ? STATUS.UPDATED : STATUS.EQUAL; |
|
||||||
} |
|
||||||
function getDeletedProperties(previousValue, nextValue) { |
|
||||||
if (!previousValue) |
|
||||||
return void 0; |
|
||||||
const prevKeys = Object.keys(previousValue); |
|
||||||
const nextKeys = Object.keys(nextValue); |
|
||||||
const deletedKeys = prevKeys.filter((prevKey) => !nextKeys.includes(prevKey)); |
|
||||||
if (deletedKeys.length > 0) { |
|
||||||
return deletedKeys.map((deletedKey) => ({ |
|
||||||
property: deletedKey, |
|
||||||
value: previousValue[deletedKey] |
|
||||||
})); |
|
||||||
} |
|
||||||
return void 0; |
|
||||||
} |
|
||||||
function getSubPropertiesDiff(previousValue, nextValue, options) { |
|
||||||
const subPropertiesDiff = []; |
|
||||||
let subDiff; |
|
||||||
const deletedMainSubProperties = getDeletedProperties( |
|
||||||
previousValue, |
|
||||||
nextValue |
|
||||||
); |
|
||||||
if (deletedMainSubProperties) { |
|
||||||
deletedMainSubProperties.forEach((deletedProperty) => { |
|
||||||
subPropertiesDiff.push({ |
|
||||||
name: deletedProperty.property, |
|
||||||
previousValue: deletedProperty.value, |
|
||||||
currentValue: void 0, |
|
||||||
status: STATUS.DELETED |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
Object.entries(nextValue).forEach(([nextSubProperty, nextSubValue]) => { |
|
||||||
const previousMatch = getPreviousMatch( |
|
||||||
previousValue, |
|
||||||
nextSubProperty, |
|
||||||
options |
|
||||||
); |
|
||||||
if (!!!previousMatch && !!nextSubProperty) { |
|
||||||
return subPropertiesDiff.push({ |
|
||||||
name: nextSubProperty, |
|
||||||
previousValue: void 0, |
|
||||||
currentValue: nextSubValue, |
|
||||||
status: STATUS.ADDED |
|
||||||
}); |
|
||||||
} |
|
||||||
if (isObject(nextSubValue)) { |
|
||||||
const data = getSubPropertiesDiff( |
|
||||||
previousMatch, |
|
||||||
nextSubValue, |
|
||||||
options |
|
||||||
); |
|
||||||
if (data && data.length > 0) { |
|
||||||
subDiff = data; |
|
||||||
} |
|
||||||
} |
|
||||||
if (previousMatch) { |
|
||||||
subPropertiesDiff.push({ |
|
||||||
name: nextSubProperty, |
|
||||||
previousValue: previousMatch, |
|
||||||
currentValue: nextSubValue, |
|
||||||
status: getValueStatus(previousMatch, nextSubValue, options), |
|
||||||
...!!subDiff && { subDiff } |
|
||||||
}); |
|
||||||
} |
|
||||||
}); |
|
||||||
return subPropertiesDiff; |
|
||||||
} |
|
||||||
function getObjectDiff(prevData, nextData, options) { |
|
||||||
if (!prevData && !nextData) { |
|
||||||
return { |
|
||||||
type: "object", |
|
||||||
status: STATUS.EQUAL, |
|
||||||
diff: [] |
|
||||||
}; |
|
||||||
} |
|
||||||
if (!prevData) { |
|
||||||
return formatSingleObjectDiff(nextData, STATUS.ADDED); |
|
||||||
} |
|
||||||
if (!nextData) { |
|
||||||
return formatSingleObjectDiff(prevData, STATUS.DELETED); |
|
||||||
} |
|
||||||
const diff = []; |
|
||||||
Object.entries(nextData).forEach(([nextProperty, nextValue]) => { |
|
||||||
const previousValue = prevData[nextProperty]; |
|
||||||
if (!!!previousValue) { |
|
||||||
return diff.push({ |
|
||||||
property: nextProperty, |
|
||||||
previousValue: void 0, |
|
||||||
currentValue: nextValue, |
|
||||||
status: STATUS.ADDED |
|
||||||
}); |
|
||||||
} |
|
||||||
if (isObject(nextValue)) { |
|
||||||
const subPropertiesDiff = getSubPropertiesDiff( |
|
||||||
previousValue, |
|
||||||
nextValue, |
|
||||||
options |
|
||||||
); |
|
||||||
return diff.push({ |
|
||||||
property: nextProperty, |
|
||||||
previousValue, |
|
||||||
currentValue: nextValue, |
|
||||||
status: getPropertyStatus(subPropertiesDiff), |
|
||||||
subPropertiesDiff |
|
||||||
}); |
|
||||||
} |
|
||||||
return diff.push({ |
|
||||||
property: nextProperty, |
|
||||||
previousValue, |
|
||||||
currentValue: nextValue, |
|
||||||
status: getValueStatus(previousValue, nextValue, options) |
|
||||||
}); |
|
||||||
}); |
|
||||||
const deletedProperties = getDeletedProperties(prevData, nextData); |
|
||||||
if (deletedProperties) { |
|
||||||
deletedProperties.forEach((deletedProperty) => { |
|
||||||
diff.push({ |
|
||||||
property: deletedProperty.property, |
|
||||||
previousValue: deletedProperty.value, |
|
||||||
currentValue: void 0, |
|
||||||
status: STATUS.DELETED |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
return { |
|
||||||
type: "object", |
|
||||||
status: getObjectStatus(diff), |
|
||||||
diff |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
// src/list-diff.ts
|
|
||||||
function formatSingleListDiff(listData, status) { |
|
||||||
return { |
|
||||||
type: "list", |
|
||||||
status, |
|
||||||
diff: listData.map((data, i) => ({ |
|
||||||
value: data, |
|
||||||
prevIndex: status === STATUS.ADDED ? null : i, |
|
||||||
newIndex: status === STATUS.ADDED ? i : null, |
|
||||||
indexDiff: null, |
|
||||||
status |
|
||||||
})) |
|
||||||
}; |
|
||||||
} |
|
||||||
function getListStatus(listDiff) { |
|
||||||
return listDiff.some((value) => value.status !== STATUS.EQUAL) ? STATUS.UPDATED : STATUS.EQUAL; |
|
||||||
} |
|
||||||
var getListDiff = (prevList, nextList) => { |
|
||||||
if (!prevList && !nextList) { |
|
||||||
return { |
|
||||||
type: "list", |
|
||||||
status: STATUS.EQUAL, |
|
||||||
diff: [] |
|
||||||
}; |
|
||||||
} |
|
||||||
if (!prevList) { |
|
||||||
return formatSingleListDiff(nextList, STATUS.ADDED); |
|
||||||
} |
|
||||||
if (!nextList) { |
|
||||||
return formatSingleListDiff(prevList, STATUS.DELETED); |
|
||||||
} |
|
||||||
const diff = []; |
|
||||||
nextList.forEach((nextValue, i) => { |
|
||||||
const prevIndex = prevList.findIndex( |
|
||||||
(prevValue) => isEqual(prevValue, nextValue) |
|
||||||
); |
|
||||||
const indexDiff = prevIndex === -1 ? null : i - prevIndex; |
|
||||||
if (indexDiff === 0) { |
|
||||||
return diff.push({ |
|
||||||
value: nextValue, |
|
||||||
prevIndex, |
|
||||||
newIndex: i, |
|
||||||
indexDiff, |
|
||||||
status: STATUS.EQUAL |
|
||||||
}); |
|
||||||
} |
|
||||||
if (prevIndex === -1) { |
|
||||||
return diff.push({ |
|
||||||
value: nextValue, |
|
||||||
prevIndex: null, |
|
||||||
newIndex: i, |
|
||||||
indexDiff, |
|
||||||
status: STATUS.ADDED |
|
||||||
}); |
|
||||||
} |
|
||||||
return diff.push({ |
|
||||||
value: nextValue, |
|
||||||
prevIndex, |
|
||||||
newIndex: i, |
|
||||||
indexDiff, |
|
||||||
status: STATUS.MOVED |
|
||||||
}); |
|
||||||
}); |
|
||||||
prevList.forEach((prevValue, i) => { |
|
||||||
if (!nextList.some((nextValue) => isEqual(nextValue, prevValue))) { |
|
||||||
return diff.splice(i, 0, { |
|
||||||
value: prevValue, |
|
||||||
prevIndex: i, |
|
||||||
newIndex: null, |
|
||||||
indexDiff: null, |
|
||||||
status: STATUS.DELETED |
|
||||||
}); |
|
||||||
} |
|
||||||
}); |
|
||||||
return { |
|
||||||
type: "list", |
|
||||||
status: getListStatus(diff), |
|
||||||
diff |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
export { getListDiff, getObjectDiff, isEqual, isObject }; |
|
||||||
|
Loading…
Reference in new issue