json-diff-ts 3.0.0-beta.4 → 3.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/dist/index.cjs +15 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -10,12 +10,26 @@ Another significant feature of this library is its ability to transform changese
|
|
|
10
10
|
|
|
11
11
|
This library is particularly valuable for applications where tracking changes in JSON data is crucial. It simplifies the process of comparing JSON objects and applying changes. The support for key-based array identification can be especially useful in complex JSON structures where tracking by index is not efficient or intuitive. JSONPath support further enhances its capabilities by allowing precise targeting of specific parts in a JSON document, making it a versatile tool for handling JSON data.
|
|
12
12
|
|
|
13
|
+
Starting with version 3, `json-diff-ts` now supports both ECMAScript Modules and CommonJS. This makes the library more versatile and compatible with various JavaScript environments. Whether you're working in a modern project that uses ES modules, or a Node.js project that uses CommonJS, you can now use `json-diff-ts` seamlessly.
|
|
14
|
+
|
|
13
15
|
## Installation
|
|
14
16
|
|
|
15
17
|
```sh
|
|
16
18
|
npm install json-diff-ts
|
|
17
19
|
```
|
|
18
20
|
|
|
21
|
+
In TypeScript or ES Modules, you can import the `diff` function like this:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { diff } from 'json-diff-ts';
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
In CommonJS, you can import the diff function like this:
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
const { diff } = require('json-diff-ts');
|
|
31
|
+
```
|
|
32
|
+
|
|
19
33
|
## Capabilities
|
|
20
34
|
|
|
21
35
|
### `diff`
|
|
@@ -24,7 +38,7 @@ Generates a difference set for JSON objects. When comparing arrays, if a specifi
|
|
|
24
38
|
|
|
25
39
|
#### Examples using Star Wars data:
|
|
26
40
|
|
|
27
|
-
```
|
|
41
|
+
```typescript
|
|
28
42
|
import { diff } from 'json-diff-ts';
|
|
29
43
|
|
|
30
44
|
const oldData = {
|
|
@@ -251,7 +265,7 @@ Reach out to the maintainer via LinkedIn or Twitter:
|
|
|
251
265
|
Discover more about the company behind this project: [hololux](https://hololux.com)
|
|
252
266
|
|
|
253
267
|
## Release Notes
|
|
254
|
-
- **v3.0.0:** Supports CommonJS and ECMAScript Modules
|
|
268
|
+
- **v3.0.0:** Supports CommonJS and ECMAScript Modules. Dependency to lodash-es was replaced with lodash to support both ECMAScript and CommonJS.
|
|
255
269
|
- **v2.2.0:** Fix lodash-es decependency, exclude keys, compare string arrays by value
|
|
256
270
|
- **v2.1.0:** Resolves a problem related to JSON Path filters by replacing the single equal sign (=) with a double equal sign (==). This update maintains compatibility with existing flat changes. Allows to use either '' or '.' as root in the path.
|
|
257
271
|
- **v2.0.0:** json-diff-ts has been upgraded to an ECMAScript module! This major update brings optimizations and enhanced documentation. Additionally, a previously existing issue where all paths were treated as regex has been fixed. In this new version, you'll need to use a Map instead of a Record for regex paths. Please note that this is a breaking change if you were using regex paths in the previous versions.
|
package/dist/index.cjs
CHANGED
|
@@ -37,7 +37,7 @@ __export(src_exports, {
|
|
|
37
37
|
module.exports = __toCommonJS(src_exports);
|
|
38
38
|
|
|
39
39
|
// src/jsonDiff.ts
|
|
40
|
-
var
|
|
40
|
+
var import_lodash = require("lodash");
|
|
41
41
|
var Operation = /* @__PURE__ */ ((Operation2) => {
|
|
42
42
|
Operation2["REMOVE"] = "REMOVE";
|
|
43
43
|
Operation2["ADD"] = "ADD";
|
|
@@ -274,7 +274,7 @@ var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath =
|
|
|
274
274
|
let changes = [];
|
|
275
275
|
const oldObjKeys = Object.keys(oldObj).filter((key) => keysToSkip.indexOf(key) === -1);
|
|
276
276
|
const newObjKeys = Object.keys(newObj).filter((key) => keysToSkip.indexOf(key) === -1);
|
|
277
|
-
const intersectionKeys = (0,
|
|
277
|
+
const intersectionKeys = (0, import_lodash.intersection)(oldObjKeys, newObjKeys);
|
|
278
278
|
for (k of intersectionKeys) {
|
|
279
279
|
newPath = path.concat([k]);
|
|
280
280
|
newKeyPath = skipPath ? keyPath : keyPath.concat([k]);
|
|
@@ -283,7 +283,7 @@ var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath =
|
|
|
283
283
|
changes = changes.concat(diffs);
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
|
-
const addedKeys = (0,
|
|
286
|
+
const addedKeys = (0, import_lodash.difference)(newObjKeys, oldObjKeys);
|
|
287
287
|
for (k of addedKeys) {
|
|
288
288
|
newPath = path.concat([k]);
|
|
289
289
|
newKeyPath = skipPath ? keyPath : keyPath.concat([k]);
|
|
@@ -293,7 +293,7 @@ var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath =
|
|
|
293
293
|
value: newObj[k]
|
|
294
294
|
});
|
|
295
295
|
}
|
|
296
|
-
const deletedKeys = (0,
|
|
296
|
+
const deletedKeys = (0, import_lodash.difference)(oldObjKeys, newObjKeys);
|
|
297
297
|
for (k of deletedKeys) {
|
|
298
298
|
newPath = path.concat([k]);
|
|
299
299
|
newKeyPath = skipPath ? keyPath : keyPath.concat([k]);
|
|
@@ -352,7 +352,7 @@ var convertArrayToObj = (arr, uniqKey) => {
|
|
|
352
352
|
obj[value] = value;
|
|
353
353
|
});
|
|
354
354
|
} else if (uniqKey !== "$index") {
|
|
355
|
-
obj = (0,
|
|
355
|
+
obj = (0, import_lodash.keyBy)(arr, uniqKey);
|
|
356
356
|
} else {
|
|
357
357
|
for (let i = 0; i < arr.length; i++) {
|
|
358
358
|
const value = arr[i];
|
|
@@ -437,7 +437,7 @@ var applyArrayChange = (arr, change) => (() => {
|
|
|
437
437
|
element = arr[index];
|
|
438
438
|
}
|
|
439
439
|
} else {
|
|
440
|
-
element = (0,
|
|
440
|
+
element = (0, import_lodash.find)(arr, (el) => el[change.embeddedKey]?.toString() === subchange.key.toString());
|
|
441
441
|
}
|
|
442
442
|
result.push(applyChangeset(element, subchange.changes));
|
|
443
443
|
}
|
|
@@ -472,7 +472,7 @@ var revertArrayChange = (arr, change) => (() => {
|
|
|
472
472
|
if (change.embeddedKey === "$index") {
|
|
473
473
|
element = arr[+subchange.key];
|
|
474
474
|
} else {
|
|
475
|
-
element = (0,
|
|
475
|
+
element = (0, import_lodash.find)(arr, (el) => el[change.embeddedKey].toString() === subchange.key);
|
|
476
476
|
}
|
|
477
477
|
result.push(revertChangeset(element, subchange.changes));
|
|
478
478
|
}
|
|
@@ -495,7 +495,7 @@ function filterExpression(basePath, filterKey, filterValue) {
|
|
|
495
495
|
}
|
|
496
496
|
|
|
497
497
|
// src/jsonCompare.ts
|
|
498
|
-
var
|
|
498
|
+
var import_lodash2 = require("lodash");
|
|
499
499
|
var CompareOperation = /* @__PURE__ */ ((CompareOperation2) => {
|
|
500
500
|
CompareOperation2["CONTAINER"] = "CONTAINER";
|
|
501
501
|
CompareOperation2["UNCHANGED"] = "UNCHANGED";
|
|
@@ -510,12 +510,12 @@ var enrich = (object) => {
|
|
|
510
510
|
const objectType = getTypeOfObj(object);
|
|
511
511
|
switch (objectType) {
|
|
512
512
|
case "Object":
|
|
513
|
-
return (0,
|
|
513
|
+
return (0, import_lodash2.keys)(object).map((key) => ({ key, value: enrich(object[key]) })).reduce((accumulator, entry) => {
|
|
514
514
|
accumulator.value[entry.key] = entry.value;
|
|
515
515
|
return accumulator;
|
|
516
516
|
}, createContainer({}));
|
|
517
517
|
case "Array":
|
|
518
|
-
return (0,
|
|
518
|
+
return (0, import_lodash2.chain)(object).map((value) => enrich(value)).reduce((accumulator, value) => {
|
|
519
519
|
accumulator.value.push(value);
|
|
520
520
|
return accumulator;
|
|
521
521
|
}, createContainer([])).value();
|
|
@@ -527,17 +527,17 @@ var enrich = (object) => {
|
|
|
527
527
|
}
|
|
528
528
|
};
|
|
529
529
|
var applyChangelist = (object, changelist) => {
|
|
530
|
-
(0,
|
|
530
|
+
(0, import_lodash2.chain)(changelist).map((entry) => ({ ...entry, path: (0, import_lodash2.replace)(entry.path, "$.", ".") })).map((entry) => ({
|
|
531
531
|
...entry,
|
|
532
|
-
path: (0,
|
|
533
|
-
})).map((entry) => ({ ...entry, path: (0,
|
|
532
|
+
path: (0, import_lodash2.replace)(entry.path, /(\[(?<array>\d)\]\.)/g, "ARRVAL_START$<array>ARRVAL_END")
|
|
533
|
+
})).map((entry) => ({ ...entry, path: (0, import_lodash2.replace)(entry.path, /(?<dot>\.)/g, ".value$<dot>") })).map((entry) => ({ ...entry, path: (0, import_lodash2.replace)(entry.path, /\./, "") })).map((entry) => ({ ...entry, path: (0, import_lodash2.replace)(entry.path, /ARRVAL_START/g, ".value[") })).map((entry) => ({ ...entry, path: (0, import_lodash2.replace)(entry.path, /ARRVAL_END/g, "].value.") })).value().forEach((entry) => {
|
|
534
534
|
switch (entry.type) {
|
|
535
535
|
case "ADD" /* ADD */:
|
|
536
536
|
case "UPDATE" /* UPDATE */:
|
|
537
|
-
(0,
|
|
537
|
+
(0, import_lodash2.set)(object, entry.path, { type: entry.type, value: entry.value, oldValue: entry.oldValue });
|
|
538
538
|
break;
|
|
539
539
|
case "REMOVE" /* REMOVE */:
|
|
540
|
-
(0,
|
|
540
|
+
(0, import_lodash2.set)(object, entry.path, { type: entry.type, value: void 0, oldValue: entry.value });
|
|
541
541
|
break;
|
|
542
542
|
default:
|
|
543
543
|
throw new Error();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/jsonDiff.ts","../src/jsonCompare.ts"],"sourcesContent":["export * from './jsonDiff.js';\nexport * from './jsonCompare.js';\n","import { difference, find, intersection, keyBy } from 'lodash-es';\n\ntype FunctionKey = (obj: any, shouldReturnKeyName?: boolean) => any;\nexport type EmbeddedObjKeysType = Record<string, string | FunctionKey>;\nexport type EmbeddedObjKeysMapType = Map<string | RegExp, string | FunctionKey>;\nexport enum Operation {\n REMOVE = 'REMOVE',\n ADD = 'ADD',\n UPDATE = 'UPDATE'\n}\n\nexport interface IChange {\n type: Operation;\n key: string;\n embeddedKey?: string | FunctionKey;\n value?: any | any[];\n oldValue?: any;\n changes?: IChange[];\n}\nexport type Changeset = IChange[];\n\nexport interface IFlatChange {\n type: Operation;\n key: string;\n path: string;\n valueType: string | null;\n value?: any;\n oldValue?: any;\n}\n\n/**\n * Computes the difference between two objects.\n *\n * @param {any} oldObj - The original object.\n * @param {any} newObj - The updated object.\n * @param {EmbeddedObjKeysType | EmbeddedObjKeysMapType} embeddedObjKeys - An optional parameter specifying keys of embedded objects.\n * @returns {IChange[]} - An array of changes that transform the old object into the new object.\n */\nexport function diff(\n oldObj: any,\n newObj: any,\n embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType,\n keysToSkip?: string[]\n): IChange[] {\n // Trim leading '.' from keys in embeddedObjKeys\n if (embeddedObjKeys instanceof Map) {\n embeddedObjKeys = new Map(\n Array.from(embeddedObjKeys.entries()).map(([key, value]) => [\n key instanceof RegExp ? key : key.replace(/^\\./, ''),\n value\n ])\n );\n } else if (embeddedObjKeys) {\n embeddedObjKeys = Object.fromEntries(\n Object.entries(embeddedObjKeys).map(([key, value]) => [key.replace(/^\\./, ''), value])\n );\n }\n\n // Compare old and new objects to generate a list of changes\n return compare(oldObj, newObj, [], embeddedObjKeys, [], keysToSkip);\n}\n\n/**\n * Applies all changes in the changeset to the object.\n *\n * @param {any} obj - The object to apply changes to.\n * @param {Changeset} changeset - The changeset to apply.\n * @returns {any} - The object after the changes from the changeset have been applied.\n *\n * The function first checks if a changeset is provided. If so, it iterates over each change in the changeset.\n * If the change value is not null or undefined, or if the change type is REMOVE, it applies the change to the object directly.\n * Otherwise, it applies the change to the corresponding branch of the object.\n */\nexport const applyChangeset = (obj: any, changeset: Changeset) => {\n if (changeset) {\n changeset.forEach((change) => {\n const { type, key, value, embeddedKey } = change;\n\n if ((value !== null && value !== undefined) || type === Operation.REMOVE) {\n // Apply the change to the object\n applyLeafChange(obj, change, embeddedKey);\n } else {\n // Apply the change to the branch\n applyBranchChange(obj[key], change);\n }\n });\n }\n return obj;\n};\n\n/**\n * Reverts the changes made to an object based on a given changeset.\n *\n * @param {any} obj - The object on which to revert changes.\n * @param {Changeset} changeset - The changeset to revert.\n * @returns {any} - The object after the changes from the changeset have been reverted.\n *\n * The function first checks if a changeset is provided. If so, it reverses the changeset to start reverting from the last change.\n * It then iterates over each change in the changeset. If the change does not have any nested changes, it reverts the change on the object directly.\n * If the change does have nested changes, it reverts the changes on the corresponding branch of the object.\n */\nexport const revertChangeset = (obj: any, changeset: Changeset) => {\n if (changeset) {\n changeset\n .reverse()\n .forEach((change: IChange): any =>\n !change.changes ? revertLeafChange(obj, change) : revertBranchChange(obj[change.key], change)\n );\n }\n\n return obj;\n};\n\n/**\n * Flattens a changeset into an array of flat changes.\n *\n * @param {Changeset | IChange} obj - The changeset or change to flatten.\n * @param {string} [path='$'] - The current path in the changeset.\n * @param {string | FunctionKey} [embeddedKey] - The key to use for embedded objects.\n * @returns {IFlatChange[]} - An array of flat changes.\n *\n * The function first checks if the input is an array. If so, it recursively flattens each change in the array.\n * If the input is not an array, it checks if the change has nested changes or an embedded key.\n * If so, it updates the path and recursively flattens the nested changes or the embedded object.\n * If the change does not have nested changes or an embedded key, it creates a flat change and returns it in an array.\n */\nexport const flattenChangeset = (\n obj: Changeset | IChange,\n path = '$',\n embeddedKey?: string | FunctionKey\n): IFlatChange[] => {\n if (Array.isArray(obj)) {\n return obj.reduce((memo, change) => [...memo, ...flattenChangeset(change, path, embeddedKey)], [] as IFlatChange[]);\n } else {\n if (obj.changes || embeddedKey) {\n if (embeddedKey) {\n if (embeddedKey === '$index') {\n path = `${path}[${obj.key}]`;\n } else if (embeddedKey === '$value') {\n path = `${path}[?(@='${obj.key}')]`;\n const valueType = getTypeOfObj(obj.value);\n return [\n {\n ...obj,\n path,\n valueType\n }\n ];\n } else if (obj.type === Operation.ADD) {\n // do nothing\n } else {\n path = filterExpression(path, embeddedKey, obj.key);\n }\n } else {\n path = append(path, obj.key);\n }\n\n return flattenChangeset(obj.changes || obj, path, obj.embeddedKey);\n } else {\n const valueType = getTypeOfObj(obj.value);\n return [\n {\n ...obj,\n path: valueType === 'Object' || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),\n valueType\n }\n ];\n }\n }\n};\n\n/**\n * Transforms a flat changeset into a nested changeset.\n *\n * @param {IFlatChange | IFlatChange[]} changes - The flat changeset to unflatten.\n * @returns {IChange[]} - The unflattened changeset.\n *\n * The function first checks if the input is a single change or an array of changes.\n * It then iterates over each change and splits its path into segments.\n * For each segment, it checks if it represents an array or a leaf node.\n * If it represents an array, it creates a new change object and updates the pointer to this new object.\n * If it represents a leaf node, it sets the key, type, value, and oldValue of the current change object.\n * Finally, it pushes the unflattened change object into the changes array.\n */\nexport const unflattenChanges = (changes: IFlatChange | IFlatChange[]) => {\n if (!Array.isArray(changes)) {\n changes = [changes];\n }\n\n const changesArr: IChange[] = [];\n\n changes.forEach((change) => {\n const obj = {} as IChange;\n let ptr = obj;\n\n const segments = change.path.split(/(?<=[^@])\\.(?=[^@])/);\n\n if (segments.length === 1) {\n ptr.key = change.key;\n ptr.type = change.type;\n ptr.value = change.value;\n ptr.oldValue = change.oldValue;\n changesArr.push(ptr);\n } else {\n for (let i = 1; i < segments.length; i++) {\n const segment = segments[i];\n // Matches JSONPath segments: \"items[?(@.id=='123')]\", \"items[?(@.id==123)]\", \"items[2]\", \"items[?(@='123')]\"\n const result = /^(.+?)\\[\\?\\(@.?(?:([^=]*))?={1,2}'(.*)'\\)\\]$|^(.+?)\\[(\\d+)\\]$/.exec(segment); //NOSONAR\n // array\n if (result) {\n let key: string;\n let embeddedKey: string;\n let arrKey: string | number;\n if (result[1]) {\n key = result[1];\n embeddedKey = result[2] || '$value';\n arrKey = result[3];\n } else {\n key = result[4];\n embeddedKey = '$index';\n arrKey = Number(result[4]);\n }\n // leaf\n if (i === segments.length - 1) {\n ptr.key = key!;\n ptr.embeddedKey = embeddedKey!;\n ptr.type = Operation.UPDATE;\n ptr.changes = [\n {\n type: change.type,\n key: arrKey!,\n value: change.value,\n oldValue: change.oldValue\n } as IChange\n ];\n } else {\n // object\n ptr.key = key;\n ptr.embeddedKey = embeddedKey;\n ptr.type = Operation.UPDATE;\n const newPtr = {} as IChange;\n ptr.changes = [\n {\n type: Operation.UPDATE,\n key: arrKey,\n changes: [newPtr]\n } as IChange\n ];\n ptr = newPtr;\n }\n } else {\n // leaf\n if (i === segments.length - 1) {\n // check if value is a primitive or object\n if (change.value !== null && change.valueType === 'Object') {\n ptr.key = segment;\n ptr.type = Operation.UPDATE;\n ptr.changes = [\n {\n key: change.key,\n type: change.type,\n value: change.value\n } as IChange\n ];\n } else {\n ptr.key = change.key;\n ptr.type = change.type;\n ptr.value = change.value;\n ptr.oldValue = change.oldValue;\n }\n } else {\n // branch\n ptr.key = segment;\n ptr.type = Operation.UPDATE;\n const newPtr = {} as IChange;\n ptr.changes = [newPtr];\n ptr = newPtr;\n }\n }\n }\n changesArr.push(obj);\n }\n });\n return changesArr;\n};\n\n/**\n * Determines the type of a given object.\n *\n * @param {any} obj - The object whose type is to be determined.\n * @returns {string | null} - The type of the object, or null if the object is null.\n *\n * This function first checks if the object is undefined or null, and returns 'undefined' or null respectively.\n * If the object is neither undefined nor null, it uses Object.prototype.toString to get the object's type.\n * The type is extracted from the string returned by Object.prototype.toString using a regular expression.\n */\nexport const getTypeOfObj = (obj: any) => {\n if (typeof obj === 'undefined') {\n return 'undefined';\n }\n\n if (obj === null) {\n return null;\n }\n\n // Extracts the \"Type\" from \"[object Type]\" string.\n return Object.prototype.toString.call(obj).match(/^\\[object\\s(.*)\\]$/)[1];\n};\n\nconst getKey = (path: string) => {\n const left = path[path.length - 1];\n return left != null ? left : '$root';\n};\n\nconst compare = (oldObj: any, newObj: any, path: any, embeddedObjKeys: any, keyPath: any, keysToSkip: string[]) => {\n let changes: any[] = [];\n\n const typeOfOldObj = getTypeOfObj(oldObj);\n const typeOfNewObj = getTypeOfObj(newObj);\n\n // if type of object changes, consider it as old obj has been deleted and a new object has been added\n if (typeOfOldObj !== typeOfNewObj) {\n changes.push({ type: Operation.REMOVE, key: getKey(path), value: oldObj });\n changes.push({ type: Operation.ADD, key: getKey(path), value: newObj });\n return changes;\n }\n\n switch (typeOfOldObj) {\n case 'Date':\n changes = changes.concat(\n comparePrimitives(oldObj.getTime(), newObj.getTime(), path).map((x) => ({\n ...x,\n value: new Date(x.value),\n oldValue: new Date(x.oldValue)\n }))\n );\n break;\n case 'Object':\n const diffs = compareObject(oldObj, newObj, path, embeddedObjKeys, keyPath, false, keysToSkip);\n if (diffs.length) {\n if (path.length) {\n changes.push({\n type: Operation.UPDATE,\n key: getKey(path),\n changes: diffs\n });\n } else {\n changes = changes.concat(diffs);\n }\n }\n break;\n case 'Array':\n changes = changes.concat(compareArray(oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip));\n break;\n case 'Function':\n break;\n // do nothing\n default:\n changes = changes.concat(comparePrimitives(oldObj, newObj, path));\n }\n\n return changes;\n};\n\nconst compareObject = (\n oldObj: any,\n newObj: any,\n path: any,\n embeddedObjKeys: any,\n keyPath: any,\n skipPath = false,\n keysToSkip: string[] = []\n) => {\n let k;\n let newKeyPath;\n let newPath;\n\n if (skipPath == null) {\n skipPath = false;\n }\n let changes: any[] = [];\n\n const oldObjKeys = Object.keys(oldObj).filter((key) => keysToSkip.indexOf(key) === -1);\n const newObjKeys = Object.keys(newObj).filter((key) => keysToSkip.indexOf(key) === -1);\n\n const intersectionKeys = intersection(oldObjKeys, newObjKeys);\n for (k of intersectionKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n const diffs = compare(oldObj[k], newObj[k], newPath, embeddedObjKeys, newKeyPath, keysToSkip);\n if (diffs.length) {\n changes = changes.concat(diffs);\n }\n }\n\n const addedKeys = difference(newObjKeys, oldObjKeys);\n for (k of addedKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n changes.push({\n type: Operation.ADD,\n key: getKey(newPath),\n value: newObj[k]\n });\n }\n\n const deletedKeys = difference(oldObjKeys, newObjKeys);\n for (k of deletedKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n changes.push({\n type: Operation.REMOVE,\n key: getKey(newPath),\n value: oldObj[k]\n });\n }\n return changes;\n};\n\nconst compareArray = (\n oldObj: any,\n newObj: any,\n path: any,\n embeddedObjKeys: any,\n keyPath: any,\n keysToSkip: string[]\n) => {\n const left = getObjectKey(embeddedObjKeys, keyPath);\n const uniqKey = left != null ? left : '$index';\n const indexedOldObj = convertArrayToObj(oldObj, uniqKey);\n const indexedNewObj = convertArrayToObj(newObj, uniqKey);\n const diffs = compareObject(indexedOldObj, indexedNewObj, path, embeddedObjKeys, keyPath, true, keysToSkip);\n if (diffs.length) {\n return [\n {\n type: Operation.UPDATE,\n key: getKey(path),\n embeddedKey: typeof uniqKey === 'function' && uniqKey.length === 2 ? uniqKey(newObj[0], true) : uniqKey,\n changes: diffs\n }\n ];\n } else {\n return [];\n }\n};\n\nconst getObjectKey = (embeddedObjKeys: any, keyPath: any) => {\n if (embeddedObjKeys != null) {\n const path = keyPath.join('.');\n\n if (embeddedObjKeys instanceof Map) {\n for (const [key, value] of embeddedObjKeys.entries()) {\n if (key instanceof RegExp) {\n if (path.match(key)) {\n return value;\n }\n } else if (path === key) {\n return value;\n }\n }\n }\n\n const key = embeddedObjKeys[path];\n if (key != null) {\n return key;\n }\n }\n return undefined;\n};\n\nconst convertArrayToObj = (arr: any[], uniqKey: any) => {\n let obj: any = {};\n if (uniqKey === '$value') {\n arr.forEach((value) => {\n obj[value] = value;\n });\n } else if (uniqKey !== '$index') {\n obj = keyBy(arr, uniqKey);\n } else {\n for (let i = 0; i < arr.length; i++) {\n const value = arr[i];\n obj[i] = value;\n }\n }\n return obj;\n};\n\nconst comparePrimitives = (oldObj: any, newObj: any, path: any) => {\n const changes = [];\n if (oldObj !== newObj) {\n changes.push({\n type: Operation.UPDATE,\n key: getKey(path),\n value: newObj,\n oldValue: oldObj\n });\n }\n return changes;\n};\n\nconst removeKey = (obj: any, key: any, embeddedKey: any) => {\n if (Array.isArray(obj)) {\n if (embeddedKey === '$index') {\n obj.splice(key);\n return;\n }\n const index = indexOfItemInArray(obj, embeddedKey, key);\n if (index === -1) {\n // tslint:disable-next-line:no-console\n console.warn(`Element with the key '${embeddedKey}' and value '${key}' could not be found in the array'`);\n return;\n }\n return obj.splice(index != null ? index : key, 1);\n } else {\n obj[key] = undefined;\n delete obj[key];\n return;\n }\n};\n\nconst indexOfItemInArray = (arr: any[], key: any, value: any) => {\n if (key === '$value') {\n return arr.indexOf(value);\n }\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i];\n if (item && item[key] ? item[key].toString() === value.toString() : undefined) {\n return i;\n }\n }\n return -1;\n};\n\nconst modifyKeyValue = (obj: any, key: any, value: any) => (obj[key] = value);\n\nconst addKeyValue = (obj: any, key: any, value: any) => {\n if (Array.isArray(obj)) {\n return obj.push(value);\n } else {\n return obj ? (obj[key] = value) : null;\n }\n};\n\nconst applyLeafChange = (obj: any, change: any, embeddedKey: any) => {\n const { type, key, value } = change;\n switch (type) {\n case Operation.ADD:\n return addKeyValue(obj, key, value);\n case Operation.UPDATE:\n return modifyKeyValue(obj, key, value);\n case Operation.REMOVE:\n return removeKey(obj, key, embeddedKey);\n }\n};\n\nconst applyArrayChange = (arr: any, change: any) =>\n (() => {\n const result = [];\n for (const subchange of change.changes) {\n if (subchange.value != null || subchange.type === Operation.REMOVE) {\n result.push(applyLeafChange(arr, subchange, change.embeddedKey));\n } else {\n let element;\n if (change.embeddedKey === '$index') {\n element = arr[subchange.key];\n } else if (change.embeddedKey === '$value') {\n const index = arr.indexOf(subchange.key);\n if (index !== -1) {\n element = arr[index];\n }\n } else {\n element = find(arr, (el) => el[change.embeddedKey]?.toString() === subchange.key.toString());\n }\n result.push(applyChangeset(element, subchange.changes));\n }\n }\n return result;\n })();\n\nconst applyBranchChange = (obj: any, change: any) => {\n if (Array.isArray(obj)) {\n return applyArrayChange(obj, change);\n } else {\n return applyChangeset(obj, change.changes);\n }\n};\n\nconst revertLeafChange = (obj: any, change: any, embeddedKey = '$index') => {\n const { type, key, value, oldValue } = change;\n switch (type) {\n case Operation.ADD:\n return removeKey(obj, key, embeddedKey);\n case Operation.UPDATE:\n return modifyKeyValue(obj, key, oldValue);\n case Operation.REMOVE:\n return addKeyValue(obj, key, value);\n }\n};\n\nconst revertArrayChange = (arr: any, change: any) =>\n (() => {\n const result = [];\n for (const subchange of change.changes) {\n if (subchange.value != null || subchange.type === Operation.REMOVE) {\n result.push(revertLeafChange(arr, subchange, change.embeddedKey));\n } else {\n let element;\n if (change.embeddedKey === '$index') {\n element = arr[+subchange.key];\n } else {\n element = find(arr, (el) => el[change.embeddedKey].toString() === subchange.key);\n }\n result.push(revertChangeset(element, subchange.changes));\n }\n }\n return result;\n })();\n\nconst revertBranchChange = (obj: any, change: any) => {\n if (Array.isArray(obj)) {\n return revertArrayChange(obj, change);\n } else {\n return revertChangeset(obj, change.changes);\n }\n};\n\n/** combine a base JSON Path with a subsequent segment */\nfunction append(basePath: string, nextSegment: string): string {\n return nextSegment.includes('.') ? `${basePath}[${nextSegment}]` : `${basePath}.${nextSegment}`;\n}\n\n/** returns a JSON Path filter expression; e.g., `$.pet[(?name='spot')]` */\nfunction filterExpression(basePath: string, filterKey: string | FunctionKey, filterValue: string | number) {\n const value = typeof filterValue === 'number' ? filterValue : `'${filterValue}'`;\n return typeof filterKey === 'string' && filterKey.includes('.')\n ? `${basePath}[?(@[${filterKey}]==${value})]`\n : `${basePath}[?(@.${filterKey}==${value})]`;\n}\n","import { chain, keys, replace, set } from 'lodash-es';\nimport { diff, flattenChangeset, getTypeOfObj, IFlatChange, Operation } from './jsonDiff.js';\n\nexport enum CompareOperation {\n CONTAINER = 'CONTAINER',\n UNCHANGED = 'UNCHANGED'\n}\n\nexport interface IComparisonEnrichedNode {\n type: Operation | CompareOperation;\n value: IComparisonEnrichedNode | IComparisonEnrichedNode[] | any | any[];\n oldValue?: any;\n}\n\nexport const createValue = (value: any): IComparisonEnrichedNode => ({ type: CompareOperation.UNCHANGED, value });\nexport const createContainer = (value: object | []): IComparisonEnrichedNode => ({\n type: CompareOperation.CONTAINER,\n value\n});\n\nexport const enrich = (object: any): IComparisonEnrichedNode => {\n const objectType = getTypeOfObj(object);\n\n switch (objectType) {\n case 'Object':\n return keys(object)\n .map((key: string) => ({ key, value: enrich(object[key]) }))\n .reduce((accumulator, entry) => {\n accumulator.value[entry.key] = entry.value;\n return accumulator;\n }, createContainer({}));\n case 'Array':\n return chain(object)\n .map((value) => enrich(value))\n .reduce((accumulator, value) => {\n accumulator.value.push(value);\n return accumulator;\n }, createContainer([]))\n .value();\n case 'Function':\n return undefined;\n case 'Date':\n default:\n // Primitive value\n return createValue(object);\n }\n};\n\nexport const applyChangelist = (\n object: IComparisonEnrichedNode,\n changelist: IFlatChange[]\n): IComparisonEnrichedNode => {\n chain(changelist)\n .map((entry) => ({ ...entry, path: replace(entry.path, '$.', '.') }))\n .map((entry) => ({\n ...entry,\n path: replace(entry.path, /(\\[(?<array>\\d)\\]\\.)/g, 'ARRVAL_START$<array>ARRVAL_END')\n }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /(?<dot>\\.)/g, '.value$<dot>') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /\\./, '') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /ARRVAL_START/g, '.value[') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /ARRVAL_END/g, '].value.') }))\n .value()\n .forEach((entry) => {\n switch (entry.type) {\n case Operation.ADD:\n case Operation.UPDATE:\n set(object, entry.path, { type: entry.type, value: entry.value, oldValue: entry.oldValue });\n break;\n case Operation.REMOVE:\n set(object, entry.path, { type: entry.type, value: undefined, oldValue: entry.value });\n break;\n default:\n throw new Error();\n }\n });\n return object;\n};\n\nexport const compare = (oldObject: any, newObject: any): IComparisonEnrichedNode => {\n return applyChangelist(enrich(oldObject), flattenChangeset(diff(oldObject, newObject)));\n};\n"],"mappings":"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","names":["compare","Operation","key","import_lodash_es","CompareOperation","compare"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/jsonDiff.ts","../src/jsonCompare.ts"],"sourcesContent":["export * from './jsonDiff.js';\nexport * from './jsonCompare.js';\n","import { difference, find, intersection, keyBy } from 'lodash';\n\ntype FunctionKey = (obj: any, shouldReturnKeyName?: boolean) => any;\nexport type EmbeddedObjKeysType = Record<string, string | FunctionKey>;\nexport type EmbeddedObjKeysMapType = Map<string | RegExp, string | FunctionKey>;\nexport enum Operation {\n REMOVE = 'REMOVE',\n ADD = 'ADD',\n UPDATE = 'UPDATE'\n}\n\nexport interface IChange {\n type: Operation;\n key: string;\n embeddedKey?: string | FunctionKey;\n value?: any | any[];\n oldValue?: any;\n changes?: IChange[];\n}\nexport type Changeset = IChange[];\n\nexport interface IFlatChange {\n type: Operation;\n key: string;\n path: string;\n valueType: string | null;\n value?: any;\n oldValue?: any;\n}\n\n/**\n * Computes the difference between two objects.\n *\n * @param {any} oldObj - The original object.\n * @param {any} newObj - The updated object.\n * @param {EmbeddedObjKeysType | EmbeddedObjKeysMapType} embeddedObjKeys - An optional parameter specifying keys of embedded objects.\n * @returns {IChange[]} - An array of changes that transform the old object into the new object.\n */\nexport function diff(\n oldObj: any,\n newObj: any,\n embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType,\n keysToSkip?: string[]\n): IChange[] {\n // Trim leading '.' from keys in embeddedObjKeys\n if (embeddedObjKeys instanceof Map) {\n embeddedObjKeys = new Map(\n Array.from(embeddedObjKeys.entries()).map(([key, value]) => [\n key instanceof RegExp ? key : key.replace(/^\\./, ''),\n value\n ])\n );\n } else if (embeddedObjKeys) {\n embeddedObjKeys = Object.fromEntries(\n Object.entries(embeddedObjKeys).map(([key, value]) => [key.replace(/^\\./, ''), value])\n );\n }\n\n // Compare old and new objects to generate a list of changes\n return compare(oldObj, newObj, [], embeddedObjKeys, [], keysToSkip);\n}\n\n/**\n * Applies all changes in the changeset to the object.\n *\n * @param {any} obj - The object to apply changes to.\n * @param {Changeset} changeset - The changeset to apply.\n * @returns {any} - The object after the changes from the changeset have been applied.\n *\n * The function first checks if a changeset is provided. If so, it iterates over each change in the changeset.\n * If the change value is not null or undefined, or if the change type is REMOVE, it applies the change to the object directly.\n * Otherwise, it applies the change to the corresponding branch of the object.\n */\nexport const applyChangeset = (obj: any, changeset: Changeset) => {\n if (changeset) {\n changeset.forEach((change) => {\n const { type, key, value, embeddedKey } = change;\n\n if ((value !== null && value !== undefined) || type === Operation.REMOVE) {\n // Apply the change to the object\n applyLeafChange(obj, change, embeddedKey);\n } else {\n // Apply the change to the branch\n applyBranchChange(obj[key], change);\n }\n });\n }\n return obj;\n};\n\n/**\n * Reverts the changes made to an object based on a given changeset.\n *\n * @param {any} obj - The object on which to revert changes.\n * @param {Changeset} changeset - The changeset to revert.\n * @returns {any} - The object after the changes from the changeset have been reverted.\n *\n * The function first checks if a changeset is provided. If so, it reverses the changeset to start reverting from the last change.\n * It then iterates over each change in the changeset. If the change does not have any nested changes, it reverts the change on the object directly.\n * If the change does have nested changes, it reverts the changes on the corresponding branch of the object.\n */\nexport const revertChangeset = (obj: any, changeset: Changeset) => {\n if (changeset) {\n changeset\n .reverse()\n .forEach((change: IChange): any =>\n !change.changes ? revertLeafChange(obj, change) : revertBranchChange(obj[change.key], change)\n );\n }\n\n return obj;\n};\n\n/**\n * Flattens a changeset into an array of flat changes.\n *\n * @param {Changeset | IChange} obj - The changeset or change to flatten.\n * @param {string} [path='$'] - The current path in the changeset.\n * @param {string | FunctionKey} [embeddedKey] - The key to use for embedded objects.\n * @returns {IFlatChange[]} - An array of flat changes.\n *\n * The function first checks if the input is an array. If so, it recursively flattens each change in the array.\n * If the input is not an array, it checks if the change has nested changes or an embedded key.\n * If so, it updates the path and recursively flattens the nested changes or the embedded object.\n * If the change does not have nested changes or an embedded key, it creates a flat change and returns it in an array.\n */\nexport const flattenChangeset = (\n obj: Changeset | IChange,\n path = '$',\n embeddedKey?: string | FunctionKey\n): IFlatChange[] => {\n if (Array.isArray(obj)) {\n return obj.reduce((memo, change) => [...memo, ...flattenChangeset(change, path, embeddedKey)], [] as IFlatChange[]);\n } else {\n if (obj.changes || embeddedKey) {\n if (embeddedKey) {\n if (embeddedKey === '$index') {\n path = `${path}[${obj.key}]`;\n } else if (embeddedKey === '$value') {\n path = `${path}[?(@='${obj.key}')]`;\n const valueType = getTypeOfObj(obj.value);\n return [\n {\n ...obj,\n path,\n valueType\n }\n ];\n } else if (obj.type === Operation.ADD) {\n // do nothing\n } else {\n path = filterExpression(path, embeddedKey, obj.key);\n }\n } else {\n path = append(path, obj.key);\n }\n\n return flattenChangeset(obj.changes || obj, path, obj.embeddedKey);\n } else {\n const valueType = getTypeOfObj(obj.value);\n return [\n {\n ...obj,\n path: valueType === 'Object' || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),\n valueType\n }\n ];\n }\n }\n};\n\n/**\n * Transforms a flat changeset into a nested changeset.\n *\n * @param {IFlatChange | IFlatChange[]} changes - The flat changeset to unflatten.\n * @returns {IChange[]} - The unflattened changeset.\n *\n * The function first checks if the input is a single change or an array of changes.\n * It then iterates over each change and splits its path into segments.\n * For each segment, it checks if it represents an array or a leaf node.\n * If it represents an array, it creates a new change object and updates the pointer to this new object.\n * If it represents a leaf node, it sets the key, type, value, and oldValue of the current change object.\n * Finally, it pushes the unflattened change object into the changes array.\n */\nexport const unflattenChanges = (changes: IFlatChange | IFlatChange[]) => {\n if (!Array.isArray(changes)) {\n changes = [changes];\n }\n\n const changesArr: IChange[] = [];\n\n changes.forEach((change) => {\n const obj = {} as IChange;\n let ptr = obj;\n\n const segments = change.path.split(/(?<=[^@])\\.(?=[^@])/);\n\n if (segments.length === 1) {\n ptr.key = change.key;\n ptr.type = change.type;\n ptr.value = change.value;\n ptr.oldValue = change.oldValue;\n changesArr.push(ptr);\n } else {\n for (let i = 1; i < segments.length; i++) {\n const segment = segments[i];\n // Matches JSONPath segments: \"items[?(@.id=='123')]\", \"items[?(@.id==123)]\", \"items[2]\", \"items[?(@='123')]\"\n const result = /^(.+?)\\[\\?\\(@.?(?:([^=]*))?={1,2}'(.*)'\\)\\]$|^(.+?)\\[(\\d+)\\]$/.exec(segment); //NOSONAR\n // array\n if (result) {\n let key: string;\n let embeddedKey: string;\n let arrKey: string | number;\n if (result[1]) {\n key = result[1];\n embeddedKey = result[2] || '$value';\n arrKey = result[3];\n } else {\n key = result[4];\n embeddedKey = '$index';\n arrKey = Number(result[4]);\n }\n // leaf\n if (i === segments.length - 1) {\n ptr.key = key!;\n ptr.embeddedKey = embeddedKey!;\n ptr.type = Operation.UPDATE;\n ptr.changes = [\n {\n type: change.type,\n key: arrKey!,\n value: change.value,\n oldValue: change.oldValue\n } as IChange\n ];\n } else {\n // object\n ptr.key = key;\n ptr.embeddedKey = embeddedKey;\n ptr.type = Operation.UPDATE;\n const newPtr = {} as IChange;\n ptr.changes = [\n {\n type: Operation.UPDATE,\n key: arrKey,\n changes: [newPtr]\n } as IChange\n ];\n ptr = newPtr;\n }\n } else {\n // leaf\n if (i === segments.length - 1) {\n // check if value is a primitive or object\n if (change.value !== null && change.valueType === 'Object') {\n ptr.key = segment;\n ptr.type = Operation.UPDATE;\n ptr.changes = [\n {\n key: change.key,\n type: change.type,\n value: change.value\n } as IChange\n ];\n } else {\n ptr.key = change.key;\n ptr.type = change.type;\n ptr.value = change.value;\n ptr.oldValue = change.oldValue;\n }\n } else {\n // branch\n ptr.key = segment;\n ptr.type = Operation.UPDATE;\n const newPtr = {} as IChange;\n ptr.changes = [newPtr];\n ptr = newPtr;\n }\n }\n }\n changesArr.push(obj);\n }\n });\n return changesArr;\n};\n\n/**\n * Determines the type of a given object.\n *\n * @param {any} obj - The object whose type is to be determined.\n * @returns {string | null} - The type of the object, or null if the object is null.\n *\n * This function first checks if the object is undefined or null, and returns 'undefined' or null respectively.\n * If the object is neither undefined nor null, it uses Object.prototype.toString to get the object's type.\n * The type is extracted from the string returned by Object.prototype.toString using a regular expression.\n */\nexport const getTypeOfObj = (obj: any) => {\n if (typeof obj === 'undefined') {\n return 'undefined';\n }\n\n if (obj === null) {\n return null;\n }\n\n // Extracts the \"Type\" from \"[object Type]\" string.\n return Object.prototype.toString.call(obj).match(/^\\[object\\s(.*)\\]$/)[1];\n};\n\nconst getKey = (path: string) => {\n const left = path[path.length - 1];\n return left != null ? left : '$root';\n};\n\nconst compare = (oldObj: any, newObj: any, path: any, embeddedObjKeys: any, keyPath: any, keysToSkip: string[]) => {\n let changes: any[] = [];\n\n const typeOfOldObj = getTypeOfObj(oldObj);\n const typeOfNewObj = getTypeOfObj(newObj);\n\n // if type of object changes, consider it as old obj has been deleted and a new object has been added\n if (typeOfOldObj !== typeOfNewObj) {\n changes.push({ type: Operation.REMOVE, key: getKey(path), value: oldObj });\n changes.push({ type: Operation.ADD, key: getKey(path), value: newObj });\n return changes;\n }\n\n switch (typeOfOldObj) {\n case 'Date':\n changes = changes.concat(\n comparePrimitives(oldObj.getTime(), newObj.getTime(), path).map((x) => ({\n ...x,\n value: new Date(x.value),\n oldValue: new Date(x.oldValue)\n }))\n );\n break;\n case 'Object':\n const diffs = compareObject(oldObj, newObj, path, embeddedObjKeys, keyPath, false, keysToSkip);\n if (diffs.length) {\n if (path.length) {\n changes.push({\n type: Operation.UPDATE,\n key: getKey(path),\n changes: diffs\n });\n } else {\n changes = changes.concat(diffs);\n }\n }\n break;\n case 'Array':\n changes = changes.concat(compareArray(oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip));\n break;\n case 'Function':\n break;\n // do nothing\n default:\n changes = changes.concat(comparePrimitives(oldObj, newObj, path));\n }\n\n return changes;\n};\n\nconst compareObject = (\n oldObj: any,\n newObj: any,\n path: any,\n embeddedObjKeys: any,\n keyPath: any,\n skipPath = false,\n keysToSkip: string[] = []\n) => {\n let k;\n let newKeyPath;\n let newPath;\n\n if (skipPath == null) {\n skipPath = false;\n }\n let changes: any[] = [];\n\n const oldObjKeys = Object.keys(oldObj).filter((key) => keysToSkip.indexOf(key) === -1);\n const newObjKeys = Object.keys(newObj).filter((key) => keysToSkip.indexOf(key) === -1);\n\n const intersectionKeys = intersection(oldObjKeys, newObjKeys);\n for (k of intersectionKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n const diffs = compare(oldObj[k], newObj[k], newPath, embeddedObjKeys, newKeyPath, keysToSkip);\n if (diffs.length) {\n changes = changes.concat(diffs);\n }\n }\n\n const addedKeys = difference(newObjKeys, oldObjKeys);\n for (k of addedKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n changes.push({\n type: Operation.ADD,\n key: getKey(newPath),\n value: newObj[k]\n });\n }\n\n const deletedKeys = difference(oldObjKeys, newObjKeys);\n for (k of deletedKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n changes.push({\n type: Operation.REMOVE,\n key: getKey(newPath),\n value: oldObj[k]\n });\n }\n return changes;\n};\n\nconst compareArray = (\n oldObj: any,\n newObj: any,\n path: any,\n embeddedObjKeys: any,\n keyPath: any,\n keysToSkip: string[]\n) => {\n const left = getObjectKey(embeddedObjKeys, keyPath);\n const uniqKey = left != null ? left : '$index';\n const indexedOldObj = convertArrayToObj(oldObj, uniqKey);\n const indexedNewObj = convertArrayToObj(newObj, uniqKey);\n const diffs = compareObject(indexedOldObj, indexedNewObj, path, embeddedObjKeys, keyPath, true, keysToSkip);\n if (diffs.length) {\n return [\n {\n type: Operation.UPDATE,\n key: getKey(path),\n embeddedKey: typeof uniqKey === 'function' && uniqKey.length === 2 ? uniqKey(newObj[0], true) : uniqKey,\n changes: diffs\n }\n ];\n } else {\n return [];\n }\n};\n\nconst getObjectKey = (embeddedObjKeys: any, keyPath: any) => {\n if (embeddedObjKeys != null) {\n const path = keyPath.join('.');\n\n if (embeddedObjKeys instanceof Map) {\n for (const [key, value] of embeddedObjKeys.entries()) {\n if (key instanceof RegExp) {\n if (path.match(key)) {\n return value;\n }\n } else if (path === key) {\n return value;\n }\n }\n }\n\n const key = embeddedObjKeys[path];\n if (key != null) {\n return key;\n }\n }\n return undefined;\n};\n\nconst convertArrayToObj = (arr: any[], uniqKey: any) => {\n let obj: any = {};\n if (uniqKey === '$value') {\n arr.forEach((value) => {\n obj[value] = value;\n });\n } else if (uniqKey !== '$index') {\n obj = keyBy(arr, uniqKey);\n } else {\n for (let i = 0; i < arr.length; i++) {\n const value = arr[i];\n obj[i] = value;\n }\n }\n return obj;\n};\n\nconst comparePrimitives = (oldObj: any, newObj: any, path: any) => {\n const changes = [];\n if (oldObj !== newObj) {\n changes.push({\n type: Operation.UPDATE,\n key: getKey(path),\n value: newObj,\n oldValue: oldObj\n });\n }\n return changes;\n};\n\nconst removeKey = (obj: any, key: any, embeddedKey: any) => {\n if (Array.isArray(obj)) {\n if (embeddedKey === '$index') {\n obj.splice(key);\n return;\n }\n const index = indexOfItemInArray(obj, embeddedKey, key);\n if (index === -1) {\n // tslint:disable-next-line:no-console\n console.warn(`Element with the key '${embeddedKey}' and value '${key}' could not be found in the array'`);\n return;\n }\n return obj.splice(index != null ? index : key, 1);\n } else {\n obj[key] = undefined;\n delete obj[key];\n return;\n }\n};\n\nconst indexOfItemInArray = (arr: any[], key: any, value: any) => {\n if (key === '$value') {\n return arr.indexOf(value);\n }\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i];\n if (item && item[key] ? item[key].toString() === value.toString() : undefined) {\n return i;\n }\n }\n return -1;\n};\n\nconst modifyKeyValue = (obj: any, key: any, value: any) => (obj[key] = value);\n\nconst addKeyValue = (obj: any, key: any, value: any) => {\n if (Array.isArray(obj)) {\n return obj.push(value);\n } else {\n return obj ? (obj[key] = value) : null;\n }\n};\n\nconst applyLeafChange = (obj: any, change: any, embeddedKey: any) => {\n const { type, key, value } = change;\n switch (type) {\n case Operation.ADD:\n return addKeyValue(obj, key, value);\n case Operation.UPDATE:\n return modifyKeyValue(obj, key, value);\n case Operation.REMOVE:\n return removeKey(obj, key, embeddedKey);\n }\n};\n\nconst applyArrayChange = (arr: any, change: any) =>\n (() => {\n const result = [];\n for (const subchange of change.changes) {\n if (subchange.value != null || subchange.type === Operation.REMOVE) {\n result.push(applyLeafChange(arr, subchange, change.embeddedKey));\n } else {\n let element;\n if (change.embeddedKey === '$index') {\n element = arr[subchange.key];\n } else if (change.embeddedKey === '$value') {\n const index = arr.indexOf(subchange.key);\n if (index !== -1) {\n element = arr[index];\n }\n } else {\n element = find(arr, (el) => el[change.embeddedKey]?.toString() === subchange.key.toString());\n }\n result.push(applyChangeset(element, subchange.changes));\n }\n }\n return result;\n })();\n\nconst applyBranchChange = (obj: any, change: any) => {\n if (Array.isArray(obj)) {\n return applyArrayChange(obj, change);\n } else {\n return applyChangeset(obj, change.changes);\n }\n};\n\nconst revertLeafChange = (obj: any, change: any, embeddedKey = '$index') => {\n const { type, key, value, oldValue } = change;\n switch (type) {\n case Operation.ADD:\n return removeKey(obj, key, embeddedKey);\n case Operation.UPDATE:\n return modifyKeyValue(obj, key, oldValue);\n case Operation.REMOVE:\n return addKeyValue(obj, key, value);\n }\n};\n\nconst revertArrayChange = (arr: any, change: any) =>\n (() => {\n const result = [];\n for (const subchange of change.changes) {\n if (subchange.value != null || subchange.type === Operation.REMOVE) {\n result.push(revertLeafChange(arr, subchange, change.embeddedKey));\n } else {\n let element;\n if (change.embeddedKey === '$index') {\n element = arr[+subchange.key];\n } else {\n element = find(arr, (el) => el[change.embeddedKey].toString() === subchange.key);\n }\n result.push(revertChangeset(element, subchange.changes));\n }\n }\n return result;\n })();\n\nconst revertBranchChange = (obj: any, change: any) => {\n if (Array.isArray(obj)) {\n return revertArrayChange(obj, change);\n } else {\n return revertChangeset(obj, change.changes);\n }\n};\n\n/** combine a base JSON Path with a subsequent segment */\nfunction append(basePath: string, nextSegment: string): string {\n return nextSegment.includes('.') ? `${basePath}[${nextSegment}]` : `${basePath}.${nextSegment}`;\n}\n\n/** returns a JSON Path filter expression; e.g., `$.pet[(?name='spot')]` */\nfunction filterExpression(basePath: string, filterKey: string | FunctionKey, filterValue: string | number) {\n const value = typeof filterValue === 'number' ? filterValue : `'${filterValue}'`;\n return typeof filterKey === 'string' && filterKey.includes('.')\n ? `${basePath}[?(@[${filterKey}]==${value})]`\n : `${basePath}[?(@.${filterKey}==${value})]`;\n}\n","import { chain, keys, replace, set } from 'lodash';\nimport { diff, flattenChangeset, getTypeOfObj, IFlatChange, Operation } from './jsonDiff.js';\n\nexport enum CompareOperation {\n CONTAINER = 'CONTAINER',\n UNCHANGED = 'UNCHANGED'\n}\n\nexport interface IComparisonEnrichedNode {\n type: Operation | CompareOperation;\n value: IComparisonEnrichedNode | IComparisonEnrichedNode[] | any | any[];\n oldValue?: any;\n}\n\nexport const createValue = (value: any): IComparisonEnrichedNode => ({ type: CompareOperation.UNCHANGED, value });\nexport const createContainer = (value: object | []): IComparisonEnrichedNode => ({\n type: CompareOperation.CONTAINER,\n value\n});\n\nexport const enrich = (object: any): IComparisonEnrichedNode => {\n const objectType = getTypeOfObj(object);\n\n switch (objectType) {\n case 'Object':\n return keys(object)\n .map((key: string) => ({ key, value: enrich(object[key]) }))\n .reduce((accumulator, entry) => {\n accumulator.value[entry.key] = entry.value;\n return accumulator;\n }, createContainer({}));\n case 'Array':\n return chain(object)\n .map((value) => enrich(value))\n .reduce((accumulator, value) => {\n accumulator.value.push(value);\n return accumulator;\n }, createContainer([]))\n .value();\n case 'Function':\n return undefined;\n case 'Date':\n default:\n // Primitive value\n return createValue(object);\n }\n};\n\nexport const applyChangelist = (\n object: IComparisonEnrichedNode,\n changelist: IFlatChange[]\n): IComparisonEnrichedNode => {\n chain(changelist)\n .map((entry) => ({ ...entry, path: replace(entry.path, '$.', '.') }))\n .map((entry) => ({\n ...entry,\n path: replace(entry.path, /(\\[(?<array>\\d)\\]\\.)/g, 'ARRVAL_START$<array>ARRVAL_END')\n }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /(?<dot>\\.)/g, '.value$<dot>') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /\\./, '') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /ARRVAL_START/g, '.value[') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /ARRVAL_END/g, '].value.') }))\n .value()\n .forEach((entry) => {\n switch (entry.type) {\n case Operation.ADD:\n case Operation.UPDATE:\n set(object, entry.path, { type: entry.type, value: entry.value, oldValue: entry.oldValue });\n break;\n case Operation.REMOVE:\n set(object, entry.path, { type: entry.type, value: undefined, oldValue: entry.value });\n break;\n default:\n throw new Error();\n }\n });\n return object;\n};\n\nexport const compare = (oldObject: any, newObject: any): IComparisonEnrichedNode => {\n return applyChangelist(enrich(oldObject), flattenChangeset(diff(oldObject, newObject)));\n};\n"],"mappings":"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","names":["compare","Operation","key","import_lodash","CompareOperation","compare"]}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/jsonDiff.ts
|
|
2
|
-
import { difference, find, intersection, keyBy } from "lodash
|
|
2
|
+
import { difference, find, intersection, keyBy } from "lodash";
|
|
3
3
|
var Operation = /* @__PURE__ */ ((Operation2) => {
|
|
4
4
|
Operation2["REMOVE"] = "REMOVE";
|
|
5
5
|
Operation2["ADD"] = "ADD";
|
|
@@ -457,7 +457,7 @@ function filterExpression(basePath, filterKey, filterValue) {
|
|
|
457
457
|
}
|
|
458
458
|
|
|
459
459
|
// src/jsonCompare.ts
|
|
460
|
-
import { chain, keys, replace, set } from "lodash
|
|
460
|
+
import { chain, keys, replace, set } from "lodash";
|
|
461
461
|
var CompareOperation = /* @__PURE__ */ ((CompareOperation2) => {
|
|
462
462
|
CompareOperation2["CONTAINER"] = "CONTAINER";
|
|
463
463
|
CompareOperation2["UNCHANGED"] = "UNCHANGED";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jsonDiff.ts","../src/jsonCompare.ts"],"sourcesContent":["import { difference, find, intersection, keyBy } from 'lodash-es';\n\ntype FunctionKey = (obj: any, shouldReturnKeyName?: boolean) => any;\nexport type EmbeddedObjKeysType = Record<string, string | FunctionKey>;\nexport type EmbeddedObjKeysMapType = Map<string | RegExp, string | FunctionKey>;\nexport enum Operation {\n REMOVE = 'REMOVE',\n ADD = 'ADD',\n UPDATE = 'UPDATE'\n}\n\nexport interface IChange {\n type: Operation;\n key: string;\n embeddedKey?: string | FunctionKey;\n value?: any | any[];\n oldValue?: any;\n changes?: IChange[];\n}\nexport type Changeset = IChange[];\n\nexport interface IFlatChange {\n type: Operation;\n key: string;\n path: string;\n valueType: string | null;\n value?: any;\n oldValue?: any;\n}\n\n/**\n * Computes the difference between two objects.\n *\n * @param {any} oldObj - The original object.\n * @param {any} newObj - The updated object.\n * @param {EmbeddedObjKeysType | EmbeddedObjKeysMapType} embeddedObjKeys - An optional parameter specifying keys of embedded objects.\n * @returns {IChange[]} - An array of changes that transform the old object into the new object.\n */\nexport function diff(\n oldObj: any,\n newObj: any,\n embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType,\n keysToSkip?: string[]\n): IChange[] {\n // Trim leading '.' from keys in embeddedObjKeys\n if (embeddedObjKeys instanceof Map) {\n embeddedObjKeys = new Map(\n Array.from(embeddedObjKeys.entries()).map(([key, value]) => [\n key instanceof RegExp ? key : key.replace(/^\\./, ''),\n value\n ])\n );\n } else if (embeddedObjKeys) {\n embeddedObjKeys = Object.fromEntries(\n Object.entries(embeddedObjKeys).map(([key, value]) => [key.replace(/^\\./, ''), value])\n );\n }\n\n // Compare old and new objects to generate a list of changes\n return compare(oldObj, newObj, [], embeddedObjKeys, [], keysToSkip);\n}\n\n/**\n * Applies all changes in the changeset to the object.\n *\n * @param {any} obj - The object to apply changes to.\n * @param {Changeset} changeset - The changeset to apply.\n * @returns {any} - The object after the changes from the changeset have been applied.\n *\n * The function first checks if a changeset is provided. If so, it iterates over each change in the changeset.\n * If the change value is not null or undefined, or if the change type is REMOVE, it applies the change to the object directly.\n * Otherwise, it applies the change to the corresponding branch of the object.\n */\nexport const applyChangeset = (obj: any, changeset: Changeset) => {\n if (changeset) {\n changeset.forEach((change) => {\n const { type, key, value, embeddedKey } = change;\n\n if ((value !== null && value !== undefined) || type === Operation.REMOVE) {\n // Apply the change to the object\n applyLeafChange(obj, change, embeddedKey);\n } else {\n // Apply the change to the branch\n applyBranchChange(obj[key], change);\n }\n });\n }\n return obj;\n};\n\n/**\n * Reverts the changes made to an object based on a given changeset.\n *\n * @param {any} obj - The object on which to revert changes.\n * @param {Changeset} changeset - The changeset to revert.\n * @returns {any} - The object after the changes from the changeset have been reverted.\n *\n * The function first checks if a changeset is provided. If so, it reverses the changeset to start reverting from the last change.\n * It then iterates over each change in the changeset. If the change does not have any nested changes, it reverts the change on the object directly.\n * If the change does have nested changes, it reverts the changes on the corresponding branch of the object.\n */\nexport const revertChangeset = (obj: any, changeset: Changeset) => {\n if (changeset) {\n changeset\n .reverse()\n .forEach((change: IChange): any =>\n !change.changes ? revertLeafChange(obj, change) : revertBranchChange(obj[change.key], change)\n );\n }\n\n return obj;\n};\n\n/**\n * Flattens a changeset into an array of flat changes.\n *\n * @param {Changeset | IChange} obj - The changeset or change to flatten.\n * @param {string} [path='$'] - The current path in the changeset.\n * @param {string | FunctionKey} [embeddedKey] - The key to use for embedded objects.\n * @returns {IFlatChange[]} - An array of flat changes.\n *\n * The function first checks if the input is an array. If so, it recursively flattens each change in the array.\n * If the input is not an array, it checks if the change has nested changes or an embedded key.\n * If so, it updates the path and recursively flattens the nested changes or the embedded object.\n * If the change does not have nested changes or an embedded key, it creates a flat change and returns it in an array.\n */\nexport const flattenChangeset = (\n obj: Changeset | IChange,\n path = '$',\n embeddedKey?: string | FunctionKey\n): IFlatChange[] => {\n if (Array.isArray(obj)) {\n return obj.reduce((memo, change) => [...memo, ...flattenChangeset(change, path, embeddedKey)], [] as IFlatChange[]);\n } else {\n if (obj.changes || embeddedKey) {\n if (embeddedKey) {\n if (embeddedKey === '$index') {\n path = `${path}[${obj.key}]`;\n } else if (embeddedKey === '$value') {\n path = `${path}[?(@='${obj.key}')]`;\n const valueType = getTypeOfObj(obj.value);\n return [\n {\n ...obj,\n path,\n valueType\n }\n ];\n } else if (obj.type === Operation.ADD) {\n // do nothing\n } else {\n path = filterExpression(path, embeddedKey, obj.key);\n }\n } else {\n path = append(path, obj.key);\n }\n\n return flattenChangeset(obj.changes || obj, path, obj.embeddedKey);\n } else {\n const valueType = getTypeOfObj(obj.value);\n return [\n {\n ...obj,\n path: valueType === 'Object' || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),\n valueType\n }\n ];\n }\n }\n};\n\n/**\n * Transforms a flat changeset into a nested changeset.\n *\n * @param {IFlatChange | IFlatChange[]} changes - The flat changeset to unflatten.\n * @returns {IChange[]} - The unflattened changeset.\n *\n * The function first checks if the input is a single change or an array of changes.\n * It then iterates over each change and splits its path into segments.\n * For each segment, it checks if it represents an array or a leaf node.\n * If it represents an array, it creates a new change object and updates the pointer to this new object.\n * If it represents a leaf node, it sets the key, type, value, and oldValue of the current change object.\n * Finally, it pushes the unflattened change object into the changes array.\n */\nexport const unflattenChanges = (changes: IFlatChange | IFlatChange[]) => {\n if (!Array.isArray(changes)) {\n changes = [changes];\n }\n\n const changesArr: IChange[] = [];\n\n changes.forEach((change) => {\n const obj = {} as IChange;\n let ptr = obj;\n\n const segments = change.path.split(/(?<=[^@])\\.(?=[^@])/);\n\n if (segments.length === 1) {\n ptr.key = change.key;\n ptr.type = change.type;\n ptr.value = change.value;\n ptr.oldValue = change.oldValue;\n changesArr.push(ptr);\n } else {\n for (let i = 1; i < segments.length; i++) {\n const segment = segments[i];\n // Matches JSONPath segments: \"items[?(@.id=='123')]\", \"items[?(@.id==123)]\", \"items[2]\", \"items[?(@='123')]\"\n const result = /^(.+?)\\[\\?\\(@.?(?:([^=]*))?={1,2}'(.*)'\\)\\]$|^(.+?)\\[(\\d+)\\]$/.exec(segment); //NOSONAR\n // array\n if (result) {\n let key: string;\n let embeddedKey: string;\n let arrKey: string | number;\n if (result[1]) {\n key = result[1];\n embeddedKey = result[2] || '$value';\n arrKey = result[3];\n } else {\n key = result[4];\n embeddedKey = '$index';\n arrKey = Number(result[4]);\n }\n // leaf\n if (i === segments.length - 1) {\n ptr.key = key!;\n ptr.embeddedKey = embeddedKey!;\n ptr.type = Operation.UPDATE;\n ptr.changes = [\n {\n type: change.type,\n key: arrKey!,\n value: change.value,\n oldValue: change.oldValue\n } as IChange\n ];\n } else {\n // object\n ptr.key = key;\n ptr.embeddedKey = embeddedKey;\n ptr.type = Operation.UPDATE;\n const newPtr = {} as IChange;\n ptr.changes = [\n {\n type: Operation.UPDATE,\n key: arrKey,\n changes: [newPtr]\n } as IChange\n ];\n ptr = newPtr;\n }\n } else {\n // leaf\n if (i === segments.length - 1) {\n // check if value is a primitive or object\n if (change.value !== null && change.valueType === 'Object') {\n ptr.key = segment;\n ptr.type = Operation.UPDATE;\n ptr.changes = [\n {\n key: change.key,\n type: change.type,\n value: change.value\n } as IChange\n ];\n } else {\n ptr.key = change.key;\n ptr.type = change.type;\n ptr.value = change.value;\n ptr.oldValue = change.oldValue;\n }\n } else {\n // branch\n ptr.key = segment;\n ptr.type = Operation.UPDATE;\n const newPtr = {} as IChange;\n ptr.changes = [newPtr];\n ptr = newPtr;\n }\n }\n }\n changesArr.push(obj);\n }\n });\n return changesArr;\n};\n\n/**\n * Determines the type of a given object.\n *\n * @param {any} obj - The object whose type is to be determined.\n * @returns {string | null} - The type of the object, or null if the object is null.\n *\n * This function first checks if the object is undefined or null, and returns 'undefined' or null respectively.\n * If the object is neither undefined nor null, it uses Object.prototype.toString to get the object's type.\n * The type is extracted from the string returned by Object.prototype.toString using a regular expression.\n */\nexport const getTypeOfObj = (obj: any) => {\n if (typeof obj === 'undefined') {\n return 'undefined';\n }\n\n if (obj === null) {\n return null;\n }\n\n // Extracts the \"Type\" from \"[object Type]\" string.\n return Object.prototype.toString.call(obj).match(/^\\[object\\s(.*)\\]$/)[1];\n};\n\nconst getKey = (path: string) => {\n const left = path[path.length - 1];\n return left != null ? left : '$root';\n};\n\nconst compare = (oldObj: any, newObj: any, path: any, embeddedObjKeys: any, keyPath: any, keysToSkip: string[]) => {\n let changes: any[] = [];\n\n const typeOfOldObj = getTypeOfObj(oldObj);\n const typeOfNewObj = getTypeOfObj(newObj);\n\n // if type of object changes, consider it as old obj has been deleted and a new object has been added\n if (typeOfOldObj !== typeOfNewObj) {\n changes.push({ type: Operation.REMOVE, key: getKey(path), value: oldObj });\n changes.push({ type: Operation.ADD, key: getKey(path), value: newObj });\n return changes;\n }\n\n switch (typeOfOldObj) {\n case 'Date':\n changes = changes.concat(\n comparePrimitives(oldObj.getTime(), newObj.getTime(), path).map((x) => ({\n ...x,\n value: new Date(x.value),\n oldValue: new Date(x.oldValue)\n }))\n );\n break;\n case 'Object':\n const diffs = compareObject(oldObj, newObj, path, embeddedObjKeys, keyPath, false, keysToSkip);\n if (diffs.length) {\n if (path.length) {\n changes.push({\n type: Operation.UPDATE,\n key: getKey(path),\n changes: diffs\n });\n } else {\n changes = changes.concat(diffs);\n }\n }\n break;\n case 'Array':\n changes = changes.concat(compareArray(oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip));\n break;\n case 'Function':\n break;\n // do nothing\n default:\n changes = changes.concat(comparePrimitives(oldObj, newObj, path));\n }\n\n return changes;\n};\n\nconst compareObject = (\n oldObj: any,\n newObj: any,\n path: any,\n embeddedObjKeys: any,\n keyPath: any,\n skipPath = false,\n keysToSkip: string[] = []\n) => {\n let k;\n let newKeyPath;\n let newPath;\n\n if (skipPath == null) {\n skipPath = false;\n }\n let changes: any[] = [];\n\n const oldObjKeys = Object.keys(oldObj).filter((key) => keysToSkip.indexOf(key) === -1);\n const newObjKeys = Object.keys(newObj).filter((key) => keysToSkip.indexOf(key) === -1);\n\n const intersectionKeys = intersection(oldObjKeys, newObjKeys);\n for (k of intersectionKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n const diffs = compare(oldObj[k], newObj[k], newPath, embeddedObjKeys, newKeyPath, keysToSkip);\n if (diffs.length) {\n changes = changes.concat(diffs);\n }\n }\n\n const addedKeys = difference(newObjKeys, oldObjKeys);\n for (k of addedKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n changes.push({\n type: Operation.ADD,\n key: getKey(newPath),\n value: newObj[k]\n });\n }\n\n const deletedKeys = difference(oldObjKeys, newObjKeys);\n for (k of deletedKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n changes.push({\n type: Operation.REMOVE,\n key: getKey(newPath),\n value: oldObj[k]\n });\n }\n return changes;\n};\n\nconst compareArray = (\n oldObj: any,\n newObj: any,\n path: any,\n embeddedObjKeys: any,\n keyPath: any,\n keysToSkip: string[]\n) => {\n const left = getObjectKey(embeddedObjKeys, keyPath);\n const uniqKey = left != null ? left : '$index';\n const indexedOldObj = convertArrayToObj(oldObj, uniqKey);\n const indexedNewObj = convertArrayToObj(newObj, uniqKey);\n const diffs = compareObject(indexedOldObj, indexedNewObj, path, embeddedObjKeys, keyPath, true, keysToSkip);\n if (diffs.length) {\n return [\n {\n type: Operation.UPDATE,\n key: getKey(path),\n embeddedKey: typeof uniqKey === 'function' && uniqKey.length === 2 ? uniqKey(newObj[0], true) : uniqKey,\n changes: diffs\n }\n ];\n } else {\n return [];\n }\n};\n\nconst getObjectKey = (embeddedObjKeys: any, keyPath: any) => {\n if (embeddedObjKeys != null) {\n const path = keyPath.join('.');\n\n if (embeddedObjKeys instanceof Map) {\n for (const [key, value] of embeddedObjKeys.entries()) {\n if (key instanceof RegExp) {\n if (path.match(key)) {\n return value;\n }\n } else if (path === key) {\n return value;\n }\n }\n }\n\n const key = embeddedObjKeys[path];\n if (key != null) {\n return key;\n }\n }\n return undefined;\n};\n\nconst convertArrayToObj = (arr: any[], uniqKey: any) => {\n let obj: any = {};\n if (uniqKey === '$value') {\n arr.forEach((value) => {\n obj[value] = value;\n });\n } else if (uniqKey !== '$index') {\n obj = keyBy(arr, uniqKey);\n } else {\n for (let i = 0; i < arr.length; i++) {\n const value = arr[i];\n obj[i] = value;\n }\n }\n return obj;\n};\n\nconst comparePrimitives = (oldObj: any, newObj: any, path: any) => {\n const changes = [];\n if (oldObj !== newObj) {\n changes.push({\n type: Operation.UPDATE,\n key: getKey(path),\n value: newObj,\n oldValue: oldObj\n });\n }\n return changes;\n};\n\nconst removeKey = (obj: any, key: any, embeddedKey: any) => {\n if (Array.isArray(obj)) {\n if (embeddedKey === '$index') {\n obj.splice(key);\n return;\n }\n const index = indexOfItemInArray(obj, embeddedKey, key);\n if (index === -1) {\n // tslint:disable-next-line:no-console\n console.warn(`Element with the key '${embeddedKey}' and value '${key}' could not be found in the array'`);\n return;\n }\n return obj.splice(index != null ? index : key, 1);\n } else {\n obj[key] = undefined;\n delete obj[key];\n return;\n }\n};\n\nconst indexOfItemInArray = (arr: any[], key: any, value: any) => {\n if (key === '$value') {\n return arr.indexOf(value);\n }\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i];\n if (item && item[key] ? item[key].toString() === value.toString() : undefined) {\n return i;\n }\n }\n return -1;\n};\n\nconst modifyKeyValue = (obj: any, key: any, value: any) => (obj[key] = value);\n\nconst addKeyValue = (obj: any, key: any, value: any) => {\n if (Array.isArray(obj)) {\n return obj.push(value);\n } else {\n return obj ? (obj[key] = value) : null;\n }\n};\n\nconst applyLeafChange = (obj: any, change: any, embeddedKey: any) => {\n const { type, key, value } = change;\n switch (type) {\n case Operation.ADD:\n return addKeyValue(obj, key, value);\n case Operation.UPDATE:\n return modifyKeyValue(obj, key, value);\n case Operation.REMOVE:\n return removeKey(obj, key, embeddedKey);\n }\n};\n\nconst applyArrayChange = (arr: any, change: any) =>\n (() => {\n const result = [];\n for (const subchange of change.changes) {\n if (subchange.value != null || subchange.type === Operation.REMOVE) {\n result.push(applyLeafChange(arr, subchange, change.embeddedKey));\n } else {\n let element;\n if (change.embeddedKey === '$index') {\n element = arr[subchange.key];\n } else if (change.embeddedKey === '$value') {\n const index = arr.indexOf(subchange.key);\n if (index !== -1) {\n element = arr[index];\n }\n } else {\n element = find(arr, (el) => el[change.embeddedKey]?.toString() === subchange.key.toString());\n }\n result.push(applyChangeset(element, subchange.changes));\n }\n }\n return result;\n })();\n\nconst applyBranchChange = (obj: any, change: any) => {\n if (Array.isArray(obj)) {\n return applyArrayChange(obj, change);\n } else {\n return applyChangeset(obj, change.changes);\n }\n};\n\nconst revertLeafChange = (obj: any, change: any, embeddedKey = '$index') => {\n const { type, key, value, oldValue } = change;\n switch (type) {\n case Operation.ADD:\n return removeKey(obj, key, embeddedKey);\n case Operation.UPDATE:\n return modifyKeyValue(obj, key, oldValue);\n case Operation.REMOVE:\n return addKeyValue(obj, key, value);\n }\n};\n\nconst revertArrayChange = (arr: any, change: any) =>\n (() => {\n const result = [];\n for (const subchange of change.changes) {\n if (subchange.value != null || subchange.type === Operation.REMOVE) {\n result.push(revertLeafChange(arr, subchange, change.embeddedKey));\n } else {\n let element;\n if (change.embeddedKey === '$index') {\n element = arr[+subchange.key];\n } else {\n element = find(arr, (el) => el[change.embeddedKey].toString() === subchange.key);\n }\n result.push(revertChangeset(element, subchange.changes));\n }\n }\n return result;\n })();\n\nconst revertBranchChange = (obj: any, change: any) => {\n if (Array.isArray(obj)) {\n return revertArrayChange(obj, change);\n } else {\n return revertChangeset(obj, change.changes);\n }\n};\n\n/** combine a base JSON Path with a subsequent segment */\nfunction append(basePath: string, nextSegment: string): string {\n return nextSegment.includes('.') ? `${basePath}[${nextSegment}]` : `${basePath}.${nextSegment}`;\n}\n\n/** returns a JSON Path filter expression; e.g., `$.pet[(?name='spot')]` */\nfunction filterExpression(basePath: string, filterKey: string | FunctionKey, filterValue: string | number) {\n const value = typeof filterValue === 'number' ? filterValue : `'${filterValue}'`;\n return typeof filterKey === 'string' && filterKey.includes('.')\n ? `${basePath}[?(@[${filterKey}]==${value})]`\n : `${basePath}[?(@.${filterKey}==${value})]`;\n}\n","import { chain, keys, replace, set } from 'lodash-es';\nimport { diff, flattenChangeset, getTypeOfObj, IFlatChange, Operation } from './jsonDiff.js';\n\nexport enum CompareOperation {\n CONTAINER = 'CONTAINER',\n UNCHANGED = 'UNCHANGED'\n}\n\nexport interface IComparisonEnrichedNode {\n type: Operation | CompareOperation;\n value: IComparisonEnrichedNode | IComparisonEnrichedNode[] | any | any[];\n oldValue?: any;\n}\n\nexport const createValue = (value: any): IComparisonEnrichedNode => ({ type: CompareOperation.UNCHANGED, value });\nexport const createContainer = (value: object | []): IComparisonEnrichedNode => ({\n type: CompareOperation.CONTAINER,\n value\n});\n\nexport const enrich = (object: any): IComparisonEnrichedNode => {\n const objectType = getTypeOfObj(object);\n\n switch (objectType) {\n case 'Object':\n return keys(object)\n .map((key: string) => ({ key, value: enrich(object[key]) }))\n .reduce((accumulator, entry) => {\n accumulator.value[entry.key] = entry.value;\n return accumulator;\n }, createContainer({}));\n case 'Array':\n return chain(object)\n .map((value) => enrich(value))\n .reduce((accumulator, value) => {\n accumulator.value.push(value);\n return accumulator;\n }, createContainer([]))\n .value();\n case 'Function':\n return undefined;\n case 'Date':\n default:\n // Primitive value\n return createValue(object);\n }\n};\n\nexport const applyChangelist = (\n object: IComparisonEnrichedNode,\n changelist: IFlatChange[]\n): IComparisonEnrichedNode => {\n chain(changelist)\n .map((entry) => ({ ...entry, path: replace(entry.path, '$.', '.') }))\n .map((entry) => ({\n ...entry,\n path: replace(entry.path, /(\\[(?<array>\\d)\\]\\.)/g, 'ARRVAL_START$<array>ARRVAL_END')\n }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /(?<dot>\\.)/g, '.value$<dot>') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /\\./, '') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /ARRVAL_START/g, '.value[') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /ARRVAL_END/g, '].value.') }))\n .value()\n .forEach((entry) => {\n switch (entry.type) {\n case Operation.ADD:\n case Operation.UPDATE:\n set(object, entry.path, { type: entry.type, value: entry.value, oldValue: entry.oldValue });\n break;\n case Operation.REMOVE:\n set(object, entry.path, { type: entry.type, value: undefined, oldValue: entry.value });\n break;\n default:\n throw new Error();\n }\n });\n return object;\n};\n\nexport const compare = (oldObject: any, newObject: any): IComparisonEnrichedNode => {\n return applyChangelist(enrich(oldObject), flattenChangeset(diff(oldObject, newObject)));\n};\n"],"mappings":"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","names":["Operation","key","CompareOperation","compare"]}
|
|
1
|
+
{"version":3,"sources":["../src/jsonDiff.ts","../src/jsonCompare.ts"],"sourcesContent":["import { difference, find, intersection, keyBy } from 'lodash';\n\ntype FunctionKey = (obj: any, shouldReturnKeyName?: boolean) => any;\nexport type EmbeddedObjKeysType = Record<string, string | FunctionKey>;\nexport type EmbeddedObjKeysMapType = Map<string | RegExp, string | FunctionKey>;\nexport enum Operation {\n REMOVE = 'REMOVE',\n ADD = 'ADD',\n UPDATE = 'UPDATE'\n}\n\nexport interface IChange {\n type: Operation;\n key: string;\n embeddedKey?: string | FunctionKey;\n value?: any | any[];\n oldValue?: any;\n changes?: IChange[];\n}\nexport type Changeset = IChange[];\n\nexport interface IFlatChange {\n type: Operation;\n key: string;\n path: string;\n valueType: string | null;\n value?: any;\n oldValue?: any;\n}\n\n/**\n * Computes the difference between two objects.\n *\n * @param {any} oldObj - The original object.\n * @param {any} newObj - The updated object.\n * @param {EmbeddedObjKeysType | EmbeddedObjKeysMapType} embeddedObjKeys - An optional parameter specifying keys of embedded objects.\n * @returns {IChange[]} - An array of changes that transform the old object into the new object.\n */\nexport function diff(\n oldObj: any,\n newObj: any,\n embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType,\n keysToSkip?: string[]\n): IChange[] {\n // Trim leading '.' from keys in embeddedObjKeys\n if (embeddedObjKeys instanceof Map) {\n embeddedObjKeys = new Map(\n Array.from(embeddedObjKeys.entries()).map(([key, value]) => [\n key instanceof RegExp ? key : key.replace(/^\\./, ''),\n value\n ])\n );\n } else if (embeddedObjKeys) {\n embeddedObjKeys = Object.fromEntries(\n Object.entries(embeddedObjKeys).map(([key, value]) => [key.replace(/^\\./, ''), value])\n );\n }\n\n // Compare old and new objects to generate a list of changes\n return compare(oldObj, newObj, [], embeddedObjKeys, [], keysToSkip);\n}\n\n/**\n * Applies all changes in the changeset to the object.\n *\n * @param {any} obj - The object to apply changes to.\n * @param {Changeset} changeset - The changeset to apply.\n * @returns {any} - The object after the changes from the changeset have been applied.\n *\n * The function first checks if a changeset is provided. If so, it iterates over each change in the changeset.\n * If the change value is not null or undefined, or if the change type is REMOVE, it applies the change to the object directly.\n * Otherwise, it applies the change to the corresponding branch of the object.\n */\nexport const applyChangeset = (obj: any, changeset: Changeset) => {\n if (changeset) {\n changeset.forEach((change) => {\n const { type, key, value, embeddedKey } = change;\n\n if ((value !== null && value !== undefined) || type === Operation.REMOVE) {\n // Apply the change to the object\n applyLeafChange(obj, change, embeddedKey);\n } else {\n // Apply the change to the branch\n applyBranchChange(obj[key], change);\n }\n });\n }\n return obj;\n};\n\n/**\n * Reverts the changes made to an object based on a given changeset.\n *\n * @param {any} obj - The object on which to revert changes.\n * @param {Changeset} changeset - The changeset to revert.\n * @returns {any} - The object after the changes from the changeset have been reverted.\n *\n * The function first checks if a changeset is provided. If so, it reverses the changeset to start reverting from the last change.\n * It then iterates over each change in the changeset. If the change does not have any nested changes, it reverts the change on the object directly.\n * If the change does have nested changes, it reverts the changes on the corresponding branch of the object.\n */\nexport const revertChangeset = (obj: any, changeset: Changeset) => {\n if (changeset) {\n changeset\n .reverse()\n .forEach((change: IChange): any =>\n !change.changes ? revertLeafChange(obj, change) : revertBranchChange(obj[change.key], change)\n );\n }\n\n return obj;\n};\n\n/**\n * Flattens a changeset into an array of flat changes.\n *\n * @param {Changeset | IChange} obj - The changeset or change to flatten.\n * @param {string} [path='$'] - The current path in the changeset.\n * @param {string | FunctionKey} [embeddedKey] - The key to use for embedded objects.\n * @returns {IFlatChange[]} - An array of flat changes.\n *\n * The function first checks if the input is an array. If so, it recursively flattens each change in the array.\n * If the input is not an array, it checks if the change has nested changes or an embedded key.\n * If so, it updates the path and recursively flattens the nested changes or the embedded object.\n * If the change does not have nested changes or an embedded key, it creates a flat change and returns it in an array.\n */\nexport const flattenChangeset = (\n obj: Changeset | IChange,\n path = '$',\n embeddedKey?: string | FunctionKey\n): IFlatChange[] => {\n if (Array.isArray(obj)) {\n return obj.reduce((memo, change) => [...memo, ...flattenChangeset(change, path, embeddedKey)], [] as IFlatChange[]);\n } else {\n if (obj.changes || embeddedKey) {\n if (embeddedKey) {\n if (embeddedKey === '$index') {\n path = `${path}[${obj.key}]`;\n } else if (embeddedKey === '$value') {\n path = `${path}[?(@='${obj.key}')]`;\n const valueType = getTypeOfObj(obj.value);\n return [\n {\n ...obj,\n path,\n valueType\n }\n ];\n } else if (obj.type === Operation.ADD) {\n // do nothing\n } else {\n path = filterExpression(path, embeddedKey, obj.key);\n }\n } else {\n path = append(path, obj.key);\n }\n\n return flattenChangeset(obj.changes || obj, path, obj.embeddedKey);\n } else {\n const valueType = getTypeOfObj(obj.value);\n return [\n {\n ...obj,\n path: valueType === 'Object' || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),\n valueType\n }\n ];\n }\n }\n};\n\n/**\n * Transforms a flat changeset into a nested changeset.\n *\n * @param {IFlatChange | IFlatChange[]} changes - The flat changeset to unflatten.\n * @returns {IChange[]} - The unflattened changeset.\n *\n * The function first checks if the input is a single change or an array of changes.\n * It then iterates over each change and splits its path into segments.\n * For each segment, it checks if it represents an array or a leaf node.\n * If it represents an array, it creates a new change object and updates the pointer to this new object.\n * If it represents a leaf node, it sets the key, type, value, and oldValue of the current change object.\n * Finally, it pushes the unflattened change object into the changes array.\n */\nexport const unflattenChanges = (changes: IFlatChange | IFlatChange[]) => {\n if (!Array.isArray(changes)) {\n changes = [changes];\n }\n\n const changesArr: IChange[] = [];\n\n changes.forEach((change) => {\n const obj = {} as IChange;\n let ptr = obj;\n\n const segments = change.path.split(/(?<=[^@])\\.(?=[^@])/);\n\n if (segments.length === 1) {\n ptr.key = change.key;\n ptr.type = change.type;\n ptr.value = change.value;\n ptr.oldValue = change.oldValue;\n changesArr.push(ptr);\n } else {\n for (let i = 1; i < segments.length; i++) {\n const segment = segments[i];\n // Matches JSONPath segments: \"items[?(@.id=='123')]\", \"items[?(@.id==123)]\", \"items[2]\", \"items[?(@='123')]\"\n const result = /^(.+?)\\[\\?\\(@.?(?:([^=]*))?={1,2}'(.*)'\\)\\]$|^(.+?)\\[(\\d+)\\]$/.exec(segment); //NOSONAR\n // array\n if (result) {\n let key: string;\n let embeddedKey: string;\n let arrKey: string | number;\n if (result[1]) {\n key = result[1];\n embeddedKey = result[2] || '$value';\n arrKey = result[3];\n } else {\n key = result[4];\n embeddedKey = '$index';\n arrKey = Number(result[4]);\n }\n // leaf\n if (i === segments.length - 1) {\n ptr.key = key!;\n ptr.embeddedKey = embeddedKey!;\n ptr.type = Operation.UPDATE;\n ptr.changes = [\n {\n type: change.type,\n key: arrKey!,\n value: change.value,\n oldValue: change.oldValue\n } as IChange\n ];\n } else {\n // object\n ptr.key = key;\n ptr.embeddedKey = embeddedKey;\n ptr.type = Operation.UPDATE;\n const newPtr = {} as IChange;\n ptr.changes = [\n {\n type: Operation.UPDATE,\n key: arrKey,\n changes: [newPtr]\n } as IChange\n ];\n ptr = newPtr;\n }\n } else {\n // leaf\n if (i === segments.length - 1) {\n // check if value is a primitive or object\n if (change.value !== null && change.valueType === 'Object') {\n ptr.key = segment;\n ptr.type = Operation.UPDATE;\n ptr.changes = [\n {\n key: change.key,\n type: change.type,\n value: change.value\n } as IChange\n ];\n } else {\n ptr.key = change.key;\n ptr.type = change.type;\n ptr.value = change.value;\n ptr.oldValue = change.oldValue;\n }\n } else {\n // branch\n ptr.key = segment;\n ptr.type = Operation.UPDATE;\n const newPtr = {} as IChange;\n ptr.changes = [newPtr];\n ptr = newPtr;\n }\n }\n }\n changesArr.push(obj);\n }\n });\n return changesArr;\n};\n\n/**\n * Determines the type of a given object.\n *\n * @param {any} obj - The object whose type is to be determined.\n * @returns {string | null} - The type of the object, or null if the object is null.\n *\n * This function first checks if the object is undefined or null, and returns 'undefined' or null respectively.\n * If the object is neither undefined nor null, it uses Object.prototype.toString to get the object's type.\n * The type is extracted from the string returned by Object.prototype.toString using a regular expression.\n */\nexport const getTypeOfObj = (obj: any) => {\n if (typeof obj === 'undefined') {\n return 'undefined';\n }\n\n if (obj === null) {\n return null;\n }\n\n // Extracts the \"Type\" from \"[object Type]\" string.\n return Object.prototype.toString.call(obj).match(/^\\[object\\s(.*)\\]$/)[1];\n};\n\nconst getKey = (path: string) => {\n const left = path[path.length - 1];\n return left != null ? left : '$root';\n};\n\nconst compare = (oldObj: any, newObj: any, path: any, embeddedObjKeys: any, keyPath: any, keysToSkip: string[]) => {\n let changes: any[] = [];\n\n const typeOfOldObj = getTypeOfObj(oldObj);\n const typeOfNewObj = getTypeOfObj(newObj);\n\n // if type of object changes, consider it as old obj has been deleted and a new object has been added\n if (typeOfOldObj !== typeOfNewObj) {\n changes.push({ type: Operation.REMOVE, key: getKey(path), value: oldObj });\n changes.push({ type: Operation.ADD, key: getKey(path), value: newObj });\n return changes;\n }\n\n switch (typeOfOldObj) {\n case 'Date':\n changes = changes.concat(\n comparePrimitives(oldObj.getTime(), newObj.getTime(), path).map((x) => ({\n ...x,\n value: new Date(x.value),\n oldValue: new Date(x.oldValue)\n }))\n );\n break;\n case 'Object':\n const diffs = compareObject(oldObj, newObj, path, embeddedObjKeys, keyPath, false, keysToSkip);\n if (diffs.length) {\n if (path.length) {\n changes.push({\n type: Operation.UPDATE,\n key: getKey(path),\n changes: diffs\n });\n } else {\n changes = changes.concat(diffs);\n }\n }\n break;\n case 'Array':\n changes = changes.concat(compareArray(oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip));\n break;\n case 'Function':\n break;\n // do nothing\n default:\n changes = changes.concat(comparePrimitives(oldObj, newObj, path));\n }\n\n return changes;\n};\n\nconst compareObject = (\n oldObj: any,\n newObj: any,\n path: any,\n embeddedObjKeys: any,\n keyPath: any,\n skipPath = false,\n keysToSkip: string[] = []\n) => {\n let k;\n let newKeyPath;\n let newPath;\n\n if (skipPath == null) {\n skipPath = false;\n }\n let changes: any[] = [];\n\n const oldObjKeys = Object.keys(oldObj).filter((key) => keysToSkip.indexOf(key) === -1);\n const newObjKeys = Object.keys(newObj).filter((key) => keysToSkip.indexOf(key) === -1);\n\n const intersectionKeys = intersection(oldObjKeys, newObjKeys);\n for (k of intersectionKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n const diffs = compare(oldObj[k], newObj[k], newPath, embeddedObjKeys, newKeyPath, keysToSkip);\n if (diffs.length) {\n changes = changes.concat(diffs);\n }\n }\n\n const addedKeys = difference(newObjKeys, oldObjKeys);\n for (k of addedKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n changes.push({\n type: Operation.ADD,\n key: getKey(newPath),\n value: newObj[k]\n });\n }\n\n const deletedKeys = difference(oldObjKeys, newObjKeys);\n for (k of deletedKeys) {\n newPath = path.concat([k]);\n newKeyPath = skipPath ? keyPath : keyPath.concat([k]);\n changes.push({\n type: Operation.REMOVE,\n key: getKey(newPath),\n value: oldObj[k]\n });\n }\n return changes;\n};\n\nconst compareArray = (\n oldObj: any,\n newObj: any,\n path: any,\n embeddedObjKeys: any,\n keyPath: any,\n keysToSkip: string[]\n) => {\n const left = getObjectKey(embeddedObjKeys, keyPath);\n const uniqKey = left != null ? left : '$index';\n const indexedOldObj = convertArrayToObj(oldObj, uniqKey);\n const indexedNewObj = convertArrayToObj(newObj, uniqKey);\n const diffs = compareObject(indexedOldObj, indexedNewObj, path, embeddedObjKeys, keyPath, true, keysToSkip);\n if (diffs.length) {\n return [\n {\n type: Operation.UPDATE,\n key: getKey(path),\n embeddedKey: typeof uniqKey === 'function' && uniqKey.length === 2 ? uniqKey(newObj[0], true) : uniqKey,\n changes: diffs\n }\n ];\n } else {\n return [];\n }\n};\n\nconst getObjectKey = (embeddedObjKeys: any, keyPath: any) => {\n if (embeddedObjKeys != null) {\n const path = keyPath.join('.');\n\n if (embeddedObjKeys instanceof Map) {\n for (const [key, value] of embeddedObjKeys.entries()) {\n if (key instanceof RegExp) {\n if (path.match(key)) {\n return value;\n }\n } else if (path === key) {\n return value;\n }\n }\n }\n\n const key = embeddedObjKeys[path];\n if (key != null) {\n return key;\n }\n }\n return undefined;\n};\n\nconst convertArrayToObj = (arr: any[], uniqKey: any) => {\n let obj: any = {};\n if (uniqKey === '$value') {\n arr.forEach((value) => {\n obj[value] = value;\n });\n } else if (uniqKey !== '$index') {\n obj = keyBy(arr, uniqKey);\n } else {\n for (let i = 0; i < arr.length; i++) {\n const value = arr[i];\n obj[i] = value;\n }\n }\n return obj;\n};\n\nconst comparePrimitives = (oldObj: any, newObj: any, path: any) => {\n const changes = [];\n if (oldObj !== newObj) {\n changes.push({\n type: Operation.UPDATE,\n key: getKey(path),\n value: newObj,\n oldValue: oldObj\n });\n }\n return changes;\n};\n\nconst removeKey = (obj: any, key: any, embeddedKey: any) => {\n if (Array.isArray(obj)) {\n if (embeddedKey === '$index') {\n obj.splice(key);\n return;\n }\n const index = indexOfItemInArray(obj, embeddedKey, key);\n if (index === -1) {\n // tslint:disable-next-line:no-console\n console.warn(`Element with the key '${embeddedKey}' and value '${key}' could not be found in the array'`);\n return;\n }\n return obj.splice(index != null ? index : key, 1);\n } else {\n obj[key] = undefined;\n delete obj[key];\n return;\n }\n};\n\nconst indexOfItemInArray = (arr: any[], key: any, value: any) => {\n if (key === '$value') {\n return arr.indexOf(value);\n }\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i];\n if (item && item[key] ? item[key].toString() === value.toString() : undefined) {\n return i;\n }\n }\n return -1;\n};\n\nconst modifyKeyValue = (obj: any, key: any, value: any) => (obj[key] = value);\n\nconst addKeyValue = (obj: any, key: any, value: any) => {\n if (Array.isArray(obj)) {\n return obj.push(value);\n } else {\n return obj ? (obj[key] = value) : null;\n }\n};\n\nconst applyLeafChange = (obj: any, change: any, embeddedKey: any) => {\n const { type, key, value } = change;\n switch (type) {\n case Operation.ADD:\n return addKeyValue(obj, key, value);\n case Operation.UPDATE:\n return modifyKeyValue(obj, key, value);\n case Operation.REMOVE:\n return removeKey(obj, key, embeddedKey);\n }\n};\n\nconst applyArrayChange = (arr: any, change: any) =>\n (() => {\n const result = [];\n for (const subchange of change.changes) {\n if (subchange.value != null || subchange.type === Operation.REMOVE) {\n result.push(applyLeafChange(arr, subchange, change.embeddedKey));\n } else {\n let element;\n if (change.embeddedKey === '$index') {\n element = arr[subchange.key];\n } else if (change.embeddedKey === '$value') {\n const index = arr.indexOf(subchange.key);\n if (index !== -1) {\n element = arr[index];\n }\n } else {\n element = find(arr, (el) => el[change.embeddedKey]?.toString() === subchange.key.toString());\n }\n result.push(applyChangeset(element, subchange.changes));\n }\n }\n return result;\n })();\n\nconst applyBranchChange = (obj: any, change: any) => {\n if (Array.isArray(obj)) {\n return applyArrayChange(obj, change);\n } else {\n return applyChangeset(obj, change.changes);\n }\n};\n\nconst revertLeafChange = (obj: any, change: any, embeddedKey = '$index') => {\n const { type, key, value, oldValue } = change;\n switch (type) {\n case Operation.ADD:\n return removeKey(obj, key, embeddedKey);\n case Operation.UPDATE:\n return modifyKeyValue(obj, key, oldValue);\n case Operation.REMOVE:\n return addKeyValue(obj, key, value);\n }\n};\n\nconst revertArrayChange = (arr: any, change: any) =>\n (() => {\n const result = [];\n for (const subchange of change.changes) {\n if (subchange.value != null || subchange.type === Operation.REMOVE) {\n result.push(revertLeafChange(arr, subchange, change.embeddedKey));\n } else {\n let element;\n if (change.embeddedKey === '$index') {\n element = arr[+subchange.key];\n } else {\n element = find(arr, (el) => el[change.embeddedKey].toString() === subchange.key);\n }\n result.push(revertChangeset(element, subchange.changes));\n }\n }\n return result;\n })();\n\nconst revertBranchChange = (obj: any, change: any) => {\n if (Array.isArray(obj)) {\n return revertArrayChange(obj, change);\n } else {\n return revertChangeset(obj, change.changes);\n }\n};\n\n/** combine a base JSON Path with a subsequent segment */\nfunction append(basePath: string, nextSegment: string): string {\n return nextSegment.includes('.') ? `${basePath}[${nextSegment}]` : `${basePath}.${nextSegment}`;\n}\n\n/** returns a JSON Path filter expression; e.g., `$.pet[(?name='spot')]` */\nfunction filterExpression(basePath: string, filterKey: string | FunctionKey, filterValue: string | number) {\n const value = typeof filterValue === 'number' ? filterValue : `'${filterValue}'`;\n return typeof filterKey === 'string' && filterKey.includes('.')\n ? `${basePath}[?(@[${filterKey}]==${value})]`\n : `${basePath}[?(@.${filterKey}==${value})]`;\n}\n","import { chain, keys, replace, set } from 'lodash';\nimport { diff, flattenChangeset, getTypeOfObj, IFlatChange, Operation } from './jsonDiff.js';\n\nexport enum CompareOperation {\n CONTAINER = 'CONTAINER',\n UNCHANGED = 'UNCHANGED'\n}\n\nexport interface IComparisonEnrichedNode {\n type: Operation | CompareOperation;\n value: IComparisonEnrichedNode | IComparisonEnrichedNode[] | any | any[];\n oldValue?: any;\n}\n\nexport const createValue = (value: any): IComparisonEnrichedNode => ({ type: CompareOperation.UNCHANGED, value });\nexport const createContainer = (value: object | []): IComparisonEnrichedNode => ({\n type: CompareOperation.CONTAINER,\n value\n});\n\nexport const enrich = (object: any): IComparisonEnrichedNode => {\n const objectType = getTypeOfObj(object);\n\n switch (objectType) {\n case 'Object':\n return keys(object)\n .map((key: string) => ({ key, value: enrich(object[key]) }))\n .reduce((accumulator, entry) => {\n accumulator.value[entry.key] = entry.value;\n return accumulator;\n }, createContainer({}));\n case 'Array':\n return chain(object)\n .map((value) => enrich(value))\n .reduce((accumulator, value) => {\n accumulator.value.push(value);\n return accumulator;\n }, createContainer([]))\n .value();\n case 'Function':\n return undefined;\n case 'Date':\n default:\n // Primitive value\n return createValue(object);\n }\n};\n\nexport const applyChangelist = (\n object: IComparisonEnrichedNode,\n changelist: IFlatChange[]\n): IComparisonEnrichedNode => {\n chain(changelist)\n .map((entry) => ({ ...entry, path: replace(entry.path, '$.', '.') }))\n .map((entry) => ({\n ...entry,\n path: replace(entry.path, /(\\[(?<array>\\d)\\]\\.)/g, 'ARRVAL_START$<array>ARRVAL_END')\n }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /(?<dot>\\.)/g, '.value$<dot>') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /\\./, '') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /ARRVAL_START/g, '.value[') }))\n .map((entry) => ({ ...entry, path: replace(entry.path, /ARRVAL_END/g, '].value.') }))\n .value()\n .forEach((entry) => {\n switch (entry.type) {\n case Operation.ADD:\n case Operation.UPDATE:\n set(object, entry.path, { type: entry.type, value: entry.value, oldValue: entry.oldValue });\n break;\n case Operation.REMOVE:\n set(object, entry.path, { type: entry.type, value: undefined, oldValue: entry.value });\n break;\n default:\n throw new Error();\n }\n });\n return object;\n};\n\nexport const compare = (oldObject: any, newObject: any): IComparisonEnrichedNode => {\n return applyChangelist(enrich(oldObject), flattenChangeset(diff(oldObject, newObject)));\n};\n"],"mappings":"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","names":["Operation","key","CompareOperation","compare"]}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-diff-ts",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.7",
|
|
4
4
|
"description": "A JSON diff tool for JavaScript written in TypeScript.",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"scripts": {
|
|
10
|
-
"build": "tsup --format cjs,esm
|
|
10
|
+
"build": "tsup --format cjs,esm",
|
|
11
11
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
12
12
|
"lint": "eslint 'src/**/*.ts'",
|
|
13
13
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest --config jest.config.mjs",
|
|
@@ -38,9 +38,6 @@
|
|
|
38
38
|
"url": "https://github.com/ltwlf/json-diff-ts/issues"
|
|
39
39
|
},
|
|
40
40
|
"homepage": "https://github.com/ltwlf/json-diff-ts#readme",
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"lodash-es": "^4.17.21"
|
|
43
|
-
},
|
|
44
41
|
"devDependencies": {
|
|
45
42
|
"@jest/globals": "^29.7.0",
|
|
46
43
|
"@types/jest": "^29.5.7",
|
|
@@ -49,8 +46,10 @@
|
|
|
49
46
|
"jest": "^29.7.0",
|
|
50
47
|
"prettier": "^3.0.3",
|
|
51
48
|
"ts-jest": "^29.0.5",
|
|
52
|
-
"tsconfig-paths": "^4.2.0",
|
|
53
49
|
"tsup": "^8.0.2",
|
|
54
50
|
"typescript": "^5.3.2"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"lodash": "4.x"
|
|
55
54
|
}
|
|
56
55
|
}
|