<commit_before>'use strict';

const FreeSurfer = require('freesurfer-parser');
const pkg = require('../package.json');
const localRunner = require('./local');
const remoteRunner = require('./remote');
const regression = require('./regression');
const n = require('numeric');
const distributions = require('distributions');
const { DEFAULT_LAMBDA, DEFAULT_MAX_ITERATIONS } = require('./constants.js');
const get = require('lodash/get');

module.exports = {
  name: pkg.name,
  version: pkg.version,
  plugins: ['group-step', 'inputs'],
  local: [
    {
      type: 'function',
      fn(opts) {
        // simulate pre-processing step.  we actually are passing in
        // pre-processed data. required s.t. remote compute node can assert
        // that all users have correct data shape (e.g. num features)
        const rslt = localRunner.preprocess(opts);
        console.log('pre-processing complete.'); // eslint-disable-line no-console
        return rslt;
      },
      verbose: true,
      inputs: [{
        help: 'Select Freesurfer region(s) of interest',
        label: 'Freesurfer ROI',
        type: 'select',
        values: FreeSurfer.validFields,
      }, {
        defaultValue: DEFAULT_MAX_ITERATIONS,
        label: 'Iteration count',
        type: 'number',
      }, {
        defaultValue: DEFAULT_LAMBDA,
        label: 'Lambda',
        max: 1,
        min: 0,
        step: 0.05,
        type: 'number',
      }, {
        defaultValue: [{
          name: 'Is Control?',
          type: 'boolean',
        }],
        label: 'Covariates',
        /**
         * @todo Determine a better `type` for this input. Something like
         * "data-map" or "covariate-map" or…something.
         */
        type: 'covariates',
      }],
    }, {
      type: 'function',
      fn(opts) {
      // if W doesn't merge, return run(), if W merge, return statistic()

        /* eslint-disable no-console */
        console.log('opts.remoteResult.data.endOfIteration is', opts.remoteResult.data.endOfIteration);
        console.log('opts.remoteResult.data.statisticStep is', opts.remoteResult.data.statisticStep);
        /* eslint-enable no-console */

        if (
          (opts.remoteResult.data.endOfIteration === true) &&
          (opts.remoteResult.data.statisticStep === 0)
        ) {
          const lambda = get(opts, 'remoteResult.data.lambda');

          // step 0 calculate local statistics and localYMean
          const biasedX = opts.previousData.biasedX;
          const y = opts.previousData.y;
          const localCount = y.length;
          const betaVector = regression.oneShot(biasedX, y, lambda);
          const rSquared = regression.rSquared(biasedX, y, betaVector);
          const tValue = regression.tValue(biasedX, y, betaVector);
          /* eslint-disable new-cap */
          const tdist = distributions.Studentt(localCount - betaVector.length);
          /* eslint-enable new-cap */
          const tcdf = tValue.map(r => tdist.cdf(r));
          const pValue = n.mul(2, n.sub(1, tcdf));
          const localMeanY = n.sum(y) / localCount;

          return {
            betaVector,
            localCount,
            localMeanY,
            rSquared,
            tValue,
            pValue,
            biasedX,
            y,
            endOfIteration: true,
            statisticStep: 0,
          };
        } else if (
          opts.remoteResult.data.endOfIteration === true &&
          opts.remoteResult.data.statisticStep === 1
        ) {
          // step 1 receive the globalMeanY and currW, then calculate sseLocal,
          // sstLocal and varXLocal
          const betaVector = opts.previousData.betaVector;
          const globalMeanY = opts.remoteResult.data.globalMeanY;
          const currW = opts.remoteResult.data.currW;
          const biasedX = opts.previousData.biasedX;
          const y = opts.previousData.y;
          const rSquared = opts.previousData.rSquared;
          const tValue = opts.previousData.tValue;
          const pValue = opts.previousData.pValue;
          const localCount = y.length;

          // calculate the local r squred and t value for averageBetaVector)
          const rSquaredLocal = regression.rSquared(biasedX, y, currW);
          const tValueLocal = regression.tValue(biasedX, y, currW);
          /* eslint-disable new-cap */
          const tdist = distributions.Studentt(localCount - betaVector.length);
          /* eslint-enable new-cap */
          const tcdf = tValueLocal.map(r => tdist.cdf(r));
          const pValueLocal = n.mul(2, n.sub(1, tcdf));

          // calculate sseLocal and sstLocal
          const sseLocal = n.sum(n.pow(n.sub(y, n.dot(biasedX, currW)), 2));
          const sstLocal = n.sum(n.pow(n.sub(y, n.rep(n.dim(y), globalMeanY)), 2));

          // calculate varXLocalMatrix
          const varXLocalMatrix = n.dot(n.transpose(biasedX), biasedX);

          /* eslint-disable no-console */
          console.log('local r squared for currW', rSquaredLocal);
          console.log('local t Values for currW', tValueLocal);
          console.log('local p Values for currW', pValueLocal);
          /* eslint-enable no-console */

          return {
            betaVector,
            sseLocal,
            sstLocal,
            varXLocalMatrix,
            currW,
            localCount,
            rSquared,
            tValue,
            pValue,
            rSquaredLocal,
            tValueLocal,
            pValueLocal,
            endOfIteration: true,
            statisticStep: 1,
          };
        }

        return localRunner.run(opts);
      },
      verbose: true,
    },
  ],
  remote: {
    type: 'function',
    fn(opts) {
      if (
        opts.userResults[0].data.endOfIteration === true &&
        opts.userResults[0].data.statisticStep === 0
      ) {
        // if statisticStep==0, remote node calculates the globalMeanY and return it to local node
        const userResults = opts.userResults;

        // Not all user results contain betas. Return early.
        if (userResults.some(userResult => !((userResult || {}).data || {}).betaVector)) {
          return {};
        }

        // calculate averageBetaVector
        const currW = opts.previousData.currW;

        // calculate globalMeanY
        const siteCount = userResults.length;
        let totalY = 0;
        let globalYCount = 0;

        for (let i = 0; i < siteCount; i += 1) {
          totalY += userResults[i].data.localMeanY * userResults[i].data.localCount;
          globalYCount += userResults[i].data.localCount;
        }

        const globalMeanY = totalY / globalYCount;

        /* eslint-disable no-console */
        console.log('currW :', currW);
        console.log('globalMeanY is :', globalMeanY);
        /* eslint-enable no-console */

        return { currW,
          globalMeanY,
          endOfIteration: true,
          statisticStep: 1,
        };
      } else if (
        opts.userResults[0].data.endOfIteration === true &&
        opts.userResults[0].data.statisticStep === 1
      ) {
        // if statisticStep==1, remote node calculates the global statistics

        const userResults = opts.userResults;

        // get passed parameters from local nodes
        const currW = opts.previousData.currW;
        const betaVectorLocal = userResults.map(r => r.data.betaVector);
        const rSquaredLocalOriginal = userResults.map(r => r.data.rSquared);
        const tValueLocalOriginal = userResults.map(r => r.data.tValue);
        const pValueLocalOriginal = userResults.map(r => r.data.pValue);
        const rSquaredLocal = userResults.map(r => r.data.rSquaredLocal);
        const tValueLocal = userResults.map(r => r.data.tValueLocal);
        const pValueLocal = userResults.map(r => r.data.pValueLocal);

        // calculate global parameters
        const sseGlobal = userResults.reduce(
          (sum, userResult) => sum + userResult.data.sseLocal, 0
        );
        const sstGlobal = userResults.reduce(
          (sum, userResult) => sum + userResult.data.sstLocal, 0
        );
        const globalYCount = userResults.reduce(
          (sum, userResult) => sum + userResult.data.localCount, 0
        );

        const varError = (1 / (globalYCount - currW.length)) * sseGlobal;
        const seBetaGlobal = [];
        const tValueGlobal = [];

        // calculate tValueGlobal
        let varXGlobalMatrix = n.rep([currW.length, currW.length], 0);

        for (let i = 0; i < userResults.length; i += 1) {
          varXGlobalMatrix = n.add(varXGlobalMatrix, userResults[i].data.varXLocalMatrix);
        }

        /* eslint-disable no-console */
        console.log('varXGlobalMatrix is', varXGlobalMatrix);
        /* eslint-enable no-console */

        const varBetaGlobal = n.mul(n.inv(varXGlobalMatrix), varError);

        for (let i = 0; i < currW.length; i += 1) {
          seBetaGlobal[i] = Math.sqrt(varBetaGlobal[i][i]);
          tValueGlobal[i] = currW[i] / seBetaGlobal[i];
        }

        // calculate r squared global
        const rSquaredGlobal = 1 - (sseGlobal / sstGlobal);

        // add t to p value transformation //
        /* eslint-disable new-cap */
        const tdist = distributions.Studentt(globalYCount - currW.length);
        /* eslint-enable new-cap */
        const tcdf = tValueGlobal.map(r => tdist.cdf(r));
        const pValueGlobal = n.mul(2, (n.sub(1, tcdf))); // two tail pValue

        /* eslint-disable no-console */
        console.log('The global r squared for currW :', rSquaredGlobal);
        console.log('The global t Values for currW :', tValueGlobal);
        console.log('The global p Values for currW :', pValueGlobal);
        /* eslint-enable no-console */

        return {
          betaVectorLocal,
          currW,
          rSquaredLocalOriginal,
          tValueLocalOriginal,
          pValueLocalOriginal,
          rSquaredLocal,
          tValueLocal,
          pValueLocal,
          rSquaredGlobal,
          tValueGlobal,
          pValueGlobal,
          complete: true,
        };
      }

      return remoteRunner.run(opts);
    },
    verbose: true,
  },
};
<commit_msg>fix P value for negative t<commit_after>'use strict';

const FreeSurfer = require('freesurfer-parser');
const pkg = require('../package.json');
const localRunner = require('./local');
const remoteRunner = require('./remote');
const regression = require('./regression');
const n = require('numeric');
const distributions = require('distributions');
const { DEFAULT_LAMBDA, DEFAULT_MAX_ITERATIONS } = require('./constants.js');
const get = require('lodash/get');

