json-diff-ts 3.0.0 → 4.0.0-beta.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
@@ -28,7 +28,7 @@ In CommonJS, you can import the diff function like this:
28
28
 
29
29
  ```javascript
30
30
  const { diff } = require('json-diff-ts');
31
- ```
31
+ ```
32
32
 
33
33
  ## Capabilities
34
34
 
@@ -132,13 +132,19 @@ const expectedDiffs = [
132
132
  Paths can be utilized to identify keys within nested arrays.
133
133
 
134
134
  ```javascript
135
- const diffs = diff(oldData, newData, { 'characters.subarray': 'id' });
135
+ const diffs = diff(oldData, newData, { embeddedObjKeys { 'characters.subarray': 'id' }});
136
136
  ```
137
137
 
138
138
  You can also designate the root by using '.' instead of an empty string ('').
139
139
 
140
140
  ```javascript
141
- const diffs = diff(oldData, newData, { '.characters.subarray': 'id' });
141
+ const diffs = diff(oldData, newData, { embeddedObjKeys: { '.characters.subarray': 'id' } });
142
+ ```
143
+
144
+ Determine if type changes are treated as a replace (remove, add) or as an update; default is replace.
145
+
146
+ ```javascript
147
+ const diffs = diff(oldData, newData, { treatTypeChangeAsReplace: false });
142
148
  ```
143
149
 
144
150
  You can use a function to dynamically resolve the key of the object.
@@ -146,7 +152,9 @@ The first parameter is the object and the second is to signal if the function sh
146
152
 
147
153
  ```javascript
148
154
  const diffs = diff(oldData, newData, {
149
- characters: (obj, shouldReturnKeyName) => (shouldReturnKeyName ? 'id' : obj.id)
155
+ embeddedObjKeys: {
156
+ characters: (obj, shouldReturnKeyName) => (shouldReturnKeyName ? 'id' : obj.id)
157
+ }
150
158
  });
151
159
  ```
152
160
 
@@ -157,30 +165,30 @@ const embeddedObjKeys: EmbeddedObjKeysMapType = new Map();
157
165
 
158
166
  embeddedObjKeys.set(/^char\w+$/, 'id'); // instead of 'id' you can specify a function
159
167
 
160
- const diffs = diff(oldObj, newObj, embeddedObjKeys);
168
+ const diffs = diff(oldObj, newObj, { embeddedObjKeys });
161
169
  ```
162
170
 
163
171
  Compare string arrays by value instead of index
164
172
 
165
173
  ```javascript
166
- const diffs = diff(oldObj, newObj, { stringArr: '$value' });
174
+ const diffs = diff(oldObj, newObj, { embeddedObjKeys: { stringArr: '$value' } });
167
175
  ```
168
176
 
169
- ### `flattenChangeset`
177
+ ### `atomizeChangeset`
170
178
 
171
- Transforms a complex changeset into a flat list of atomic changes, each describable by a JSONPath.
179
+ Transforms a complex changeset into a list of atomic changes, each describable by a JSONPath.
172
180
 
173
181
  #### Examples:
174
182
 
175
183
  ```javascript
176
- const flatChanges = flattenChangeset(diffs);
177
- // Restore the changeset from a selection of flat changes
178
- const changeset = unflattenChanges(flatChanges.slice(0, 3));
184
+ const atomicChanges = atomizeChangeset(diffs);
185
+ // Restore the changeset from a selection of atomic changes
186
+ const changeset = unatomizeChangeset(flatChanges.slice(0, 3));
179
187
  // Alternatively, apply the changes using a JSONPath-capable library
180
188
  // ...
181
189
  ```
182
190
 
183
- A **flatChange** will have the following structure:
191
+ **Atomic Changes** will have the following structure:
184
192
 
