|
2 years ago | |
---|---|---|
dist | 2 years ago | |
src | 2 years ago | |
test | 2 years ago | |
.gitignore | 2 years ago | |
README.md | 2 years ago | |
index.ts | 2 years ago | |
jest.config.js | 2 years ago | |
package.json | 2 years ago | |
tsconfig.json | 2 years ago | |
tsup.config.ts | 2 years ago | |
yarn.lock | 2 years ago |
README.md

SUPERDIFF
This library compares two arrays or objects and return a complete diff of their differences.
WHY YOU SHOULD USE THIS LIB
All other existing solutions return a weird diff format which often require an additional parsing. They are also slow and limited to object comparison. 👎
Superdiff gives you a complete diff for both array and objects with a very readable format. Last but not least, it's battled tested and super fast. Import. Enjoy. 👍
Benchmark:
Objects | Deep-diff 🐢 | Superdiff ⚡ |
---|---|---|
1.000 | 10.47ms | 5.73ms |
10.000 | 43.05ms | 18.60ms |
100.000 | 289.71ms | 50.96ms |
1.000.000 | 2786.70ms | 389.78ms |
DIFF FORMAT COMPARISON
Let's compare the diff format of Superdiff and Deep-diff, the most popular diff lib on npm:
input:
const objectA = {
id: 54,
user: {
name: "joe",
- member: true,
- hobbies: ["golf", "football"],
age: 66,
},
}
const objectB = {
id: 54,
user: {
name: "joe",
+ member: false,
+ hobbies: ["golf", "chess"],
age: 66,
},
}
Deep-Diff output:
[
DiffEdit {
kind: 'E',
path: [ 'user', 'member' ],
lhs: true,
rhs: false
},
DiffEdit {
kind: 'E',
path: [ 'user', 'hobbies', 1 ],
lhs: 'football',
rhs: 'chess'
}
]
SuperDiff output:
{
type: "object",
+ status: "updated",
diff: [
{
property: "id",
previousValue: 54,
currentValue: 54,
status: "equal",
},
{
property: "user",
previousValue: {
name: "joe",
member: true,
hobbies: ["golf", "football"],
age: 66,
},
currentValue: {
name: "joe",
member: false,
hobbies: ["golf", "chess"],
age: 66,
},
+ status: "updated",
subPropertiesDiff: [
{
property: "name",
previousValue: "joe",
currentValue: "joe",
status: "equal",
},
+ {
+ property: "member",
+ previousValue: true,
+ currentValue: false,
+ status: "updated",
+ },
+ {
+ property: "hobbies",
+ previousValue: ["golf", "football"],
+ currentValue: ["golf", "chess"],
+ status: "updated",
+ },
{
property: "age",
previousValue: 66,
currentValue: 66,
status: "equal",
},
],
},
],
}
FEATURES
Superdiff exports 4 functions:
getObjectDiff()
import { getObjectDiff } from "@donedeal0/superdiff";
Compares two objects and return a diff for each value and their potential subvalues:
- property name
- status:
added
,deleted
,equal
,updated
- previous value, current value
- supports deeply nested objects with any kind of values
format:
type ObjectDiff = {
type: "object";
status: "added" | "deleted" | "equal" | "moved" | "updated";
diff: {
property: string;
previousValue: any;
currentValue: any;
status: "added" | "deleted" | "equal" | "moved" | "updated";
// only appears if some subproperties have been added/deleted/updated
subPropertiesDiff?: {
property: string;
previousValue: any;
currentValue: any;
status: "added" | "deleted" | "equal" | "moved" | "updated";
// subDiff is a recursive diff in case of nested subproperties
subDiff?: SubProperties[];
}[];
}[];
};
Options
{
ignoreArrayOrder?: boolean // false by default,
showOnly?: {
statuses: ("added" | "deleted" | "updated" | "equal")[], // [] by default
granularity?: "basic" | "deep" // basic by default
}
}
-
ignoreArrayOrder
: if set totrue
,["hello", "world"]
and["world", "hello"]
will be considered asequal
, because the two arrays have the same value, just not in the same order. -
showOnly
: gives you the option to only return the values whose status interest you. It has two parameters:statuses
: status you want to see in the output (ex:["added", "equal"]
)granularity
:basic
only returns the main properties whose status match your request, without taking into account their eventual subproperties.deep
return main properties whose status match your request but also their relevant subproperties.
getListDiff()
import { getListDiff } from "@donedeal0/superdiff";
Compares two arrays and return a diff for each value:
- index change:
prevIndex
,newIndex
,indexDiff
- status:
added
,deleted
,equal
,moved
,updated
- value
- supports arrays of primitive values and objects
- supports arrays with duplicated values
format:
type ListDiff = {
type: "list";
status: "added" | "deleted" | "equal" | "moved" | "updated";
diff: {
value: any;
prevIndex: number | null;
newIndex: number | null;
indexDiff: number | null;
status: "added" | "deleted" | "equal" | "moved" | "updated";
}[];
};
Options
{
showOnly?: ("added" | "deleted" | "moved" | "updated" | "equal")[], // [] by default
}
showOnly
gives you the option to only return the values whose status interest you (ex:["added", "equal"]
).
isEqual()
import { isEqual } from "@donedeal0/superdiff";
Checks if two values are equal.
Options
{
ignoreArrayOrder?: boolean // false by default,
}
ignoreArrayOrder
: if set totrue
,["hello", "world"]
and["world", "hello"]
will be considered asequal
, because the two arrays have the same value, just not in the same order.
isObject()
import { isObject } from "@donedeal0/superdiff";
Checks if a value is an object.
EXAMPLES
getListDiff()
input
getListDiff(
- ["mbappe", "mendes", "verratti", "ruiz"],
+ ["mbappe", "messi", "ruiz"]
);
output
{
type: "list",
+ status: "updated",
diff: [
{
value: "mbappe",
prevIndex: 0,
newIndex: 0,
indexDiff: 0,
status: "equal",
},
- {
- value: "mendes",
- prevIndex: 1,
- newIndex: null,
- indexDiff: null,
- status: "deleted",
- },
- {
- value: "verratti",
- prevIndex: 2,
- newIndex: null,
- indexDiff: null,
- status: "deleted",
- },
+ {
+ value: "messi",
+ prevIndex: null,
+ newIndex: 1,
+ indexDiff: null,
+ status: "added",
+ },
+ {
+ value: "ruiz",
+ prevIndex: 3,
+ newIndex: 2,
+ indexDiff: -1,
+ status: "moved",
},
],
}
getObjectDiff()
input
getObjectDiff(
{
id: 54,
user: {
name: "joe",
- member: true,
- hobbies: ["golf", "football"],
age: 66,
},
},
{
id: 54,
user: {
name: "joe",
+ member: false,
+ hobbies: ["golf", "chess"],
age: 66,
},
}
);
output
{
type: "object",
+ status: "updated",
diff: [
{
property: "id",
previousValue: 54,
currentValue: 54,
status: "equal",
},
{
property: "user",
previousValue: {
name: "joe",
member: true,
hobbies: ["golf", "football"],
age: 66,
},
currentValue: {
name: "joe",
member: false,
hobbies: ["golf", "chess"],
age: 66,
},
+ status: "updated",
subPropertiesDiff: [
{
property: "name",
previousValue: "joe",
currentValue: "joe",
status: "equal",
},
+ {
+ property: "member",
+ previousValue: true,
+ currentValue: false,
+ status: "updated",
+ },
+ {
+ property: "hobbies",
+ previousValue: ["golf", "football"],
+ currentValue: ["golf", "chess"],
+ status: "updated",
+ },
{
property: "age",
previousValue: 66,
currentValue: 66,
status: "equal",
},
],
},
],
}
isEqual()
isEqual(
[
{ name: "joe", age: 99 },
{ name: "nina", age: 23 },
],
[
{ name: "joe", age: 98 },
{ name: "nina", age: 23 },
]
);
output
false;
isObject()
input
isObject(["hello", "world"]);
output
false;
More examples are availble in the tests of the source code.
CREDITS
DoneDeal0
SUPPORT
If you or your company use Superdiff, please show your support by buying me coffee: https://www.buymeacoffee.com/donedeal0

CONTRIBUTING
Pull requests are welcome!