diff --git a/README.md b/README.md
index bf84553..d19bbda 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,9 @@ This library compares two arrays or objects and returns a full diff of their dif
All other existing solutions return a strange diff format that often requires additional parsing. They are also limited to object comparison.
-**Superdiff** gives you a complete diff for both array and objects in a very readable format. Last but not least, it's battle-tested, has zero dependencies, and is super fast. Import. Enjoy. đ
+**Superdiff** gives you a complete diff for both array and objects in a very readable format. Last but not least, it's battle-tested, has zero dependencies, and is super fast.
+
+Import. Enjoy. đ
@@ -38,17 +40,21 @@ I am grateful to the generous donors of **Superdiff**!
## FEATURES
-**Superdiff** exports 4 functions:
+**Superdiff** exports 5 functions:
```ts
-// Compares two objects and return a diff for each value and their potential subvalues
+// Returns a complete diff of two objects
getObjectDiff(prevObject, nextObject)
-// Compares two arrays and returns a diff for each value
+
+// Returns a complete diff of two arrays
getListDiff(prevList, nextList)
+
// Streams the diff of two object lists, ideal for large lists and maximum performance
streamListDiff(prevList, nextList, referenceProperty)
+
// Checks whether two values are equal
isEqual(dataA, dataB)
+
// Checks whether a value is an object
isObject(data)
```
@@ -62,9 +68,9 @@ import { getObjectDiff } from "@donedeal0/superdiff";
Compares two objects and return a diff for each value and their potential subvalues. Supports deeply nested objects with any kind of values.
-**Format**
+#### FORMAT
-input
+**Input**
```ts
prevData: Record;
@@ -78,8 +84,8 @@ options?: {
}
```
-- `prevData`: the original object
-- `nextData`: the new object
+- `prevData`: the original object.
+- `nextData`: the new object.
- `options`
- `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.
- `showOnly`: returns only the values whose status you are interested in. It takes two parameters:
@@ -89,7 +95,7 @@ options?: {
- `basic` returns only the main properties whose status matches your query.
- `deep` can return main properties if some of their subproperties' status match your request. The subproperties are filtered accordingly.
-output
+**Output**
```ts
type ObjectDiff = {
@@ -107,9 +113,9 @@ type Diff = {
diff?: Diff[];
};
```
-**Usage**
+#### USAGE
-input
+**Input**
```diff
getObjectDiff(
@@ -134,7 +140,7 @@ getObjectDiff(
);
```
-output
+**Output**
```diff
{
@@ -202,9 +208,9 @@ import { getListDiff } from "@donedeal0/superdiff";
Compares two arrays and returns a diff for each entry. Supports duplicate values, primitive values and objects.
-**Format**
+#### FORMAT
-input
+**Input**
```ts
prevList: T[];
@@ -216,15 +222,15 @@ input
considerMoveAsUpdate?: boolean // false by default
}
```
-- `prevList`: the original list
-- `nextList`: the new list
+- `prevList`: the original list.
+- `nextList`: the new list.
- `options`
- `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.
- `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.
- - `considerMoveAsUpdate`: if set to `true` the `moved` value will be considered as `updated`.
+ - `considerMoveAsUpdate`: if set to `true` a `moved` value will be considered as `updated`.
-output
+**Output**
```ts
type ListDiff = {
@@ -239,9 +245,9 @@ type ListDiff = {
}[];
};
```
-**Usage**
+#### USAGE
-input
+**Input**
```diff
getListDiff(
@@ -250,7 +256,7 @@ getListDiff(
);
```
-output
+**Output**
```diff
{
@@ -297,7 +303,7 @@ output
```
-### streamListDiff()
+### streamListDiff()
```js
import { streamListDiff } from "@donedeal0/superdiff";
@@ -305,16 +311,16 @@ import { streamListDiff } from "@donedeal0/superdiff";
Streams the diff of two object lists, ideal for large lists and maximum performance.
-**Format**
+#### FORMAT
-input
+**Input**
```ts
- prevList: T[],
- nextList: T[],
- referenceProperty: ReferenceProperty,
+ prevList: Record[],
+ nextList: Record[],
+ referenceProperty: keyof Record,
options: {
- showOnly?: returns only the values whose status you are interested in. (e.g. `["added", "equal"]`), // [] by default
+ showOnly?: ("added" | "deleted" |Â "moved" | "updated" | "equal")[], // [] by default
chunksSize?: number, // // 0 by default
considerMoveAsUpdate? boolean; // false by default
}
@@ -324,13 +330,32 @@ input
- `nextList`: the new object list.
- `referenceProperty`: a common property in all the objects of your lists (e.g. `id`).
- `options`
- - `chunksSize` the number of object diffs returned by each stream chunk. If set to `0`, each stream will return a single object diff. If set to `10` each stream will return 10 object diffs.
+ - `chunksSize` the number of object diffs returned by each streamed chunk. (e.g. `0` = 1 object diff by chunk, `10` = 10 object diffs by chunk).
- `showOnly` gives you the option to return only the values whose status you are interested in (e.g. `["added", "equal"]`).
- - `considerMoveAsUpdate`: if set to `true` the `moved` value will be considered as `updated`.
+ - `considerMoveAsUpdate`: if set to `true` a `moved` value will be considered as `updated`.
+
+**Output**
-output
+The objects diff are grouped in arrays - called `chunks` - and are consumed thanks to an event listener. You have access to 3 events:
+ - `data`: to be notified when a new chunk of object diffs is available.
+ - `finish`: to be notified when the stream is complete.
+ - `error`: to be notified of an error during the stream.
```ts
+interface StreamListener> {
+ on>(
+ event: E,
+ listener: Listener[E]>,
+ ): this;
+}
+
+type EmitterEvents> = {
+ data: [StreamListDiff[]];
+ error: [Error];
+ finish: [];
+};
+
+
type StreamListDiff> = {
currentValue: T | null;
previousValue: T | null;
@@ -341,9 +366,9 @@ type StreamListDiff> = {
};
```
-**Usage**
+#### USAGE
-input
+**Input**
```diff
const diff = streamListDiff(
@@ -362,7 +387,7 @@ const diff = streamListDiff(
);
```
-output
+**Output**
```diff
diff.on("data", (chunk) => {
@@ -407,7 +432,7 @@ diff.on("data", (chunk) => {
});
diff.on("finish", () => console.log("The full diff is available"))
-diff.on("error", (err)=> console.log(err))
+diff.on("error", (err) => console.log(err))
```
@@ -419,19 +444,22 @@ import { isEqual } from "@donedeal0/superdiff";
Checks whether two values are equal.
-**Options**
+#### FORMAT
-You can add a third `options` parameter to `isEqual`.
+**Input**
```ts
-{
- ignoreArrayOrder?: boolean // false by default,
-}
+a: unknown,
+b: unknown,
+options: {
+ ignoreArrayOrder: boolean; // false by default
+ },
```
-
+- `a`: the value to compare to the value `b`.
+- `b`: the value that will be compared to the value `a`.
- `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.
-**Usage**
+#### USAGE
```ts
@@ -447,7 +475,7 @@ isEqual(
);
```
-output
+**Output**
```ts
false;
@@ -462,15 +490,25 @@ import { isObject } from "@donedeal0/superdiff";
Tests whether a value is an object.
-**Usage**
+#### FORMAT
+
+**Input**
+
+```ts
+value: unknown;
+```
+
+- `value`: the value whose type will be checked.
-input
+#### USAGE
+
+**Input**
```ts
isObject(["hello", "world"]);
```
-output
+**Output**
```ts
false;
@@ -478,7 +516,8 @@ false;
-### More examples are available in the source code tests.
+### âšī¸ More examples are available in the source code tests.
+
@@ -498,4 +537,4 @@ If you or your company uses **Superdiff**, please show your support by becoming
## CONTRIBUTING
-Pull requests are welcome!
+Issues and pull requests are welcome!
diff --git a/dist/index.d.mts b/dist/index.d.mts
deleted file mode 100644
index b2559e6..0000000
--- a/dist/index.d.mts
+++ /dev/null
@@ -1,107 +0,0 @@
-declare const STATUS: Record;
-declare const LIST_STATUS: Record;
-declare const GRANULARITY: Record;
-type ListDiffStatus = "added" | "equal" | "moved" | "deleted" | "updated";
-type ObjectDiffStatus = "added" | "equal" | "deleted" | "updated";
-type ObjectData = Record | 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;
- granularity?: (typeof GRANULARITY)[keyof typeof GRANULARITY];
- };
-};
-type ListOptions = {
- showOnly?: Array;
- 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} prevData - The original object.
- * @param {Record} 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} prevList - The original array.
- * @param {Array} 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: (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
- */
-declare function isObject(value: any): value is Record;
-
-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 };
diff --git a/dist/index.d.ts b/dist/index.d.ts
deleted file mode 100644
index b2559e6..0000000
--- a/dist/index.d.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-declare const STATUS: Record;
-declare const LIST_STATUS: Record;
-declare const GRANULARITY: Record;
-type ListDiffStatus = "added" | "equal" | "moved" | "deleted" | "updated";
-type ObjectDiffStatus = "added" | "equal" | "deleted" | "updated";
-type ObjectData = Record | 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;
- granularity?: (typeof GRANULARITY)[keyof typeof GRANULARITY];
- };
-};
-type ListOptions = {
- showOnly?: Array;
- 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} prevData - The original object.
- * @param {Record} 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} prevList - The original array.
- * @param {Array} 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: (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
- */
-declare function isObject(value: any): value is Record;
-
-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 };
diff --git a/dist/index.js b/dist/index.js
deleted file mode 100644
index b527bb3..0000000
--- a/dist/index.js
+++ /dev/null
@@ -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;
diff --git a/dist/index.mjs b/dist/index.mjs
deleted file mode 100644
index 68cdd2c..0000000
--- a/dist/index.mjs
+++ /dev/null
@@ -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 };
diff --git a/package.json b/package.json
index 61b0065..02202ee 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@donedeal0/superdiff",
- "version": "2.0.0",
+ "version": "2.1.0",
"description": "SuperDiff checks the changes between two objects or arrays. It returns a complete diff with relevant information for each property or piece of data",
"main": "dist/index.js",
"module": "dist/index.mjs",
@@ -18,6 +18,10 @@
"bugs": {
"url": "https://github.com/DoneDeal0/superdiff/issues"
},
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/DoneDeal0"
+ },
"readme": "./README.md",
"release": {
"branches": [
@@ -57,7 +61,9 @@
"diff",
"deep-diff",
"comparison",
- "compare"
+ "compare",
+ "stream",
+ "streaming"
],
"scripts": {
"build": "tsup",
diff --git a/src/lib/object-diff/object-diff.test.ts b/src/lib/object-diff/object-diff.test.ts
index ab38818..62295c3 100644
--- a/src/lib/object-diff/object-diff.test.ts
+++ b/src/lib/object-diff/object-diff.test.ts
@@ -1,4 +1,4 @@
-import { GRANULARITY, OBJECT_STATUS } from "../../models/object";
+import { GRANULARITY, OBJECT_STATUS } from "@models/object";
import { getObjectDiff } from ".";
describe("getObjectDiff", () => {
diff --git a/src/models/list/index.ts b/src/models/list/index.ts
index 79fc9ba..8616faa 100644
--- a/src/models/list/index.ts
+++ b/src/models/list/index.ts
@@ -6,8 +6,6 @@ export enum LIST_STATUS {
MOVED = "moved",
}
-export type ListData = unknown;
-
export type ListDiffOptions = {
showOnly?: `${LIST_STATUS}`[];
referenceProperty?: string;
@@ -26,7 +24,7 @@ export type ListDiff = {
type: "list";
status: LIST_STATUS;
diff: {
- value: ListData;
+ value: unknown;
prevIndex: number | null;
newIndex: number | null;
indexDiff: number | null;
diff --git a/src/models/stream/index.ts b/src/models/stream/index.ts
index d932ebd..d5d0df4 100644
--- a/src/models/stream/index.ts
+++ b/src/models/stream/index.ts
@@ -17,7 +17,7 @@ export type StreamReferences> = Map<
>;
export type ListStreamOptions = {
- chunksSize?: number; // 0 by default. If 0, stream will be live
+ chunksSize?: number; // 0 by default.
showOnly?: `${LIST_STATUS}`[];
considerMoveAsUpdate?: boolean;
};