module.exports = {
  name: pkg.name,
  version: pkg.version,
  plugins: ['group-step', 'inputs'],
  local: [
    {
      type: 'function',
      fn(opts) {
        // simulate pre-processing step.  we actually are passing in
        // pre-processed data. required s.t. remote compute node can assert
        // that all users have correct data shape (e.g. num features)
        const rslt = localRunner.preprocess(opts);
        console.log('pre-processing complete.'); // eslint-disable-line no-console
        return rslt;
      },
      verbose: true,
      inputs: [{
        help: 'Select Freesurfer region(s) of interest',
        label: 'Freesurfer ROI',
        type: 'select',
        values: FreeSurfer.validFields,
      }, {
        defaultValue: DEFAULT_MAX_ITERATIONS,
        label: 'Iteration count',
        type: 'number',
      }, {
        defaultValue: DEFAULT_LAMBDA,
        label: 'Lambda',
        max: 1,
        min: 0,
        step: 0.05,
        type: 'number',
      }, {
        defaultValue: [{
          name: 'Is Control?',
          type: 'boolean',
        }],
        label: 'Covariates',
        /**
         * @todo Determine a better `type` for this input. Something like
         * "data-map" or "covariate-map" or…something.
         */
        type: 'covariates',
      }],
    }, {
      type: 'function',
      fn(opts) {
      // if W doesn't merge, return run(), if W merge, return statistic()

        /* eslint-disable no-console */
        console.log('opts.remoteResult.data.endOfIteration is', opts.remoteResult.data.endOfIteration);
        console.log('opts.remoteResult.data.statisticStep is', opts.remoteResult.data.statisticStep);
        /* eslint-enable no-console */

        if (
          (opts.remoteResult.data.endOfIteration === true) &&
          (opts.remoteResult.data.statisticStep === 0)
        ) {
          const lambda = get(opts, 'remoteResult.data.lambda');

          // step 0 calculate local statistics and localYMean
          const biasedX = opts.previousData.biasedX;
          const y = opts.previousData.y;
          const localCount = y.length;
          const betaVector = regression.oneShot(biasedX, y, lambda);
          const rSquared = regression.rSquared(biasedX, y, betaVector);
          const tValue = regression.tValue(biasedX, y, betaVector);
          /* eslint-disable new-cap */
          const tdist = distributions.Studentt(localCount - betaVector.length);
          /* eslint-enable new-cap */
          const tcdf = tValue.map(r => tdist.cdf(Math.abs(r)));
          const pValue = n.mul(2, n.sub(1, tcdf));
          const localMeanY = n.sum(y) / localCount;

          return {
            betaVector,
            localCount,
            localMeanY,
            rSquared,
            tValue,
            pValue,
            biasedX,
            y,
            endOfIteration: true,
            statisticStep: 0,
          };
        } else if (
          opts.remoteResult.data.endOfIteration === true &&
          opts.remoteResult.data.statisticStep === 1
        ) {
          // step 1 receive the globalMeanY and currW, then calculate sseLocal,
          // sstLocal and varXLocal
          const betaVector = opts.previousData.betaVector;
          const globalMeanY = opts.remoteResult.data.globalMeanY;
          const currW = opts.remoteResult.data.currW;
          const biasedX = opts.previousData.biasedX;
          const y = opts.previousData.y;
          const rSquared = opts.previousData.rSquared;
          const tValue = opts.previousData.tValue;
          const pValue = opts.previousData.pValue;
          const localCount = y.length;

          // calculate the local r squred and t value for averageBetaVector)
          const rSquaredLocal = regression.rSquared(biasedX, y, currW);
          const tValueLocal = regression.tValue(biasedX, y, currW);
          /* eslint-disable new-cap */
          const tdist = distributions.Studentt(localCount - betaVector.length);
          /* eslint-enable new-cap */
          const tcdf = tValueLocal.map(r => tdist.cdf(Math.abs(r)));
          const pValueLocal = n.mul(2, n.sub(1, tcdf));

          // calculate sseLocal and sstLocal
          const sseLocal = n.sum(n.pow(n.sub(y, n.dot(biasedX, currW)), 2));
          const sstLocal = n.sum(n.pow(n.sub(y, n.rep(n.dim(y), globalMeanY)), 2));

          // calculate varXLocalMatrix
          const varXLocalMatrix = n.dot(n.transpose(biasedX), biasedX);

          /* eslint-disable no-console */
          console.log('local r squared for currW', rSquaredLocal);
          console.log('local t Values for currW', tValueLocal);
          console.log('local p Values for currW', pValueLocal);
          /* eslint-enable no-console */

          return {
            betaVector,
            sseLocal,
            sstLocal,
            varXLocalMatrix,
            currW,
            localCount,
            rSquared,
            tValue,
            pValue,
            rSquaredLocal,
            tValueLocal,
            pValueLocal,
            endOfIteration: true,
            statisticStep: 1,
          };
        }

        return localRunner.run(opts);
      },
      verbose: true,
    },
  ],
  remote: {
    type: 'function',
    fn(opts) {
      if (
        opts.userResults[0].data.endOfIteration === true &&
        opts.userResults[0].data.statisticStep === 0
      ) {
        // if statisticStep==0, remote node calculates the globalMeanY and return it to local node
        const userResults = opts.userResults;

        // Not all user results contain betas. Return early.
        if (userResults.some(userResult => !((userResult || {}).data || {}).betaVector)) {
          return {};
        }

        // calculate averageBetaVector
        const currW = opts.previousData.currW;

        // calculate globalMeanY
        const siteCount = userResults.length;
        let totalY = 0;
        let globalYCount = 0;

        for (let i = 0; i < siteCount; i += 1) {
          totalY += userResults[i].data.localMeanY * userResults[i].data.localCount;
          globalYCount += userResults[i].data.localCount;
        }

        const globalMeanY = totalY / globalYCount;

        /* eslint-disable no-console */
        console.log('currW :', currW);
        console.log('globalMeanY is :', globalMeanY);
        /* eslint-enable no-console */

        return { currW,
          globalMeanY,
          endOfIteration: true,
          statisticStep: 1,
        };
      } else if (
        opts.userResults[0].data.endOfIteration === true &&
        opts.userResults[0].data.statisticStep === 1
      ) {
        // if statisticStep==1, remote node calculates the global statistics

        const userResults = opts.userResults;

        // get passed parameters from local nodes
        const currW = opts.previousData.currW;
        const betaVectorLocal = userResults.map(r => r.data.betaVector);
        const rSquaredLocalOriginal = userResults.map(r => r.data.rSquared);
        const tValueLocalOriginal = userResults.map(r => r.data.tValue);
        const pValueLocalOriginal = userResults.map(r => r.data.pValue);
        const rSquaredLocal = userResults.map(r => r.data.rSquaredLocal);
        const tValueLocal = userResults.map(r => r.data.tValueLocal);
        const pValueLocal = userResults.map(r => r.data.pValueLocal);

        // calculate global parameters
        const sseGlobal = userResults.reduce(
          (sum, userResult) => sum + userResult.data.sseLocal, 0
        );
        const sstGlobal = userResults.reduce(
          (sum, userResult) => sum + userResult.data.sstLocal, 0
        );
        const globalYCount = userResults.reduce(
          (sum, userResult) => sum + userResult.data.localCount, 0
        );

        const varError = (1 / (globalYCount - currW.length)) * sseGlobal;
        const seBetaGlobal = [];
        const tValueGlobal = [];

        // calculate tValueGlobal
        let varXGlobalMatrix = n.rep([currW.length, currW.length], 0);

        for (let i = 0; i < userResults.length; i += 1) {
          varXGlobalMatrix = n.add(varXGlobalMatrix, userResults[i].data.varXLocalMatrix);
        }

        /* eslint-disable no-console */
        console.log('varXGlobalMatrix is', varXGlobalMatrix);
        /* eslint-enable no-console */

        const varBetaGlobal = n.mul(n.inv(varXGlobalMatrix), varError);

        for (let i = 0; i < currW.length; i += 1) {
          seBetaGlobal[i] = Math.sqrt(varBetaGlobal[i][i]);
          tValueGlobal[i] = currW[i] / seBetaGlobal[i];
        }

        // calculate r squared global
        const rSquaredGlobal = 1 - (sseGlobal / sstGlobal);

        // add t to p value transformation //
        /* eslint-disable new-cap */
        const tdist = distributions.Studentt(globalYCount - currW.length);
        /* eslint-enable new-cap */
        const tcdf = tValueGlobal.map(r => tdist.cdf(Math.abs(r)));
        const pValueGlobal = n.mul(2, (n.sub(1, tcdf))); // two tail pValue

        /* eslint-disable no-console */
        console.log('The global r squared for currW :', rSquaredGlobal);
        console.log('The global t Values for currW :', tValueGlobal);
        console.log('The global p Values for currW :', pValueGlobal);
        /* eslint-enable no-console */

        return {
          betaVectorLocal,
          currW,
          rSquaredLocalOriginal,
          tValueLocalOriginal,
          pValueLocalOriginal,
          rSquaredLocal,
          tValueLocal,
          pValueLocal,
          rSquaredGlobal,
          tValueGlobal,
          pValueGlobal,
          complete: true,
        };
      }

      return remoteRunner.run(opts);
    },
    verbose: true,
  },
};
<|endoftext|>


<commit_before>var q = require('q');
var leAsymmetricEncryptionService = require('le-asymmetric-encryption');
/**
 * A tool for creating and processing background jobs
 * @class JobQueueService
 * @param {StorageService} storage an instance of le-storage-service that is used to create records
 * @param {string} type the type of queue you want to create, supported types are 'default', 'session', and 'fast', leaving the field undefined is the same as 'default'
 * @returns {service}
 */
var JobQueueService = function (storage, type) {
  if (!storage) { throw new Error('Instance of storage service required'); }
  if (type !== 'session' && type !== 'fast' && type !== 'default' && type !== undefined) {
    throw new Error('Invalid value for the type param, value: ' + type);
  }
  var queueType = type;
  var _storage = storage;
  var _provider;
  /**
   * Stores a new job to process
   * @function addJob
   * @memberof JobQueueService
   * @instance
   * @param {string} type the type of the job, used to determine how it should be processed
   * @param {string} data the data necessary to complete the job
   * @returns {promise} resolves with the newly created job record
   */
  this.addJob = function (type, data, sensitiveData) {
    if (!this.publicKey & sensitiveData) {
      this.fetchPublicKey();
    }
    if (sensitiveData) {
      sensitiveData = JSON.stringify(sensitiveData);
      var encryptedData = leAsymmetricEncryptionService.encrypt(sensitiveData, this.publicKey);
      data.encryptedData = encryptedData;
    }
    var record;
    if (queueType === 'fast') {
      record = _storage.createRecord('_fastQueue/task');
    } else if (queueType === 'session') {
      record = _storage.createRecord('_sessionQueue/task');
    } else {
      record = _storage.createRecord('_queue/task');
    }
    return record.update({
      type: type,
      data: data
    }).then(function () {
      return record;
    });
  }
  this.fetchPublicKey = function () {
    var publicKeyRecord = _storage.fetchRecord('Public Key', 'BACKGROUND_PUBLIC_KEY');
    this.publicKey = publicKeyRecord.getData();
  }
  /**
   * Stores a new job and resolve when the job is complete
   * @function performJob
   * @memberof JobQueueService
   * @instance
   * @param {string} type the type of the job, used to determine how it should be processed
   * @param {string} data the data necessary to complete the job
   * @returns {promise} resolves when the task is complete
   */
  this.performJob = function (type, data) {
    var deferred = q.defer();
    this.addJob(type, data)
    .then(function (record) {
      record.sync(function (recordData) {
        if (recordData === null) {
          record.unsync();
          deferred.resolve();
        }
      });
    });
    return deferred.promise;
  }
  /**
   * Creates a worker to process the jobs in the queue
   * @function createWorker
   * @memberof JobQueueService
   * @instance
   * @param {JobQueueProvider} provider the provider this service delegates to
   * @param {Function}  processJob function that processes the job. Called with two params `job` and `complete`. This function must call `complete()` to finish processing a job
   */
  this.createWorker = function (provider, processJob, privateKey) {
    if (!provider) { throw new Error('Job queue provider required'); }
    if (!processJob) { throw new Error('Process job callback required'); }
    var innerProcessJob = function (job, complete) {
      var decryptedDataJson = leAsymmetricEncryptionService.decrypt(job.encryptedData, privateKey);
      var decryptedData = JSON.parse(decryptedData);
      Object.assign(job.data, decryptedData)
      processJob(job, complete);
    }
    _provider = provider;
    _provider.createWorker(innerProcessJob);
  }
  /**
   * Prevents the worker from picking up new jobs and resolves once current jobs are complete
   * @function shutdown
   * @memberof JobQueueService
   * @instance
   * @returns {promise}
   */
  this.shutdown = function () {
    if (!_provider) { throw new Error('Job queue provider required'); }
    return _provider.shutdown();
  }
}

module.exports = JobQueueService;
<commit_msg>fix(index): properly require le-asymmetric-encryption<commit_after>var q = require('q');
var leAsymmetricEncryptionService = require('@castle/le-asymmetric-encryption');
/**
 * A tool for creating and processing background jobs
 * @class JobQueueService
 * @param {StorageService} storage an instance of le-storage-service that is used to create records
 * @param {string} type the type of queue you want to create, supported types are 'default', 'session', and 'fast', leaving the field undefined is the same as 'default'
 * @returns {service}
 */
