index.js
function I(obj) {
  function isObject(v) {
    return {}.toString.call(v) === '[object Object]';
  }
  function isArray(v) {
    return {}.toString.call(v) === '[object Array]';
  }
  function isFunc(v) {
    return {}.toString.call(v) === '[object Function]';
  }
  function assertA(v, msg) {
    if (!isArray(v)) throw new Error(msg);
  }
  function assertAO(v, msg) {
    if (!isArray(v) && !isObject(v)) throw new Error(msg);
  }
  function _get(o, p) {
    var key = isFunc(p[0]) ? o.findIndex(p[0]) : p[0];
    return p.length ? _get(o[key], p.slice(1)) : o;
  }
  function _set(o, p, v) {
    var key = isFunc(p[0]) ? o.findIndex(p[0]) : p[0];
    // eslint-disable-next-line no-param-reassign
    if (p.length === 1) o[key] = v;else _set(o[key], p.slice(1), v);
  }
  function _copy(o, path) {
    var p = [].concat(toConsumableArray(path));
    var n = p.splice(0, 1)[0];
    if (isFunc(n)) n = o.findIndex(n);
    if (n !== undefined) {
      if (o[n] === undefined) throw new Error('Path not found');
      return isArray(o) ? [].concat(toConsumableArray(o.slice(0, n)), [_copy(o[n], p)], toConsumableArray(o.slice(n + 1))) : _extends({}, o, defineProperty({}, n, _copy(o[n], p)));
    }
    return isArray(o) ? [].concat(toConsumableArray(o)) : _extends({}, o);
  }
  function _diff(a, b) {
    var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
    var acc = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;

    function log(p, msg, value) {
      acc.push(value ? { path: p, msg: msg, value: value } : { path: p, msg: msg });
    }
    function strPath(p, key) {
      var p2 = key !== undefined ? [].concat(toConsumableArray(p), [key]) : p;
      return p2.length ? p2.join('.') : '(root)';
    }
    if (isArray(a) && isArray(b)) {
      if (a !== b) log(strPath(path), 'different reference');
      var deletions = {};
      b.forEach(function (v, k) {
        if (a.indexOf(v) === -1) deletions[k] = v;
      });
      a.forEach(function (v, k) {
        var bk = b.indexOf(v);
        if (bk === -1) {
          if (deletions[k] !== undefined) {
            log(strPath(path, k), 'replace', v);
            delete deletions[k];
          } else {
            log(strPath(path, k), 'add', v);
          }
        } else if (bk !== k && !Object.keys(deletions)) log(strPath(path, k), 'index changed from ' + bk, v);
      });
      Object.keys(deletions).forEach(function (k) {
        return log(strPath(path, k), 'delete');
      });
    } else if (isObject(a) && isObject(b)) {
      if (a !== b) log(strPath(path), 'different reference');
      Object.keys(b).forEach(function (k) {
        if (a[k] === undefined) log(strPath(path, k), 'delete', b[k]);
      });
      Object.keys(a).forEach(function (k) {
        if (b[k] === undefined) log(strPath(path, k), 'add', a[k]);else if (a[k] !== b[k]) _diff(a[k], b[k], path.concat([k]), acc);
      });
    } else if ((typeof a === 'undefined' ? 'undefined' : _typeof(a)) === 'object' || (typeof b === 'undefined' ? 'undefined' : _typeof(b)) === 'object') log(strPath(path), 'different types!');else if (a !== b) log(strPath(path), 'change', a);
  }

  assertAO(obj, 'obj must be an object or array');
  return {
    result: obj,
    get: function get$$1(path) {
      assertA(path, 'path must be an array');
      return _get(this.result, path);
    },
    set: function set$$1(value, path) {
      assertA(path, 'path must be an array');
      if (this.copy(path.slice(0, path.length - 1))) {
        _set(this.result, path, value);
      }
      return this;
    },
    push: function push(value) {
      var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

      assertA(path, 'path must be an array');
      if (this.copy(path)) {
        if (path.length) _set(this.result, path, [].concat(toConsumableArray(_get(this.result, path)), [value]));else this.result.push(value);
      }
      return this;
    },
    delete: function _delete(path) {
      assertA(path, 'path must be an array');
      var parentPath = path.slice(0, path.length - 1);
      var last = path.slice(path.length - 1, path.length)[0];
      if (this.copy(parentPath)) {
        var o = parentPath.length ? _get(this.result, parentPath) : this.result;
        if (isArray(o)) {
          if (isFunc(last)) last = o.findIndex(last);
          if (parentPath.length) {
            _set(this.result, parentPath, [].concat(toConsumableArray(o.slice(0, last)), toConsumableArray(o.slice(last + 1))));
          } else this.result = [].concat(toConsumableArray(o.slice(0, last)), toConsumableArray(o.slice(last + 1)));
        } else delete o[last];
      }
      return this;
    },
    copy: function copy(path) {
      assertA(path, 'path must be an array');
      try {
        this.result = _copy(this.result, path);
      } catch (e) {
        console.warn(e);
        return false;
      }
      return this;
    },
    diff: function diff(other) {
      var acc = [];
      _diff(this.result, other, [], acc);
      return acc;
    }
  };
}
function I(obj) {
  function isObject(v) {
    return {}.toString.call(v) === '[object Object]';
  }
  function isArray(v) {
    return {}.toString.call(v) === '[object Array]';
  }
  function isFunc(v) {
    return {}.toString.call(v) === '[object Function]';
  }
  function assertA(v, msg) {
    if (!isArray(v)) throw new Error(msg);
  }
  function assertAO(v, msg) {
    if (!isArray(v) && !isObject(v)) throw new Error(msg);
  }
  function _get(o, p) {
    var key = isFunc(p[0]) ? o.findIndex(p[0]) : p[0];
    return p.length ? _get(o[key], p.slice(1)) : o;
  }
  function _set(o, p, v) {
    var key = isFunc(p[0]) ? o.findIndex(p[0]) : p[0];
    // eslint-disable-next-line no-param-reassign
    if (p.length === 1) o[key] = v;else _set(o[key], p.slice(1), v);
  }
  function _copy(o, path) {
    var p = [].concat(toConsumableArray(path));
    var n = p.splice(0, 1)[0];
    if (isFunc(n)) n = o.findIndex(n);
    if (n !== undefined) {
      if (o[n] === undefined) throw new Error('Path not found');
      return isArray(o) ? [].concat(toConsumableArray(o.slice(0, n)), [_copy(o[n], p)], toConsumableArray(o.slice(n + 1))) : _extends({}, o, defineProperty({}, n, _copy(o[n], p)));
    }
    return isArray(o) ? [].concat(toConsumableArray(o)) : _extends({}, o);
  }
  function _diff(a, b) {
    var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
    var acc = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;

    function log(p, msg, value) {
      acc.push(value ? { path: p, msg: msg, value: value } : { path: p, msg: msg });
    }
    function strPath(p, key) {
      var p2 = key !== undefined ? [].concat(toConsumableArray(p), [key]) : p;
      return p2.length ? p2.join('.') : '(root)';
    }
    if (isArray(a) && isArray(b)) {
      if (a !== b) log(strPath(path), 'different reference');
      var deletions = {};
      b.forEach(function (v, k) {
        if (a.indexOf(v) === -1) deletions[k] = v;
      });
      a.forEach(function (v, k) {
        var bk = b.indexOf(v);
        if (bk === -1) {
          if (deletions[k] !== undefined) {
            log(strPath(path, k), 'replace', v);
            delete deletions[k];
          } else {
            log(strPath(path, k), 'add', v);
          }
        } else if (bk !== k && !Object.keys(deletions)) log(strPath(path, k), 'index changed from ' + bk, v);
      });
      Object.keys(deletions).forEach(function (k) {
        return log(strPath(path, k), 'delete');
      });
    } else if (isObject(a) && isObject(b)) {
      if (a !== b) log(strPath(path), 'different reference');
      Object.keys(b).forEach(function (k) {
        if (a[k] === undefined) log(strPath(path, k), 'delete', b[k]);
      });
      Object.keys(a).forEach(function (k) {
        if (b[k] === undefined) log(strPath(path, k), 'add', a[k]);else if (a[k] !== b[k]) _diff(a[k], b[k], path.concat([k]), acc);
      });
    } else if ((typeof a === 'undefined' ? 'undefined' : _typeof(a)) === 'object' || (typeof b === 'undefined' ? 'undefined' : _typeof(b)) === 'object') log(strPath(path), 'different types!');else if (a !== b) log(strPath(path), 'change', a);
  }

  assertAO(obj, 'obj must be an object or array');
  return {
    result: obj,
    get: function get$$1(path) {
      assertA(path, 'path must be an array');
      return _get(this.result, path);
    },
    set: function set$$1(value, path) {
      assertA(path, 'path must be an array');
      if (this.copy(path.slice(0, path.length - 1))) {
        _set(this.result, path, value);
      }
      return this;
    },
    push: function push(value) {
      var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

      assertA(path, 'path must be an array');
      if (this.copy(path)) {
        if (path.length) _set(this.result, path, [].concat(toConsumableArray(_get(this.result, path)), [value]));else this.result.push(value);
      }
      return this;
    },
    delete: function _delete(path) {
      assertA(path, 'path must be an array');
      var parentPath = path.slice(0, path.length - 1);
      var last = path.slice(path.length - 1, path.length)[0];
      if (this.copy(parentPath)) {
        var o = parentPath.length ? _get(this.result, parentPath) : this.result;
        if (isArray(o)) {
          if (isFunc(last)) last = o.findIndex(last);
          if (parentPath.length) {
            _set(this.result, parentPath, [].concat(toConsumableArray(o.slice(0, last)), toConsumableArray(o.slice(last + 1))));
          } else this.result = [].concat(toConsumableArray(o.slice(0, last)), toConsumableArray(o.slice(last + 1)));
        } else delete o[last];
      }
      return this;
    },
    copy: function copy(path) {
      assertA(path, 'path must be an array');
      try {
        this.result = _copy(this.result, path);
      } catch (e) {
        console.warn(e);
        return false;
      }
      return this;
    },
    diff: function diff(other) {
      var acc = [];
      _diff(this.result, other, [], acc);
      return acc;
    }
  };
}
function I ( obj ) { function isObject ( v ) { return { } . toString . call ( v ) === '[object Object]' ; } function isArray ( v ) { return { } . toString . call ( v ) === '[object Array]' ; } function isFunc ( v ) { return { } . toString . call ( v ) === '[object Function]' ; } function assertA ( v , msg ) { if ( ! isArray ( v ) ) throw new Error ( msg ) ; } function assertAO ( v , msg ) { if ( ! isArray ( v ) && ! isObject ( v ) ) throw new Error ( msg ) ; } function _get ( o , p ) { var key = isFunc ( p [ 0 ] ) ? o . findIndex ( p [ 0 ] ) : p [ 0 ] ; return p . length ? _get ( o [ key ] , p . slice ( 1 ) ) : o ; } function _set ( o , p , v ) { var key = isFunc ( p [ 0 ] ) ? o . findIndex ( p [ 0 ] ) : p [ 0 ] ; // eslint-disable-next-line no-param-reassign if ( p . length === 1 ) o [ key ] = v ; else _set ( o [ key ] , p . slice ( 1 ) , v ) ; } function _copy ( o , path ) { var p = [ ] . concat ( toConsumableArray ( path ) ) ; var n = p . splice ( 0 , 1 ) [ 0 ] ; if ( isFunc ( n ) ) n = o . findIndex ( n ) ; if ( n !== undefined ) { if ( o [ n ] === undefined ) throw new Error ( 'Path not found' ) ; return isArray ( o ) ? [ ] . concat ( toConsumableArray ( o . slice ( 0 , n ) ) , [ _copy ( o [ n ] , p ) ] , toConsumableArray ( o . slice ( n + 1 ) ) ) : _extends ( { } , o , defineProperty ( { } , n , _copy ( o [ n ] , p ) ) ) ; } return isArray ( o ) ? [ ] . concat ( toConsumableArray ( o ) ) : _extends ( { } , o ) ; } function _diff ( a , b ) { var path = arguments . length > 2 && arguments [ 2 ] !== undefined ? arguments [ 2 ] : [ ] ; var acc = arguments . length > 3 && arguments [ 3 ] !== undefined ? arguments [ 3 ] : 0 ; function log ( p , msg , value ) { acc . push ( value ? { path : p , msg : msg , value : value } : { path : p , msg : msg } ) ; } function strPath ( p , key ) { var p2 = key !== undefined ? [ ] . concat ( toConsumableArray ( p ) , [ key ] ) : p ; return p2 . length ? p2 . join ( '.' ) : '(root)' ; } if ( isArray ( a ) && isArray ( b ) ) { if ( a !== b ) log ( strPath ( path ) , 'different reference' ) ; var deletions = { } ; b . forEach ( function ( v , k ) { if ( a . indexOf ( v ) === - 1 ) deletions [ k ] = v ; } ) ; a . forEach ( function ( v , k ) { var bk = b . indexOf ( v ) ; if ( bk === - 1 ) { if ( deletions [ k ] !== undefined ) { log ( strPath ( path , k ) , 'replace' , v ) ; delete deletions [ k ] ; } else { log ( strPath ( path , k ) , 'add' , v ) ; } } else if ( bk !== k && ! Object . keys ( deletions ) ) log ( strPath ( path , k ) , 'index changed from ' + bk , v ) ; } ) ; Object . keys ( deletions ) . forEach ( function ( k ) { return log ( strPath ( path , k ) , 'delete' ) ; } ) ; } else if ( isObject ( a ) && isObject ( b ) ) { if ( a !== b ) log ( strPath ( path ) , 'different reference' ) ; Object . keys ( b ) . forEach ( function ( k ) { if ( a [ k ] === undefined ) log ( strPath ( path , k ) , 'delete' , b [ k ] ) ; } ) ; Object . keys ( a ) . forEach ( function ( k ) { if ( b [ k ] === undefined ) log ( strPath ( path , k ) , 'add' , a [ k ] ) ; else if ( a [ k ] !== b [ k ] ) _diff ( a [ k ] , b [ k ] , path . concat ( [ k ] ) , acc ) ; } ) ; } else if ( ( typeof a === 'undefined' ? 'undefined' : _typeof ( a ) ) === 'object' || ( typeof b === 'undefined' ? 'undefined' : _typeof ( b ) ) === 'object' ) log ( strPath ( path ) , 'different types!' ) ; else if ( a !== b ) log ( strPath ( path ) , 'change' , a ) ; } assertAO ( obj , 'obj must be an object or array' ) ; return { result : obj , get : function get$$1 ( path ) { assertA ( path , 'path must be an array' ) ; return _get ( this . result , path ) ; } , set : function set$$1 ( value , path ) { assertA ( path , 'path must be an array' ) ; if ( this . copy ( path . slice ( 0 , path . length - 1 ) ) ) { _set ( this . result , path , value ) ; } return this ; } , push : function push ( value ) { var path = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : [ ] ; assertA ( path , 'path must be an array' ) ; if ( this . copy ( path ) ) { if ( path . length ) _set ( this . result , path , [ ] . concat ( toConsumableArray ( _get ( this . result , path ) ) , [ value ] ) ) ; else this . result . push ( value ) ; } return this ; } , delete : function _delete ( path ) { assertA ( path , 'path must be an array' ) ; var parentPath = path . slice ( 0 , path . length - 1 ) ; var last = path . slice ( path . length - 1 , path . length ) [ 0 ] ; if ( this . copy ( parentPath ) ) { var o = parentPath . length ? _get ( this . result , parentPath ) : this . result ; if ( isArray ( o ) ) { if ( isFunc ( last ) ) last = o . findIndex ( last ) ; if ( parentPath . length ) { _set ( this . result , parentPath , [ ] . concat ( toConsumableArray ( o . slice ( 0 , last ) ) , toConsumableArray ( o . slice ( last + 1 ) ) ) ) ; } else this . result = [ ] . concat ( toConsumableArray ( o . slice ( 0 , last ) ) , toConsumableArray ( o . slice ( last + 1 ) ) ) ; } else delete o [ last ] ; } return this ; } , copy : function copy ( path ) { assertA ( path , 'path must be an array' ) ; try { this . result = _copy ( this . result , path ) ; } catch ( e ) { console . warn ( e ) ; return false ; } return this ; } , diff : function diff ( other ) { var acc = [ ] ; _diff ( this . result , other , [ ] , acc ) ; return acc ; } } ; }
/* eslint-disable no-console
/ * eslint - disable no - console