json-diff-ts 2.0.0 → 2.1.0

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 CHANGED
@@ -119,6 +119,18 @@ Paths can be utilized to identify keys within nested arrays.
119
119
  const diffs = diff(oldData, newData, { characters.subarray: 'id' });
120
120
  ```
121
121
 
122
+ Alternative Syntax
123
+
124
+ ```javascript
125
+ const diffs = diff(oldData, newData, { 'characters.subarray': 'id' });
126
+ ```
127
+
128
+ You can also designate the root by using '.' instead of an empty string ('').
129
+
130
+ ```javascript
131
+ const diffs = diff(oldData, newData, { '.characters.subarray': 'id' });
132
+ ```
133
+
122
134
  You can use a function to dynamically resolve the key of the object.
123
135
  The first parameter is the object and the second is to signal if the function should return the key name instead of the value. This is needed to flatten the changeset
124
136
 
@@ -238,6 +250,7 @@ Discover more about the company behind this project: [hololux](https://hololux.c
238
250
 
239
251
  ## Release Notes
240
252
 
253
+ - **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.
241
254
  - **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.
242
255
  - **v1.2.6:** Enhanced JSON Path handling for period-inclusive segments.
243
256
  - **v1.2.5:** Patched dependencies; added key name resolution support for key functions.
package/lib/jsonDiff.d.ts CHANGED
@@ -23,6 +23,14 @@ export interface IFlatChange {
23
23
  value?: any;
24
24
  oldValue?: any;
25
25
  }
26
+ /**
27
+ * Computes the difference between two objects.
28
+ *
29
+ * @param {any} oldObj - The original object.
30
+ * @param {any} newObj - The updated object.
31
+ * @param {EmbeddedObjKeysType | EmbeddedObjKeysMapType} embeddedObjKeys - An optional parameter specifying keys of embedded objects.
32
+ * @returns {IChange[]} - An array of changes that transform the old object into the new object.
33
+ */
26
34
  export declare function diff(oldObj: any, newObj: any, embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType): IChange[];
27
35
  /**
28
36
  * Applies all changes in the changeset to the object.
package/lib/jsonDiff.js CHANGED
@@ -5,7 +5,26 @@ export var Operation;
5
5
  Operation["ADD"] = "ADD";
6
6
  Operation["UPDATE"] = "UPDATE";
7
7
  })(Operation || (Operation = {}));
8
+ /**
9
+ * Computes the difference between two objects.
10
+ *
11
+ * @param {any} oldObj - The original object.
12
+ * @param {any} newObj - The updated object.
13
+ * @param {EmbeddedObjKeysType | EmbeddedObjKeysMapType} embeddedObjKeys - An optional parameter specifying keys of embedded objects.
14
+ * @returns {IChange[]} - An array of changes that transform the old object into the new object.
15
+ */
8
16
  export function diff(oldObj, newObj, embeddedObjKeys) {
17
+ // Trim leading '.' from keys in embeddedObjKeys
18
+ if (embeddedObjKeys instanceof Map) {
19
+ embeddedObjKeys = new Map(Array.from(embeddedObjKeys.entries()).map(([key, value]) => [
20
+ key instanceof RegExp ? key : key.replace(/^\./, ''),
21
+ value
22
+ ]));
23
+ }
24
+ else if (embeddedObjKeys) {
25
+ embeddedObjKeys = Object.fromEntries(Object.entries(embeddedObjKeys).map(([key, value]) => [key.replace(/^\./, ''), value]));
26
+ }
27
+ // Compare old and new objects to generate a list of changes
9
28
  return compare(oldObj, newObj, [], embeddedObjKeys, []);
10
29
  }
11
30
  /**
@@ -115,14 +134,7 @@ export const unflattenChanges = (changes) => {
115
134
  changes.forEach((change) => {
116
135
  const obj = {};
117
136
  let ptr = obj;
118
- const segments = change.path.split(/([^@])\./).reduce((acc, curr, i) => {
119
- const x = Math.floor(i / 2);
120
- if (!acc[x]) {
121
- acc[x] = '';
122
- }
123
- acc[x] += curr;
124
- return acc;
125
- }, []);
137
+ const segments = change.path.split(/(?<=[^@])\.(?=[^@])/);
126
138
  if (segments.length === 1) {
127
139
  ptr.key = change.key;
128
140
  ptr.type = change.type;
@@ -133,8 +145,8 @@ export const unflattenChanges = (changes) => {
133
145
  else {
134
146
  for (let i = 1; i < segments.length; i++) {
135
147
  const segment = segments[i];
136
- // Matches JSONPath segments: "items[?(@.id='123')]" or "items[2]"
137
- const result = /^(.+)\[\?\(@\.(.+)='(.+)'\)]$|^(.+)\[(\d+)\]/.exec(segment);
148
+ // Matches JSONPath segments: "items[?(@.id=='123')]", items[?(@.id==123)], "items[2]"
149
+ const result = /^(.+)\[\?\(@\.([^=]+)={1,2}(?:'(.*)'|(\d+))\)\]$|^(.+)\[(\d+)\]$/.exec(segment);
138
150
  // array
139
151
  if (result) {
140
152
  let key;
@@ -146,9 +158,9 @@ export const unflattenChanges = (changes) => {
146
158
  arrKey = result[3];
147
159
  }
148
160
  else {
149
- key = result[4];
161
+ key = result[5];
150
162
  embeddedKey = '$index';
151
- arrKey = Number(result[5]);
163
+ arrKey = Number(result[6]);
152
164
  }
153
165
  // leaf
154
166
  if (i === segments.length - 1) {
@@ -454,7 +466,7 @@ const applyArrayChange = (arr, change) => (() => {
454
466
  element = arr[subchange.key];
455
467
  }
456
468
  else {
457
- element = find(arr, (el) => el[change.embeddedKey].toString() === subchange.key.toString());
469
+ element = find(arr, (el) => el[change.embeddedKey]?.toString() === subchange.key.toString());
458
470
  }
459
471
  result.push(applyChangeset(element, subchange.changes));
460
472
  }
@@ -513,7 +525,8 @@ function append(basePath, nextSegment) {
513
525
  }
514
526
  /** returns a JSON Path filter expression; e.g., `$.pet[(?name='spot')]` */
515
527
  function filterExpression(basePath, filterKey, filterValue) {
528
+ const value = typeof filterValue === 'number' ? filterValue : `'${filterValue}'`;
516
529
  return typeof filterKey === 'string' && filterKey.includes('.')
517
- ? `${basePath}[?(@[${filterKey}]='${filterValue}')]`
518
- : `${basePath}[?(@.${filterKey}='${filterValue}')]`;
530
+ ? `${basePath}[?(@[${filterKey}]==${value})]`
531
+ : `${basePath}[?(@.${filterKey}==${value})]`;
519
532
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-diff-ts",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "A JSON diff tool for JavaScript written in TypeScript.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",