var JobQueueService = function (storage, type) {
  if (!storage) { throw new Error('Instance of storage service required'); }
  if (type !== 'session' && type !== 'fast' && type !== 'default' && type !== undefined) {
    throw new Error('Invalid value for the type param, value: ' + type);
  }
  var queueType = type;
  var _storage = storage;
  var _provider;
  /**
   * Stores a new job to process
   * @function addJob
   * @memberof JobQueueService
   * @instance
   * @param {string} type the type of the job, used to determine how it should be processed
   * @param {string} data the data necessary to complete the job
   * @returns {promise} resolves with the newly created job record
   */
  this.addJob = function (type, data, sensitiveData) {
    if (!this.publicKey & sensitiveData) {
      this.fetchPublicKey();
    }
    if (sensitiveData) {
      sensitiveData = JSON.stringify(sensitiveData);
      var encryptedData = leAsymmetricEncryptionService.encrypt(sensitiveData, this.publicKey);
      data.encryptedData = encryptedData;
    }
    var record;
    if (queueType === 'fast') {
      record = _storage.createRecord('_fastQueue/task');
    } else if (queueType === 'session') {
      record = _storage.createRecord('_sessionQueue/task');
    } else {
      record = _storage.createRecord('_queue/task');
    }
    return record.update({
      type: type,
      data: data
    }).then(function () {
      return record;
    });
  }
  this.fetchPublicKey = function () {
    var publicKeyRecord = _storage.fetchRecord('Public Key', 'BACKGROUND_PUBLIC_KEY');
    this.publicKey = publicKeyRecord.getData();
  }
  /**
   * Stores a new job and resolve when the job is complete
   * @function performJob
   * @memberof JobQueueService
   * @instance
   * @param {string} type the type of the job, used to determine how it should be processed
   * @param {string} data the data necessary to complete the job
   * @returns {promise} resolves when the task is complete
   */
  this.performJob = function (type, data) {
    var deferred = q.defer();
    this.addJob(type, data)
    .then(function (record) {
      record.sync(function (recordData) {
        if (recordData === null) {
          record.unsync();
          deferred.resolve();
        }
      });
    });
    return deferred.promise;
  }
  /**
   * Creates a worker to process the jobs in the queue
   * @function createWorker
   * @memberof JobQueueService
   * @instance
   * @param {JobQueueProvider} provider the provider this service delegates to
   * @param {Function}  processJob function that processes the job. Called with two params `job` and `complete`. This function must call `complete()` to finish processing a job
   */
  this.createWorker = function (provider, processJob, privateKey) {
    if (!provider) { throw new Error('Job queue provider required'); }
    if (!processJob) { throw new Error('Process job callback required'); }
    var innerProcessJob = function (job, complete) {
      var decryptedDataJson = leAsymmetricEncryptionService.decrypt(job.encryptedData, privateKey);
      var decryptedData = JSON.parse(decryptedData);
      Object.assign(job.data, decryptedData)
      processJob(job, complete);
    }
    _provider = provider;
    _provider.createWorker(innerProcessJob);
  }
  /**
   * Prevents the worker from picking up new jobs and resolves once current jobs are complete
   * @function shutdown
   * @memberof JobQueueService
   * @instance
   * @returns {promise}
   */
  this.shutdown = function () {
    if (!_provider) { throw new Error('Job queue provider required'); }
    return _provider.shutdown();
  }
}

module.exports = JobQueueService;
<|endoftext|>


<commit_before>import Client from './client';
import * as events from './events';
import jsonPlugin from './plugins/json';
import jwtPlugin from './plugins/jwt';
import PluginError from './plugin-error';

export {
  events,
  jsonPlugin,
  jwtPlugin,
  PluginError,
};

export default Client;
<commit_msg>export oauth plugin (#67)<commit_after>import Client from './client';
import * as events from './events';
import jsonPlugin from './plugins/json';
import jwtPlugin from './plugins/jwt';
import oauthPlugin from './plugins/oauth';
import PluginError from './plugin-error';

export {
  events,
  jsonPlugin,
  jwtPlugin,
  oauthPlugin,
  PluginError,
};

export default Client;
<|endoftext|>


<commit_before>/**
 * Provides public API.
 *
 * @module index
 *
 * @public
 */

import Application from './application';
import Plugin from './plugin';
import querySelector from './query-selector';

/**
 * Default query selector which used by default.
 *
 * Use them as a base if you want to write custom query selector.
 *
 * @example
 *
 * function customQuerySelector(tree, selector) {
 *   const modifiedSelector = modifySelector(selector);
 *
 *   return querySelector(tree, modifiedSelector);
 * }
 *
 * @constant querySelector
 * @type QuerySelector
 *
 * @public
 * @since 0.4.1
 */
export { querySelector };

/**
 * Creates application instance.
 *
 * @example
 *
 * const application = createApplication();
 *
 * application.component('.example', {
 *   // ...
 * });
 *
 * @param {?ApplicationOptions} options - application options.
 *
 * @return {module:application~Application} created application instance.
 *
 * @public
 * @since 0.2.0
 */
export function createApplication(options) {
  return new Application(options);
}

/**
 * Creates {@link module:plugin~Plugin} factory with given name and initializer.
 *
 * Initializer used for transportation arguments to transformation function if
 * needed.
 *
 * @example
 *
 * const plugin = createPlugin('awesome-plugin', function initializer() {
 *   return function transform(component, element) {
 *     // transform component here
 *   }
 * });
 *
 * const application = create({ plugins: [plugin] });
 *
 * @example
 *
 * const factory = createPlugin('awesome-plugin', function initializer(...args) {
 *   return function transform(component, element) {
 *     // `args` available here
 *   };
 * });
 *
 * const plugin = factory(
 *   // your awesome arguments here
 * );
 *
 * const application = create({ plugins: [plugin] });
 *
 * @param {String} name - plugin's name.
 * @param {PluginInitializationFn} initializer - add description.
 *
 * @return {PluginFactoryFn} plugin's factory.
 *
 * @public
 * @since 0.2.0
 */
export function createPlugin(name, initializer) {
  return function factory(...args) {
    return new Plugin(name, initializer(...args));
  };
}
<commit_msg>Update docs for `index` module<commit_after>/**
 * Provides public API.
 *
 * @module index
 *
 * @public
 */

import Application from './application';
import Plugin from './plugin';
import querySelector from './query-selector';

/**
 * Default query selector which used by default.
 *
 * Use them as a base if you want to write custom query selector.
 *
 * @example
 *
 * function customQuerySelector(tree, selector) {
 *   const modifiedSelector = modifySelector(selector);
 *
 *   return querySelector(tree, modifiedSelector);
 * }
 *
 * @constant querySelector
 * @type QuerySelector
 *
 * @public
 * @since 0.4.1
 */
export { querySelector };

/**
 * Creates application instance.
 *
 * @example
 *
 * const application = createApplication();
 *
 * application.component('.example', {
 *   // ...
 * });
 *
 * @param {?ApplicationOptions} options - application options.
 *
 * @return {module:application~Application} created application instance.
 *
 * @public
 * @since 0.5.0
 */
export function createApplication(options) {
  return new Application(options);
}

/**
 * Creates {@link module:plugin~Plugin} factory with given name and initializer.
 *
 * Initializer used for transportation arguments to transformation function if
 * needed.
 *
 * @example
 *
 * const plugin = createPlugin('awesome-plugin', function initializer() {
 *   return function transform(component, element) {
 *     // transform component here
 *   }
 * });
 *
 * const application = create({ plugins: [plugin] });
 *
 * @example
 *
 * const factory = createPlugin('awesome-plugin', function initializer(...args) {
 *   return function transform(component, element) {
 *     // `args` available here
 *   };
 * });
 *
 * const plugin = factory(
 *   // your awesome arguments here
 * );
 *
 * const application = createApplication({ plugins: [plugin] });
 *
 * @param {String} name - plugin's name.
 * @param {PluginInitializationFn} initializer - add description.
 *
 * @return {PluginFactoryFn} plugin's factory.
 *
 * @public
 * @since 0.5.0
 */
export function createPlugin(name, initializer) {
  return function factory(...args) {
    return new Plugin(name, initializer(...args));
  };
}
<|endoftext|>


<commit_before>/* @flow */
import WatchmanPlugin from './WatchmanPlugin';

export default WatchmanPlugin;
<commit_msg>Export as default node export<commit_after>/* @flow */
import WatchmanPlugin from './WatchmanPlugin';

module.exports = WatchmanPlugin;
<|endoftext|>


<commit_before>var React = require('react');
var marked = require('marked');
var he = require('he');
var CodeComponent = React.createFactory(require('./CodeComponent.js'));
var renderer = new marked.Renderer();
var options = {};
var inlineIds = 0;
var keys = 0;
var inlines = {};
var result = [];
var toc = [];

// Converts inline IDs to actual elements
var createBlockContent = function (content) {
  var textWithInlines = content.split(/(\{\{.*?\}\})/);
  content = textWithInlines.map(function (text) {
    var inline = text.match(/\{\{(.*)\}\}/);
    if (inline) {
      return inlines[inline[1]];
    } else {
			if (text != '') {
      	return he.decode(text);
			}
    }
  });

	console.log(content)

  return content;
};

var getTocPosition = function (toc, level) {
  var currentLevel = toc.children;
  while (true) {
    if (!currentLevel.length || currentLevel[currentLevel.length - 1].level === level) {
      return currentLevel;
    } else {
      currentLevel = currentLevel[currentLevel.length - 1].children;
    }
  }
};

renderer.code = function (code, language) {
  var props = {
    key: keys++,
    language: language,
    code: code
  };

  if (options.code) {
    result.push(React.createElement(options.code, props));
  } else {
    result.push(CodeComponent(props));
  }
};

renderer.blockquote = function (text) {
  var count = text.split(/(\{\{.*?\}\})/).filter(function(n){ return n != ""});

  count.forEach(function(){
    result.pop();
  });

  result.push(React.createElement(options.blockquote || 'blockquote', {key: keys++}, createBlockContent(text)));
};

renderer.html = function (html) {
    result.push(React.createElement(options.html || React.createClass({
        render: function render () {
            return React.createElement('div', {
                dangerouslySetInnerHTML: {
                    __html: this.props.html
                }
            });
        }
    }), {
        html: html
    }));
};

renderer.heading = function (text, level) {
  var type = 'h' + level;
  type = options[type] || type;
  var id = text.replace(/\s/g, '-').toLowerCase();
  var lastToc = toc[toc.length -1];
  if (!lastToc || lastToc.level > level) {
    toc.push({
      id: id,
      title: text,
      level: level,
      children: []
    });
  } else {
    var tocPosition = getTocPosition(lastToc, level);
    tocPosition.push({
      id: id,
      title: text,
      level: level,
      children: []
    });
  }
  var inId = inlineIds++;
  inlines[inId] = React.createElement(type, {
    key: keys++,
    id: id
  },
    createBlockContent(text));
  result.push(inlines[inId]);
  return '{{' + inId + '}}';
};

renderer.hr = function () {
  result.push(React.createElement(options.hr || 'hr', {key: keys++}));
};

renderer.list = function (body, ordered) {
  var id = inlineIds++;
  inlines[id] = React.createElement(ordered ? options.ol || 'ol' : options.ul || 'ul', {key: keys++}, createBlockContent(body));
  result.push(inlines[id]);
  return '{{' + id + '}}';

};

renderer.listitem = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.li || 'li', {key: keys++}, createBlockContent(text));
  return '{{' + id + '}}';
};

renderer.paragraph = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.p || 'p', {key: keys++}, createBlockContent(text));
  result.push(inlines[id]);
  return '{{' + id + '}}';
};

renderer.table = function (header, body) {
  var id = inlineIds++;
  inlines[id] =  React.createElement(options.table || 'table', {key: keys++},
    React.createElement(options.thead || 'thead', null, createBlockContent(header)),
    React.createElement(options.tbody || 'tbody', null, createBlockContent(body))
  );
  result.push(inlines[id]);
  return '{{' + id + '}}';
};

