9 changed files with 98 additions and 283 deletions
@ -1,107 +0,0 @@
@@ -1,107 +0,0 @@
|
||||
declare const STATUS: Record<string, ObjectDiffStatus>; |
||||
declare const LIST_STATUS: Record<string, ListDiffStatus>; |
||||
declare const GRANULARITY: Record<string, "basic" | "deep">; |
||||
type ListDiffStatus = "added" | "equal" | "moved" | "deleted" | "updated"; |
||||
type ObjectDiffStatus = "added" | "equal" | "deleted" | "updated"; |
||||
type ObjectData = Record<string, any> | undefined | null; |
||||
type ListData = any; |
||||
type ObjectStatusTuple = readonly [ |
||||
"added", |
||||
"equal", |
||||
"deleted", |
||||
"updated" |
||||
]; |
||||
type ListStatusTuple = readonly [ |
||||
"added", |
||||
"equal", |
||||
"deleted", |
||||
"moved", |
||||
"updated" |
||||
]; |
||||
type isEqualOptions = { |
||||
ignoreArrayOrder?: boolean; |
||||
}; |
||||
type ObjectOptions = { |
||||
ignoreArrayOrder?: boolean; |
||||
showOnly?: { |
||||
statuses: Array<ObjectStatusTuple[number]>; |
||||
granularity?: (typeof GRANULARITY)[keyof typeof GRANULARITY]; |
||||
}; |
||||
}; |
||||
type ListOptions = { |
||||
showOnly?: Array<ListStatusTuple[number]>; |
||||
referenceProperty?: string; |
||||
considerMoveAsUpdate?: boolean; |
||||
ignoreArrayOrder?: boolean; |
||||
}; |
||||
type ListDiff = { |
||||
type: "list"; |
||||
status: ListDiffStatus; |
||||
diff: { |
||||
value: ListData; |
||||
prevIndex: number | null; |
||||
newIndex: number | null; |
||||
indexDiff: number | null; |
||||
status: ListDiffStatus; |
||||
}[]; |
||||
}; |
||||
type SubProperties = { |
||||
property: string; |
||||
previousValue: any; |
||||
currentValue: any; |
||||
status: ObjectDiffStatus; |
||||
subPropertiesDiff?: SubProperties[]; |
||||
}; |
||||
type ObjectDiff = { |
||||
type: "object"; |
||||
status: ObjectDiffStatus; |
||||
diff: { |
||||
property: string; |
||||
previousValue: any; |
||||
currentValue: any; |
||||
status: ObjectDiffStatus; |
||||
subPropertiesDiff?: SubProperties[]; |
||||
}[]; |
||||
}; |
||||
type DataDiff = ListDiff | ObjectDiff; |
||||
|
||||
/** |
||||
* Returns the diff between two objects |
||||
* @param {Record<string, any>} prevData - The original object. |
||||
* @param {Record<string, any>} nextData - The new object. |
||||
* * @param {ListOptions} options - Options to refine your output. |
||||
- `showOnly`: returns only the values whose status you are interested in. It takes two parameters: `statuses` and `granularity` |
||||
`statuses` are the status you want to see in the output (e.g. `["added", "equal"]`) |
||||
`granularity` can be either `basic` (to return only the main properties whose status matches your query) or `deep` (to return the main properties if some of their subproperties' status match your request. The subproperties are filtered accordingly). |
||||
- `ignoreArrayOrder` if set to `true`, `["hello", "world"]` and `["world", "hello"]` will be treated as `equal`, because the two arrays have the same value, just not in the same order. |
||||
* @returns ObjectDiff |
||||
*/ |
||||
declare function getObjectDiff(prevData: ObjectData, nextData: ObjectData, options?: ObjectOptions): ObjectDiff; |
||||
|
||||
/** |
||||
* Returns the diff between two arrays |
||||
* @param {Array<T>} prevList - The original array. |
||||
* @param {Array<T>} nextList - The new array. |
||||
* @param {ListOptions} options - Options to refine your output. |
||||
- `showOnly` gives you the option to return only the values whose status you are interested in (e.g. `["added", "equal"]`). |
||||
- `referenceProperty` will consider an object to be updated instead of added or deleted if one of its properties remains stable, such as its `id`. This option has no effect on other datatypes. |
||||
* @returns ListDiff |
||||
*/ |
||||
declare const getListDiff: <T>(prevList: T[] | undefined | null, nextList: T[] | undefined | null, options?: ListOptions) => ListDiff; |
||||
|
||||
/** |
||||
* Returns true if two data are equal |
||||
* @param {any} a - The original data. |
||||
* @param {any} b - The data to compare. |
||||
* @param {isEqualOptions} options - The options to compare the data. |
||||
* @returns boolean |
||||
*/ |
||||
declare function isEqual(a: any, b: any, options?: isEqualOptions): boolean; |
||||
/** |
||||
* Returns true if the provided value is an object |
||||
* @param {any} value - The data to check. |
||||
* @returns value is Record<string, any> |
||||
*/ |
||||
declare function isObject(value: any): value is Record<string, any>; |
||||
|
||||
export { type DataDiff, GRANULARITY, LIST_STATUS, type ListData, type ListDiff, type ListDiffStatus, type ListOptions, type ListStatusTuple, type ObjectData, type ObjectDiff, type ObjectDiffStatus, type ObjectOptions, type ObjectStatusTuple, STATUS, type SubProperties, getListDiff, getObjectDiff, isEqual, type isEqualOptions, isObject }; |
@ -1,107 +0,0 @@
@@ -1,107 +0,0 @@
|
||||
declare const STATUS: Record<string, ObjectDiffStatus>; |
||||
declare const LIST_STATUS: Record<string, ListDiffStatus>; |
||||
declare const GRANULARITY: Record<string, "basic" | "deep">; |
||||
type ListDiffStatus = "added" | "equal" | "moved" | "deleted" | "updated"; |
||||
type ObjectDiffStatus = "added" | "equal" | "deleted" | "updated"; |
||||
type ObjectData = Record<string, any> | undefined | null; |
||||
type ListData = any; |
||||
type ObjectStatusTuple = readonly [ |
||||
"added", |
||||
"equal", |
||||
"deleted", |
||||
"updated" |
||||
]; |
||||
type ListStatusTuple = readonly [ |
||||
"added", |
||||
"equal", |
||||
"deleted", |
||||
"moved", |
||||
"updated" |
||||
]; |
||||
type isEqualOptions = { |
||||
ignoreArrayOrder?: boolean; |
||||
}; |
||||
type ObjectOptions = { |
||||
ignoreArrayOrder?: boolean; |
||||
showOnly?: { |
||||
statuses: Array<ObjectStatusTuple[number]>; |
||||
granularity?: (typeof GRANULARITY)[keyof typeof GRANULARITY]; |
||||
}; |
||||
}; |
||||
type ListOptions = { |
||||
showOnly?: Array<ListStatusTuple[number]>; |
||||
referenceProperty?: string; |
||||
considerMoveAsUpdate?: boolean; |
||||
ignoreArrayOrder?: boolean; |
||||
}; |
||||
type ListDiff = { |
||||
type: "list"; |
||||
status: ListDiffStatus; |
||||
diff: { |
||||
value: ListData; |
||||
prevIndex: number | null; |
||||
newIndex: number | null; |
||||
indexDiff: number | null; |
||||
status: ListDiffStatus; |
||||
}[]; |
||||
}; |
||||
type SubProperties = { |
||||
property: string; |
||||
previousValue: any; |
||||
currentValue: any; |
||||
status: ObjectDiffStatus; |
||||
subPropertiesDiff?: SubProperties[]; |
||||
}; |
||||
type ObjectDiff = { |
||||
type: "object"; |
||||
status: ObjectDiffStatus; |
||||
diff: { |
||||
property: string; |
||||
previousValue: any; |
||||
currentValue: any; |
||||
status: ObjectDiffStatus; |
||||
subPropertiesDiff?: SubProperties[]; |
||||
}[]; |
||||
}; |
||||
type DataDiff = ListDiff | ObjectDiff; |
||||
|
||||
/** |
||||
* Returns the diff between two objects |
||||
* @param {Record<string, any>} prevData - The original object. |
||||
* @param {Record<string, any>} nextData - The new object. |
||||
* * @param {ListOptions} options - Options to refine your output. |
||||
- `showOnly`: returns only the values whose status you are interested in. It takes two parameters: `statuses` and `granularity` |
||||
`statuses` are the status you want to see in the output (e.g. `["added", "equal"]`) |
||||
`granularity` can be either `basic` (to return only the main properties whose status matches your query) or `deep` (to return the main properties if some of their subproperties' status match your request. The subproperties are filtered accordingly). |
||||
- `ignoreArrayOrder` if set to `true`, `["hello", "world"]` and `["world", "hello"]` will be treated as `equal`, because the two arrays have the same value, just not in the same order. |
||||
* @returns ObjectDiff |
||||
*/ |
||||
declare function getObjectDiff(prevData: ObjectData, nextData: ObjectData, options?: ObjectOptions): ObjectDiff; |
||||
|
||||
/** |
||||
* Returns the diff between two arrays |
||||
* @param {Array<T>} prevList - The original array. |
||||
* @param {Array<T>} nextList - The new array. |
||||
* @param {ListOptions} options - Options to refine your output. |
||||
- `showOnly` gives you the option to return only the values whose status you are interested in (e.g. `["added", "equal"]`). |
||||
- `referenceProperty` will consider an object to be updated instead of added or deleted if one of its properties remains stable, such as its `id`. This option has no effect on other datatypes. |
||||
* @returns ListDiff |
||||
*/ |
||||
declare const getListDiff: <T>(prevList: T[] | undefined | null, nextList: T[] | undefined | null, options?: ListOptions) => ListDiff; |
||||
|
||||
/** |
||||
* Returns true if two data are equal |
||||
* @param {any} a - The original data. |
||||
* @param {any} b - The data to compare. |
||||
* @param {isEqualOptions} options - The options to compare the data. |
||||
* @returns boolean |
||||
*/ |
||||
declare function isEqual(a: any, b: any, options?: isEqualOptions): boolean; |
||||
/** |
||||
* Returns true if the provided value is an object |
||||
* @param {any} value - The data to check. |
||||
* @returns value is Record<string, any> |
||||
*/ |
||||
declare function isObject(value: any): value is Record<string, any>; |
||||
|
||||
export { type DataDiff, GRANULARITY, LIST_STATUS, type ListData, type ListDiff, type ListDiffStatus, type ListOptions, type ListStatusTuple, type ObjectData, type ObjectDiff, type ObjectDiffStatus, type ObjectOptions, type ObjectStatusTuple, STATUS, type SubProperties, getListDiff, getObjectDiff, isEqual, type isEqualOptions, isObject }; |
@ -1,11 +0,0 @@
@@ -1,11 +0,0 @@
|
||||
'use strict'; |
||||
|
||||
var u={ADDED:"added",EQUAL:"equal",DELETED:"deleted",UPDATED:"updated"},c={...u,MOVED:"moved"},y={BASIC:"basic",DEEP:"deep"};function D(e,t,i={ignoreArrayOrder:!1}){return typeof e!=typeof t?!1:Array.isArray(e)&&Array.isArray(t)?e.length!==t.length?!1:i.ignoreArrayOrder?e.every(f=>t.some(n=>JSON.stringify(n)===JSON.stringify(f))):e.every((f,n)=>JSON.stringify(f)===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 O(e,t={statuses:[],granularity:y.BASIC}){let{statuses:i,granularity:f}=t;return e.reduce((n,r)=>{if(f===y.DEEP&&r.subPropertiesDiff){let s=O(r.subPropertiesDiff,t);if(s.length>0)return [...n,{...r,subPropertiesDiff:s}]}if(f===y.DEEP&&r.subDiff){let s=O(r.subDiff,t);if(s.length>0)return [...n,{...r,subDiff:s}]}return i.includes(r.status)?[...n,r]:n},[])}function E(e){return e.some(t=>t.status!==u.EQUAL)?u.UPDATED:u.EQUAL}function A(e,t,i={ignoreArrayOrder:!1,showOnly:{statuses:[],granularity:y.BASIC}}){if(!e)return {type:"object",status:u.EQUAL,diff:[]};let f=[];return Object.entries(e).forEach(([n,r])=>{if(p(r)){let s=[];return Object.entries(r).forEach(([o,d])=>{s.push({property:o,previousValue:t===u.ADDED?void 0:d,currentValue:t===u.ADDED?d:void 0,status:t});}),f.push({property:n,previousValue:t===u.ADDED?void 0:e[n],currentValue:t===u.ADDED?r:void 0,status:t,subPropertiesDiff:s})}return f.push({property:n,previousValue:t===u.ADDED?void 0:e[n],currentValue:t===u.ADDED?r:void 0,status:t})}),i.showOnly&&i.showOnly.statuses.length>0?{type:"object",status:t,diff:O(f,i.showOnly)}:{type:"object",status:t,diff:f}}function P(e,t,i){if(!e)return;let f=Object.entries(e).find(([n])=>D(n,t,i));return f?f[1]:void 0}function j(e,t,i){return D(e,t,i)?u.EQUAL:u.UPDATED}function U(e){return e.some(t=>t.status!==u.EQUAL)?u.UPDATED:u.EQUAL}function g(e,t){if(!e)return;let i=Object.keys(e),f=Object.keys(t),n=i.filter(r=>!f.includes(r));if(n.length>0)return n.map(r=>({property:r,value:e[r]}))}function S(e,t,i){let f=[],n,r=g(e,t);return r&&r.forEach(s=>{f.push({property:s.property,previousValue:s.value,currentValue:void 0,status:u.DELETED});}),Object.entries(t).forEach(([s,o])=>{let d=P(e,s,i);if(!d)return f.push({property:s,previousValue:d,currentValue:o,status:!e||!(s in e)?u.ADDED:d===o?u.EQUAL:u.UPDATED});if(p(o)){let a=S(d,o,i);a&&a.length>0&&(n=a);}d&&f.push({property:s,previousValue:d,currentValue:o,status:j(d,o,i),...!!n&&{subDiff:n}});}),f}function m(e,t,i={ignoreArrayOrder:!1,showOnly:{statuses:[],granularity:y.BASIC}}){if(!e&&!t)return {type:"object",status:u.EQUAL,diff:[]};if(!e)return A(t,u.ADDED,i);if(!t)return A(e,u.DELETED,i);let f=[];Object.entries(t).forEach(([r,s])=>{let o=e[r];if(!o)return f.push({property:r,previousValue:o,currentValue:s,status:r in e?o===s?u.EQUAL:u.UPDATED:u.ADDED});if(p(s)){let d=S(o,s,i),a=U(d);return f.push({property:r,previousValue:o,currentValue:s,status:a,...a!==u.EQUAL&&{subPropertiesDiff:d}})}return f.push({property:r,previousValue:o,currentValue:s,status:j(o,s,i)})});let n=g(e,t);return n&&n.forEach(r=>{f.push({property:r.property,previousValue:r.value,currentValue:void 0,status:u.DELETED});}),i.showOnly&&i.showOnly.statuses.length>0?{type:"object",status:E(f),diff:O(f,i.showOnly)}:{type:"object",status:E(f),diff:f}}function w(e,t=[]){return e.filter(i=>t?.includes(i.status))}function h(e,t,i={showOnly:[]}){let f=e.map((n,r)=>({value:n,prevIndex:t===c.ADDED?null:r,newIndex:t===c.ADDED?r:null,indexDiff:null,status:t}));return i.showOnly&&i.showOnly.length>0?{type:"list",status:t,diff:f.filter(n=>i.showOnly?.includes(n.status))}:{type:"list",status:t,diff:f}}function L(e){return e.some(t=>t.status!==c.EQUAL)?c.UPDATED:c.EQUAL}function T(e,t){return p(e)&&t?Object.hasOwn(e,t):!1}var I=(e,t,i={showOnly:[],referenceProperty:void 0,considerMoveAsUpdate:!1,ignoreArrayOrder:!1})=>{if(!e&&!t)return {type:"list",status:c.EQUAL,diff:[]};if(!e)return h(t,c.ADDED,i);if(!t)return h(e,c.DELETED,i);let f=[],n=[];return t.forEach((r,s)=>{let o=e.findIndex((a,b)=>T(a,i.referenceProperty)?p(r)?D(a[i.referenceProperty],r[i.referenceProperty])&&!n.includes(b):!1:D(a,r)&&!n.includes(b));o>-1&&n.push(o);let d=o===-1?null:s-o;if(d===0||i.ignoreArrayOrder){let a=c.EQUAL;return T(r,i.referenceProperty)&&(D(e[o],r)||(a=c.UPDATED)),f.push({value:r,prevIndex:o,newIndex:s,indexDiff:d,status:a})}return o===-1?f.push({value:r,prevIndex:null,newIndex:s,indexDiff:d,status:c.ADDED}):f.push({value:r,prevIndex:o,newIndex:s,indexDiff:d,status:i.considerMoveAsUpdate?c.UPDATED:c.MOVED})}),e.forEach((r,s)=>{if(!n.includes(s))return f.splice(s,0,{value:r,prevIndex:s,newIndex:null,indexDiff:null,status:c.DELETED})}),i.showOnly&&i?.showOnly?.length>0?{type:"list",status:L(f),diff:w(f,i.showOnly)}:{type:"list",status:L(f),diff:f}}; |
||||
|
||||
exports.GRANULARITY = y; |
||||
exports.LIST_STATUS = c; |
||||
exports.STATUS = u; |
||||
exports.getListDiff = I; |
||||
exports.getObjectDiff = m; |
||||
exports.isEqual = D; |
||||
exports.isObject = p; |
@ -1,3 +0,0 @@
@@ -1,3 +0,0 @@
|
||||
var u={ADDED:"added",EQUAL:"equal",DELETED:"deleted",UPDATED:"updated"},c={...u,MOVED:"moved"},y={BASIC:"basic",DEEP:"deep"};function D(e,t,i={ignoreArrayOrder:!1}){return typeof e!=typeof t?!1:Array.isArray(e)&&Array.isArray(t)?e.length!==t.length?!1:i.ignoreArrayOrder?e.every(f=>t.some(n=>JSON.stringify(n)===JSON.stringify(f))):e.every((f,n)=>JSON.stringify(f)===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:i,granularity:f}=t;return e.reduce((n,r)=>{if(f===y.DEEP&&r.subPropertiesDiff){let s=b(r.subPropertiesDiff,t);if(s.length>0)return [...n,{...r,subPropertiesDiff:s}]}if(f===y.DEEP&&r.subDiff){let s=b(r.subDiff,t);if(s.length>0)return [...n,{...r,subDiff:s}]}return i.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,i={ignoreArrayOrder:!1,showOnly:{statuses:[],granularity:y.BASIC}}){if(!e)return {type:"object",status:u.EQUAL,diff:[]};let f=[];return Object.entries(e).forEach(([n,r])=>{if(p(r)){let s=[];return Object.entries(r).forEach(([o,d])=>{s.push({property:o,previousValue:t===u.ADDED?void 0:d,currentValue:t===u.ADDED?d:void 0,status:t});}),f.push({property:n,previousValue:t===u.ADDED?void 0:e[n],currentValue:t===u.ADDED?r:void 0,status:t,subPropertiesDiff:s})}return f.push({property:n,previousValue:t===u.ADDED?void 0:e[n],currentValue:t===u.ADDED?r:void 0,status:t})}),i.showOnly&&i.showOnly.statuses.length>0?{type:"object",status:t,diff:b(f,i.showOnly)}:{type:"object",status:t,diff:f}}function U(e,t,i){if(!e)return;let f=Object.entries(e).find(([n])=>D(n,t,i));return f?f[1]:void 0}function g(e,t,i){return D(e,t,i)?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 i=Object.keys(e),f=Object.keys(t),n=i.filter(r=>!f.includes(r));if(n.length>0)return n.map(r=>({property:r,value:e[r]}))}function h(e,t,i){let f=[],n,r=S(e,t);return r&&r.forEach(s=>{f.push({property:s.property,previousValue:s.value,currentValue:void 0,status:u.DELETED});}),Object.entries(t).forEach(([s,o])=>{let d=U(e,s,i);if(!d)return f.push({property:s,previousValue:d,currentValue:o,status:!e||!(s in e)?u.ADDED:d===o?u.EQUAL:u.UPDATED});if(p(o)){let a=h(d,o,i);a&&a.length>0&&(n=a);}d&&f.push({property:s,previousValue:d,currentValue:o,status:g(d,o,i),...!!n&&{subDiff:n}});}),f}function w(e,t,i={ignoreArrayOrder:!1,showOnly:{statuses:[],granularity:y.BASIC}}){if(!e&&!t)return {type:"object",status:u.EQUAL,diff:[]};if(!e)return j(t,u.ADDED,i);if(!t)return j(e,u.DELETED,i);let f=[];Object.entries(t).forEach(([r,s])=>{let o=e[r];if(!o)return f.push({property:r,previousValue:o,currentValue:s,status:r in e?o===s?u.EQUAL:u.UPDATED:u.ADDED});if(p(s)){let d=h(o,s,i),a=m(d);return f.push({property:r,previousValue:o,currentValue:s,status:a,...a!==u.EQUAL&&{subPropertiesDiff:d}})}return f.push({property:r,previousValue:o,currentValue:s,status:g(o,s,i)})});let n=S(e,t);return n&&n.forEach(r=>{f.push({property:r.property,previousValue:r.value,currentValue:void 0,status:u.DELETED});}),i.showOnly&&i.showOnly.statuses.length>0?{type:"object",status:A(f),diff:b(f,i.showOnly)}:{type:"object",status:A(f),diff:f}}function I(e,t=[]){return e.filter(i=>t?.includes(i.status))}function L(e,t,i={showOnly:[]}){let f=e.map((n,r)=>({value:n,prevIndex:t===c.ADDED?null:r,newIndex:t===c.ADDED?r:null,indexDiff:null,status:t}));return i.showOnly&&i.showOnly.length>0?{type:"list",status:t,diff:f.filter(n=>i.showOnly?.includes(n.status))}:{type:"list",status:t,diff:f}}function T(e){return e.some(t=>t.status!==c.EQUAL)?c.UPDATED:c.EQUAL}function P(e,t){return p(e)&&t?Object.hasOwn(e,t):!1}var R=(e,t,i={showOnly:[],referenceProperty:void 0,considerMoveAsUpdate:!1,ignoreArrayOrder:!1})=>{if(!e&&!t)return {type:"list",status:c.EQUAL,diff:[]};if(!e)return L(t,c.ADDED,i);if(!t)return L(e,c.DELETED,i);let f=[],n=[];return t.forEach((r,s)=>{let o=e.findIndex((a,E)=>P(a,i.referenceProperty)?p(r)?D(a[i.referenceProperty],r[i.referenceProperty])&&!n.includes(E):!1:D(a,r)&&!n.includes(E));o>-1&&n.push(o);let d=o===-1?null:s-o;if(d===0||i.ignoreArrayOrder){let a=c.EQUAL;return P(r,i.referenceProperty)&&(D(e[o],r)||(a=c.UPDATED)),f.push({value:r,prevIndex:o,newIndex:s,indexDiff:d,status:a})}return o===-1?f.push({value:r,prevIndex:null,newIndex:s,indexDiff:d,status:c.ADDED}):f.push({value:r,prevIndex:o,newIndex:s,indexDiff:d,status:i.considerMoveAsUpdate?c.UPDATED:c.MOVED})}),e.forEach((r,s)=>{if(!n.includes(s))return f.splice(s,0,{value:r,prevIndex:s,newIndex:null,indexDiff:null,status:c.DELETED})}),i.showOnly&&i?.showOnly?.length>0?{type:"list",status:T(f),diff:I(f,i.showOnly)}:{type:"list",status:T(f),diff:f}}; |
||||
|
||||
export { y as GRANULARITY, c as LIST_STATUS, u as STATUS, R as getListDiff, w as getObjectDiff, D as isEqual, p as isObject }; |
Loading…
Reference in new issue