From cd0d1e152329b558acb900750e650d04d72bd5d3 Mon Sep 17 00:00:00 2001 From: lucas cordeiro da Silva Date: Mon, 24 Jul 2023 22:24:08 -0300 Subject: [PATCH] fix: root path was not collected (#47) * fix: root path was not collected * feat: update build files --- dist.browser/json-difference.mjs | 51 +++++++++++++++-------------- dist.browser/json-difference.umd.js | 2 +- src/core/get-diff.spec.ts | 13 ++++++++ src/core/get-struct-paths.spec.ts | 38 +++++++++++++++++---- src/core/get-struct-paths.ts | 6 +++- 5 files changed, 76 insertions(+), 34 deletions(-) diff --git a/dist.browser/json-difference.mjs b/dist.browser/json-difference.mjs index 48bc864..a82673f 100644 --- a/dist.browser/json-difference.mjs +++ b/dist.browser/json-difference.mjs @@ -1,47 +1,48 @@ -const p = (f, i) => { +const O = (f, n) => { const o = []; for (const e in f) - if (i.hasOwnProperty(e)) { - if (typeof f[e] == "object" && typeof i[e] == "object" && JSON.stringify(f[e]) === JSON.stringify(i[e]) || f[e] === i[e]) + if (n.hasOwnProperty(e)) { + if (typeof f[e] == "object" && typeof n[e] == "object" && JSON.stringify(f[e]) === JSON.stringify(n[e]) || f[e] === n[e]) continue; if (f[e] === "@{}" || f[e] === "@[]") { - const n = i[e] === "@{}" ? {} : i[e] === "@[]" ? [] : i[e]; - f[e] === "@{}" ? JSON.stringify(i[e]) !== "{}" && o.push([e, {}, n]) : JSON.stringify(i[e]) !== "[]" && o.push([e, [], n]); + const i = n[e] === "@{}" ? {} : n[e] === "@[]" ? [] : n[e]; + f[e] === "@{}" ? JSON.stringify(n[e]) !== "{}" && o.push([e, {}, i]) : JSON.stringify(n[e]) !== "[]" && o.push([e, [], i]); } else - o.push([e, f[e], i[e]]); + o.push([e, f[e], n[e]]); } return o; -}, d = (f, i) => { +}, g = (f, n) => { const o = []; let e = 0; - for (const n in f) - if (!(n in i)) { - const y = f[n] === "@{}" ? {} : f[n] === "@[]" ? [] : f[n]; - o[e] = [n, y], e++; + for (const i in f) + if (!(i in n)) { + const y = f[i] === "@{}" ? {} : f[i] === "@[]" ? [] : f[i]; + o[e] = [i, y], e++; } return o; -}, O = (f, i, o, e) => { - const n = e ? f ? "[" : "." : "/", y = e ? f ? "]" : "" : f ? "[]" : ""; - return i !== "" ? `${i}${n}${o}${y}` : `${e && f ? "[" : ""}${o}${y}`; -}, g = (f, i = !1, o = {}, e = "") => { - for (const n of Object.keys(f)) { - const y = O(Array.isArray(f), e, n, i); - typeof f[n] == "object" && f[n] !== null ? (Object.keys(f[n]).length === 0 ? o[y] = f[n] : o[y] = Array.isArray(f[n]) ? "@[]" : "@{}", g(f[n], i, o, y)) : o[y] = f[n]; +}, p = (f, n, o, e) => { + const i = e ? f ? "[" : "." : "/", y = e ? f ? "]" : "" : f ? "[]" : ""; + return n !== "" ? `${n}${i}${o}${y}` : `${e && f ? "[" : ""}${o}${y}`; +}, d = (f, n = !1, o, e = "") => { + o === void 0 && (o = Array.isArray(f) ? { "": "@[]" } : { "": "@{}" }); + for (const i of Object.keys(f)) { + const y = p(Array.isArray(f), e, i, n); + typeof f[i] == "object" && f[i] !== null ? (Object.keys(f[i]).length === 0 ? o[y] = f[i] : o[y] = Array.isArray(f[i]) ? "@[]" : "@{}", d(f[i], n, o, y)) : o[y] = f[i]; } return o; }, $ = { isLodashLike: !1 -}, b = (f, i, o) => { - const { isLodashLike: e } = o ?? $, n = { +}, b = (f, n, o) => { + const { isLodashLike: e } = o ?? $, i = { added: [], removed: [], edited: [] - }, y = g(f, e), s = g(i, e); - return n.removed = d(y, s), n.added = d(s, y), n.edited = p(y, s), n; + }, y = d(f, e), s = d(n, e); + return i.removed = g(y, s), i.added = g(s, y), i.edited = O(y, s), i; }; export { b as getDiff, - p as getEditedPaths, - d as getPathsDiff, - g as getStructPaths + O as getEditedPaths, + g as getPathsDiff, + d as getStructPaths }; diff --git a/dist.browser/json-difference.umd.js b/dist.browser/json-difference.umd.js index 3a8c8e8..5896680 100644 --- a/dist.browser/json-difference.umd.js +++ b/dist.browser/json-difference.umd.js @@ -1 +1 @@ -(function(s,y){typeof exports=="object"&&typeof module<"u"?y(exports):typeof define=="function"&&define.amd?define(["exports"],y):(s=typeof globalThis<"u"?globalThis:s||self,y(s["json-difference"]={}))})(this,function(s){"use strict";const y=(f,n)=>{const o=[];for(const e in f)if(n.hasOwnProperty(e)){if(typeof f[e]=="object"&&typeof n[e]=="object"&&JSON.stringify(f[e])===JSON.stringify(n[e])||f[e]===n[e])continue;if(f[e]==="@{}"||f[e]==="@[]"){const i=n[e]==="@{}"?{}:n[e]==="@[]"?[]:n[e];f[e]==="@{}"?JSON.stringify(n[e])!=="{}"&&o.push([e,{},i]):JSON.stringify(n[e])!=="[]"&&o.push([e,[],i])}else o.push([e,f[e],n[e]])}return o},p=(f,n)=>{const o=[];let e=0;for(const i in f)if(!(i in n)){const d=f[i]==="@{}"?{}:f[i]==="@[]"?[]:f[i];o[e]=[i,d],e++}return o},c=(f,n,o,e)=>{const i=e?f?"[":".":"/",d=e?f?"]":"":f?"[]":"";return n!==""?`${n}${i}${o}${d}`:`${e&&f?"[":""}${o}${d}`},g=(f,n=!1,o={},e="")=>{for(const i of Object.keys(f)){const d=c(Array.isArray(f),e,i,n);typeof f[i]=="object"&&f[i]!==null?(Object.keys(f[i]).length===0?o[d]=f[i]:o[d]=Array.isArray(f[i])?"@[]":"@{}",g(f[i],n,o,d)):o[d]=f[i]}return o},O={isLodashLike:!1},b=(f,n,o)=>{const{isLodashLike:e}=o??O,i={added:[],removed:[],edited:[]},d=g(f,e),t=g(n,e);return i.removed=p(d,t),i.added=p(t,d),i.edited=y(d,t),i};s.getDiff=b,s.getEditedPaths=y,s.getPathsDiff=p,s.getStructPaths=g,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})}); +(function(s,y){typeof exports=="object"&&typeof module<"u"?y(exports):typeof define=="function"&&define.amd?define(["exports"],y):(s=typeof globalThis<"u"?globalThis:s||self,y(s["json-difference"]={}))})(this,function(s){"use strict";const y=(f,n)=>{const o=[];for(const e in f)if(n.hasOwnProperty(e)){if(typeof f[e]=="object"&&typeof n[e]=="object"&&JSON.stringify(f[e])===JSON.stringify(n[e])||f[e]===n[e])continue;if(f[e]==="@{}"||f[e]==="@[]"){const i=n[e]==="@{}"?{}:n[e]==="@[]"?[]:n[e];f[e]==="@{}"?JSON.stringify(n[e])!=="{}"&&o.push([e,{},i]):JSON.stringify(n[e])!=="[]"&&o.push([e,[],i])}else o.push([e,f[e],n[e]])}return o},p=(f,n)=>{const o=[];let e=0;for(const i in f)if(!(i in n)){const d=f[i]==="@{}"?{}:f[i]==="@[]"?[]:f[i];o[e]=[i,d],e++}return o},t=(f,n,o,e)=>{const i=e?f?"[":".":"/",d=e?f?"]":"":f?"[]":"";return n!==""?`${n}${i}${o}${d}`:`${e&&f?"[":""}${o}${d}`},g=(f,n=!1,o,e="")=>{o===void 0&&(o=Array.isArray(f)?{"":"@[]"}:{"":"@{}"});for(const i of Object.keys(f)){const d=t(Array.isArray(f),e,i,n);typeof f[i]=="object"&&f[i]!==null?(Object.keys(f[i]).length===0?o[d]=f[i]:o[d]=Array.isArray(f[i])?"@[]":"@{}",g(f[i],n,o,d)):o[d]=f[i]}return o},O={isLodashLike:!1},b=(f,n,o)=>{const{isLodashLike:e}=o??O,i={added:[],removed:[],edited:[]},d=g(f,e),c=g(n,e);return i.removed=p(d,c),i.added=p(c,d),i.edited=y(d,c),i};s.getDiff=b,s.getEditedPaths=y,s.getPathsDiff=p,s.getStructPaths=g,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})}); diff --git a/src/core/get-diff.spec.ts b/src/core/get-diff.spec.ts index 362c25a..898f1a4 100644 --- a/src/core/get-diff.spec.ts +++ b/src/core/get-diff.spec.ts @@ -18,6 +18,19 @@ describe('GetDiff function', () => { expect(lodashResult).toEqual(expectedLodashResult) }) + test('Should return the difference between [] and {}', () => { + const struct1 = [] as any + const struct2 = {} + const expectedResult: Delta = { edited: [['', [], {}]], added: [], removed: [] } + const expectedLodashResult: Delta = { edited: [['', [], {}]], added: [], removed: [] } + + const result = getDiff(struct1, struct2) + const lodashResult = getDiff(struct1, struct2, { isLodashLike: true }) + + expect(result).toEqual(expectedResult) + expect(lodashResult).toEqual(expectedLodashResult) + }) + test('Should return the difference between two structures containing Array property', () => { const struct1 = { a: 1, b: [{ c1: 1 }, { c2: 2 }] } const struct2 = { a: 11, b: [{ c1: 1 }, { c2: 22 }] } diff --git a/src/core/get-struct-paths.spec.ts b/src/core/get-struct-paths.spec.ts index 909dc78..6c72437 100644 --- a/src/core/get-struct-paths.spec.ts +++ b/src/core/get-struct-paths.spec.ts @@ -3,7 +3,25 @@ import { getStructPaths } from '.' describe('GetStructPaths function', () => { test('Should return all paths from a basic structure', () => { const oldStruct = { 1: { 2: 7, 3: { 4: 6 } } } - const expectedResult = { '1': '@{}', '1/2': 7, '1/3': '@{}', '1/3/4': 6 } + const expectedResult = { '': '@{}', '1': '@{}', '1/2': 7, '1/3': '@{}', '1/3/4': 6 } + + const result = getStructPaths(oldStruct) + + expect(result).toEqual(expectedResult) + }) + + test('Should return path for root []', () => { + const oldStruct = [] as any + const expectedResult = { '': '@[]' } + + const result = getStructPaths(oldStruct) + + expect(result).toEqual(expectedResult) + }) + + test('Should return path for root {}', () => { + const oldStruct = {} as any + const expectedResult = { '': '@{}' } const result = getStructPaths(oldStruct) @@ -13,6 +31,7 @@ describe('GetStructPaths function', () => { test('Should return all paths containing Array property', () => { const oldStruct = { a: 1, b: [{ c1: [{ c3: { c5: [1, 2, { c6: 3 }] } }, { c4: 6 }] }, { c2: 2 }] } const expectedResult = { + '': '@{}', a: 1, b: '@[]', 'b/0[]': '@{}', @@ -30,6 +49,7 @@ describe('GetStructPaths function', () => { 'b/1[]/c2': 2 } const expectedLodashLikeResult = { + '': '@{}', a: 1, b: '@[]', 'b[0]': '@{}', @@ -56,8 +76,8 @@ describe('GetStructPaths function', () => { test('Should return paths when the values are objects', () => { const oldStruct = { a: [], b: {} } - const expectedResult = { a: [], b: {} } - const expectedLodashLikeResult = { a: [], b: {} } + const expectedResult = { '': '@{}', a: [], b: {} } + const expectedLodashLikeResult = { '': '@{}', a: [], b: {} } const result = getStructPaths(oldStruct) const lodashLikeResult = getStructPaths(oldStruct, true) @@ -69,10 +89,10 @@ describe('GetStructPaths function', () => { test('Should return different paths when containing object and array with same key value at root', () => { const oldStruct = { '0': 0 } const newStruct = [0] - const expectedOldStructPaths = { '0': 0 } - const expectedOldStructLodashLikePaths = { '0': 0 } - const expectedNewStructPaths = { '0[]': 0 } - const expectedNewStructLodashLikePaths = { '[0]': 0 } + const expectedOldStructPaths = { '': '@{}', '0': 0 } + const expectedOldStructLodashLikePaths = { '': '@{}', '0': 0 } + const expectedNewStructPaths = { '': '@[]', '0[]': 0 } + const expectedNewStructLodashLikePaths = { '': '@[]', '[0]': 0 } const oldStructPaths = getStructPaths(oldStruct) const newStructPaths = getStructPaths(newStruct) @@ -89,21 +109,25 @@ describe('GetStructPaths function', () => { const oldStruct = { '0': [{ '0': 1 }] } const newStruct = { '0': { '0': [1] } } const expectedOldStructPaths = { + '': '@{}', '0': '@[]', '0/0[]': '@{}', '0/0[]/0': 1 } const expectedOldStructLodashLikePaths = { + '': '@{}', '0': '@[]', '0[0]': '@{}', '0[0].0': 1 } const expectedNewStructPaths = { + '': '@{}', '0': '@{}', '0/0': '@[]', '0/0/0[]': 1 } const expectedNewStructLodashLikePaths = { + '': '@{}', '0': '@{}', '0.0': '@[]', '0.0[0]': 1 diff --git a/src/core/get-struct-paths.ts b/src/core/get-struct-paths.ts index c9855b6..3523e7f 100644 --- a/src/core/get-struct-paths.ts +++ b/src/core/get-struct-paths.ts @@ -29,7 +29,11 @@ const generatePath = (isArray: boolean, currentPath: string, newPath: string, lo * console.log(result) * // Output: {"1": "@{}","1.2": null} */ -export const getStructPaths = (struct: any, isLodashLike = false, paths: { [key: string]: any } = {}, currentPath = ''): StructPaths => { +export const getStructPaths = (struct: any, isLodashLike = false, paths?: { [key: string]: any }, currentPath = ''): StructPaths => { + if (paths === undefined) { + paths = Array.isArray(struct) ? { '': '@[]' } : { '': '@{}' } + } + for (const key of Object.keys(struct)) { const path = generatePath(Array.isArray(struct), currentPath, key, isLodashLike)