renderer.thead = function (content) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.thead || 'thead', {key: keys++}, createBlockContent(content));
  return '{{' + id + '}}';
};

renderer.tbody = function (content) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.tbody || 'tbody', {key: keys++}, createBlockContent(content));
  return '{{' + id + '}}';
};

renderer.tablerow = function (content) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.tr || 'tr', {key: keys++}, createBlockContent(content));
  return '{{' + id + '}}';
};

renderer.tablecell = function (content, flags) {
  var id = inlineIds++;
  var props =  flags.align ? {className: 'text-' + flags.align} : {key: keys++};
  inlines[id] = React.createElement(flags.header ? options.th || 'th' : options.td || 'td', props, createBlockContent(content));
  return '{{' + id + '}}';
};

renderer.link = function (href, title, text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.a || 'a', {
    href: href,
    title: title,
    key: keys++,
    target: 'new'
  }, createBlockContent(text));
  return '{{' + id + '}}';
};

renderer.strong = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.strong || 'strong', {key: keys++}, createBlockContent(text));
  return '{{' + id + '}}';
};

renderer.em = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.em || 'em', {key: keys++}, createBlockContent(text));
  return '{{' + id + '}}';
};

renderer.codespan = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.codespan || 'code', {key: keys++}, he.decode(text));
  return '{{' + id + '}}';
};

renderer.br = function () {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.br || 'br', {key: keys++});
  return '{{' + id + '}}';
};

renderer.del = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.del || 'del', {key: keys++}, he.decode(text));
  return '{{' + id + '}}';
};

renderer.image = function (href, title, text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.img || 'img', {src: href, alt: title, key: keys++});
  return '{{' + id + '}}';
};

var exec = function (content) {
  result = [];
  toc = [];
  inlines = {};
  keys = 0;
  marked(content, {renderer: renderer, smartypants: true});
  return {
    tree: result,
    toc: toc
  };
};

exec.configure = function (newOptions) {
  options = newOptions;
};

module.exports = exec;
<commit_msg>remove console log<commit_after>var React = require('react');
var marked = require('marked');
var he = require('he');
var CodeComponent = React.createFactory(require('./CodeComponent.js'));
var renderer = new marked.Renderer();
var options = {};
var inlineIds = 0;
var keys = 0;
var inlines = {};
var result = [];
var toc = [];

// Converts inline IDs to actual elements
var createBlockContent = function (content) {
  var textWithInlines = content.split(/(\{\{.*?\}\})/);
  content = textWithInlines.map(function (text) {
    var inline = text.match(/\{\{(.*)\}\}/);
    if (inline) {
      return inlines[inline[1]];
    } else {
			if (text != '') {
      	return he.decode(text);
			}
    }
  });

  return content;
};

var getTocPosition = function (toc, level) {
  var currentLevel = toc.children;
  while (true) {
    if (!currentLevel.length || currentLevel[currentLevel.length - 1].level === level) {
      return currentLevel;
    } else {
      currentLevel = currentLevel[currentLevel.length - 1].children;
    }
  }
};

renderer.code = function (code, language) {
  var props = {
    key: keys++,
    language: language,
    code: code
  };

  if (options.code) {
    result.push(React.createElement(options.code, props));
  } else {
    result.push(CodeComponent(props));
  }
};

renderer.blockquote = function (text) {
  var count = text.split(/(\{\{.*?\}\})/).filter(function(n){ return n != ""});

  count.forEach(function(){
    result.pop();
  });

  result.push(React.createElement(options.blockquote || 'blockquote', {key: keys++}, createBlockContent(text)));
};

renderer.html = function (html) {
    result.push(React.createElement(options.html || React.createClass({
        render: function render () {
            return React.createElement('div', {
                dangerouslySetInnerHTML: {
                    __html: this.props.html
                }
            });
        }
    }), {
        html: html
    }));
};

renderer.heading = function (text, level) {
  var type = 'h' + level;
  type = options[type] || type;
  var id = text.replace(/\s/g, '-').toLowerCase();
  var lastToc = toc[toc.length -1];
  if (!lastToc || lastToc.level > level) {
    toc.push({
      id: id,
      title: text,
      level: level,
      children: []
    });
  } else {
    var tocPosition = getTocPosition(lastToc, level);
    tocPosition.push({
      id: id,
      title: text,
      level: level,
      children: []
    });
  }
  var inId = inlineIds++;
  inlines[inId] = React.createElement(type, {
    key: keys++,
    id: id
  },
    createBlockContent(text));
  result.push(inlines[inId]);
  return '{{' + inId + '}}';
};

renderer.hr = function () {
  result.push(React.createElement(options.hr || 'hr', {key: keys++}));
};

renderer.list = function (body, ordered) {
  var id = inlineIds++;
  inlines[id] = React.createElement(ordered ? options.ol || 'ol' : options.ul || 'ul', {key: keys++}, createBlockContent(body));
  result.push(inlines[id]);
  return '{{' + id + '}}';

};

renderer.listitem = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.li || 'li', {key: keys++}, createBlockContent(text));
  return '{{' + id + '}}';
};

renderer.paragraph = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.p || 'p', {key: keys++}, createBlockContent(text));
  result.push(inlines[id]);
  return '{{' + id + '}}';
};

renderer.table = function (header, body) {
  var id = inlineIds++;
  inlines[id] =  React.createElement(options.table || 'table', {key: keys++},
    React.createElement(options.thead || 'thead', null, createBlockContent(header)),
    React.createElement(options.tbody || 'tbody', null, createBlockContent(body))
  );
  result.push(inlines[id]);
  return '{{' + id + '}}';
};

renderer.thead = function (content) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.thead || 'thead', {key: keys++}, createBlockContent(content));
  return '{{' + id + '}}';
};

renderer.tbody = function (content) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.tbody || 'tbody', {key: keys++}, createBlockContent(content));
  return '{{' + id + '}}';
};

renderer.tablerow = function (content) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.tr || 'tr', {key: keys++}, createBlockContent(content));
  return '{{' + id + '}}';
};

renderer.tablecell = function (content, flags) {
  var id = inlineIds++;
  var props =  flags.align ? {className: 'text-' + flags.align} : {key: keys++};
  inlines[id] = React.createElement(flags.header ? options.th || 'th' : options.td || 'td', props, createBlockContent(content));
  return '{{' + id + '}}';
};

renderer.link = function (href, title, text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.a || 'a', {
    href: href,
    title: title,
    key: keys++,
    target: 'new'
  }, createBlockContent(text));
  return '{{' + id + '}}';
};

renderer.strong = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.strong || 'strong', {key: keys++}, createBlockContent(text));
  return '{{' + id + '}}';
};

renderer.em = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.em || 'em', {key: keys++}, createBlockContent(text));
  return '{{' + id + '}}';
};

renderer.codespan = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.codespan || 'code', {key: keys++}, he.decode(text));
  return '{{' + id + '}}';
};

renderer.br = function () {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.br || 'br', {key: keys++});
  return '{{' + id + '}}';
};

renderer.del = function (text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.del || 'del', {key: keys++}, he.decode(text));
  return '{{' + id + '}}';
};

renderer.image = function (href, title, text) {
  var id = inlineIds++;
  inlines[id] = React.createElement(options.img || 'img', {src: href, alt: title, key: keys++});
  return '{{' + id + '}}';
};

var exec = function (content) {
  result = [];
  toc = [];
  inlines = {};
  keys = 0;
  marked(content, {renderer: renderer, smartypants: true});
  return {
    tree: result,
    toc: toc
  };
};

exec.configure = function (newOptions) {
  options = newOptions;
};

module.exports = exec;
<|endoftext|>


<commit_before>import Menubar from 'menubar'
import Shell from 'shell'
import Server from 'electron-rpc/server'
import Path from 'path'
import _ from 'lodash'
import AutoUpdateManager from './server/auto_update_manager'
import StoryManager from './server/story_manager'
import TrayManager from './server/tray_manager'
import StoryType from './model/story_type'
import ReadCache from './model/read_cache'
import Winston from 'winston'
import NewrelicWinston from 'newrelic-winston'
import Nslog from './winston/nslog'
import fs from 'fs'

var server = new Server()

var opts = {
  dir: __dirname,
  icon: Path.join(__dirname, '..', 'images', 'Icon.png'),
  iconNew: Path.join(__dirname, '..', 'images', 'Icon-new.png'),
  preloadWindow: true
}
var menu = Menubar(opts)
var appDataPath = Path.join(menu.app.getPath('appData'), menu.app.getName())

var env = 'prod'
try {
  fs.statSync(Path.join(__dirname, 'newrelic.js'))
} catch (err) {
  env = 'dev'
}
var logger = new Winston.Logger({
  transports: [
    new Nslog(),
    new NewrelicWinston({ env: env })
  ]
})

var readCache = new ReadCache(appDataPath, 500, logger)

process.on('uncaughtException', function (error) {
  if (error) {
    logger.error('uncaughtException', { message: error.message, stack: error.stack })
  }
})

menu.on('after-create-window', function () {
  server.configure(menu.window.webContents)
  readCache.load()

  menu.window.webContents.on('new-window', function (e, url, frameName, disposition) {
    e.preventDefault()
    Shell.openExternal(url)
  })

  menu.window.on('closed', function () {
    menu.window = null
    readCache.store()
  })
})

menu.on('ready', function () {
  menu.tray.setToolTip('Hacker Menu')

  var autoUpdateManager = new AutoUpdateManager(menu.app.getVersion(), logger)
  autoUpdateManager.on('update-available', function (releaseVersion) {
    server.send('update-available', releaseVersion)
  })

  var trayManager = new TrayManager(menu.window, menu.tray, opts.icon, opts.iconNew)

  var storyManager = new StoryManager(20, readCache)
  storyManager.on('new-story', function () {
    trayManager.notifyNewStories()
  })
  storyManager.on('story-manager-status', function (status) {
    logger.info('story-manager-status', status)
  })

  _.each(StoryType.ALL, function (type) {
    server.on(type, function (req, next) {
      storyManager.fetch(type, function (err, stories) {
        if (err) {
          return next(err)
        }

        var body = {}
        body[type] = stories

        next(null, body)
      })
    })

    storyManager.watch(type, function (err, stories) {
      if (err) {
        logger.error('story-manager-watch-error', { message: err.message, stack: err.stack })
        return
      }

      var body = {}
      body[type] = stories

      server.send(type, body)
    })
  })

  server.on('current-version', function (req, next) {
    next(null, menu.app.getVersion())
  })

  server.on('terminate', function (e) {
    server.destroy()

    if (autoUpdateManager.isUpdateAvailable()) {
      autoUpdateManager.quitAndInstall()
    } else {
      menu.app.terminate()
    }
  })

  server.on('open-url', function (req) {
    var url = _.trim(req.body.url, '#')
    Shell.openExternal(url)
  })

  server.on('mark-as-read', function (req, next) {
    readCache.set(req.body.id)
    next()
  })
})
<commit_msg>Add version to logging<commit_after>import Menubar from 'menubar'
import Shell from 'shell'
import Server from 'electron-rpc/server'
import Path from 'path'
import _ from 'lodash'
import AutoUpdateManager from './server/auto_update_manager'
import StoryManager from './server/story_manager'
import TrayManager from './server/tray_manager'
import StoryType from './model/story_type'
import ReadCache from './model/read_cache'
import Winston from 'winston'
import NewrelicWinston from 'newrelic-winston'
import Nslog from './winston/nslog'
import fs from 'fs'

var server = new Server()

var opts = {
  dir: __dirname,
  icon: Path.join(__dirname, '..', 'images', 'Icon.png'),
  iconNew: Path.join(__dirname, '..', 'images', 'Icon-new.png'),
  preloadWindow: true
}
var menu = Menubar(opts)
var appDataPath = Path.join(menu.app.getPath('appData'), menu.app.getName())

