<commit_before>﻿var resolveSrv = require('./dns.js'),
    EventEmitter = require('events').EventEmitter,
    jptr = require('json-ptr'),
    assert = require('assert-plus'),
    async = require('async');
/**
* Attempts to provide a configuration based on a required configuration input
* @module lib
*/
module.exports =(function () {
  'use strict';

  var CONSUL_HOST = 'CONSUL_HOST',
      CONSUL_PORT = 'CONSUL_PORT',
      CONSUL_SECURE = 'CONSUL_SECURE',
      ee = new EventEmitter(),
      matchSlashGreedy = new RegExp('/', 'g');

  /**
   * Does Service Have Ptr checks to see if a value **bound** to this is present in
   * any of the three fields used to define a JSON Ptr in a service spec
   *
   * This function can be used on its own, but it is intended to be used with the Array.some(...) function
   *
   * @param {object} val - An object, generally expected to be a service specification from configuration-schema.json
   * @returns {boolean} True or false based on whether the bound name 'this' was present in any of the JSON Ptr fields
   */
  function doesServiceHavePtr(val) {
    //Stop jshint from whining about 'this' since this func is explicitly meant
    //to be used with 'bind()'
    /*jshint validthis:true */
    return val.key === this || val.prefix === this || val.suffix === this;
  }

  /**
   * Match and set env var looks for an environment variable given an name prefix and a JSON ptr
   * @param {object} finalConfig - The object to store the value of the env var in if found
   * @param {string} prefix - A prefix to apply to names being looked for in the environment
   * @param {object} ptr - A JSON ptr object
   */
  function matchAndSetEnvVar(finalConfig, prefix, ptr) {
    var requestedProp,
        envVal;
    requestedProp = ptr.pointer.replace(matchSlashGreedy, '_').toUpperCase();
    envVal = process.env[prefix.concat(requestedProp)];
    if (envVal !== undefined) {
      ensureObjPath(finalConfig, ptr);
      ptr.set(finalConfig, envVal);
    }
  }

  /**
   * Ensure object path is a small utility function for use with JSON pointers that ensures a particular pointer path
   * exists in an object. The function is non-destructive and only creates a path component as necessary.
   * @param {object} object - A JSON object to ensure that a particular pointer path exists in
   * @param {object} ptr - A {@link https://github.com/flitbit/json-ptr|JSON pointer object}
   */
  function ensureObjPath(object, ptr) {
    var cursor = object,
        currentName,
        idx,
        pathAry = ptr.path;
    for (idx = 0; idx < pathAry.length; idx++) {
      currentName = pathAry[idx];
      if (!cursor[currentName]) {
        cursor[currentName] = {};
      }
      cursor = cursor[currentName];
    }

  }

  /**
   * Determines if we should use a consul agent to add configuration
   * @param {object} configurationRequest - A configuration request object that may contain information required to contact a consul agent
   * @returns {object} A reference to an active consule agent if one could be configured, undefined otherwise
   */
  function setupConsul(configRequest) {
    //client must fully specify how we will talk to consul
    var consulClient,
        consulHost = process.env[CONSUL_HOST],
        consulPort = process.env[CONSUL_PORT],
        consulSecure = (process.env[CONSUL_SECURE] === 'true');
    if (consulHost !== undefined &&
    consulPort !== undefined &&
    consulSecure !== undefined) {
      consulClient = require('consul')({
        host: consulHost,
        port: consulPort,
        secure: consulSecure
      });
    }
    return consulClient;
  }

  /**
   * Handles the retrieval of KV pairs from a consul agent, if the given consulClient isn't defined then
   * the method is a no-op
   * @param {object} configRequest - A client provided object that may have a key value section for required key value pairs
   * @param {object} consulClient - A pre-configured client used to communicate with a consul agent, may be undefined to indicate that
   * we are not supposed to use consul
   * @param {object[]} errors - An initially null array of errors that can be added as configuration is processed
   * @param {object} finalConfig - A object in which to store the retrieved configuration
   */
  function createConsulProcessor(configRequest, consulClient, errors, finalConfig) {
    return function processKeyValuePairsInConsul(callback) {
      var requestedKeys = configRequest.keys,
          requestedServices = configRequest.services,
          requestedKey,
          pathPrefixIdx,
          idx,
          resultPtr;
      if (consulClient !== undefined && (requestedKeys || requestedServices)) {
        requestedKeys = requestedKeys || [];
        requestedServices = requestedServices || [];
        consulClient.kv.get({
          key: configRequest.name + '/',
          recurse: true
        }, function (err, result) {
          var foundKeyIdx,
              hasService,
              pathPtr;
          if (err) {
            if (!errors) {
              errors = [];
            }
            errors.push(err);
          } else if (result) {
            //MSH 2015-03-03 The following loop & block deserve some explanation. The goal
            //is to take keys returned from Consul and set config values for services & keys
            //services is, unfortunately, an array of objects with *3* properties that may need
            //to be fulfilled (key, prefix, and suffix).
            for (idx = 0; idx < result.length; idx++) {
              pathPrefixIdx = result[idx].Key.indexOf(configRequest.name);
              pathPtr = '#' + result[idx].Key.slice(pathPrefixIdx + configRequest.name.length);
              foundKeyIdx = requestedKeys.indexOf(pathPtr);
              resultPtr = jptr.create(pathPtr);
              if (foundKeyIdx !== -1) {
                ensureObjPath(finalConfig, resultPtr);
                resultPtr.set(finalConfig, result[idx].Value);
              } else {
                hasService = requestedServices.some(doesServiceHavePtr, pathPtr);
                if (hasService) {
                  ensureObjPath(finalConfig, resultPtr);
                  resultPtr.set(finalConfig, result[idx].Value);
                }
              }
            }
          }
          callback(null, configRequest, errors, finalConfig);
        });
      } else {
        callback(null, configRequest, errors, finalConfig);
      }
    };
  }

  /**
   * Handles the retrieval of KV pairs from the application's runtime environment
   * @param {object} configRequest - A client provided object that may have a key value section for required key value pairs
   * @param {object[]} errors - An initially null array of errors that can be added as configuration is processed
   * @param {object} finalConfig - A object in which to store the retrieved configuration
   */
  function processKeyValuesPairsInEnv(configRequest, errors, finalConfig, callback) {
    var requestedKeys = configRequest.keys,
        requestedServices = configRequest.services,
        prefix,
        ptr,
        idx;
    if (configRequest.name) {
      prefix = configRequest.name.toUpperCase();
    } else {
      prefix = '';
    }
    if (requestedKeys) {
      for (idx = 0; idx < requestedKeys.length; idx++) {
        ptr = jptr.create(requestedKeys[idx]);
        matchAndSetEnvVar(finalConfig, prefix, ptr);
      }
    }
    if (requestedServices) {
      for (idx = 0; idx < requestedServices.length; idx++) {
        ptr = jptr.create(requestedServices[idx].key);
        matchAndSetEnvVar(finalConfig, prefix, ptr);
        if (requestedServices[idx].prefix) {
          ptr = jptr.create(requestedServices[idx].prefix);
          matchAndSetEnvVar(finalConfig, prefix, ptr);
        }
        if (requestedServices[idx].suffix) {
          ptr = jptr.create(requestedServices[idx].suffix);
          matchAndSetEnvVar(finalConfig, prefix, ptr);
        }
      }
    }
    callback(null, configRequest, errors, finalConfig);
  }

  /**
  * Handles the retrieval of KV pairs based on DNS SRV requests
  * @param {object} configRequest - A client provided object that may have a services section<commit_msg>Config name, when used as a prefix for environment variables, now converts hyphens to underscores.<commit_after>﻿var resolveSrv = require('./dns.js'),
    EventEmitter = require('events').EventEmitter,
    jptr = require('json-ptr'),
    assert = require('assert-plus'),
    async = require('async');
/**
* Attempts to provide a configuration based on a required configuration input
* @module lib
*/
module.exports =(function () {
  'use strict';

  var CONSUL_HOST = 'CONSUL_HOST',
      CONSUL_PORT = 'CONSUL_PORT',
      CONSUL_SECURE = 'CONSUL_SECURE',
      ee = new EventEmitter(),
      matchSlashGreedy = new RegExp('/', 'g');

  /**
   * Does Service Have Ptr checks to see if a value **bound** to this is present in
   * any of the three fields used to define a JSON Ptr in a service spec
   *
   * This function can be used on its own, but it is intended to be used with the Array.some(...) function
   *
   * @param {object} val - An object, generally expected to be a service specification from configuration-schema.json
   * @returns {boolean} True or false based on whether the bound name 'this' was present in any of the JSON Ptr fields
   */
  function doesServiceHavePtr(val) {
    //Stop jshint from whining about 'this' since this func is explicitly meant
    //to be used with 'bind()'
    /*jshint validthis:true */
    return val.key === this || val.prefix === this || val.suffix === this;
  }

  /**
   * Match and set env var looks for an environment variable given an name prefix and a JSON ptr
   * @param {object} finalConfig - The object to store the value of the env var in if found
   * @param {string} prefix - A prefix to apply to names being looked for in the environment
   * @param {object} ptr - A JSON ptr object
   */
  function matchAndSetEnvVar(finalConfig, prefix, ptr) {
    var requestedProp,
        envVal;
    requestedProp = ptr.pointer.replace(matchSlashGreedy, '_').toUpperCase();
    envVal = process.env[prefix.concat(requestedProp)];
    if (envVal !== undefined) {
      ensureObjPath(finalConfig, ptr);
      ptr.set(finalConfig, envVal);
    }
  }

  /**
   * Ensure object path is a small utility function for use with JSON pointers that ensures a particular pointer path
   * exists in an object. The function is non-destructive and only creates a path component as necessary.
   * @param {object} object - A JSON object to ensure that a particular pointer path exists in
   * @param {object} ptr - A {@link https://github.com/flitbit/json-ptr|JSON pointer object}
   */
  function ensureObjPath(object, ptr) {
    var cursor = object,
        currentName,
        idx,
        pathAry = ptr.path;
    for (idx = 0; idx < pathAry.length; idx++) {
      currentName = pathAry[idx];
      if (!cursor[currentName]) {
        cursor[currentName] = {};
      }
      cursor = cursor[currentName];
    }

  }

  /**
   * Determines if we should use a consul agent to add configuration
   * @param {object} configurationRequest - A configuration request object that may contain information required to contact a consul agent
   * @returns {object} A reference to an active consule agent if one could be configured, undefined otherwise
   */
  function setupConsul(configRequest) {
    //client must fully specify how we will talk to consul
    var consulClient,
        consulHost = process.env[CONSUL_HOST],
        consulPort = process.env[CONSUL_PORT],
        consulSecure = (process.env[CONSUL_SECURE] === 'true');
    if (consulHost !== undefined &&
    consulPort !== undefined &&
    consulSecure !== undefined) {
      consulClient = require('consul')({
        host: consulHost,
        port: consulPort,
        secure: consulSecure
      });
    }
    return consulClient;
  }

  /**
   * Handles the retrieval of KV pairs from a consul agent, if the given consulClient isn't defined then
   * the method is a no-op
   * @param {object} configRequest - A client provided object that may have a key value section for required key value pairs
   * @param {object} consulClient - A pre-configured client used to communicate with a consul agent, may be undefined to indicate that
   * we are not supposed to use consul
   * @param {object[]} errors - An initially null array of errors that can be added as configuration is processed
   * @param {object} finalConfig - A object in which to store the retrieved configuration
   */
  function createConsulProcessor(configRequest, consulClient, errors, finalConfig) {
    return function processKeyValuePairsInConsul(callback) {
      var requestedKeys = configRequest.keys,
          requestedServices = configRequest.services,
          requestedKey,
          pathPrefixIdx,
          idx,
          resultPtr;
      if (consulClient !== undefined && (requestedKeys || requestedServices)) {
        requestedKeys = requestedKeys || [];
        requestedServices = requestedServices || [];
        consulClient.kv.get({
          key: configRequest.name + '/',
          recurse: true
        }, function (err, result) {
          var foundKeyIdx,
              hasService,
              pathPtr;
          if (err) {
            if (!errors) {
              errors = [];
            }
            errors.push(err);
          } else if (result) {
            //MSH 2015-03-03 The following loop & block deserve some explanation. The goal
            //is to take keys returned from Consul and set config values for services & keys
            //services is, unfortunately, an array of objects with *3* properties that may need
            //to be fulfilled (key, prefix, and suffix).
            for (idx = 0; idx < result.length; idx++) {
              pathPrefixIdx = result[idx].Key.indexOf(configRequest.name);
              pathPtr = '#' + result[idx].Key.slice(pathPrefixIdx + configRequest.name.length);
              foundKeyIdx = requestedKeys.indexOf(pathPtr);
              resultPtr = jptr.create(pathPtr);
              if (foundKeyIdx !== -1) {
                ensureObjPath(finalConfig, resultPtr);
                resultPtr.set(finalConfig, result[idx].Value);
              } else {
                hasService = requestedServices.some(doesServiceHavePtr, pathPtr);
                if (hasService) {
                  ensureObjPath(finalConfig, resultPtr);
                  resultPtr.set(finalConfig, result[idx].Value);
                }
              }
            }
          }
          callback(null, configRequest, errors, finalConfig);
        });
      } else {
        callback(null, configRequest, errors, finalConfig);
      }
    };
  }

  /**
   * Handles the retrieval of KV pairs from the application's runtime environment
   * @param {object} configRequest - A client provided object that may have a key value section for required key value pairs
   * @param {object[]} errors - An initially null array of errors that can be added as configuration is processed
   * @param {object} finalConfig - A object in which to store the retrieved configuration
   */
  function processKeyValuesPairsInEnv(configRequest, errors, finalConfig, callback) {
    var requestedKeys = configRequest.keys,
        requestedServices = configRequest.services,
        prefix,
        ptr,
        idx;
    if (configRequest.name) {
      prefix = configRequest.name.toUpperCase();
      //prefix = prefix.replace('-', '_');
    } else {
      prefix = '';
    }
    if (requestedKeys) {
      for (idx = 0; idx < requestedKeys.length; idx++) {
        ptr = jptr.create(requestedKeys[idx]);
        matchAndSetEnvVar(finalConfig, prefix, ptr);
      }
    }
    if (requestedServices) {
      for (idx = 0; idx < requestedServices.length; idx++) {
        ptr = jptr.create(requestedServices[idx].key);
        matchAndSetEnvVar(finalConfig, prefix, ptr);
        if (requestedServices[idx].prefix) {
          ptr = jptr.create(requestedServices[idx].prefix);
          matchAndSetEnvVar(finalConfig, prefix, ptr);
        }
        if (requestedServices[idx].suffix) {
          ptr = jptr.create(requestedServices[idx].suffix);
          matchAndSetEnvVar(finalConfig, prefix, ptr);
        }
      }
    }
    callback(null, configRequest, errors, finalConfig);
  }

  /**
  * Handles the retrieval of KV pairs based on DNS SRV requests
  * @param {object} configRequest - A client provided object that may have a services section
{'fraction_non_alphanumeric': 0.09638118214716526, 'fraction_numerical': 0.0016887816646562123, 'mean_word_length': 2.609272964736613, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '48385', 'n_tokens_mistral': 4494, 'n_tokens_neox': 4423, 'n_words': 1551}