lib/client-options.js
function extend(baseOptions, userOptions) {
  if (arguments.length === 1) {
    userOptions = arguments[0];
    baseOptions = {};
  }
  const options = utils.deepExtend(baseOptions, defaultOptions(), userOptions);
  if (!util.isArray(options.contactPoints) || options.contactPoints.length === 0) {
    throw new TypeError('Contacts points are not defined.');
  }
  for (let i = 0; i < options.contactPoints.length; i++) {
    const hostName = options.contactPoints[i];
    if (!hostName) {
      throw new TypeError(util.format('Contact point %s (%s) is not a valid host name, ' +
        'the following values are valid contact points: ipAddress, hostName or ipAddress:port', i, hostName));
    }
  }
  if (!options.logEmitter) {
    options.logEmitter = function () {};
  }
  if (!options.queryOptions) {
    throw new TypeError('queryOptions not defined in options');
  }

  if (options.requestTracker !== null && !(options.requestTracker instanceof tracker.RequestTracker)) {
    throw new TypeError('requestTracker must be an instance of RequestTracker');
  }

  if (!(options.metrics instanceof metrics.ClientMetrics)) {
    throw new TypeError('metrics must be an instance of ClientMetrics');
  }

  validatePoliciesOptions(options.policies);
  validateProtocolOptions(options.protocolOptions);
  validateSocketOptions(options.socketOptions);
  options.encoding = options.encoding || {};
  validateEncodingOptions(options.encoding);
  if (options.profiles && !util.isArray(options.profiles)) {
    throw new TypeError('profiles must be an Array of ExecutionProfile instances');
  }
  return options;
}
function extend(baseOptions, userOptions) {
  if (arguments.length === 1) {
    userOptions = arguments[0];
    baseOptions = {};
  }
  const options = utils.deepExtend(baseOptions, defaultOptions(), userOptions);
  if (!util.isArray(options.contactPoints) || options.contactPoints.length === 0) {
    throw new TypeError('Contacts points are not defined.');
  }
  for (let i = 0; i < options.contactPoints.length; i++) {
    const hostName = options.contactPoints[i];
    if (!hostName) {
      throw new TypeError(util.format('Contact point %s (%s) is not a valid host name, ' +
        'the following values are valid contact points: ipAddress, hostName or ipAddress:port', i, hostName));
    }
  }
  if (!options.logEmitter) {
    options.logEmitter = function () {};
  }
  if (!options.queryOptions) {
    throw new TypeError('queryOptions not defined in options');
  }

  if (options.requestTracker !== null && !(options.requestTracker instanceof tracker.RequestTracker)) {
    throw new TypeError('requestTracker must be an instance of RequestTracker');
  }

  if (!(options.metrics instanceof metrics.ClientMetrics)) {
    throw new TypeError('metrics must be an instance of ClientMetrics');
  }

  validatePoliciesOptions(options.policies);
  validateProtocolOptions(options.protocolOptions);
  validateSocketOptions(options.socketOptions);
  options.encoding = options.encoding || {};
  validateEncodingOptions(options.encoding);
  if (options.profiles && !util.isArray(options.profiles)) {
    throw new TypeError('profiles must be an Array of ExecutionProfile instances');
  }
  return options;
}
Extends and validates the user options
@param {Object} [baseOptions] The source object instance that will be overridden
@param {Object} userOptions
@returns {Object}