var env = 'prod'
try {
  fs.statSync(Path.join(__dirname, 'newrelic.js'))
} catch (err) {
  env = 'dev'
}

var versionRewriter = function (level, msg, meta) {
  if (!meta) {
    meta = {}
  }

  meta.version = menu.app.getVersion()
  return meta
}

var logger = new Winston.Logger({
  transports: [
    new Nslog(),
    new NewrelicWinston({ env: env })
  ],
  rewriters: [ versionRewriter ]
})

var readCache = new ReadCache(appDataPath, 500, logger)

process.on('uncaughtException', function (error) {
  if (error) {
    logger.error('uncaughtException', { message: error.message, stack: error.stack })
  }
})

menu.on('after-create-window', function () {
  server.configure(menu.window.webContents)
  readCache.load()

  menu.window.webContents.on('new-window', function (e, url, frameName, disposition) {
    e.preventDefault()
    Shell.openExternal(url)
  })

  menu.window.on('closed', function () {
    menu.window = null
    readCache.store()
  })
})

menu.on('ready', function () {
  menu.tray.setToolTip('Hacker Menu')

  var autoUpdateManager = new AutoUpdateManager(menu.app.getVersion(), logger)
  autoUpdateManager.on('update-available', function (releaseVersion) {
    server.send('update-available', releaseVersion)
  })

  var trayManager = new TrayManager(menu.window, menu.tray, opts.icon, opts.iconNew)

  var storyManager = new StoryManager(20, readCache)
  storyManager.on('new-story', function () {
    trayManager.notifyNewStories()
  })
  storyManager.on('story-manager-status', function (status) {
    logger.info('story-manager-status', status)
  })

  _.each(StoryType.ALL, function (type) {
    server.on(type, function (req, next) {
      storyManager.fetch(type, function (err, stories) {
        if (err) {
          return next(err)
        }

        var body = {}
        body[type] = stories

        next(null, body)
      })
    })

    storyManager.watch(type, function (err, stories) {
      if (err) {
        logger.error('story-manager-watch-error', { message: err.message, stack: err.stack })
        return
      }

      var body = {}
      body[type] = stories

      server.send(type, body)
    })
  })

  server.on('current-version', function (req, next) {
    next(null, menu.app.getVersion())
  })

  server.on('terminate', function (e) {
    server.destroy()

    if (autoUpdateManager.isUpdateAvailable()) {
      autoUpdateManager.quitAndInstall()
    } else {
      menu.app.terminate()
    }
  })

  server.on('open-url', function (req) {
    var url = _.trim(req.body.url, '#')
    Shell.openExternal(url)
  })

  server.on('mark-as-read', function (req, next) {
    readCache.set(req.body.id)
    next()
  })
})
<|endoftext|>


<commit_before>/* global define */

(function (root, factory) {
  'use strict'
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['angular'], factory)
  } else if (typeof module !== 'undefined' && typeof module.exports === 'object') {
    // CommonJS support (for us webpack/browserify/ComponentJS folks)
    module.exports = factory(require('angular'))
  } else {
    // in the case of no module loading system
    // then don't worry about creating a global
    // variable like you would in normal UMD.
    // It's not really helpful... Just call your factory
    return factory(root.angular)
  }
}(this, function (angular) {
  'use strict'

  require('angular-animate')
  require('angular-aria')
  // require('angular-hotkeys')
  require('angular-material')
  require('angular-messages')
  require('angular-notification-icons')
  require('angular-sanitize')
  require('angular-touch')
  require('moment')
  require('v-accordion')
  require('webcam/dist/webcam.min.js')

  var moduleName = 'md-form-builder'
  var mod = angular.module(moduleName, [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngMessages',
    'ngSanitize',
    'ngMaterial',
    // 'cfp.hotkeys',
    'angular-notification-icons',
    'vAccordion',
    'webcam'
  ])

  require('./mdFormBuilder.css')

  require('./mdFormBuilder.html')
  require('./controls/mdfbAccordian.html')
  require('./controls/mdfbCheckboxes.html')
  require('./controls/mdfbChips.html')
  require('./controls/mdfbDatePicker.html')
  require('./controls/mdfbDisplay.html')
  require('./controls/mdfbPopupLink.html')
  require('./controls/mdfbEmail.html')
  require('./controls/mdfbTime.html')
  require('./controls/mdfbInput.html')
  require('./controls/mdfbFileInput.html')
  require('./controls/mdfbInputID.html')
  require('./controls/mdfbInputPhoneNumber.html')
  require('./controls/mdfbInputNumber.html')
  require('./controls/mdfbMatrix.html')
  require('./controls/mdfbPassword.html')
  require('./controls/mdfbRadio.html')
  require('./controls/mdfbRadioCustom.html')
  require('./controls/mdfbSelect.html')
  require('./controls/mdfbSelectSearch.html')
  require('./controls/mdfbWebcam.html')
  require('./controls/mdfbWebcamDialogPopup.html')

  mod.directive('mdfbAccordian', require('./controls/mdfbAccordian'))
  mod.directive('mdfbCheckboxes', require('./controls/mdfbCheckboxes'))
  mod.directive('mdfbChips', require('./controls/mdfbChips'))
  mod.directive('mdfbDatepicker', require('./controls/mdfbDatePicker'))
  mod.directive('mdfbDisplay', require('./controls/mdfbDisplay'))
  mod.directive('mdfbPopupLink', require('./controls/mdfbPopupLink'))
  mod.directive('mdfbEmail', require('./controls/mdfbEmail'))
  mod.directive('mdfbTime', require('./controls/mdfbTime'))
  mod.directive('mdfbInput', require('./controls/mdfbInput'))
  mod.directive('mdfbFileInput', require('./controls/mdfbFileInput'))
  mod.directive('mdfbInputId', require('./controls/mdfbInputID'))
  mod.directive('mdfbInputPhoneNumber', require('./controls/mdfbInputPhoneNumber'))
  mod.directive('mdfbInputNumber', require('./controls/mdfbInputNumber'))
  mod.directive('mdfbMatrix', require('./controls/mdfbMatrix'))
  mod.directive('mdfbPassword', require('./controls/mdfbPassword'))
  mod.directive('mdfbRadio', require('./controls/mdfbRadio'))
  mod.directive('mdfbRadioCustom', require('./controls/mdfbRadioCustom'))
  mod.directive('mdfbSelect', require('./controls/mdfbSelect'))
  mod.directive('mdfbSelectSearch', require('./controls/mdfbSelectSearch'))
  mod.directive('mdfbWebcam', require('./controls/mdfbWebcam'))
  mod.directive('mdFormBuilder', require('./mdFormBuilder'))

  // validators
  mod.directive('checkRsaIdNumber', require('./validators/rsaIdNumber'))
  mod.directive('checkPhoneNumber', require('./validators/phoneNumber'))
  mod.directive('regexValidation', require('./validators/regex'))

  return moduleName
}))
<commit_msg>Update index.js<commit_after>/* global define */

(function (root, factory) {
  'use strict'
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['angular'], factory)
  } else if (typeof module !== 'undefined' && typeof module.exports === 'object') {
    // CommonJS support (for us webpack/browserify/ComponentJS folks)
    module.exports = factory(require('angular'))
  } else {
    // in the case of no module loading system
    // then don't worry about creating a global
    // variable like you would in normal UMD.
    // It's not really helpful... Just call your factory
    return factory(root.angular)
  }
}(this, function (angular) {
  'use strict'

  require('angular-animate')
  require('angular-aria')
  require('angular-material')
  require('angular-messages')
  require('angular-notification-icons')
  require('angular-sanitize')
  require('angular-touch')
  require('moment')
  require('v-accordion')
  require('webcam/dist/webcam.min.js')

  var moduleName = 'md-form-builder'
  var mod = angular.module(moduleName, [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngMessages',
    'ngSanitize',
    'ngMaterial',
    'angular-notification-icons',
    'vAccordion',
    'webcam'
  ])

  require('./mdFormBuilder.css')

  require('./mdFormBuilder.html')
  require('./controls/mdfbAccordian.html')
  require('./controls/mdfbCheckboxes.html')
  require('./controls/mdfbChips.html')
  require('./controls/mdfbDatePicker.html')
  require('./controls/mdfbDisplay.html')
  require('./controls/mdfbPopupLink.html')
  require('./controls/mdfbEmail.html')
  require('./controls/mdfbTime.html')
  require('./controls/mdfbInput.html')
  require('./controls/mdfbFileInput.html')
  require('./controls/mdfbInputID.html')
  require('./controls/mdfbInputPhoneNumber.html')
  require('./controls/mdfbInputNumber.html')
  require('./controls/mdfbMatrix.html')
  require('./controls/mdfbPassword.html')
  require('./controls/mdfbRadio.html')
  require('./controls/mdfbRadioCustom.html')
  require('./controls/mdfbSelect.html')
  require('./controls/mdfbSelectSearch.html')
  require('./controls/mdfbWebcam.html')
  require('./controls/mdfbWebcamDialogPopup.html')

  mod.directive('mdfbAccordian', require('./controls/mdfbAccordian'))
  mod.directive('mdfbCheckboxes', require('./controls/mdfbCheckboxes'))
  mod.directive('mdfbChips', require('./controls/mdfbChips'))
  mod.directive('mdfbDatepicker', require('./controls/mdfbDatePicker'))
  mod.directive('mdfbDisplay', require('./controls/mdfbDisplay'))
  mod.directive('mdfbPopupLink', require('./controls/mdfbPopupLink'))
  mod.directive('mdfbEmail', require('./controls/mdfbEmail'))
  mod.directive('mdfbTime', require('./controls/mdfbTime'))
  mod.directive('mdfbInput', require('./controls/mdfbInput'))
  mod.directive('mdfbFileInput', require('./controls/mdfbFileInput'))
  mod.directive('mdfbInputId', require('./controls/mdfbInputID'))
  mod.directive('mdfbInputPhoneNumber', require('./controls/mdfbInputPhoneNumber'))
  mod.directive('mdfbInputNumber', require('./controls/mdfbInputNumber'))
  mod.directive('mdfbMatrix', require('./controls/mdfbMatrix'))
  mod.directive('mdfbPassword', require('./controls/mdfbPassword'))
  mod.directive('mdfbRadio', require('./controls/mdfbRadio'))
  mod.directive('mdfbRadioCustom', require('./controls/mdfbRadioCustom'))
  mod.directive('mdfbSelect', require('./controls/mdfbSelect'))
  mod.directive('mdfbSelectSearch', require('./controls/mdfbSelectSearch'))
  mod.directive('mdfbWebcam', require('./controls/mdfbWebcam'))
  mod.directive('mdFormBuilder', require('./mdFormBuilder'))

  // validators
  mod.directive('checkRsaIdNumber', require('./validators/rsaIdNumber'))
  mod.directive('checkPhoneNumber', require('./validators/phoneNumber'))
  mod.directive('regexValidation', require('./validators/regex'))

  return moduleName
}))
<|endoftext|>


<commit_before>import render from 'preact-render-to-string';

/*global chai*/

/** Options for all assertions.
 *	@property {function} isJsx A test to see if the given parameter is a JSX VNode. Defaults to checking for the existence of an __isVNode property
 */
export const options = {};

// create an assertion template string for the given action
let msg = act => `expected #{act} to ${act} #{exp}`;

// assert that an object is JSX (or more correctly, a VNode)
let isJsx = obj => obj && (options.isJsx ? options.isJsx(obj) : (obj.__isVNode || isVNode(obj)));

// does it look like a vnode?
let isVNode = obj => obj.hasOwnProperty('nodeName') && obj.hasOwnProperty('attributes') && obj.hasOwnProperty('children') && obj.constructor.name==='VNode';

