cosmicanant/recursive-diff

visitorCallbackFn is not called for diffs in the first level

Opened this issue · 0 comments

I'm having an issue regarding visitorCallbackFn. Seems like it's not called if the diff is on the first level of the jsons...
I suspect it's because of this line. Any reason for this check? I'd change this code to be something like this:

if (i !== length - 1) {
      val = val[key];
      if (visitorCallback) {
        visitorCallback(val);
      }
    } else {
      val[key] = value;
      if (i === length -1 && length === 1 && visitorCallback) {
        visitorCallback(val);
      }
    }

In my use case I would like to call the visitor in the first level, which happens to be also the last...
I'll demonstrate the issue by a failing test:
In jsonDiff.js:

import { applyDiff, getDiff } from 'recursive-diff';

export const getNewObjWithDiff = (originalObj, newObj) => {
  const callback = (ob) => {
    if (ob instanceof Object) {
      ob.isVisited = true;
    }
  };
  const delta = getDiff(originalObj, newObj);
  return applyDiff({ ...originalObj, ...newObj }, delta, callback);
};

In jsonDiff.spec.js:

import { getNewObjWithDiff } from './jsonDiff';

const json = { '/hello': {} };
const newJson = {
  '/hello': { leaf: true },
  '/drafts': {
    leaf: true,
  },
};

describe('jsonDiff', () => {
  it('should return new json with diff inside', () => {
    expect(getNewObjWithDiff(json, newJson)).toEqual({
      '/hello': {
        leaf: true,
        isVisited: true,
      },
      '/drafts': {
        leaf: true,
        isVisited: true,
      },
    });
  });
});

This currently fails with the following returned output (missing isVisited in "/drafts"):

{
  "/drafts": {
    "leaf": true
  },
  "/hello": {
    "isVisited": true,
    "leaf": true
  }
}