'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

exports.apply = apply;
/**
 * Test if a value is a plain object.
 * @param {*} val - A value.
 * @return {boolean} true if `val` is a plain object.
 */
var isObject = function isObject(val) {
  return val != null && (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object' && Array.isArray(val) === false;
};

/**
 * Apply a JSON merge patch. The origin is *not* modified, but unchanged
 * properties will be recycled.
 * 
 * @param {*} origin - The value to patch.
 * @param {*} patch - An [RFC 7396](https://tools.ietf.org/html/rfc7396) patch.
 * @return {*} The patched value.
 */
function apply(origin, patch) {
  if (!isObject(patch)) {
    // If the patch is not an object, it replaces the origin.
    return patch;
  }

  var result = !isObject(origin) ? // Non objects are being replaced.
  {} : // Make sure we never modify the origin.
  Object.assign({}, origin);

  Object.keys(patch).forEach(function (key) {
    var patchVal = patch[key];
    if (patchVal === null) {
      delete result[key];
    } else {
      result[key] = apply(result[key], patchVal);
    }
  });
  return result;
}

exports.default = apply;