// inject a chai assertion if the values being tested are JSX VNodes
let ifJsx = (fn, opts) => next => function(jsx, ...args) {
	if (!isJsx(this._obj)) return next.call(this, jsx, ...args);
	let expected = render(jsx, opts).trim();
	let actual = render(this._obj, opts).trim();
	return fn(this, { expected, actual, jsx });
};

// create a passthrough function
let through = next => function(...args) { return next.call(this, ...args); };

// assert that a String is equal to the given string
let equal = (a, { expected, actual }) => a.assert(actual===expected, msg('equal'), msg('not equal'), expected, actual, true);

// assert that a String contains the given string
let include = (a, { expected, actual }) => a.assert(~actual.indexOf(expected), msg('include'), msg('not include'), expected, actual, true);

/** Middleware: pass to `chai.use()` to add JSX assertion support. */
export default function assertJsx({ Assertion }) {
	if (Assertion.__assertJsxMounted===true) return;
	Assertion.__assertJsxMounted = true;

	Assertion.overwriteMethod('eql', ifJsx(equal));
	Assertion.overwriteMethod('eqls', ifJsx(equal));

	Assertion.overwriteMethod('equal', ifJsx(equal, { shallow:true }));
	Assertion.overwriteMethod('equals', ifJsx(equal, { shallow:true }));

	['include', 'includes', 'contain', 'contains'].forEach( method => {
		Assertion.overwriteChainableMethod(method, ifJsx(include), through);
	});
}

// auto-mount if possible
if (typeof chai!=='undefined' && chai.use) chai.use(assertJsx);
<commit_msg>Fixes shallow assertions (`.equal()` rather than `.deep.equal()` or `.eql()`) not working correctly.<commit_after>import render from 'preact-render-to-string';

/*global chai*/

/** Options for all assertions.
 *	@property {function} isJsx A test to see if the given parameter is a JSX VNode. Defaults to checking for the existence of an __isVNode property
 */
export const options = {};

// options to pass to renderToString() when doing a deep comparison
const RENDER_OPTS = {
	sortAttributes: true
};

// options to pass to renderToString() when doing a shallow comparison
const SHALLOW_OPTS = {
	sortAttributes: true,
	shallow: true
};

// create an assertion template string for the given action
let msg = act => `expected #{act} to ${act} #{exp}`;

// assert that an object is JSX (or more correctly, a VNode)
let isJsx = obj => obj && (options.isJsx ? options.isJsx(obj) : (obj.__isVNode || isVNode(obj)));

// does it look like a vnode?
let isVNode = obj => obj.hasOwnProperty('nodeName') && obj.hasOwnProperty('attributes') && obj.hasOwnProperty('children') && obj.constructor.name==='VNode';

// inject a chai assertion if the values being tested are JSX VNodes
let ifJsx = (fn, opts) => next => function(jsx, ...args) {
	if (!isJsx(this._obj)) return next.call(this, jsx, ...args);
	let expected = render(jsx, null, opts).trim();
	let actual = render(this._obj, null, opts).trim();
	return fn(this, { expected, actual, jsx });
};

// create a passthrough function
let through = next => function(...args) { return next.call(this, ...args); };

// assert that a String is equal to the given string
let equal = (a, { expected, actual }) => a.assert(actual===expected, msg('equal'), msg('not equal'), expected, actual, true);

// assert that a String contains the given string
let include = (a, { expected, actual }) => a.assert(~actual.indexOf(expected), msg('include'), msg('not include'), expected, actual, true);

/** Middleware: pass to `chai.use()` to add JSX assertion support. */
export default function assertJsx({ Assertion }) {
	if (Assertion.__assertJsxMounted===true) return;
	Assertion.__assertJsxMounted = true;

	Assertion.overwriteMethod('eql', ifJsx(equal, RENDER_OPTS));
	Assertion.overwriteMethod('eqls', ifJsx(equal, RENDER_OPTS));

	Assertion.overwriteMethod('equal', ifJsx(equal, SHALLOW_OPTS));
	Assertion.overwriteMethod('equals', ifJsx(equal, SHALLOW_OPTS));

	['include', 'includes', 'contain', 'contains'].forEach( method => {
		Assertion.overwriteChainableMethod(method, ifJsx(include), through);
	});
}

// auto-mount if possible
if (typeof chai!=='undefined' && chai.use) chai.use(assertJsx);
<|endoftext|>


<commit_before>(function() {
  // next-tick requiring stream so that by the time i actually need it webpack has processed the
  // Readable and PassThrough exports
  require('stream');
  const browser = require('os').platform() === 'browser';
  const http = require('http');
  const https = require('https');
  const URL = require('url');
  const zlib = require('zlib');
  const Stream = require('stream');
  const FormData = require('./FormData');
  const Package = require('../package.json');

  class Snekfetch extends Stream.Readable {
    constructor(method, url) {
      super();
      const { hostname, path, protocol } = URL.parse(url);
      this.protocol = protocol;
      this.url = url;
      this.options = {
        method: method.toUpperCase(),
        hostname,
        path,
        headers: {},
      };
      this.data = null;
      this.ended = false;
    }

    set(name, value) {
      if (name !== null && typeof name === 'object') {
        for (const key of Object.keys(name)) this.set(key, name[key]);
      } else {
        this.options.headers[name.toLowerCase()] = value;
      }
      return this;
    }

    attach(name, data, filename) {
      const form = this._getFormData();
      this.set('Content-Type', `multipart/form-data; boundary=${form.boundary}`);
      form.append(name, data, filename);
      this.data = form;
      return this;
    }

    send(data) {
      if (typeof data === 'object') {
        this.set('Content-Type', 'application/json');
        this.data = JSON.stringify(data);
      } else {
        this.data = data;
      }
      return this;
    }

    go() {
      return new Promise((resolve, reject) => {
        this.ended = true;
        if (!this.options.headers['user-agent']) {
          this.set('user-agent', `snekfetch/${Snekfetch.version} (${Package.repository.url.replace(/\.?git/, '')})`);
        }
        const request = (this.protocol === 'https:' ? https : http)
        .request(this.options, (response) => {
          response.request = request;
          const stream = new Stream.PassThrough();
          if (this._shouldUnzip(response)) {
            response.pipe(zlib.createUnzip({
              flush: zlib.Z_SYNC_FLUSH,
              finishFlush: zlib.Z_SYNC_FLUSH,
            })).pipe(stream);
          } else {
            response.pipe(stream);
          }

          let body = [];
          stream.on('data', (chunk) => {
            if (!this.push(chunk)) this.pause();
            body.push(Buffer.from(chunk));
          });
          stream.on('end', () => {
            this.push(null);
            const concated = Buffer.concat(body);
            if ([301, 302, 303, 307, 308].includes(response.statusCode)) {
              resolve(Snekfetch[this.options.method.toLowerCase()](URL.resolve(this.url, response.headers.location)));
              return;
            }
            const res = {
              request: this.options,
              body: concated,
              text: concated.toString(),
              ok: response.statusCode >= 200 && response.statusCode < 300,
              headers: response.headers,
              status: response.statusCode,
              statusText: response.statusText || http.STATUS_CODES[response.statusCode],
              url: this.url,
            };

            const type = response.headers['content-type'];
            if (type.includes('application/json')) {
              try {
                res.body = JSON.parse(res.text);
              } catch (err) {} // eslint-disable-line no-empty
            } else if (type.includes('application/x-www-form-urlencoded')) {
              res.body = {};
              for (const [k, v] of res.text.split('&').map(q => q.split('='))) res.body[k] = v;
            }

            if (res.ok) {
              resolve(res);
            } else {
              const error = new Error(`${res.status} ${res.statusText}`.trim());
              error.response = res;
              reject(error);
            }
          });
        });
        const data = this.data ? this.data.end ? this.data.end() : this.data : null;
        request.end(data);
      });
    }

    then(s, f) {
      return this.go()
      .then((res) => s ? s(res) : res)
      .catch((err) => f ? f(err) : err);
    }

    end(cb) {
      this.then((res) => {
        cb(null, res);
      }).catch((err) => {
        cb(err, err.response ? err.response : null);
      });
    }

    catch(f) {
      return this.then(null, f);
    }

    _read() {
      this.resume();
      if (this.ended) return;
      this.end(() => {}); // eslint-disable-line no-empty-function
    }

    _shouldUnzip(res) {
      if (res.statusCode === 204 || res.statusCode === 304) return false;
      if (res.headers['content-length'] === '0') return false;
      return /^\s*(?:deflate|gzip)\s*$/.test(res.headers['content-encoding']);
    }

    _getFormData() {
      if (!this._formData) this._formData = new FormData();
      return this._formData;
    }
  }

  Snekfetch.version = Package.version;

  Snekfetch.METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH', 'BREW'];
  for (const method of Snekfetch.METHODS) Snekfetch[method.toLowerCase()] = (url) => new Snekfetch(method, url);

  module.exports = Snekfetch;
  if (browser) window.Snekfetch = Snekfetch;
}());
<commit_msg>change behavior with res.ok<commit_after>(function() {
  // next-tick requiring stream so that by the time i actually need it webpack has processed the
  // Readable and PassThrough exports
  require('stream');
  const browser = require('os').platform() === 'browser';
  const http = require('http');
  const https = require('https');
  const URL = require('url');
  const zlib = require('zlib');
  const Stream = require('stream');
  const FormData = require('./FormData');
  const Package = require('../package.json');

  class Snekfetch extends Stream.Readable {
    constructor(method, url) {
      super();
      const { hostname, path, protocol } = URL.parse(url);
      this.protocol = protocol;
      this.url = url;
      this.options = {
        method: method.toUpperCase(),
        hostname,
        path,
        headers: {},
      };
      this.data = null;
      this.ended = false;
    }

    set(name, value) {
      if (name !== null && typeof name === 'object') {
        for (const key of Object.keys(name)) this.set(key, name[key]);
      } else {
        this.options.headers[name.toLowerCase()] = value;
      }
      return this;
    }

    attach(name, data, filename) {
      const form = this._getFormData();
      this.set('Content-Type', `multipart/form-data; boundary=${form.boundary}`);
      form.append(name, data, filename);
      this.data = form;
      return this;
    }

    send(data) {
      if (typeof data === 'object') {
        this.set('Content-Type', 'application/json');
        this.data = JSON.stringify(data);
      } else {
        this.data = data;
      }
      return this;
    }

    go() {
      return new Promise((resolve) => {
        this.ended = true;
        if (!this.options.headers['user-agent']) {
          this.set('user-agent', `snekfetch/${Snekfetch.version} (${Package.repository.url.replace(/\.?git/, '')})`);
        }
        const request = (this.protocol === 'https:' ? https : http)
        .request(this.options, (response) => {
          response.request = request;
          const stream = new Stream.PassThrough();
          if (this._shouldUnzip(response)) {
            response.pipe(zlib.createUnzip({
              flush: zlib.Z_SYNC_FLUSH,
              finishFlush: zlib.Z_SYNC_FLUSH,
            })).pipe(stream);
          } else {
            response.pipe(stream);
          }

          let body = [];
          stream.on('data', (chunk) => {
            if (!this.push(chunk)) this.pause();
            body.push(Buffer.from(chunk));
          });
          stream.on('end', () => {
            this.push(null);
            const concated = Buffer.concat(body);
            if ([301, 302, 303, 307, 308].includes(response.statusCode)) {
              resolve(Snekfetch[this.options.method.toLowerCase()](URL.resolve(this.url, response.headers.location)));
              return;
            }

            const res = {
              request: this.options,
              body: concated,
              text: concated.toString(),
              ok: response.statusCode >= 200 && response.statusCode < 300,
              headers: response.headers,
              status: response.statusCode,
              statusText: response.statusText || http.STATUS_CODES[response.statusCode],
              url: this.url,
            };

            const type = response.headers['content-type'];
            if (type.includes('application/json')) {
              try {
                res.body = JSON.parse(res.text);
              } catch (err) {} // eslint-disable-line no-empty
            } else if (type.includes('application/x-www-form-urlencoded')) {
              res.body = {};
              for (const [k, v] of res.text.split('&').map(q => q.split('='))) res.body[k] = v;
            }

            resolve(res);
          });
        });
        const data = this.data ? this.data.end ? this.data.end() : this.data : null;
        request.end(data);
      });
    }

    then(s, f) {
      return this.go()
      .then((res) => s ? s(res) : res)
      .catch((err) => f ? f(err) : err);
    }

    end(cb) {
      return this.go().then((res) => {
        if (res.ok) return cb(null, res);
        else return cb(new Error(res), res);
      }).catch((err) => cb(err));
    }

    catch(f) {
      return this.then(null, f);
    }

    _read() {
      this.resume();
      if (this.ended) return;
      this.end(() => {}); // eslint-disable-line no-empty-function
    }

    _shouldUnzip(res) {
      if (res.statusCode === 204 || res.statusCode === 304) return false;
      if (res.headers['content-length'] === '0') return false;
      return /^\s*(?:deflate|gzip)\s*$/.test(res.headers['content-encoding']);
    }

    _getFormData() {
      if (!this._formData) this._formData = new FormData();
      return this._formData;
    }
  }

  Snekfetch.version = Package.version;

  Snekfetch.METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH', 'BREW'];
  for (const method of Snekfetch.METHODS) Snekfetch[method.toLowerCase()] = (url) => new Snekfetch(method, url);

  module.exports = Snekfetch;
  if (browser) window.Snekfetch = Snekfetch;
}());
<|endoftext|>


