Gathering detailed insights and metrics for differrer
Gathering detailed insights and metrics for differrer
Utility to perform deep diff on any data types with smart order detection in arrays and different views implemented for convenience
npm install differrer
Typescript
Module System
Node Version
NPM Version
71.9
Supply Chain
98.8
Quality
82.9
Maintenance
100
Vulnerability
100
License
HTML (48.63%)
TypeScript (41.97%)
JavaScript (5.92%)
CSS (3.48%)
Total Downloads
1,418
Last Day
3
Last Week
30
Last Month
176
Last Year
870
7 Commits
1 Watching
1 Branches
1 Contributors
Minified
Minified + Gzipped
Latest Version
1.1.2
Package Id
differrer@1.1.2
Unpacked Size
41.06 kB
Size
11.46 kB
File Count
10
NPM Version
10.9.0
Node Version
22.11.0
Publised On
26 Dec 2024
Cumulative downloads
Total Downloads
Last day
-57.1%
3
Compared to previous day
Last week
20%
30
Compared to previous week
Last month
-39.5%
176
Compared to previous month
Last year
58.8%
870
Compared to previous year
7
Utility to perform deep diff on any data types with smart order detection in arrays and different views implemented for convenience
Differrer is a JavaScript library that provides a set of tools for performing deep-diff operations on any data type, including nested arrays and objects. It enables the developer to pass a custom function to detect the order of objects in arrays.
Several views are implemented to create a more human-readable version of the diff results.
npm i differrer
1import createDiff, { getType } from 'differrer'; 2 3const diff = createDiff({ 4 sortArrayItems: true, // default false 5 getArrayElementId: (item: any) => getType(item) === 'object' ? item.id : item, 6}); 7 8const source = [{ id: 10, value: 'foo' }, { id: 1, value: 'bar' }]; 9const compare = [{ id: 1, value: 'bar' }, { id: 10, value: 'foo' }]; 10 11const diffResult = diff(source, compare);
The diffResult will look like this:
1{ 2 sourcePath: [], 3 targetPath: [], 4 sourceValue: [ 5 { 6 id: 10, 7 value: 'foo', 8 }, 9 { 10 id: 1, 11 value: 'bar', 12 }, 13 ], 14 targetValue: [ 15 { 16 id: 1, 17 value: 'barr', 18 }, 19 { 20 id: 10, 21 value: 'foo', 22 }, 23 ], 24 sameValue: false, 25 sameValueZero: false, 26 retrievedId: null, 27 sourceOrder: null, 28 targetOrder: null, 29 sameOrder: null, 30 sourceType: 'array', 31 targetType: 'array', 32 sameType: true, 33 added: false, 34 removed: false, 35 changed: true, 36 children: [ 37 { 38 sourcePath: [ 39 1, 40 ], 41 targetPath: [ 42 0, 43 ], 44 sourceValue: { 45 id: 1, 46 value: 'bar', 47 }, 48 targetValue: { 49 id: 1, 50 value: 'barr', 51 }, 52 sameValue: false, 53 sameValueZero: false, 54 retrievedId: '1', 55 sourceOrder: 1, 56 targetOrder: 0, 57 sameOrder: false, 58 sourceType: 'object', 59 targetType: 'object', 60 sameType: true, 61 added: false, 62 removed: false, 63 changed: true, 64 children: { 65 id: { 66 sourcePath: [ 67 1, 68 'id', 69 ], 70 targetPath: [ 71 0, 72 'id', 73 ], 74 sourceValue: 1, 75 targetValue: 1, 76 sameValue: true, 77 sameValueZero: true, 78 retrievedId: null, 79 sourceOrder: 0, 80 targetOrder: 0, 81 sameOrder: true, 82 sourceType: 'number', 83 targetType: 'number', 84 sameType: true, 85 added: false, 86 removed: false, 87 changed: false, 88 children: null, 89 }, 90 value: { 91 sourcePath: [ 92 1, 93 'value', 94 ], 95 targetPath: [ 96 0, 97 'value', 98 ], 99 sourceValue: 'bar', 100 targetValue: 'barr', 101 sameValue: false, 102 sameValueZero: false, 103 retrievedId: null, 104 sourceOrder: 1, 105 targetOrder: 1, 106 sameOrder: true, 107 sourceType: 'string', 108 targetType: 'string', 109 sameType: true, 110 added: false, 111 removed: false, 112 changed: true, 113 children: null, 114 }, 115 }, 116 }, 117 { 118 sourcePath: [ 119 0, 120 ], 121 targetPath: [ 122 1, 123 ], 124 sourceValue: { 125 id: 10, 126 value: 'foo', 127 }, 128 targetValue: { 129 id: 10, 130 value: 'foo', 131 }, 132 sameValue: true, 133 sameValueZero: false, 134 retrievedId: '10', 135 sourceOrder: 0, 136 targetOrder: 1, 137 sameOrder: false, 138 sourceType: 'object', 139 targetType: 'object', 140 sameType: true, 141 added: false, 142 removed: false, 143 changed: false, 144 children: { 145 id: { 146 sourcePath: [ 147 0, 148 'id', 149 ], 150 targetPath: [ 151 1, 152 'id', 153 ], 154 sourceValue: 10, 155 targetValue: 10, 156 sameValue: true, 157 sameValueZero: true, 158 retrievedId: null, 159 sourceOrder: 0, 160 targetOrder: 0, 161 sameOrder: true, 162 sourceType: 'number', 163 targetType: 'number', 164 sameType: true, 165 added: false, 166 removed: false, 167 changed: false, 168 children: null, 169 }, 170 value: { 171 sourcePath: [ 172 0, 173 'value', 174 ], 175 targetPath: [ 176 1, 177 'value', 178 ], 179 sourceValue: 'foo', 180 targetValue: 'foo', 181 sameValue: true, 182 sameValueZero: true, 183 retrievedId: null, 184 sourceOrder: 1, 185 targetOrder: 1, 186 sameOrder: true, 187 sourceType: 'string', 188 targetType: 'string', 189 sameType: true, 190 added: false, 191 removed: false, 192 changed: false, 193 children: null, 194 }, 195 }, 196 }, 197 ], 198}
createDiff function accepts the following arguments
The diff function accepts two arguments: source and compare. Both arguments can be of any type (number, string, boolean, null, undefined, object, array).
The diff function returns a tree diff result objects. They contain the following properties:
sourcePath: string[] - the path to the source value in the source object
targetPath: string[] - the path to the target value in the target object
sourceValue: any - the value from the source object
targetValue: any - the value from the target object
sameValue: boolean - true if the source and target values are the same
sameValueZero: boolean - true if the source and target values are the same (using SameValueZero comparison)
retrievedId: string|number - the id of the object if it was retrieved from the source object
sourceOrder: number - the order of the element in the source (if the value is a field in an object or element of the array)
targetOrder: number - the order of the element in the target (if the value is a field in an object or element of the array)
sameOrder: boolean - true if the source and target orders are the same
sourceType: string - the type of the source value (one of the following: 'undefined', 'null', 'boolean', 'number', 'string', 'object', 'array', 'unknown')
targetType: string - the type of the target value (one of the following: 'undefined', 'null', 'boolean', 'number', 'string', 'object', 'array', 'unknown')
sameType: boolean - true if the source and target types are the same
added: boolean - true if the value was added in the target
removed: boolean - true if the value was removed in the target
changed: boolean - true if the value was changed in the target
children: object|array - the children of the value (if the value is an object or an array)
getValue function, if provided, will be used to calculate each value, on each level before the diff. For it to be useful, in most cases you need to either only modify the value for certain types (e.g. to allow for Map or Set support) or to modify only values in particular paths.
Usage example
1import createDiff, { getType, diffJsView, diffSortedView } from 'differrer'; 2 3const source = [{ id: 10, random: Math.random(), value: 'foo' }, { id: 1, random: Math.random(), value: 'bar' }]; 4const compare = [{ id: 1, random: Math.random(), value: 'bar' }, { id: 10, random: Math.random(), value: 'foo' }]; 5 6const diff = createDiff({ 7 getArrayElementId: (value: any) => value && typeof value === 'object' ? value.id : null, 8 getValue: (value, path) => { 9 if (path && path[path.length - 1] === 'random') { 10 return '[placeholder]'; 11 } 12 return value; 13 }, 14}); 15 16const results = diff(source, compare); 17 18expect(results.sameValue).toBe(true);
Keep in mind that the modified value will appear in diff structure only at the leaf that has been changed. The "sourceValue" and "targetValue" in all higher levels will still contain the original values.
The diff function understands the following types: undefined, null, boolean, number, string, array and object (only plain JS objects are considered objects). Anything else will have "unknown" type.
The diff result is not very readable in it's raw form. You can use one of the provided views functions to turn it into something more pleasant. The views functions accept the diff result object and return a string.
Usage example
1import createDiff, { getType, diffJsView, diffSortedView } from 'differrer'; 2 3const diff = createDiff({ getArrayElementId: (item: any) => getType(item) === 'object' ? item.id : item }); 4 5const source = [{ id: 10, value: 'foo' }, { id: 1, value: 'bar' }]; 6const compare = [{ id: 1, value: 'bar' }, { id: 10, value: 'foo' }]; 7 8const diffResult = diff(source, compare); 9 10const jsView = diffJsView(diffResults); 11const sortedView = diffSortedView(diffResults);
A view that will generate valid javascript (or JSON5) representation of source with changes marked in comments (change // ~, add // +, remove // -).
Here are a few examples:
Source | Compare | Result |
|
|
|
|
|
|
|
|
|
|
|
|
You can save the result to a file and have a valid JS code (or valid JSON5):
1import fs from 'fs';
2
3// ...
4
5const jsView = diffJsView(diffResults);
6
7writeFileSync('results.js', `const diff = ${jsView};`);
View that allows easier comparison in text diff tools that compare strings line by line (like diffchecker.com, diffmerge or diff view in JetBrains IDEs). It will align source and target objects in arrays according to provided getArrayElementId and leave empty lines for a diff tool to pick up easily.
Here are a few examples:
Data: | |
Source | Compare |
|
|
Results: | |
Source | Compare |
|
|
| |
Data: | |
Source | Compare |
|
|
Results: | |
Source | Compare |
|
|
| |
Data: | |
Source | Compare |
|
|
Results: | |
Source | Compare |
|
|
| |
Data: | |
Source | Compare |
|
|
Results: | |
Source | Compare |
|
|
View that displays only differences, useful for terminal output.
NOTE: diffChangesView does not support colored output in mjs build, as of version 1.1.1.
Here are a few examples:
Source | Compare | Result |
|
| |
|
| |
|
| |
|
|
No vulnerabilities found.
No security vulnerabilities found.