185
193
  ```javascript
186
194
  [
@@ -265,6 +273,8 @@ Reach out to the maintainer via LinkedIn or Twitter:
265
273
  Discover more about the company behind this project: [hololux](https://hololux.com)
266
274
 
267
275
  ## Release Notes
276
+ - **v4.0.0:** Change naming of flattenChangest and unflattenChanges to atomizeChangeset and unatomizeChangeset; option to set treatTypeChangeAsReplace
277
+ - **v3.0.1:** Fix issue with unflattenChanges when a key has periods
268
278
  - **v3.0.0:** Supports CommonJS and ECMAScript Modules. Dependency to lodash-es was replaced with lodash to support both ECMAScript and CommonJS.
269
279
  - **v2.2.0:** Fix lodash-es decependency, exclude keys, compare string arrays by value
270
280
  - **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.
package/dist/index.cjs CHANGED
@@ -24,27 +24,58 @@ __export(src_exports, {
24
24
  Operation: () => Operation,
25
25
  applyChangelist: () => applyChangelist,
26
26
  applyChangeset: () => applyChangeset,
27
+ atomizeChangeset: () => atomizeChangeset,
27
28
  compare: () => compare2,
28
29
  createContainer: () => createContainer,
29
30
  createValue: () => createValue,
30
31
  diff: () => diff,
31
32
  enrich: () => enrich,
32
- flattenChangeset: () => flattenChangeset,
33
33
  getTypeOfObj: () => getTypeOfObj,
34
34
  revertChangeset: () => revertChangeset,
35
- unflattenChanges: () => unflattenChanges
35
+ unatomizeChangeset: () => unatomizeChangeset
36
36
  });
37
37
  module.exports = __toCommonJS(src_exports);
38
38
 
39
39
  // src/jsonDiff.ts
40
40
  var import_lodash = require("lodash");
41
+
42
+ // src/helpers.ts
43
+ function splitJSONPath(path) {
44
+ let parts = [];
45
+ let currentPart = "";
46
+ let inSingleQuotes = false;
47
+ let inBrackets = 0;
48
+ for (let i = 0; i < path.length; i++) {
49
+ const char = path[i];
50
+ if (char === "'" && path[i - 1] !== "\\") {
51
+ inSingleQuotes = !inSingleQuotes;
52
+ } else if (char === "[" && !inSingleQuotes) {
53
+ inBrackets++;
54
+ } else if (char === "]" && !inSingleQuotes) {
55
+ inBrackets--;
56
+ }
57
+ if (char === "." && !inSingleQuotes && inBrackets === 0) {
58
+ parts.push(currentPart);
59
+ currentPart = "";
60
+ } else {
61
+ currentPart += char;
62
+ }
63
+ }
64
+ if (currentPart !== "") {
65
+ parts.push(currentPart);
66
+ }
67
+ return parts;
68
+ }
69
+
70
+ // src/jsonDiff.ts
41
71
  var Operation = /* @__PURE__ */ ((Operation2) => {
42
72
  Operation2["REMOVE"] = "REMOVE";
43
73
  Operation2["ADD"] = "ADD";
44
74
  Operation2["UPDATE"] = "UPDATE";
45
75
  return Operation2;
46
76
  })(Operation || {});
47
- function diff(oldObj, newObj, embeddedObjKeys, keysToSkip) {
77
+ function diff(oldObj, newObj, options = {}) {
78
+ let { embeddedObjKeys, keysToSkip, treatTypeChangeAsReplace } = options;
48
79
  if (embeddedObjKeys instanceof Map) {
49
80
  embeddedObjKeys = new Map(
50
81
  Array.from(embeddedObjKeys.entries()).map(([key, value]) => [
@@ -57,7 +88,11 @@ function diff(oldObj, newObj, embeddedObjKeys, keysToSkip) {
57
88
  Object.entries(embeddedObjKeys).map(([key, value]) => [key.replace(/^\./, ""), value])
58
89
  );
59
90
  }
60
- return compare(oldObj, newObj, [], embeddedObjKeys, [], keysToSkip);
91
+ return compare(oldObj, newObj, [], [], {
92
+ embeddedObjKeys,
93
+ keysToSkip: keysToSkip ?? [],
94
+ treatTypeChangeAsReplace: treatTypeChangeAsReplace ?? true
95
+ });
61
96
  }
62
97
  var applyChangeset = (obj, changeset) => {
63
98
  if (changeset) {
@@ -80,45 +115,55 @@ var revertChangeset = (obj, changeset) => {
80
115
  }
81
116
  return obj;
82
117
  };
83
- var flattenChangeset = (obj, path = "$", embeddedKey) => {
118
+ var atomizeChangeset = (obj, path = "$", embeddedKey) => {
84
119
  if (Array.isArray(obj)) {
85
- return obj.reduce((memo, change) => [...memo, ...flattenChangeset(change, path, embeddedKey)], []);
86
- } else {
87
- if (obj.changes || embeddedKey) {
88
- if (embeddedKey) {
89
- if (embeddedKey === "$index") {
90
- path = `${path}[${obj.key}]`;
91
- } else if (embeddedKey === "$value") {
92
- path = `${path}[?(@='${obj.key}')]`;
93
- const valueType = getTypeOfObj(obj.value);
94
- return [
95
- {
96
- ...obj,
97
- path,
98
- valueType
99
- }
100
- ];
101
- } else if (obj.type === "ADD" /* ADD */) {
102
- } else {
103
- path = filterExpression(path, embeddedKey, obj.key);
104
- }
105
- } else {
106
- path = append(path, obj.key);
120
+ return handleArray(obj, path, embeddedKey);
121
+ } else if (obj.changes || embeddedKey) {
122
+ if (embeddedKey) {
123
+ const [updatedPath, atomicChange] = handleEmbeddedKey(embeddedKey, obj, path);
124
+ path = updatedPath;
125
+ if (atomicChange) {
126
+ return atomicChange;
107
127
  }
108
- return flattenChangeset(obj.changes || obj, path, obj.embeddedKey);
109
128
  } else {
110
- const valueType = getTypeOfObj(obj.value);
111
- return [
112
- {
113
- ...obj,
114
- path: valueType === "Object" || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),
115
- valueType
116
- }
117
- ];
129
+ path = append(path, obj.key);
118
130
  }
131
+ return atomizeChangeset(obj.changes || obj, path, obj.embeddedKey);
132
+ } else {
133
+ const valueType = getTypeOfObj(obj.value);
134
+ return [{
135
+ ...obj,
136
+ path: valueType === "Object" || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),
137
+ valueType
138
+ }];
119
139
  }
120
140
  };
121
- var unflattenChanges = (changes) => {
141
+ function handleEmbeddedKey(embeddedKey, obj, path) {
142
+ if (embeddedKey === "$index") {
143
+ path = `${path}[${obj.key}]`;
144
+ return [path];
145
+ } else if (embeddedKey === "$value") {
146
+ path = `${path}[?(@=='${obj.key}')]`;
147
+ const valueType = getTypeOfObj(obj.value);
148
+ return [
149
+ path,
150
+ [{
151
+ ...obj,
152
+ path,
153
+ valueType
154
+ }]
155
+ ];
156
+ } else if (obj.type === "ADD" /* ADD */) {
157
+ return [path];
158
+ } else {
159
+ path = filterExpression(path, embeddedKey, obj.key);
160
+ return [path];
161
+ }
162
+ }
163
+ var handleArray = (obj, path, embeddedKey) => {
164
+ return obj.reduce((memo, change) => [...memo, ...atomizeChangeset(change, path, embeddedKey)], []);
165
+ };
166
+ var unatomizeChangeset = (changes) => {
122
167
  if (!Array.isArray(changes)) {
123
168
  changes = [changes];
124
169
  }
@@ -126,7 +171,7 @@ var unflattenChanges = (changes) => {
126
171
  changes.forEach((change) => {
127
172
  const obj = {};
128
173
  let ptr = obj;
129
- const segments = change.path.split(/(?<=[^@])\.(?=[^@])/);
174
+ const segments = splitJSONPath(change.path);
130
175
  if (segments.length === 1) {
131
176
  ptr.key = change.key;
132
177
  ptr.type = change.type;
@@ -136,7 +181,7 @@ var unflattenChanges = (changes) => {
136
181
  } else {
137
182
  for (let i = 1; i < segments.length; i++) {
138
183
  const segment = segments[i];
139
- const result = /^(.+?)\[\?\(@.?(?:([^=]*))?={1,2}'(.*)'\)\]$|^(.+?)\[(\d+)\]$/.exec(segment);
184
+ const result = /^([^[\]]+)\[\?\(@\.?([^=]*)=+'([^']+)'\)\]$|^(.+)\[(\d+)\]$/.exec(segment);
140
185
  if (result) {
141
186
  let key;
142
187
  let embeddedKey;
@@ -148,7 +193,7 @@ var unflattenChanges = (changes) => {
148
193
  } else {
149
194
  key = result[4];
150
195
  embeddedKey = "$index";
151
- arrKey = Number(result[4]);
196
+ arrKey = Number(result[5]);
152
197
  }
153
198
  if (i === segments.length - 1) {
154
199
  ptr.key = key;
@@ -221,15 +266,19 @@ var getKey = (path) => {
221
266
  const left = path[path.length - 1];
222
267
  return left != null ? left : "$root";
223
268
  };
224
- var compare = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
269
+ var compare = (oldObj, newObj, path, keyPath, options) => {
225
270
  let changes = [];
226
271
  const typeOfOldObj = getTypeOfObj(oldObj);
227
272
  const typeOfNewObj = getTypeOfObj(newObj);
228
- if (typeOfOldObj !== typeOfNewObj) {
273
+ if (options.treatTypeChangeAsReplace && typeOfOldObj !== typeOfNewObj) {
229
274
  changes.push({ type: "REMOVE" /* REMOVE */, key: getKey(path), value: oldObj });
230
275
  changes.push({ type: "ADD" /* ADD */, key: getKey(path), value: newObj });
231
276
  return changes;
232
277
  }
278
+ if (typeOfNewObj === "Object" && typeOfOldObj === "Array") {
279
+ changes.push({ type: "UPDATE" /* UPDATE */, key: getKey(path), value: newObj, oldValue: oldObj });
280
+ return changes;
281
+ }
233
282
  switch (typeOfOldObj) {
234
283
  case "Date":
235
284
  changes = changes.concat(
@@ -240,8 +289,8 @@ var compare = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
240
289
  }))
241
290
  );
242
291
  break;
243
- case "Object":
244
- const diffs = compareObject(oldObj, newObj, path, embeddedObjKeys, keyPath, false, keysToSkip);
292
+ case "Object": {
293
+ const diffs = compareObject(oldObj, newObj, path, keyPath, false, options);
245
294
  if (diffs.length) {
246
295
  if (path.length) {
247
296
  changes.push({
@@ -254,8 +303,9 @@ var compare = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
254
303
  }
255
304
  }
256
305
  break;
306
+ }
257
307
  case "Array":
258
- changes = changes.concat(compareArray(oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip));
308
+ changes = changes.concat(compareArray(oldObj, newObj, path, keyPath, options));
259
309
  break;
260
310
  case "Function":
261
311
  break;
@@ -264,7 +314,7 @@ var compare = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
264
314
  }
265
315
  return changes;
266
316
  };
267
- var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath = false, keysToSkip = []) => {
317
+ var compareObject = (oldObj, newObj, path, keyPath, skipPath = false, options = {}) => {
268
318
  let k;
269
319
  let newKeyPath;
270
320
  let newPath;
@@ -272,13 +322,13 @@ var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath =
272
322
  skipPath = false;
273
323
  }
274
324
  let changes = [];
275
- const oldObjKeys = Object.keys(oldObj).filter((key) => keysToSkip.indexOf(key) === -1);
276
- const newObjKeys = Object.keys(newObj).filter((key) => keysToSkip.indexOf(key) === -1);
325
+ const oldObjKeys = Object.keys(oldObj).filter((key) => options.keysToSkip.indexOf(key) === -1);
326
+ const newObjKeys = Object.keys(newObj).filter((key) => options.keysToSkip.indexOf(key) === -1);
277
327
  const intersectionKeys = (0, import_lodash.intersection)(oldObjKeys, newObjKeys);
278
328
  for (k of intersectionKeys) {
279
329
  newPath = path.concat([k]);
280
330
  newKeyPath = skipPath ? keyPath : keyPath.concat([k]);
281
- const diffs = compare(oldObj[k], newObj[k], newPath, embeddedObjKeys, newKeyPath, keysToSkip);
331
+ const diffs = compare(oldObj[k], newObj[k], newPath, newKeyPath, options);
282
332
  if (diffs.length) {
283
333
  changes = changes.concat(diffs);
284
334
  }
@@ -305,12 +355,12 @@ var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath =
305
355
  }
306
356
  return changes;
307
357
  };
308
- var compareArray = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
309
- const left = getObjectKey(embeddedObjKeys, keyPath);
358
+ var compareArray = (oldObj, newObj, path, keyPath, options) => {
359
+ const left = getObjectKey(options.embeddedObjKeys, keyPath);
310
360
  const uniqKey = left != null ? left : "$index";
311
361
  const indexedOldObj = convertArrayToObj(oldObj, uniqKey);
312
362
  const indexedNewObj = convertArrayToObj(newObj, uniqKey);
313
- const diffs = compareObject(indexedOldObj, indexedNewObj, path, embeddedObjKeys, keyPath, true, keysToSkip);
363
+ const diffs = compareObject(indexedOldObj, indexedNewObj, path, keyPath, true, options);
314
364
  if (diffs.length) {
315
365
  return [
316
366
  {
@@ -546,7 +596,7 @@ var applyChangelist = (object, changelist) => {
546
596
  return object;
547
597
  };
548
598
  var compare2 = (oldObject, newObject) => {
549
- return applyChangelist(enrich(oldObject), flattenChangeset(diff(oldObject, newObject)));
599
+ return applyChangelist(enrich(oldObject), atomizeChangeset(diff(oldObject, newObject)));
550
600
  };
551
601
  // Annotate the CommonJS export names for ESM import in node:
552
602
  0 && (module.exports = {
@@ -554,14 +604,14 @@ var compare2 = (oldObject, newObject) => {
554
604
  Operation,
555
605
  applyChangelist,
556
606
  applyChangeset,
607
+ atomizeChangeset,
557
608
  compare,
558
609
  createContainer,
559
610
  createValue,
560
611
  diff,
561
612
  enrich,
562
- flattenChangeset,
563
613
  getTypeOfObj,
564
614
  revertChangeset,
565
- unflattenChanges
615
+ unatomizeChangeset
566
616
  });
567
617
  //# sourceMappingURL=index.cjs.map
@@ -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';\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"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/jsonDiff.ts","../src/helpers.ts","../src/jsonCompare.ts"],"sourcesContent":["export * from './jsonDiff.js';\nexport * from './jsonCompare.js';\n","import { difference, find, intersection, keyBy } from 'lodash';\nimport { splitJSONPath } from './helpers';\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;\n oldValue?: any;\n changes?: IChange[];\n}\nexport type Changeset = IChange[];\n\nexport interface IAtomicChange {\n type: Operation;\n key: string;\n path: string;\n valueType: string | null;\n value?: any;\n oldValue?: any;\n}\n\nexport interface Options {\n embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType;\n keysToSkip?: string[];\n treatTypeChangeAsReplace?: boolean;\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 {Options} options - An optional parameter specifying keys of embedded objects and keys to skip.\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 options: Options = {}\n): IChange[] {\n let { embeddedObjKeys, keysToSkip, treatTypeChangeAsReplace } = options;\n\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, [], [], {\n embeddedObjKeys,\n keysToSkip: keysToSkip ?? [],\n treatTypeChangeAsReplace: treatTypeChangeAsReplace ?? true\n });\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 * Atomize a changeset into an array of single 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 {IAtomicChange[]} - An array of atomic changes.\n *\n * The function first checks if the input is an array. If so, it recursively atomize 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 atomic change and returns it in an array.\n */\nexport const atomizeChangeset = (\n obj: Changeset | IChange,\n path = '$',\n embeddedKey?: string | FunctionKey\n): IAtomicChange[] => {\n if (Array.isArray(obj)) {\n return handleArray(obj, path, embeddedKey);\n } else if (obj.changes || embeddedKey) {\n if (embeddedKey) {\n const [updatedPath, atomicChange] = handleEmbeddedKey(embeddedKey, obj, path);\n path = updatedPath;\n if (atomicChange) {\n return atomicChange;\n }\n } else {\n path = append(path, obj.key);\n }\n return atomizeChangeset(obj.changes || obj, path, obj.embeddedKey);\n } else {\n const valueType = getTypeOfObj(obj.value);\n return [{\n ...obj,\n path: valueType === 'Object' || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),\n valueType\n }];\n }\n};\n\n// Function to handle embeddedKey logic and update the path\nfunction handleEmbeddedKey(embeddedKey: string | FunctionKey, obj: IChange, path: string): [string, IAtomicChange[]?] {\n if (embeddedKey === '$index') {\n path = `${path}[${obj.key}]`;\n return [path]\n } else if (embeddedKey === '$value') {\n path = `${path}[?(@=='${obj.key}')]`;\n const valueType = getTypeOfObj(obj.value);\n return [\n path,\n [{\n ...obj,\n path,\n valueType\n }]\n ];\n } else if (obj.type === Operation.ADD) {\n // do nothing\n return [path];\n } else {\n path = filterExpression(path, embeddedKey, obj.key);\n return [path];\n }\n}\n\n\nconst handleArray = (obj: Changeset | IChange[], path: string, embeddedKey?: string | FunctionKey): IAtomicChange[] => {\n return obj.reduce((memo, change) => [...memo, ...atomizeChangeset(change, path, embeddedKey)], [] as IAtomicChange[]);\n}\n\n\n\n/**\n * Transforms an atomized changeset into a nested changeset.\n *\n * @param {IAtomicChange | IAtomicChange[]} changes - The atomic 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 unatomizeChangeset = (changes: IAtomicChange | IAtomicChange[]) => {\n if (!Array.isArray(changes)) {\n changes = [changes];\n }\n\n const changesArr: IChange[] = [];\n\n\n changes.forEach((change) => {\n const obj = {} as IChange;\n let ptr = obj;\n\n const segments = splitJSONPath(change.path);\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 = /^([^[\\]]+)\\[\\?\\(@\\.?([^=]*)=+'([^']+)'\\)\\]$|^(.+)\\[(\\d+)\\]$/.exec(segment);\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[5]);\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, keyPath: any, options: Options) => {\n let changes: any[] = [];\n\n const typeOfOldObj = getTypeOfObj(oldObj);\n const typeOfNewObj = getTypeOfObj(newObj);\n\n // `treatTypeChangeAsReplace` is a flag used to determine if a change in type should be treated as a replacement.\n if (options.treatTypeChangeAsReplace && 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 if (typeOfNewObj === 'Object' && typeOfOldObj === 'Array') {\n changes.push({ type: Operation.UPDATE, key: getKey(path), value: newObj, oldValue: oldObj });\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 {\n const diffs = compareObject(oldObj, newObj, path, keyPath, false, options);\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 }\n case 'Array':\n changes = changes.concat(compareArray(oldObj, newObj, path, keyPath, options));\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 keyPath: any,\n skipPath = false,\n options: Options = {},\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) => options.keysToSkip.indexOf(key) === -1);\n const newObjKeys = Object.keys(newObj).filter((key) => options.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, newKeyPath, options);\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 keyPath: any,\n options: Options\n) => {\n const left = getObjectKey(options.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, keyPath, true, options);\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\n","export function splitJSONPath(path: string): string[] {\n let parts: string[] = [];\n let currentPart = '';\n let inSingleQuotes = false;\n let inBrackets = 0;\n\n for (let i = 0; i < path.length; i++) {\n const char = path[i];\n\n if (char === \"'\" && path[i - 1] !== '\\\\') {\n // Toggle single quote flag if not escaped\n inSingleQuotes = !inSingleQuotes;\n } else if (char === '[' && !inSingleQuotes) {\n // Increase bracket nesting level\n inBrackets++;\n } else if (char === ']' && !inSingleQuotes) {\n // Decrease bracket nesting level\n inBrackets--;\n }\n\n if (char === '.' && !inSingleQuotes && inBrackets === 0) {\n // Split at period if not in quotes or brackets\n parts.push(currentPart);\n currentPart = '';\n } else {\n // Otherwise, keep adding to the current part\n currentPart += char;\n }\n }\n\n // Add the last part if there's any\n if (currentPart !== '') {\n parts.push(currentPart);\n }\n\n return parts;\n}\n","import { chain, keys, replace, set } from 'lodash';\nimport { diff, atomizeChangeset, getTypeOfObj, IAtomicChange, 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: IAtomicChange[]\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), atomizeChangeset(diff(oldObject, newObject)));\n};\n"],"mappings":"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","names":["compare","Operation","key","import_lodash","CompareOperation","compare"]}
package/dist/index.d.cts CHANGED
@@ -10,12 +10,12 @@ interface IChange {
10
10
  type: Operation;
11
11
  key: string;
12
12
  embeddedKey?: string | FunctionKey;
13
- value?: any | any[];
13
+ value?: any;
14
14
  oldValue?: any;
15
15
  changes?: IChange[];
16
16
  }
17
17
  type Changeset = IChange[];
18
- interface IFlatChange {
18
+ interface IAtomicChange {
19
19
  type: Operation;
20
20
  key: string;
21
21
  path: string;
@@ -23,15 +23,20 @@ interface IFlatChange {
23
23
  value?: any;
24
24
  oldValue?: any;
25
25
  }
26
+ interface Options {
27
+ embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType;
28
+ keysToSkip?: string[];
29
+ treatTypeChangeAsReplace?: boolean;
30
+ }
26
31
  /**
27
32
  * Computes the difference between two objects.
28
33
  *
29
34
  * @param {any} oldObj - The original object.
30
35
  * @param {any} newObj - The updated object.
31
- * @param {EmbeddedObjKeysType | EmbeddedObjKeysMapType} embeddedObjKeys - An optional parameter specifying keys of embedded objects.
36
+ * @param {Options} options - An optional parameter specifying keys of embedded objects and keys to skip.
32
37
  * @returns {IChange[]} - An array of changes that transform the old object into the new object.
33
38
  */
34
- declare function diff(oldObj: any, newObj: any, embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType, keysToSkip?: string[]): IChange[];
39
+ declare function diff(oldObj: any, newObj: any, options?: Options): IChange[];
35
40
  /**
36
41
  * Applies all changes in the changeset to the object.
37
42
  *
@@ -57,23 +62,23 @@ declare const applyChangeset: (obj: any, changeset: Changeset) => any;
57
62
  */
58
63
  declare const revertChangeset: (obj: any, changeset: Changeset) => any;
59
64
  /**
60
- * Flattens a changeset into an array of flat changes.
65
+ * Atomize a changeset into an array of single changes.
61
66
  *
62
67
  * @param {Changeset | IChange} obj - The changeset or change to flatten.
63
68
  * @param {string} [path='$'] - The current path in the changeset.
64
69
  * @param {string | FunctionKey} [embeddedKey] - The key to use for embedded objects.
65
- * @returns {IFlatChange[]} - An array of flat changes.
70
+ * @returns {IAtomicChange[]} - An array of atomic changes.
66
71
  *
67
- * The function first checks if the input is an array. If so, it recursively flattens each change in the array.
72
+ * The function first checks if the input is an array. If so, it recursively atomize each change in the array.
68
73
  * If the input is not an array, it checks if the change has nested changes or an embedded key.
69
74
  * If so, it updates the path and recursively flattens the nested changes or the embedded object.
70
- * If the change does not have nested changes or an embedded key, it creates a flat change and returns it in an array.
75
+ * If the change does not have nested changes or an embedded key, it creates a atomic change and returns it in an array.
71
76
  */
72
- declare const flattenChangeset: (obj: Changeset | IChange, path?: string, embeddedKey?: string | FunctionKey) => IFlatChange[];
77
+ declare const atomizeChangeset: (obj: Changeset | IChange, path?: string, embeddedKey?: string | FunctionKey) => IAtomicChange[];
73
78
  /**
74
- * Transforms a flat changeset into a nested changeset.
79
+ * Transforms an atomized changeset into a nested changeset.
75
80
  *
76
- * @param {IFlatChange | IFlatChange[]} changes - The flat changeset to unflatten.
81
+ * @param {IAtomicChange | IAtomicChange[]} changes - The atomic changeset to unflatten.
77
82
  * @returns {IChange[]} - The unflattened changeset.
78
83
  *
79
84
  * The function first checks if the input is a single change or an array of changes.
@@ -83,7 +88,7 @@ declare const flattenChangeset: (obj: Changeset | IChange, path?: string, embedd
83
88
  * If it represents a leaf node, it sets the key, type, value, and oldValue of the current change object.
84
89
  * Finally, it pushes the unflattened change object into the changes array.
85
90
  */
86
- declare const unflattenChanges: (changes: IFlatChange | IFlatChange[]) => IChange[];
91
+ declare const unatomizeChangeset: (changes: IAtomicChange | IAtomicChange[]) => IChange[];
87
92
  /**
88
93
  * Determines the type of a given object.
89
94
  *
@@ -109,7 +114,7 @@ declare const createValue: (value: any) => IComparisonEnrichedNode;
109
114
  declare const createContainer: (value: object | [
110
115
  ]) => IComparisonEnrichedNode;
111
116
  declare const enrich: (object: any) => IComparisonEnrichedNode;
112
- declare const applyChangelist: (object: IComparisonEnrichedNode, changelist: IFlatChange[]) => IComparisonEnrichedNode;
117
+ declare const applyChangelist: (object: IComparisonEnrichedNode, changelist: IAtomicChange[]) => IComparisonEnrichedNode;
113
118
  declare const compare: (oldObject: any, newObject: any) => IComparisonEnrichedNode;
114
119
 
115
- export { type Changeset, CompareOperation, type EmbeddedObjKeysMapType, type EmbeddedObjKeysType, type IChange, type IComparisonEnrichedNode, type IFlatChange, Operation, applyChangelist, applyChangeset, compare, createContainer, createValue, diff, enrich, flattenChangeset, getTypeOfObj, revertChangeset, unflattenChanges };
120
+ export { type Changeset, CompareOperation, type EmbeddedObjKeysMapType, type EmbeddedObjKeysType, type IAtomicChange, type IChange, type IComparisonEnrichedNode, Operation, type Options, applyChangelist, applyChangeset, atomizeChangeset, compare, createContainer, createValue, diff, enrich, getTypeOfObj, revertChangeset, unatomizeChangeset };
package/dist/index.d.ts CHANGED
@@ -10,12 +10,12 @@ interface IChange {
10
10
  type: Operation;
11
11
  key: string;
12
12
  embeddedKey?: string | FunctionKey;
13
- value?: any | any[];
13
+ value?: any;
14
14
  oldValue?: any;
15
15
  changes?: IChange[];
16
16
  }
17
17
  type Changeset = IChange[];
18
- interface IFlatChange {
18
+ interface IAtomicChange {
19
19
  type: Operation;
20
20
  key: string;
21
21
  path: string;
@@ -23,15 +23,20 @@ interface IFlatChange {
23
23
  value?: any;
24
24
  oldValue?: any;
25
25
  }
26
+ interface Options {
27
+ embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType;
28
+ keysToSkip?: string[];
29
+ treatTypeChangeAsReplace?: boolean;
30
+ }
26
31
  /**
27
32
  * Computes the difference between two objects.
28
33
  *
29
34
  * @param {any} oldObj - The original object.
30
35
  * @param {any} newObj - The updated object.
31
- * @param {EmbeddedObjKeysType | EmbeddedObjKeysMapType} embeddedObjKeys - An optional parameter specifying keys of embedded objects.
36
+ * @param {Options} options - An optional parameter specifying keys of embedded objects and keys to skip.
32
37
  * @returns {IChange[]} - An array of changes that transform the old object into the new object.
33
38
  */
34
- declare function diff(oldObj: any, newObj: any, embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType, keysToSkip?: string[]): IChange[];
39
+ declare function diff(oldObj: any, newObj: any, options?: Options): IChange[];
35
40
  /**
36
41
  * Applies all changes in the changeset to the object.
37
42
  *
@@ -57,23 +62,23 @@ declare const applyChangeset: (obj: any, changeset: Changeset) => any;
57
62
  */
58
63
  declare const revertChangeset: (obj: any, changeset: Changeset) => any;
59
64
  /**
60
- * Flattens a changeset into an array of flat changes.
65
+ * Atomize a changeset into an array of single changes.
61
66
  *
62
67
  * @param {Changeset | IChange} obj - The changeset or change to flatten.
63
68
  * @param {string} [path='$'] - The current path in the changeset.
64
69
  * @param {string | FunctionKey} [embeddedKey] - The key to use for embedded objects.
65
- * @returns {IFlatChange[]} - An array of flat changes.
70
+ * @returns {IAtomicChange[]} - An array of atomic changes.
66
71
  *
67
- * The function first checks if the input is an array. If so, it recursively flattens each change in the array.
72
+ * The function first checks if the input is an array. If so, it recursively atomize each change in the array.
68
73
  * If the input is not an array, it checks if the change has nested changes or an embedded key.
69
74
  * If so, it updates the path and recursively flattens the nested changes or the embedded object.
70
- * If the change does not have nested changes or an embedded key, it creates a flat change and returns it in an array.
75
+ * If the change does not have nested changes or an embedded key, it creates a atomic change and returns it in an array.
71
76
  */
72
- declare const flattenChangeset: (obj: Changeset | IChange, path?: string, embeddedKey?: string | FunctionKey) => IFlatChange[];
77
+ declare const atomizeChangeset: (obj: Changeset | IChange, path?: string, embeddedKey?: string | FunctionKey) => IAtomicChange[];
73
78
  /**
74
- * Transforms a flat changeset into a nested changeset.
79
+ * Transforms an atomized changeset into a nested changeset.
75
80
  *
76
- * @param {IFlatChange | IFlatChange[]} changes - The flat changeset to unflatten.
81
+ * @param {IAtomicChange | IAtomicChange[]} changes - The atomic changeset to unflatten.
77
82
  * @returns {IChange[]} - The unflattened changeset.
78
83
  *
79
84
  * The function first checks if the input is a single change or an array of changes.
@@ -83,7 +88,7 @@ declare const flattenChangeset: (obj: Changeset | IChange, path?: string, embedd
83
88
  * If it represents a leaf node, it sets the key, type, value, and oldValue of the current change object.
84
89
  * Finally, it pushes the unflattened change object into the changes array.
85
90
  */
86
- declare const unflattenChanges: (changes: IFlatChange | IFlatChange[]) => IChange[];
91
+ declare const unatomizeChangeset: (changes: IAtomicChange | IAtomicChange[]) => IChange[];
87
92
  /**
88
93
  * Determines the type of a given object.
89
94
  *
@@ -109,7 +114,7 @@ declare const createValue: (value: any) => IComparisonEnrichedNode;
109
114
  declare const createContainer: (value: object | [
110
115
  ]) => IComparisonEnrichedNode;
111
116
  declare const enrich: (object: any) => IComparisonEnrichedNode;
112
- declare const applyChangelist: (object: IComparisonEnrichedNode, changelist: IFlatChange[]) => IComparisonEnrichedNode;
117
+ declare const applyChangelist: (object: IComparisonEnrichedNode, changelist: IAtomicChange[]) => IComparisonEnrichedNode;
113
118
  declare const compare: (oldObject: any, newObject: any) => IComparisonEnrichedNode;
114
119
 
115
- export { type Changeset, CompareOperation, type EmbeddedObjKeysMapType, type EmbeddedObjKeysType, type IChange, type IComparisonEnrichedNode, type IFlatChange, Operation, applyChangelist, applyChangeset, compare, createContainer, createValue, diff, enrich, flattenChangeset, getTypeOfObj, revertChangeset, unflattenChanges };
120
+ export { type Changeset, CompareOperation, type EmbeddedObjKeysMapType, type EmbeddedObjKeysType, type IAtomicChange, type IChange, type IComparisonEnrichedNode, Operation, type Options, applyChangelist, applyChangeset, atomizeChangeset, compare, createContainer, createValue, diff, enrich, getTypeOfObj, revertChangeset, unatomizeChangeset };
package/dist/index.js CHANGED
@@ -1,12 +1,43 @@
1
1
  // src/jsonDiff.ts
2
2
  import { difference, find, intersection, keyBy } from "lodash";
3
+
4
+ // src/helpers.ts
5
+ function splitJSONPath(path) {
6
+ let parts = [];
7
+ let currentPart = "";
8
+ let inSingleQuotes = false;
9
+ let inBrackets = 0;
10
+ for (let i = 0; i < path.length; i++) {
11
+ const char = path[i];
12
+ if (char === "'" && path[i - 1] !== "\\") {
13
+ inSingleQuotes = !inSingleQuotes;
14
+ } else if (char === "[" && !inSingleQuotes) {
15
+ inBrackets++;
16
+ } else if (char === "]" && !inSingleQuotes) {
17
+ inBrackets--;
18
+ }
19
+ if (char === "." && !inSingleQuotes && inBrackets === 0) {
20
+ parts.push(currentPart);
21
+ currentPart = "";
22
+ } else {
23
+ currentPart += char;
24
+ }
25
+ }
26
+ if (currentPart !== "") {
27
+ parts.push(currentPart);
28
+ }
29
+ return parts;
30
+ }
31
+
32
+ // src/jsonDiff.ts
3
33
  var Operation = /* @__PURE__ */ ((Operation2) => {
4
34
  Operation2["REMOVE"] = "REMOVE";
5
35
  Operation2["ADD"] = "ADD";
6
36
  Operation2["UPDATE"] = "UPDATE";
7
37
  return Operation2;
8
38
  })(Operation || {});
9
- function diff(oldObj, newObj, embeddedObjKeys, keysToSkip) {
39
+ function diff(oldObj, newObj, options = {}) {
40
+ let { embeddedObjKeys, keysToSkip, treatTypeChangeAsReplace } = options;
10
41
  if (embeddedObjKeys instanceof Map) {
11
42
  embeddedObjKeys = new Map(
12
43
  Array.from(embeddedObjKeys.entries()).map(([key, value]) => [
@@ -19,7 +50,11 @@ function diff(oldObj, newObj, embeddedObjKeys, keysToSkip) {
19
50
  Object.entries(embeddedObjKeys).map(([key, value]) => [key.replace(/^\./, ""), value])
20
51
  );
21
52
  }
22
- return compare(oldObj, newObj, [], embeddedObjKeys, [], keysToSkip);
53
+ return compare(oldObj, newObj, [], [], {
54
+ embeddedObjKeys,
55
+ keysToSkip: keysToSkip ?? [],
56
+ treatTypeChangeAsReplace: treatTypeChangeAsReplace ?? true
57
+ });
23
58
  }
24
59
  var applyChangeset = (obj, changeset) => {
25
60
  if (changeset) {
@@ -42,45 +77,55 @@ var revertChangeset = (obj, changeset) => {
42
77
  }
43
78
  return obj;
44
79
  };
45
- var flattenChangeset = (obj, path = "$", embeddedKey) => {
80
+ var atomizeChangeset = (obj, path = "$", embeddedKey) => {
46
81
  if (Array.isArray(obj)) {
47
- return obj.reduce((memo, change) => [...memo, ...flattenChangeset(change, path, embeddedKey)], []);
48
- } else {
49
- if (obj.changes || embeddedKey) {
50
- if (embeddedKey) {
51
- if (embeddedKey === "$index") {
52
- path = `${path}[${obj.key}]`;
53
- } else if (embeddedKey === "$value") {
54
- path = `${path}[?(@='${obj.key}')]`;
55
- const valueType = getTypeOfObj(obj.value);
56
- return [
57
- {
58
- ...obj,
59
- path,
60
- valueType
61
- }
62
- ];
63
- } else if (obj.type === "ADD" /* ADD */) {
64
- } else {
65
- path = filterExpression(path, embeddedKey, obj.key);
66
- }
67
- } else {
68
- path = append(path, obj.key);
82
+ return handleArray(obj, path, embeddedKey);
83
+ } else if (obj.changes || embeddedKey) {
84
+ if (embeddedKey) {
85
+ const [updatedPath, atomicChange] = handleEmbeddedKey(embeddedKey, obj, path);
86
+ path = updatedPath;
87
+ if (atomicChange) {
88
+ return atomicChange;
69
89
  }
70
- return flattenChangeset(obj.changes || obj, path, obj.embeddedKey);
71
90
  } else {
72
- const valueType = getTypeOfObj(obj.value);
73
- return [
74
- {
75
- ...obj,
76
- path: valueType === "Object" || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),
77
- valueType
78
- }
79
- ];
91
+ path = append(path, obj.key);
80
92
  }
93
+ return atomizeChangeset(obj.changes || obj, path, obj.embeddedKey);
94
+ } else {
95
+ const valueType = getTypeOfObj(obj.value);
96
+ return [{
97
+ ...obj,
98
+ path: valueType === "Object" || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),
99
+ valueType
100
+ }];
81
101
  }
82
102
  };
83
- var unflattenChanges = (changes) => {
103
+ function handleEmbeddedKey(embeddedKey, obj, path) {
104
+ if (embeddedKey === "$index") {
105
+ path = `${path}[${obj.key}]`;
106
+ return [path];
107
+ } else if (embeddedKey === "$value") {
108
+ path = `${path}[?(@=='${obj.key}')]`;
109
+ const valueType = getTypeOfObj(obj.value);
110
+ return [
111
+ path,
112
+ [{
113
+ ...obj,
114
+ path,
115
+ valueType
116
+ }]
117
+ ];
118
+ } else if (obj.type === "ADD" /* ADD */) {
119
+ return [path];
120
+ } else {
121
+ path = filterExpression(path, embeddedKey, obj.key);
122
+ return [path];
123
+ }
124
+ }
125
+ var handleArray = (obj, path, embeddedKey) => {
126
+ return obj.reduce((memo, change) => [...memo, ...atomizeChangeset(change, path, embeddedKey)], []);
127
+ };
128
+ var unatomizeChangeset = (changes) => {
84
129
  if (!Array.isArray(changes)) {
85
130
  changes = [changes];
86
131
  }
@@ -88,7 +133,7 @@ var unflattenChanges = (changes) => {
88
133
  changes.forEach((change) => {
89
134
  const obj = {};
90
135
  let ptr = obj;
91
- const segments = change.path.split(/(?<=[^@])\.(?=[^@])/);
136
+ const segments = splitJSONPath(change.path);
92
137
  if (segments.length === 1) {
93
138
  ptr.key = change.key;
94
139
  ptr.type = change.type;
@@ -98,7 +143,7 @@ var unflattenChanges = (changes) => {
98
143
  } else {
99
144
  for (let i = 1; i < segments.length; i++) {
100
145
  const segment = segments[i];
101
- const result = /^(.+?)\[\?\(@.?(?:([^=]*))?={1,2}'(.*)'\)\]$|^(.+?)\[(\d+)\]$/.exec(segment);
146
+ const result = /^([^[\]]+)\[\?\(@\.?([^=]*)=+'([^']+)'\)\]$|^(.+)\[(\d+)\]$/.exec(segment);
102
147
  if (result) {
103
148
  let key;
104
149
  let embeddedKey;
@@ -110,7 +155,7 @@ var unflattenChanges = (changes) => {
110
155
  } else {
111
156
  key = result[4];
112
157
  embeddedKey = "$index";
113
- arrKey = Number(result[4]);
158
+ arrKey = Number(result[5]);
114
159
  }
115
160
  if (i === segments.length - 1) {
116
161
  ptr.key = key;
@@ -183,15 +228,19 @@ var getKey = (path) => {
183
228
  const left = path[path.length - 1];
184
229
  return left != null ? left : "$root";
185
230
  };
186
- var compare = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
231
+ var compare = (oldObj, newObj, path, keyPath, options) => {
187
232
  let changes = [];
188
233
  const typeOfOldObj = getTypeOfObj(oldObj);
189
234
  const typeOfNewObj = getTypeOfObj(newObj);
190
- if (typeOfOldObj !== typeOfNewObj) {
235
+ if (options.treatTypeChangeAsReplace && typeOfOldObj !== typeOfNewObj) {
191
236
  changes.push({ type: "REMOVE" /* REMOVE */, key: getKey(path), value: oldObj });
192
237
  changes.push({ type: "ADD" /* ADD */, key: getKey(path), value: newObj });
193
238
  return changes;
194
239
  }
240
+ if (typeOfNewObj === "Object" && typeOfOldObj === "Array") {
241
+ changes.push({ type: "UPDATE" /* UPDATE */, key: getKey(path), value: newObj, oldValue: oldObj });
242
+ return changes;
243
+ }
195
244
  switch (typeOfOldObj) {
196
245
  case "Date":
197
246
  changes = changes.concat(
@@ -202,8 +251,8 @@ var compare = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
202
251
  }))
203
252
  );
204
253
  break;
205
- case "Object":
206
- const diffs = compareObject(oldObj, newObj, path, embeddedObjKeys, keyPath, false, keysToSkip);
254
+ case "Object": {
255
+ const diffs = compareObject(oldObj, newObj, path, keyPath, false, options);
207
256
  if (diffs.length) {
208
257
  if (path.length) {
209
258
  changes.push({
@@ -216,8 +265,9 @@ var compare = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
216
265
  }
217
266
  }
218
267
  break;
268
+ }
219
269
  case "Array":
220
- changes = changes.concat(compareArray(oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip));
270
+ changes = changes.concat(compareArray(oldObj, newObj, path, keyPath, options));
221
271
  break;
222
272
  case "Function":
223
273
  break;
@@ -226,7 +276,7 @@ var compare = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
226
276
  }
227
277
  return changes;
228
278
  };
229
- var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath = false, keysToSkip = []) => {
279
+ var compareObject = (oldObj, newObj, path, keyPath, skipPath = false, options = {}) => {
230
280
  let k;
231
281
  let newKeyPath;
232
282
  let newPath;
@@ -234,13 +284,13 @@ var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath =
234
284
  skipPath = false;
235
285
  }
236
286
  let changes = [];
237
- const oldObjKeys = Object.keys(oldObj).filter((key) => keysToSkip.indexOf(key) === -1);
238
- const newObjKeys = Object.keys(newObj).filter((key) => keysToSkip.indexOf(key) === -1);
287
+ const oldObjKeys = Object.keys(oldObj).filter((key) => options.keysToSkip.indexOf(key) === -1);
288
+ const newObjKeys = Object.keys(newObj).filter((key) => options.keysToSkip.indexOf(key) === -1);
239
289
  const intersectionKeys = intersection(oldObjKeys, newObjKeys);
240
290
  for (k of intersectionKeys) {
241
291
  newPath = path.concat([k]);
242
292
  newKeyPath = skipPath ? keyPath : keyPath.concat([k]);
243
- const diffs = compare(oldObj[k], newObj[k], newPath, embeddedObjKeys, newKeyPath, keysToSkip);
293
+ const diffs = compare(oldObj[k], newObj[k], newPath, newKeyPath, options);
244
294
  if (diffs.length) {
245
295
  changes = changes.concat(diffs);
246
296
  }
@@ -267,12 +317,12 @@ var compareObject = (oldObj, newObj, path, embeddedObjKeys, keyPath, skipPath =
267
317
  }
268
318
  return changes;
269
319
  };
270
- var compareArray = (oldObj, newObj, path, embeddedObjKeys, keyPath, keysToSkip) => {
271
- const left = getObjectKey(embeddedObjKeys, keyPath);
320
+ var compareArray = (oldObj, newObj, path, keyPath, options) => {
321
+ const left = getObjectKey(options.embeddedObjKeys, keyPath);
272
322
  const uniqKey = left != null ? left : "$index";
273
323
  const indexedOldObj = convertArrayToObj(oldObj, uniqKey);
274
324
  const indexedNewObj = convertArrayToObj(newObj, uniqKey);
275
- const diffs = compareObject(indexedOldObj, indexedNewObj, path, embeddedObjKeys, keyPath, true, keysToSkip);
325
+ const diffs = compareObject(indexedOldObj, indexedNewObj, path, keyPath, true, options);
276
326
  if (diffs.length) {
277
327
  return [
278
328
  {
@@ -508,21 +558,21 @@ var applyChangelist = (object, changelist) => {
508
558
  return object;
509
559
  };
510
560
  var compare2 = (oldObject, newObject) => {
511
- return applyChangelist(enrich(oldObject), flattenChangeset(diff(oldObject, newObject)));
561
+ return applyChangelist(enrich(oldObject), atomizeChangeset(diff(oldObject, newObject)));
512
562
  };
513
563
  export {
514
564
  CompareOperation,
515
565
  Operation,
516
566
  applyChangelist,
517
567
  applyChangeset,
568
+ atomizeChangeset,
518
569
  compare2 as compare,
519
570
  createContainer,
520
571
  createValue,
521
572
  diff,
522
573
  enrich,
523
- flattenChangeset,
524
574
  getTypeOfObj,
525
575
  revertChangeset,
526
- unflattenChanges
576
+ unatomizeChangeset
527
577
  };
528
578
  //# sourceMappingURL=index.js.map
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';\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"]}
1
+ {"version":3,"sources":["../src/jsonDiff.ts","../src/helpers.ts","../src/jsonCompare.ts"],"sourcesContent":["import { difference, find, intersection, keyBy } from 'lodash';\nimport { splitJSONPath } from './helpers';\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;\n oldValue?: any;\n changes?: IChange[];\n}\nexport type Changeset = IChange[];\n\nexport interface IAtomicChange {\n type: Operation;\n key: string;\n path: string;\n valueType: string | null;\n value?: any;\n oldValue?: any;\n}\n\nexport interface Options {\n embeddedObjKeys?: EmbeddedObjKeysType | EmbeddedObjKeysMapType;\n keysToSkip?: string[];\n treatTypeChangeAsReplace?: boolean;\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 {Options} options - An optional parameter specifying keys of embedded objects and keys to skip.\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 options: Options = {}\n): IChange[] {\n let { embeddedObjKeys, keysToSkip, treatTypeChangeAsReplace } = options;\n\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, [], [], {\n embeddedObjKeys,\n keysToSkip: keysToSkip ?? [],\n treatTypeChangeAsReplace: treatTypeChangeAsReplace ?? true\n });\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 * Atomize a changeset into an array of single 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 {IAtomicChange[]} - An array of atomic changes.\n *\n * The function first checks if the input is an array. If so, it recursively atomize 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 atomic change and returns it in an array.\n */\nexport const atomizeChangeset = (\n obj: Changeset | IChange,\n path = '$',\n embeddedKey?: string | FunctionKey\n): IAtomicChange[] => {\n if (Array.isArray(obj)) {\n return handleArray(obj, path, embeddedKey);\n } else if (obj.changes || embeddedKey) {\n if (embeddedKey) {\n const [updatedPath, atomicChange] = handleEmbeddedKey(embeddedKey, obj, path);\n path = updatedPath;\n if (atomicChange) {\n return atomicChange;\n }\n } else {\n path = append(path, obj.key);\n }\n return atomizeChangeset(obj.changes || obj, path, obj.embeddedKey);\n } else {\n const valueType = getTypeOfObj(obj.value);\n return [{\n ...obj,\n path: valueType === 'Object' || path.endsWith(`[${obj.key}]`) ? path : append(path, obj.key),\n valueType\n }];\n }\n};\n\n// Function to handle embeddedKey logic and update the path\nfunction handleEmbeddedKey(embeddedKey: string | FunctionKey, obj: IChange, path: string): [string, IAtomicChange[]?] {\n if (embeddedKey === '$index') {\n path = `${path}[${obj.key}]`;\n return [path]\n } else if (embeddedKey === '$value') {\n path = `${path}[?(@=='${obj.key}')]`;\n const valueType = getTypeOfObj(obj.value);\n return [\n path,\n [{\n ...obj,\n path,\n valueType\n }]\n ];\n } else if (obj.type === Operation.ADD) {\n // do nothing\n return [path];\n } else {\n path = filterExpression(path, embeddedKey, obj.key);\n return [path];\n }\n}\n\n\nconst handleArray = (obj: Changeset | IChange[], path: string, embeddedKey?: string | FunctionKey): IAtomicChange[] => {\n return obj.reduce((memo, change) => [...memo, ...atomizeChangeset(change, path, embeddedKey)], [] as IAtomicChange[]);\n}\n\n\n\n/**\n * Transforms an atomized changeset into a nested changeset.\n *\n * @param {IAtomicChange | IAtomicChange[]} changes - The atomic 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 unatomizeChangeset = (changes: IAtomicChange | IAtomicChange[]) => {\n if (!Array.isArray(changes)) {\n changes = [changes];\n }\n\n const changesArr: IChange[] = [];\n\n\n changes.forEach((change) => {\n const obj = {} as IChange;\n let ptr = obj;\n\n const segments = splitJSONPath(change.path);\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 = /^([^[\\]]+)\\[\\?\\(@\\.?([^=]*)=+'([^']+)'\\)\\]$|^(.+)\\[(\\d+)\\]$/.exec(segment);\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[5]);\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, keyPath: any, options: Options) => {\n let changes: any[] = [];\n\n const typeOfOldObj = getTypeOfObj(oldObj);\n const typeOfNewObj = getTypeOfObj(newObj);\n\n // `treatTypeChangeAsReplace` is a flag used to determine if a change in type should be treated as a replacement.\n if (options.treatTypeChangeAsReplace && 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 if (typeOfNewObj === 'Object' && typeOfOldObj === 'Array') {\n changes.push({ type: Operation.UPDATE, key: getKey(path), value: newObj, oldValue: oldObj });\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 {\n const diffs = compareObject(oldObj, newObj, path, keyPath, false, options);\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 }\n case 'Array':\n changes = changes.concat(compareArray(oldObj, newObj, path, keyPath, options));\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 keyPath: any,\n skipPath = false,\n options: Options = {},\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) => options.keysToSkip.indexOf(key) === -1);\n const newObjKeys = Object.keys(newObj).filter((key) => options.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, newKeyPath, options);\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 keyPath: any,\n options: Options\n) => {\n const left = getObjectKey(options.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, keyPath, true, options);\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\n","export function splitJSONPath(path: string): string[] {\n let parts: string[] = [];\n let currentPart = '';\n let inSingleQuotes = false;\n let inBrackets = 0;\n\n for (let i = 0; i < path.length; i++) {\n const char = path[i];\n\n if (char === \"'\" && path[i - 1] !== '\\\\') {\n // Toggle single quote flag if not escaped\n inSingleQuotes = !inSingleQuotes;\n } else if (char === '[' && !inSingleQuotes) {\n // Increase bracket nesting level\n inBrackets++;\n } else if (char === ']' && !inSingleQuotes) {\n // Decrease bracket nesting level\n inBrackets--;\n }\n\n if (char === '.' && !inSingleQuotes && inBrackets === 0) {\n // Split at period if not in quotes or brackets\n parts.push(currentPart);\n currentPart = '';\n } else {\n // Otherwise, keep adding to the current part\n currentPart += char;\n }\n }\n\n // Add the last part if there's any\n if (currentPart !== '') {\n parts.push(currentPart);\n }\n\n return parts;\n}\n","import { chain, keys, replace, set } from 'lodash';\nimport { diff, atomizeChangeset, getTypeOfObj, IAtomicChange, 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: IAtomicChange[]\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), atomizeChangeset(diff(oldObject, newObject)));\n};\n"],"mappings":"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","names":["Operation","key","CompareOperation","compare"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-diff-ts",
3
- "version": "3.0.0",
3
+ "version": "4.0.0-beta.0",
4
4
  "description": "A JSON diff tool for JavaScript written in TypeScript.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -10,8 +10,8 @@
10
10
  "build": "tsup --format cjs,esm",
11
11
  "format": "prettier --write \"src/**/*.ts\"",
12
12
  "lint": "eslint 'src/**/*.ts'",
13
- "test": "NODE_OPTIONS=--experimental-vm-modules jest --config jest.config.mjs",
14
- "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch --config jest.config.mjs",
13
+ "test": "jest --config jest.config.mjs",
14
+ "test:watch": "jest --watch --config jest.config.mjs",
15
15
  "prepare": "npm run build",
16
16
  "prepublishOnly": "npm test && npm run lint",
17
17
  "preversion": "npm run lint",