<commit_before>'use strict';
import config from 'config';
import path from 'path';
import errors from '@hoist/errors';
import Authorization from './authorization';
import fs from 'fs';
import redisLock from 'redis-lock';
import redis from 'redis';
import redisSentinel from 'redis-sentinel-client';
import moment from 'moment';
import {
  filter
}
from 'lodash';
import {
  BouncerToken
}
from '@hoist/model';
import logger from '@hoist/logger';

function createRedisClient() {
  if (config.has('Hoist.redis.clustered') && config.get('Hoist.redis.clustered')) {
    return redisSentinel.createClient({
      host: config.get('Hoist.redis.host'),
      port: config.get('Hoist.redis.port'),
      masterName: config.get('Hoist.redis.masterName')
    });
  } else {
    return redis.createClient(config.get('Hoist.redis.port'), config.get('Hoist.redis.host'));
  }
}

/**
 * a proxy class to the underlying connector
 */
class ConnectorProxy {

  /**
   * setup the connector proxy described by the {@link ConnectorSetting} object
   * @param {ConnectorSetting} connectorSetting - the settings for the underlying connector
   */
  constructor(connectorSetting) {
    this._logger = logger.child({
      cls: this.constructor.name,
      applicationId: connectorSetting.application,
      connectorKey: connectorSetting.key
    });
    this._connectorSetting = connectorSetting;
    let connectorsPath = path.resolve(config.get('Hoist.filePaths.connectors'));
    let connectorPath = path.join(connectorsPath, connectorSetting.connectorType, 'current');
    this._connectorPath = fs.realpathSync(connectorPath);
    this._settings = this._connectorSetting.settings;
  }

  _refreshCredentials() {

    //reload the connector settings to see if they've been refreshed
    //only one server will go into this step at a time
    let refreshed;
    let client;
    return Promise.resolve()
      .then(() => {
        if (!this._bouncerToken) {
          throw new Error('Connector is not authorized');
        }
        client = createRedisClient();
        return new Promise((resolve) => {
          redisLock(client)(`connector-refresh-${this._connectorSetting._id}`, 10000, (done) => {
            refreshed = done;
            resolve();
          });
        });
      }).then(() => {
        return BouncerToken.findOneAsync({
          _id: this._bouncerToken._id
        });
      }).then((latestBouncerToken) => {
        if (moment(latestBouncerToken.updatedAt).isSame(moment(this._bouncerToken.updatedAt))) {
          //rely on inbuilt update to credentials
          return this.connector._refreshCredentials();
        } else {
          return this.authorize(latestBouncerToken);
        }
      }).then(() => {
        refreshed();
        client.quit();
      }).catch((err) => {
        client.quit();
        throw err;
      });
  }

  /**
   * initialize this proxy instance
   * @param {Context} context - the current context
   * @returns {Promise<ConnectorProxy>} - this proxy object to allow chaining
   */
  init(context) {
    return Promise.resolve()
      .then(() => {
        let ConnectorType = require(this._connectorPath);
        this._connector = new ConnectorType(this._settings);
        if (this._connector.refreshCredentials) {
          this._connector._refreshCredentials = this._connector.refreshCredentials;
          this._connector.refreshCredentials = () => {
            return this._refreshCredentials();
          };
        }
        let methods = filter(Object.getOwnPropertyNames(Object.getPrototypeOf((this._connector))), (property) => {
          if (property.startsWith('_') || property === 'receiveBounce' || this[property] || property === 'constructor') {
            return false;
          } else {
            return true;
          }
        });
        this._logger.info({
          connector: this._connector,
          methods
        }, 'mapping methods');
        methods.forEach((method) => {<commit_msg>adding some guards<commit_after>'use strict';
import config from 'config';
import path from 'path';
import errors from '@hoist/errors';
import Authorization from './authorization';
import fs from 'fs';
import redisLock from 'redis-lock';
import redis from 'redis';
import redisSentinel from 'redis-sentinel-client';
import moment from 'moment';
import {
  filter
}
from 'lodash';
import {
  BouncerToken
}
from '@hoist/model';
import logger from '@hoist/logger';

function createRedisClient() {
  if (config.has('Hoist.redis.clustered') && config.get('Hoist.redis.clustered')) {
    return redisSentinel.createClient({
      host: config.get('Hoist.redis.host'),
      port: config.get('Hoist.redis.port'),
      masterName: config.get('Hoist.redis.masterName')
    });
  } else {
    return redis.createClient(config.get('Hoist.redis.port'), config.get('Hoist.redis.host'));
  }
}

/**
 * a proxy class to the underlying connector
 */
class ConnectorProxy {

  /**
   * setup the connector proxy described by the {@link ConnectorSetting} object
   * @param {ConnectorSetting} connectorSetting - the settings for the underlying connector
   */
  constructor(connectorSetting) {
    this._logger = logger.child({
      cls: this.constructor.name,
      applicationId: connectorSetting.application,
      connectorKey: connectorSetting.key
    });
    this._connectorSetting = connectorSetting;
    let connectorsPath = path.resolve(config.get('Hoist.filePaths.connectors'));
    let connectorPath = path.join(connectorsPath, connectorSetting.connectorType, 'current');
    this._connectorPath = fs.realpathSync(connectorPath);
    this._settings = this._connectorSetting.settings;
  }

  _refreshCredentials() {

    //reload the connector settings to see if they've been refreshed
    //only one server will go into this step at a time
    let refreshed;
    let client;
    return Promise.resolve()
      .then(() => {
        if (!this._bouncerToken) {
          throw new Error('Connector is not authorized');
        }
        client = createRedisClient();
        return new Promise((resolve) => {
          redisLock(client)(`connector-refresh-${this._connectorSetting._id}`, 10000, (done) => {
            refreshed = done;
            resolve();
          });
        });
      }).then(() => {
        return BouncerToken.findOneAsync({
          _id: this._bouncerToken._id
        });
      }).then((latestBouncerToken) => {
        if (moment(latestBouncerToken.updatedAt).isSame(moment(this._bouncerToken.updatedAt))) {
          //rely on inbuilt update to credentials
          return this.connector._refreshCredentials();
        } else {
          return this.authorize(latestBouncerToken);
        }
      }).then(() => {
        refreshed();
        client.quit();
      }).catch((err) => {
        this._logger.error(err);
        this._logger.alert(err);
        if (client) {
          client.quit();
          throw err;
        }
      });
  }

  /**
   * initialize this proxy instance
   * @param {Context} context - the current context
   * @returns {Promise<ConnectorProxy>} - this proxy object to allow chaining
   */
  init(context) {
    return Promise.resolve()
      .then(() => {
        let ConnectorType = require(this._connectorPath);
        this._connector = new ConnectorType(this._settings);
        if (this._connector.refreshCredentials) {
          this._connector._refreshCredentials = this._connector.refreshCredentials;
          this._connector.refreshCredentials = () => {
            return this._refreshCredentials();
          };
        }
        let methods = filter(Object.getOwnPropertyNames(Object.getPrototypeOf((this._connector))), (property) => {
          if (property.startsWith('_') || property === 'receiveBounce' || this[property] || property === 'constructor') {
            return false;
          } else {
            return true;
          }
        });
        this._logger.info({
          connector: this._connector,
          methods
        }, 'mapping methods');
        methods.forEach((method) => {
{'fraction_non_alphanumeric': 0.12859097127222982, 'fraction_numerical': 0.0012436264146250466, 'mean_word_length': 2.7738151102768653, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, 'https://': 0, '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': '7504855', 'n_tokens_mistral': 2253, 'n_tokens_neox': 2204, 'n_words': 506}