Eserian/frontend-project-lvl2

View on GitHub
src/buildDiff.js

Summary

Maintainability
A
1 hr
Test Coverage
A
100%
import _ from 'lodash';

const map = [
  {
    check: (obj1, obj2, key) => _.isObject(obj1[key]) && _.isObject(obj2[key]),
    action: (obj1, obj2, key, f) => ({
      type: 'nested',
      key,
      children: f(obj1[key], obj2[key]),
    }),
  },
  {
    check: (obj1, obj2, key) => _.has(obj1, key) && _.has(obj2, key) && obj1[key] === obj2[key],
    action: (obj1, obj2, key) => ({
      type: 'unchanged',
      key,
      value: obj1[key],
    }),
  },
  {
    check: (obj1, obj2, key) => _.has(obj1, key) && _.has(obj2, key) && obj1[key] !== obj2[key],
    action: (obj1, obj2, key) => ({
      type: 'changed',
      key,
      value: {
        oldValue: obj1[key],
        newValue: obj2[key],
      },
    }),
  },
  {
    check: (obj1, obj2, key) => !_.has(obj1, key) && _.has(obj2, key),
    action: (_obj1, obj2, key) => ({
      type: 'added',
      key,
      value: obj2[key],
    }),
  },
  {
    check: (obj1, obj2, key) => _.has(obj1, key) && !_.has(obj2, key),
    action: (obj1, _obj2, key) => ({
      type: 'removed',
      key,
      value: obj1[key],
    }),
  },
];

const buildDiff = (obj1, obj2) => {
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  const keys = _.union(keys1, keys2).sort();

  const diff = keys.map((key) => {
    const { action } = map.find((item) => item.check(obj1, obj2, key));
    return action(obj1, obj2, key, buildDiff);
  });

  return diff;
};

export default buildDiff;