<commit_before>import forIn from 'lodash/object/forIn';

export function onConnect(init, responses, connections, tab, error) {
  if (typeof connections === 'undefined' && !window.bgConnections) {
    window.bgConnections = {}; connections = window.bgConnections;
  }

  chrome.runtime.onConnect.addListener(function(port) {
    function extensionListener(message) {
      if (message.name === 'init') {
        connections[message.tabId || port.sender.tab.id] = port;

        if (tab && message.tabId !== tab.id) {
          error(port);
          return;
        }
        port.postMessage(init());
      }
      else if(responses[message.name]) {
        const res = responses[message.name](message);
        if (res) port.postMessage(res);
      }
    }

    port.onMessage.addListener(extensionListener);
    port.onDisconnect.addListener(function(portDiscon) {
      portDiscon.onMessage.removeListener(extensionListener);
      Object.keys(connections).forEach(function(id) {
        if (connections[id] === portDiscon) {
          delete connections[id];
        }
      });
    });

  });
}

export function connect(arg) {
  if (!arg) return chrome.runtime.connect();
  if (typeof arg === 'boolean' && arg) {
    window.bgConnection = chrome.runtime.connect();
    return window.bgConnection;
  }
  return chrome.runtime.connect(arg);
}

export function onMessage(messaging) {
  if (chrome.runtime.onMessage) chrome.runtime.onMessage.addListener(messaging);
}

export function sendToBg(...args) {
  if (!window.bgConnection) chrome.runtime.sendMessage(...args);
  else {
    window.bgConnection.postMessage(...args);
  }
}

export function sendToTab(...args) {
  chrome.tabs.sendMessage(...args);
}

export function sendToTabs(message, connections) {
  if (!connections) {
    if (window.bgConnections) connections = window.bgConnections;
    else return;
  }
  forIn(connections, connection => {
    connection.postMessage(message);
  });
}
<commit_msg>Universal sendMessage function - from background and to background<commit_after>import forIn from 'lodash/object/forIn';

export function onConnect(init, responses, connections, tab, error) {
  if (typeof connections === 'undefined' && !window.bgConnections) {
    window.bgConnections = {}; connections = window.bgConnections;
  }

  chrome.runtime.onConnect.addListener(function(port) {
    function extensionListener(message) {
      if (message.name === 'init') {
        connections[message.tabId || port.sender.tab.id] = port;

        if (tab && message.tabId !== tab.id) {
          error(port);
          return;
        }
        port.postMessage(init());
      }
      else if(responses[message.name]) {
        const res = responses[message.name](message);
        if (res) port.postMessage(res);
      }
    }

    port.onMessage.addListener(extensionListener);
    port.onDisconnect.addListener(function(portDiscon) {
      portDiscon.onMessage.removeListener(extensionListener);
      Object.keys(connections).forEach(function(id) {
        if (connections[id] === portDiscon) {
          delete connections[id];
        }
      });
    });

  });
}

export function connect(arg) {
  if (!arg) return chrome.runtime.connect();
  if (typeof arg === 'boolean' && arg) {
    window.bgConnection = chrome.runtime.connect();
    return window.bgConnection;
  }
  return chrome.runtime.connect(arg);
}

export function onMessage(messaging) {
  if (chrome.runtime.onMessage) chrome.runtime.onMessage.addListener(messaging);
}

export function sendToBg(...args) {
  if (!window.bgConnection) chrome.runtime.sendMessage(...args);
  else {
    window.bgConnection.postMessage(...args);
  }
}

export function sendToTab(...args) {
  chrome.tabs.sendMessage(...args);
}

export function sendToTabs(message, connections) {
  if (!connections) {
    if (window.bgConnections) connections = window.bgConnections;
    else return;
  }
  forIn(connections, connection => {
    connection.postMessage(message);
  });
}

export function sendMessage(message) {
  if (window.bgConnection) window.bgConnection.postMessage(message);
  else sendToTabs(message);
}
<|endoftext|>


<commit_before>//Code translate from Pascal source in http://pubs.acs.org/doi/pdf/10.1021/ac00205a007
var extend = require('extend');
var stat = require('ml-stat');

var defaultOptions = {
    windowSize: 11,
    derivative: 0,
    polynomial: 2,
};

function SavitzkyGolay(data, h, options) {
    options = extend({}, defaultOptions, options);

    if ((options.windowSize % 2 === 0) || (options.windowSize < 5) || !(Number.isInteger(options.windowSize)))
            throw new RangeError('Invalid window size (should be odd and at least 5 integer number)')

    if (options.windowSize>data.length)
        throw new RangeError('Window size is higher than the data length '+options.windowSize+">"+data.length);
    if ((options.derivative < 0) || !(Number.isInteger(options.derivative)))
        throw new RangeError('Derivative should be a positive integer');
    if ((options.polynomial < 1) || !(Number.isInteger(options.polynomial)))
        throw new RangeError('Polynomial should be a positive integer');
    if (options.polynomial >= 6)
        console.warn('You should not use polynomial grade higher than 5 if you are' +
            ' not sure that your data arises from such a model. Possible polynomial oscillation problems');

    var windowSize = options.windowSize;

    var half = Math.floor(windowSize/2);
    var np = data.length;
    var ans = new Array(np);
    var weights = fullWeights(windowSize,options.polynomial,options.derivative);
    var hs = 0;
    var constantH = true;
    if( Object.prototype.toString.call( h ) === '[object Array]' ) {
        constantH = false;
    }
    else{
        hs = Math.pow(h, options.derivative);
    }
    //console.log("Constant h: "+constantH);
    //For the borders
    for(var i=0;i<half;i++){
        var wg1=weights[half-i-1];
        var wg2=weights[half+i+1];
        var d1 = 0,d2=0;
        for (var l = 0; l < windowSize; l++){
            d1 += wg1[l] * data[l];
            d2 += wg2[l] * data[np-windowSize+l-1];
        }
        if(constantH){
            ans[half-i-1] = d1/hs;
            ans[np-half+i] = d2/hs;
        }
        else{
            hs = getHs(h,half-i-1,half, options.derivative);
            ans[half-i-1] = d1/hs;
            hs = getHs(h,np-half+i,half, options.derivative);
            ans[np-half+i] = d2/hs;
        }
    }
    //For the internal points
    var wg = weights[half];
    for(var i=windowSize;i<np+1;i++){
        var d = 0;
        for (var l = 0; l < windowSize; l++)
            d += wg[l] * data[l+i-windowSize];
        if(!constantH)
            hs = getHs(h,i-half-1,half, options.derivative);
        ans[i-half-1] = d/hs;
    }
    return ans;
}

function getHs(h,center,half,derivative){
    var hs = 0;
    var count = 0;
    for(var i=center-half;i<center+half;i++){
        if(i>=0 && i < h.length-1){
            hs+= (h[i+1]-h[i]);
            count++;
        }
    }
    return Math.pow(hs/count,derivative);
}

function GramPoly(i,m,k,s){
    var Grampoly = 0;
    if(k>0){
        Grampoly = (4*k-2)/(k*(2*m-k+1))*(i*GramPoly(i,m,k-1,s) +
            s*GramPoly(i,m,k-1,s-1)) - ((k-1)*(2*m+k))/(k*(2*m-k+1))*GramPoly(i,m,k-2,s);
    }
    else{
        if(k==0&&s==0){
            Grampoly=1;
        }
        else{
            Grampoly=0;
        }
    }
    //console.log(Grampoly);
    return Grampoly;
}

function GenFact(a,b){
    var gf=1;
    if(a>=b){
        for(var j=a-b+1;j<=a;j++){
            gf*=j;
        }
    }
    return gf;
}

function Weight(i,t,m,n,s){
    var sum=0;
    for(var k=0;k<=n;k++){
        //console.log(k);
        sum+=(2*k+1)*(GenFact(2*m,k)/GenFact(2*m+k+1,k+1))*GramPoly(i,m,k,0)*GramPoly(t,m,k,s)
    }
    return sum;
}

/**
 *
 * @param m  Number of points
 * @param n  Polynomial grade
 * @param s  Derivative
 */
function fullWeights(m,n,s){
    var weights = new Array(m);
    var np = Math.floor(m/2);
    for(var t=-np;t<=np;t++){
        weights[t+np] = new Array(m);
        for(var j=-np;j<=np;j++){
            weights[t+np][j+np]=Weight(j,t,np,n,s);
        }
    }
    return weights;
}

/*function entropy(data,h,options){
    var trend = SavitzkyGolay(data,h,trendOptions);
    var copy = new Array(data.length);
    var sum = 0;
    var max = 0;
    for(var i=0;i<data.length;i++){
        copy[i] = data[i]-trend[i];
    }

    sum/=data.length;
    console.log(sum+" "+max);
    console.log(stat.array.standardDeviation(copy));
    console.log(Math.abs(stat.array.mean(copy))/stat.array.standardDeviation(copy));
    return sum;

}

function guessWindowSize(data, h){
    console.log("entropy "+entropy(data,h,trendOptions));
    return 5;
}
*/
module.exports = SavitzkyGolay;

<commit_msg>Default parameters<commit_after>//Code translate from Pascal source in http://pubs.acs.org/doi/pdf/10.1021/ac00205a007
var extend = require('extend');
var stat = require('ml-stat');

var defaultOptions = {
    windowSize: 9,
    derivative: 0,
    polynomial: 3,
};

