lib/obs.js
function mergeObjectSchema(object, other, options) {
  var settings = options || {},
      prune = settings.prune || false,
      placeholder = settings.placeholder || false,
      source, sourceKeys,
      keysDiff,
      outputObject, i, value;

  // Don't bother doing anything with non-plain objects.
  if (!isObjectObject(object) || !isObjectObject(other)) { return object; }

  outputObject = {};

  source = getObjectSchema(other);
  sourceKeys = Object.keys(source);

  i = -1;

  while (++i < sourceKeys.length) {
    // Original object already has property.
    if (object.hasOwnProperty(sourceKeys[i])) {
      // Recurse or copy defined property.
      if (isObjectObject(object[sourceKeys[i]])) {
        value = mergeObjectSchema(object[sourceKeys[i]], source[sourceKeys[i]], settings);
      }
      // Add placeholder for empty value.
      else if (placeholder && object[sourceKeys[i]].length === 0) {
        value = sourceKeys[i];
      }
      // Copy value.
      else {
        value = object[sourceKeys[i]];
      }
    }
    // Original object does not have property.
    else {
      // Recurse source property or add empty value.
      if (isObjectObject(source[sourceKeys[i]])) {
        value = mergeObjectSchema({}, source[sourceKeys[i]], settings);
      }
      else {
        value = placeholder ? sourceKeys[i] : '';
      }
    }

    outputObject[sourceKeys[i]] = value;
  }

  // Add extra properties found in original object to the end of the object.
  if (!Boolean(prune)) {
    keysDiff = _.difference(Object.keys(object), sourceKeys);
    i = -1;

    while (++i < keysDiff.length) {
      outputObject[keysDiff[i]] = object[keysDiff[i]];
    }
  }

  return outputObject;
}
function mergeObjectSchema(object, other, options) {
  var settings = options || {},
      prune = settings.prune || false,
      placeholder = settings.placeholder || false,
      source, sourceKeys,
      keysDiff,
      outputObject, i, value;

  // Don't bother doing anything with non-plain objects.
  if (!isObjectObject(object) || !isObjectObject(other)) { return object; }

  outputObject = {};

  source = getObjectSchema(other);
  sourceKeys = Object.keys(source);

  i = -1;

  while (++i < sourceKeys.length) {
    // Original object already has property.
    if (object.hasOwnProperty(sourceKeys[i])) {
      // Recurse or copy defined property.
      if (isObjectObject(object[sourceKeys[i]])) {
        value = mergeObjectSchema(object[sourceKeys[i]], source[sourceKeys[i]], settings);
      }
      // Add placeholder for empty value.
      else if (placeholder && object[sourceKeys[i]].length === 0) {
        value = sourceKeys[i];
      }
      // Copy value.
      else {
        value = object[sourceKeys[i]];
      }
    }
    // Original object does not have property.
    else {
      // Recurse source property or add empty value.
      if (isObjectObject(source[sourceKeys[i]])) {
        value = mergeObjectSchema({}, source[sourceKeys[i]], settings);
      }
      else {
        value = placeholder ? sourceKeys[i] : '';
      }
    }

    outputObject[sourceKeys[i]] = value;
  }

  // Add extra properties found in original object to the end of the object.
  if (!Boolean(prune)) {
    keysDiff = _.difference(Object.keys(object), sourceKeys);
    i = -1;

    while (++i < keysDiff.length) {
      outputObject[keysDiff[i]] = object[keysDiff[i]];
    }
  }

  return outputObject;
}
function mergeObjectSchema ( object , other , options ) { var settings = options || { } , prune = settings . prune || false , placeholder = settings . placeholder || false , source , sourceKeys , keysDiff , outputObject , i , value ; // Don't bother doing anything with non-plain objects. if ( ! isObjectObject ( object ) || ! isObjectObject ( other ) ) { return object ; } outputObject = { } ; source = getObjectSchema ( other ) ; sourceKeys = Object . keys ( source ) ; i = - 1 ; while ( ++ i < sourceKeys . length ) { // Original object already has property. if ( object . hasOwnProperty ( sourceKeys [ i ] ) ) { // Recurse or copy defined property. if ( isObjectObject ( object [ sourceKeys [ i ] ] ) ) { value = mergeObjectSchema ( object [ sourceKeys [ i ] ] , source [ sourceKeys [ i ] ] , settings ) ; } // Add placeholder for empty value. else if ( placeholder && object [ sourceKeys [ i ] ] . length === 0 ) { value = sourceKeys [ i ] ; } // Copy value. else { value = object [ sourceKeys [ i ] ] ; } } // Original object does not have property. else { // Recurse source property or add empty value. if ( isObjectObject ( source [ sourceKeys [ i ] ] ) ) { value = mergeObjectSchema ( { } , source [ sourceKeys [ i ] ] , settings ) ; } else { value = placeholder ? sourceKeys [ i ] : '' ; } } outputObject [ sourceKeys [ i ] ] = value ; } // Add extra properties found in original object to the end of the object. if ( ! Boolean ( prune ) ) { keysDiff = _ . difference ( Object . keys ( object ) , sourceKeys ) ; i = - 1 ; while ( ++ i < keysDiff . length ) { outputObject [ keysDiff [ i ] ] = object [ keysDiff [ i ] ] ; } } return outputObject ; }
Merge object schemas together. Original object properties and
values are preserved.

@param {object} object
@param {object} other
@param {object} options
@param {bool} options.prune - Prune extra properties found in destination
objects
@param {bool} options.placeholder - Add source object key as a value for
empty destination object properties
@returns {object} Merged object schema.
Merge object schemas together . Original object properties and values are preserved .