function SavitzkyGolay(data, h, options) {
    options = extend({}, defaultOptions, options);

    if ((options.windowSize % 2 === 0) || (options.windowSize < 5) || !(Number.isInteger(options.windowSize)))
            throw new RangeError('Invalid window size (should be odd and at least 5 integer number)')

    if (options.windowSize>data.length)
        throw new RangeError('Window size is higher than the data length '+options.windowSize+">"+data.length);
    if ((options.derivative < 0) || !(Number.isInteger(options.derivative)))
        throw new RangeError('Derivative should be a positive integer');
    if ((options.polynomial < 1) || !(Number.isInteger(options.polynomial)))
        throw new RangeError('Polynomial should be a positive integer');
    if (options.polynomial >= 6)
        console.warn('You should not use polynomial grade higher than 5 if you are' +
            ' not sure that your data arises from such a model. Possible polynomial oscillation problems');

    var windowSize = options.windowSize;

    var half = Math.floor(windowSize/2);
    var np = data.length;
    var ans = new Array(np);
    var weights = fullWeights(windowSize,options.polynomial,options.derivative);
    var hs = 0;
    var constantH = true;
    if( Object.prototype.toString.call( h ) === '[object Array]' ) {
        constantH = false;
    }
    else{
        hs = Math.pow(h, options.derivative);
    }
    //console.log("Constant h: "+constantH);
    //For the borders
    for(var i=0;i<half;i++){
        var wg1=weights[half-i-1];
        var wg2=weights[half+i+1];
        var d1 = 0,d2=0;
        for (var l = 0; l < windowSize; l++){
            d1 += wg1[l] * data[l];
            d2 += wg2[l] * data[np-windowSize+l-1];
        }
        if(constantH){
            ans[half-i-1] = d1/hs;
            ans[np-half+i] = d2/hs;
        }
        else{
            hs = getHs(h,half-i-1,half, options.derivative);
            ans[half-i-1] = d1/hs;
            hs = getHs(h,np-half+i,half, options.derivative);
            ans[np-half+i] = d2/hs;
        }
    }
    //For the internal points
    var wg = weights[half];
    for(var i=windowSize;i<np+1;i++){
        var d = 0;
        for (var l = 0; l < windowSize; l++)
            d += wg[l] * data[l+i-windowSize];
        if(!constantH)
            hs = getHs(h,i-half-1,half, options.derivative);
        ans[i-half-1] = d/hs;
    }
    return ans;
}

function getHs(h,center,half,derivative){
    var hs = 0;
    var count = 0;
    for(var i=center-half;i<center+half;i++){
        if(i>=0 && i < h.length-1){
            hs+= (h[i+1]-h[i]);
            count++;
        }
    }
    return Math.pow(hs/count,derivative);
}

function GramPoly(i,m,k,s){
    var Grampoly = 0;
    if(k>0){
        Grampoly = (4*k-2)/(k*(2*m-k+1))*(i*GramPoly(i,m,k-1,s) +
            s*GramPoly(i,m,k-1,s-1)) - ((k-1)*(2*m+k))/(k*(2*m-k+1))*GramPoly(i,m,k-2,s);
    }
    else{
        if(k==0&&s==0){
            Grampoly=1;
        }
        else{
            Grampoly=0;
        }
    }
    //console.log(Grampoly);
    return Grampoly;
}

function GenFact(a,b){
    var gf=1;
    if(a>=b){
        for(var j=a-b+1;j<=a;j++){
            gf*=j;
        }
    }
    return gf;
}

function Weight(i,t,m,n,s){
    var sum=0;
    for(var k=0;k<=n;k++){
        //console.log(k);
        sum+=(2*k+1)*(GenFact(2*m,k)/GenFact(2*m+k+1,k+1))*GramPoly(i,m,k,0)*GramPoly(t,m,k,s)
    }
    return sum;
}

/**
 *
 * @param m  Number of points
 * @param n  Polynomial grade
 * @param s  Derivative
 */
function fullWeights(m,n,s){
    var weights = new Array(m);
    var np = Math.floor(m/2);
    for(var t=-np;t<=np;t++){
        weights[t+np] = new Array(m);
        for(var j=-np;j<=np;j++){
            weights[t+np][j+np]=Weight(j,t,np,n,s);
        }
    }
    return weights;
}

/*function entropy(data,h,options){
    var trend = SavitzkyGolay(data,h,trendOptions);
    var copy = new Array(data.length);
    var sum = 0;
    var max = 0;
    for(var i=0;i<data.length;i++){
        copy[i] = data[i]-trend[i];
    }

    sum/=data.length;
    console.log(sum+" "+max);
    console.log(stat.array.standardDeviation(copy));
    console.log(Math.abs(stat.array.mean(copy))/stat.array.standardDeviation(copy));
    return sum;

}

function guessWindowSize(data, h){
    console.log("entropy "+entropy(data,h,trendOptions));
    return 5;
}
*/
module.exports = SavitzkyGolay;

<|endoftext|>


<commit_before>import * as React from 'react';
import { debounce } from 'lodash';
import PropTypes from 'prop-types';

class TextEllipsis extends React.Component {
  constructor(props) {
    super(props);

    this.isSupportNativeClamp = this.props.useJsOnly ? false : 'webkitLineClamp' in document.body.style;
    this.truncate = this.truncate.bind(this);
    this.debounceProcess = debounce(this.process, this.props.debounceTimeoutOnResize);
  }

  componentDidMount() {
    this.text = this.container.innerHTML;
    this.process();

    window.addEventListener('resize', this.debounceProcess, false);
  }

  componentDidUpdate() {
    this.text = this.container.innerHTML;
    this.process();
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.debounceProcess, false);
  }

  onResult() {
    if (this.container.scrollWidth > this.container.clientWidth || this.container.scrollHeight > this.container.clientHeight) {
      this.props.onResult(TextEllipsis.RESULT.TRUNCATED);
    } else {
      this.props.onResult(TextEllipsis.RESULT.NOT_TRUNCATED);
    }
  }

  getLineHeight() {
    const lineHeight = this.computedStyle("line-height");

    if (lineHeight === 'normal') {
      // Normal line heights vary from browser to browser. The spec recommends
      // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
      return Math.ceil(parseFloat(this.computedStyle('font-size')) * 1.2);
    }
    return Math.ceil(parseFloat(lineHeight));
  }

  getTextWithEllipsis(start, end) {
    this.currentText = this.text.slice(start, end);
    return this.currentText + this.props.ellipsisChars;
  }

  truncate() {
    if (this.container.offsetHeight > this.lineHeight * this.props.lines) {
      this.container.innerHTML = this.getTextWithEllipsis(0, this.end - 1);
      this.onResult();
    } else if (this.end >= this.textLength) {
      this.container.innerHTML = this.currentText;
      this.onResult();
    } else {
      this.container.innerHTML = this.getTextWithEllipsis(this.start, ++this.end);
      this.truncate();
    }
  }

  process() {
    if (this.isSupportNativeClamp) {
      const sty = this.container.style;
      sty.overflow = 'hidden';
      sty.textOverflow = 'ellipsis';
      sty.webkitBoxOrient = 'vertical';
      sty.display = '-webkit-box';
      sty.webkitLineClamp = this.props.lines;

      this.container.innerHTML = this.text;
      this.onResult();
    } else {
      this.textLength = this.text.length;
      this.currentText = '';
      this.start = 0;
      this.end = this.text.length > 0 ? 1 : 0;
      this.lineHeight = this.getLineHeight();
      this.container.innerHTML = '';

      this.truncate();
    }
  }

  computedStyle(name) {
    return document.defaultView.getComputedStyle(this.container, null).getPropertyValue(name);
  }

  render() {
    return (
      React.createElement(this.props.tag, {
          ref: (node) => {
            this.container = node;
          },
          className: this.props.tagClass,
          style: Object.assign({ width: '100%', wordWrap: 'break-word' }, this.props.style),
        },
        this.props.children,
      )
    );
  }
}

TextEllipsis.RESULT = {
  TRUNCATED: "TRUNCATED",
  NOT_TRUNCATED: "NOT_TRUNCATED",
};

TextEllipsis.propTypes = {
  lines: PropTypes.number.isRequired,
  children: PropTypes.element.isRequired,
  tag: PropTypes.string,
  ellipsisChars: PropTypes.string,
  tagClass: PropTypes.string,
  debounceTimeoutOnResize: PropTypes.number,
  useJsOnly: PropTypes.bool,
  onResult: PropTypes.func,
  style: PropTypes.shape,
};

TextEllipsis.defaultProps = {
  tag: 'div',
  ellipsisChars: '...',
  tagClass: '',
  debounceTimeoutOnResize: 200,
  useJsOnly: false,
  style: {},
  onResult: () => {},
};

export default TextEllipsis;
<commit_msg>bug fix: react complains about PropTypes.shape<commit_after>import * as React from 'react';
import { debounce } from 'lodash';
import PropTypes from 'prop-types';

class TextEllipsis extends React.Component {
  constructor(props) {
    super(props);

    this.isSupportNativeClamp = this.props.useJsOnly ? false : 'webkitLineClamp' in document.body.style;
    this.truncate = this.truncate.bind(this);
    this.debounceProcess = debounce(this.process, this.props.debounceTimeoutOnResize);
  }

  componentDidMount() {
    this.text = this.container.innerHTML;
    this.process();

    window.addEventListener('resize', this.debounceProcess, false);
  }

  componentDidUpdate() {
    this.text = this.container.innerHTML;
    this.process();
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.debounceProcess, false);
  }

  onResult() {
    if (this.container.scrollWidth > this.container.clientWidth || this.container.scrollHeight > this.container.clientHeight) {
      this.props.onResult(TextEllipsis.RESULT.TRUNCATED);
    } else {
      this.props.onResult(TextEllipsis.RESULT.NOT_TRUNCATED);
    }
  }

  getLineHeight() {
    const lineHeight = this.computedStyle("line-height");

    if (lineHeight === 'normal') {
      // Normal line heights vary from browser to browser. The spec recommends
      // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
      return Math.ceil(parseFloat(this.computedStyle('font-size')) * 1.2);
    }
    return Math.ceil(parseFloat(lineHeight));
  }

  getTextWithEllipsis(start, end) {
    this.currentText = this.text.slice(start, end);
    return this.currentText + this.props.ellipsisChars;
  }

  truncate() {
    if (this.container.offsetHeight > this.lineHeight * this.props.lines) {
      this.container.innerHTML = this.getTextWithEllipsis(0, this.end - 1);
      this.onResult();
    } else if (this.end >= this.textLength) {
      this.container.innerHTML = this.currentText;
      this.onResult();
    } else {
      this.container.innerHTML = this.getTextWithEllipsis(this.start, ++this.end);
      this.truncate();
    }
  }

  process() {
    if (this.isSupportNativeClamp) {
      const sty = this.container.style;
      sty.overflow = 'hidden';
      sty.textOverflow = 'ellipsis';
      sty.webkitBoxOrient = 'vertical';
      sty.display = '-webkit-box';
      sty.webkitLineClamp = this.props.lines;

      this.container.innerHTML = this.text;
      this.onResult();
    } else {
      this.textLength = this.text.length;
      this.currentText = '';
      this.start = 0;
      this.end = this.text.length > 0 ? 1 : 0;
      this.lineHeight = this.getLineHeight();
      this.container.innerHTML = '';

      this.truncate();
    }
  }

  computedStyle(name) {
    return document.defaultView.getComputedStyle(this.container, null).getPropertyValue(name);
  }

  render() {
    return (
      React.createElement(this.props.tag, {
          ref: (node) => {
            this.container = node;
          },
          className: this.props.tagClass,
          style: Object.assign({ width: '100%', wordWrap: 'break-word' }, this.props.style),
        },
        this.props.children,
      )
    );
  }
}

TextEllipsis.RESULT = {
  TRUNCATED: "TRUNCATED",
  NOT_TRUNCATED: "NOT_TRUNCATED",
};

TextEllipsis.propTypes = {
  lines: PropTypes.number.isRequired,
  children: PropTypes.element.isRequired,
  tag: PropTypes.string,
  ellipsisChars: PropTypes.string,
  tagClass: PropTypes.string,
  debounceTimeoutOnResize: PropTypes.number,
  useJsOnly: PropTypes.bool,
  onResult: PropTypes.func,
  style: PropTypes.object,
};

TextEllipsis.defaultProps = {
  tag: 'div',
  ellipsisChars: '...',
  tagClass: '',
  debounceTimeoutOnResize: 200,
  useJsOnly: false,
  style: {},
  onResult: () => {},
};

export default TextEllipsis;
<|endoftext|>