<commit_before>/*
 * Jake JavaScript build tool
 * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

let fs = require('fs');
let parseargs = require('./parseargs');
let utils = require('./utils');
let Program;
let optsReg;
let preempts;
let usage;
let die;

optsReg = [
  { full: 'jakefile',
   abbr: 'f',
   preempts: false,
   expectValue: true
  }
, { full: 'quiet',
   abbr: 'q',
   preempts: false,
   expectValue: false
  }
, { full: 'directory',
   abbr: 'C',
   preempts: false,
   expectValue: true
  }
, { full: 'always-make',
   abbr: 'B',
   preempts: false,
   expectValue: false
  }
, { full: 'tasks',
    abbr: 'T',
    preempts: false,
    expectValue: false,
    allowValue: true
  }
// Alias ls
, { full: 'tasks',
    abbr: 'T',
    preempts: false,
    expectValue: false,
    allowValue: true
  }
, { full: 'trace',
   abbr: 't',
   preempts: false,
   expectValue: false
  }
, { full: 'help',
   abbr: 'h',
   preempts: true
  }
, { full: 'version',
   abbr: 'V',
   preempts: true
  }
  // Alias lowercase v
, { full: 'version',
   abbr: 'v',
   preempts: true
  }
, { full: 'jakelibdir',
   abbr: 'J',
   preempts: false,
   expectValue: true
  }
, { full: 'allow-rejection',
   abbr: 'ar',
   preempts: false,
   expectValue: false
  }
];

preempts = {
  version: function () {
    die(jake.version);
  },
 help: function () {
    die(usage);
  }
};

usage = ''
    + 'Jake JavaScript build tool\n'
    + '********************************************************************************\n'
    + 'If no flags are given, Jake looks for a Jakefile or Jakefile.js in the current directory.\n'
    + '********************************************************************************\n'
    + '{Usage}: jake [options ...] [env variables ...] target\n'
    + '\n'
    + '{Options}:\n'
    + '  -f,     --jakefile FILE            Use FILE as the Jakefile.\n'
    + '  -C,     --directory DIRECTORY      Change to DIRECTORY before running tasks.\n'
    + '  -q,     --quiet                    Do not log messages to standard output.\n'
    + '  -B,     --always-make              Unconditionally make all targets.\n'
    + '  -T/ls,  --tasks                 Display the tasks (matching optional PATTERN) with descriptions, then exit.\n'
    + '  -J,     --jakelibdir JAKELIBDIR    Auto-import any .jake files in JAKELIBDIR. (default is \'jakelib\')\n'
    + '  -t,     --trace                    Enable full backtrace.\n'
    + '  -h,     --help                     Display this help message.\n'
    + '  -V/v,   --version                  Display the Jake version.\n'
    + '  -ar,    --allow-rejection          Keep running even after unhandled promise rejection\n'
    + '';

Program = function () {
  this.opts = {};
  this.taskNames = null;
  this.taskArgs = null;
  this.envVars = null;
};

Program.prototype = new (function () {

  this.handleErr = function (err) {
    if (jake.listeners('error').length !== 0) {
      jake.emit('error', err);
      return;
    }

    let msg;

    if (jake.listeners('error').length) {
      jake.emit('error', err);
      return;
    }

    utils.logger.error('jake aborted.');
    if (this.opts.trace && err.stack) {
      utils.logger.error(err.stack);
    }
    else {
      if (err.stack) {
        msg = err.stack.split('\n').slice(0, 3).join('\n');
        utils.logger.error(msg);
        utils.logger.error('(See full trace by running task with --trace)');
      }
      else {
        utils.logger.error(err.message);
      }
    }
    process.stdout.write('', function () {
      process.stderr.write('', function () {
        jake.errorCode = jake.errorCode || 1;
        process.exit(jake.errorCode);
      });
    });
  };

  this.parseArgs = function (args) {
    let result = (new parseargs.Parser(optsReg)).parse(args);
    this.setOpts(result.opts);
    this.setTaskNames(result.taskNames);
    this.setEnvVars(result.envVars);
  };

  this.setOpts = function (options) {
    let opts = options || {};
    utils.mixin(this.opts, opts);
  };

  this.internalOpts = function (options) {
    optsReg = optsReg.concat(options);
  };

  this.autocompletions = function (cur) {
    let p; let i; let task;
    let commonPrefix = '';
    let matches = [];

    for (p in jake.Task) {
      task = jake.Task[p];
      if (
        'fullName' in task
          && (
            // if empty string, program converts to true
            cur === true ||
            task.fullName.indexOf(cur) === 0
          )
      ) {
        if (matches.length === 0) {
          commonPrefix = task.fullName;
        }
        else {
          for (i = commonPrefix.length; i > -1; --i) {
            commonPrefix = commonPrefix.substr(0, i);
            if (task.fullName.indexOf(commonPrefix) === 0) {
              break;
            }
          }
        }
        matches.push(task.fullName);
      }
    }

    if (matches.length > 1 && commonPrefix === cur) {
      matches.unshift('yes-space');
    }
    else {
      matches.unshift('no-space');
    }

    process.stdout.write(matches.join(' '));
  };

  this.setTaskNames = function (names) {
    if (names && !Array.isArray(names)) {
      throw new Error('Task names must be an array');
    }
    this.taskNames = (names && names.length) ? names : ['default'];
  };

  this.setEnvVars = function (vars) {
    this.envVars = vars || null;
  };

  this.firstPreemptiveOption = function () {
    let opts = this.opts;
    for (let p in opts) {
      if (preempts[p]) {
        return preempts[p];
      }
    }
    return false;
  };

  this.init = function (configuration) {
    let self = this;
       let config = configuration || {};
    if (config.options) {
      this.setOpts(config.options);
    }
    if (config.taskNames) {
      this.setTaskNames(config.taskNames);
    }
    if (config.envVars) {
      this.setEnvVars(config.envVars);
    }
    process.addListener('uncaughtException', function (err) {
      self.handleErr(err);
    });
    if (!this.opts['allow-rejection']) {
      process.addListener('unhandledRejection', (reason, promise) => {
        console.error('Unhandled rejection at:', promise, 'reason:', reason);
        self.program.handleErr(reason);
      });
    }
    if (this.envVars) {
      utils.mixin(process.env, this.envVars);
    }
  };

  this.run = function () {
    let rootTask;
    let taskNames;
    let dirname;
    let opts = this.opts;

    if (opts.autocomplete) {
      return this.autocompletions(opts['autocomplete-cur'], opts['autocomplete-prev']);
    }
    // Run with `jake -T`, just show descriptions
    if (opts.tasks) {
      return jake.showAllTaskDescriptions(opts.tasks);
    }

    taskNames = this.taskNames;
    if (!(Array.isArray(taskNames) && taskNames.length)) {
      throw new Error('Please pass jake.runTasks an array of task-names');
    }

    // Set working dir
    dirname = opts.directory;
    if (dirname) {
      if (utils.file.existsSync(dirname) &&
        fs.statSync(dirname).isDirectory()) {
        process.chdir(dirname);
      }
      else {
        throw new Error(dirname + ' is not a valid directory path');
      }
    }

    rootTask = task('__root__', taskNames, function () {});
    rootTask._internal = true;

    rootTask.once('complete', function () {
      jake.emit('complete');
    });
    jake.emit('start');
    rootTask.invoke();
  };

})();

die = function (msg) {
  console.log(msg);
  process.stdout.write('', function () {
    process.stderr.write('', function () {
      process.exit();
	});
  });
};

module.exports.Program = Program;
<commit_msg>Fix -ls alias, add -t alias for task list, change trace to -s<commit_after>/*
 * Jake JavaScript build tool
 * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

let fs = require('fs');
let parseargs = require('./parseargs');
let utils = require('./utils');
let Program;
let optsReg;
let preempts;
let usage;
let die;

optsReg = [
  { full: 'jakefile',
   abbr: 'f',
   preempts: false,
   expectValue: true
  }
, { full: 'quiet',
   abbr: 'q',
   preempts: false,
   expectValue: false
  }
, { full: 'directory',
   abbr: 'C',
   preempts: false,
   expectValue: true
  }
, { full: 'always-make',
   abbr: 'B',
   preempts: false,
   expectValue: false
  }
, { full: 'tasks',
    abbr: 'T',
    preempts: false,
    expectValue: false,
    allowValue: true
  }
// Alias t
, { full: 'tasks',
    abbr: 't',
    preempts: false,
    expectValue: false,
    allowValue: true
  }
// Alias ls
, { full: 'tasks',
    abbr: 'ls',
    preempts: false,
    expectValue: false,
    allowValue: true
  }
, { full: 'trace',
   abbr: 's',
   preempts: false,
   expectValue: false
  }
, { full: 'help',
   abbr: 'h',
   preempts: true
  }
, { full: 'version',
   abbr: 'V',
   preempts: true
  }
  // Alias lowercase v
, { full: 'version',
   abbr: 'v',
   preempts: true
  }
, { full: 'jakelibdir',
   abbr: 'J',
   preempts: false,
   expectValue: true
  }
, { full: 'allow-rejection',
   abbr: 'ar',
   preempts: false,
   expectValue: false
  }
];

preempts = {
  version: function () {
    die(jake.version);
  },
 help: function () {
    die(usage);
  }
};

usage = ''
    + 'Jake JavaScript build tool\n'
    + '********************************************************************************\n'
    + 'If no flags are given, Jake looks for a Jakefile or Jakefile.js in the current directory.\n'
    + '********************************************************************************\n'
    + '{Usage}: jake [options ...] [env variables ...] target\n'
    + '\n'
    + '{Options}:\n'
    + '  -f,     --jakefile FILE            Use FILE as the Jakefile.\n'
    + '  -C,     --directory DIRECTORY      Change to DIRECTORY before running tasks.\n'
    + '  -q,     --quiet                    Do not log messages to standard output.\n'
    + '  -B,     --always-make              Unconditionally make all targets.\n'
    + '  -T/ls,  --tasks                 Display the tasks (matching optional PATTERN) with descriptions, then exit.\n'
    + '  -J,     --jakelibdir JAKELIBDIR    Auto-import any .jake files in JAKELIBDIR. (default is \'jakelib\')\n'
    + '  -t,     --trace                    Enable full backtrace.\n'
    + '  -h,     --help                     Display this help message.\n'
    + '  -V/v,   --version                  Display the Jake version.\n'
    + '  -ar,    --allow-rejection          Keep running even after unhandled promise rejection\n'
    + '';

Program = function () {
  this.opts = {};
  this.taskNames = null;
  this.taskArgs = null;
  this.envVars = null;
};

Program.prototype = new (function () {

  this.handleErr = function (err) {
    if (jake.listeners('error').length !== 0) {
      jake.emit('error', err);
      return;
    }

    let msg;

    if (jake.listeners('error').length) {
      jake.emit('error', err);
      return;
    }

    utils.logger.error('jake aborted.');
    if (this.opts.trace && err.stack) {
      utils.logger.error(err.stack);
    }
    else {
      if (err.stack) {
        msg = err.stack.split('\n').slice(0, 3).join('\n');
        utils.logger.error(msg);
        utils.logger.error('(See full trace by running task with --trace)');
      }
      else {
        utils.logger.error(err.message);
      }
    }
    process.stdout.write('', function () {
      process.stderr.write('', function () {
        jake.errorCode = jake.errorCode || 1;
        process.exit(jake.errorCode);
      });
    });
  };

  this.parseArgs = function (args) {
    let result = (new parseargs.Parser(optsReg)).parse(args);
    this.setOpts(result.opts);
    this.setTaskNames(result.taskNames);
    this.setEnvVars(result.envVars);
  };

  this.setOpts = function (options) {
    let opts = options || {};
    utils.mixin(this.opts, opts);
  };

  this.internalOpts = function (options) {
    optsReg = optsReg.concat(options);
  };

  this.autocompletions = function (cur) {
    let p; let i; let task;
    let commonPrefix = '';
    let matches = [];

    for (p in jake.Task) {
      task = jake.Task[p];
      if (
        'fullName' in task
          && (
            // if empty string, program converts to true
            cur === true ||
            task.fullName.indexOf(cur) === 0
          )
      ) {
        if (matches.length === 0) {
          commonPrefix = task.fullName;
        }
        else {
          for (i = commonPrefix.length; i > -1; --i) {
            commonPrefix = commonPrefix.substr(0, i);
            if (task.fullName.indexOf(commonPrefix) === 0) {
              break;
            }
          }
        }
        matches.push(task.fullName);
      }
    }

    if (matches.length > 1 && commonPrefix === cur) {
      matches.unshift('yes-space');
    }
    else {
      matches.unshift('no-space');
    }

    process.stdout.write(matches.join(' '));
  };

  this.setTaskNames = function (names) {
    if (names && !Array.isArray(names)) {
      throw new Error('Task names must be an array');
    }
    this.taskNames = (names && names.length) ? names : ['default'];
  };

  this.setEnvVars = function (vars) {
    this.envVars = vars || null;
  };

  this.firstPreemptiveOption = function () {
    let opts = this.opts;
    for (let p in opts) {
      if (preempts[p]) {
        return preempts[p];
      }
    }
    return false;
  };

  this.init = function (configuration) {
    let self = this;
       let config = configuration || {};
    if (config.options) {
      this.setOpts(config.options);
    }
    if (config.taskNames) {
      this.setTaskNames(config.taskNames);
    }
    if (config.envVars) {
      this.setEnvVars(config.envVars);
    }
    process.addListener('uncaughtException', function (err) {
      self.handleErr(err);
    });
    if (!this.opts['allow-rejection']) {
      process.addListener('unhandledRejection', (reason, promise) => {
        console.error('Unhandled rejection at:', promise, 'reason:', reason);
        self.program.handleErr(reason);
      });
    }
    if (this.envVars) {
      utils.mixin(process.env, this.envVars);
    }
  };

  this.run = function () {
    let rootTask;
    let taskNames;
    let dirname;
    let opts = this.opts;

    if (opts.autocomplete) {
      return this.autocompletions(opts['autocomplete-cur'], opts['autocomplete-prev']);
    }
    // Run with `jake -T`, just show descriptions
    if (opts.tasks) {
      return jake.showAllTaskDescriptions(opts.tasks);
    }

    taskNames = this.taskNames;
    if (!(Array.isArray(taskNames) && taskNames.length)) {
      throw new Error('Please pass jake.runTasks an array of task-names');
    }

    // Set working dir
    dirname = opts.directory;
    if (dirname) {
      if (utils.file.existsSync(dirname) &&
        fs.statSync(dirname).isDirectory()) {
        process.chdir(dirname);
      }
      else {
        throw new Error(dirname + ' is not a valid directory path');
      }
    }

    rootTask = task('__root__', taskNames, function () {});
    rootTask._internal = true;

    rootTask.once('complete', function () {
      jake.emit('complete');
    });
    jake.emit('start');
    rootTask.invoke();
  };

})();

die = function (msg) {
  console.log(msg);
  process.stdout.write('', function () {
    process.stderr.write('', function () {
      process.exit();
	});
  });
};

module.exports.Program = Program;
<|endoftext|>


<commit_before>'use strict'

const getEventData = require('./modules/get-event-data')
const uniqueRandomArray = require('unique-random-array')

function chooseAWinner (confirmedMembersList) {
  return new Promise((resolve, reject) => {
    const winner = uniqueRandomArray(confirmedMembersList)()

    resolve(winner)
  })
}

function excludeNonConfirmedMembers (membersList) {
  return new Promise((resolve, reject) => {
    const confirmedMembersList = membersList.reduce(
      (previous, current) => {
        if (current.response === 'yes') {
          let photoURL

          if (current.member.photo && current.member.photo.highres_link) {
            photoURL = current.member.photo.highres_link
          }

          previous.push({
            name: current.member.name,
            photoURL,
            profileURL: `http://www.meetup.com/${current.group.urlname}/members/${current.member.id}`
          })
        }

        return previous
      },
      []
    )

    resolve(confirmedMembersList)
  })
}

module.exports = function program (meetupName, eventId) {
  return getEventData(meetupName, eventId)
    .then(excludeNonConfirmedMembers)
    .then(chooseAWinner)
}
<commit_msg>feat(program): Exclude host members from the available people to perform the draw<commit_after>'use strict'

const getEventData = require('./modules/get-event-data')
const uniqueRandomArray = require('unique-random-array')

function chooseAWinner (confirmedMembersList) {
  return new Promise((resolve, reject) => {
    const winner = uniqueRandomArray(confirmedMembersList)()

    resolve(winner)
  })
}

function excludeHosts (membersList) {
  return new Promise((resolve, reject) => {
    const membersListWithoutHosts = membersList.filter(m => !m.member.event_context.host)

    resolve(membersListWithoutHosts)
  })
}

function excludeNonConfirmedMembers (membersListWithoutHosts) {
  return new Promise((resolve, reject) => {
    const confirmedMembersList = membersListWithoutHosts.reduce(
      (previous, current) => {
        if (current.response === 'yes') {
          let photoURL

          if (current.member.photo && current.member.photo.highres_link) {
            photoURL = current.member.photo.highres_link
          }

          previous.push({
            name: current.member.name,
            photoURL,
            profileURL: `http://www.meetup.com/${current.group.urlname}/members/${current.member.id}`
          })
        }

        return previous
      },
      []
    )

    resolve(confirmedMembersList)
  })
}

module.exports = function program (meetupName, eventId) {
  return getEventData(meetupName, eventId)
    .then(excludeHosts)
    .then(excludeNonConfirmedMembers)
    .then(chooseAWinner)
}
<|endoftext|>


<commit_before>'use strict';

var minimist = require('minimist');
var HJSON = require('hjson');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');

var opt = function(name, desc, parser) { return {'name':name, 'desc':desc, 'parser':parser};};

var parseHson = function(input) {
  try {
    return HJSON.parse(input);
  } catch (e) {
    throw new Error('Failed to parse option \''+this.name+'\': ' + e.message);
  }
};

var options = [
  opt('query',          'standard Mongo query object (json), to filter the set of documents required before analysis', parseHson),
  opt('sort',           'analyze documents in the specified order, takes Mongo sort object (json)', parseHson),
  opt('maxDepth',       'limit the <n> depth Variety will recursively search to find new objects', parseInt),
  opt('limit',          'analyze only the <n> newest documents in a collection', parseInt),
  opt('outputFormat',   'output format of results, possible variants are "ascii" or "json", default is "ascii"', String),
  opt('persistResults', 'save results in MongoDB for future use, default is "false".', function(val) {return val == 'true';}),
  opt('slaveOk',        'allow queries on slave instances, default is "false".', function(val) {return val == 'true';}),
  opt('plugins',        'comma separated list of paths to the variety plugins (see examples below).', String),
  opt('help',           'returns information on the options and use of variety CLI', _.identity)
];

var parsedOpts = function(options, args) {
  return Object
    .keys(args)
    .map(function(key) {
      var def = _.find(options, function(opt){return opt.name === key;});
      return {'name':key, 'value':args[key], 'def': def};
    });
};

var parseVarietyArgs = function(options, args) {
  return parsedOpts(options, args)
    .filter(function(opt){return opt.def;})
    .map(function(opt){opt.value = opt.def.parser(opt.value); return opt;})
    .reduce(function(acc, val){
      acc[val.name] = val.value;
      return acc;
    }, {});
};

var parseMongoArgs = function(options, args) {
  var unknownOpts = parsedOpts(options, args).filter(function(opt){return !opt.def && opt.name != '_';});
  var accumulate = function(acc, opt) {
    if(opt.name.length > 1) {
      acc.push('--' + opt.name);
    } else {
      acc.push('-' + opt.name);
    }
    if(typeof opt.value !== 'boolean') {
      acc.push(opt.value);
    }
    return acc;
  };
  return _.reduce(unknownOpts, accumulate, []);
};

var parseDbCollection = function(args) {
  var db = null;
  var collection = null;
  if(args._.length > 0 && args._[0].split('/').length == 2) {
    db = args._[0].split('/')[0];
    collection = args._[0].split('/')[1];
  }
  return {'db':db, 'collection':collection};
};

var parse = function(argv) {
  var args = minimist(argv.slice(2));
  var ids = parseDbCollection(args);
  return {
    'db':ids.db,
    'collection':ids.collection,
    'params':parseVarietyArgs(options, args),
    'shellParams': parseMongoArgs(options, args)
  };
};

var help = function() {
  var maxOptionLength = _.max(options.map(function(opt){return opt.name.length;}));
  var optsDesc = options
    .map(function(option) {return '  --' + _.padEnd(option.name, maxOptionLength) + '  ' + option.desc;})
    .join('\n');

  var buf = fs.readFileSync(path.join(__dirname, 'MANPAGE.txt'), 'utf8');
  return buf.replace('{OPTIONS}', optsDesc);
};

module.exports = {
  'parse': parse,
  'help':help
};
<commit_msg>Add support for connection strings. (#16)<commit_after>'use strict';

var minimist = require('minimist');
var HJSON = require('hjson');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');

var opt = function(name, desc, parser) { return {'name':name, 'desc':desc, 'parser':parser};};

var parseHson = function(input) {
  try {
    return HJSON.parse(input);
  } catch (e) {
    throw new Error('Failed to parse option \''+this.name+'\': ' + e.message);
  }
};

var options = [
  opt('query',          'standard Mongo query object (json), to filter the set of documents required before analysis', parseHson),
  opt('sort',           'analyze documents in the specified order, takes Mongo sort object (json)', parseHson),
  opt('maxDepth',       'limit the <n> depth Variety will recursively search to find new objects', parseInt),
  opt('limit',          'analyze only the <n> newest documents in a collection', parseInt),
  opt('outputFormat',   'output format of results, possible variants are "ascii" or "json", default is "ascii"', String),
  opt('persistResults', 'save results in MongoDB for future use, default is "false".', function(val) {return val == 'true';}),
  opt('slaveOk',        'allow queries on slave instances, default is "false".', function(val) {return val == 'true';}),
  opt('plugins',        'comma separated list of paths to the variety plugins (see examples below).', String),
  opt('help',           'returns information on the options and use of variety CLI', _.identity)
];

var parsedOpts = function(options, args) {
  return Object
    .keys(args)
    .map(function(key) {
      var def = _.find(options, function(opt){return opt.name === key;});
      return {'name':key, 'value':args[key], 'def': def};
    });
};

var parseVarietyArgs = function(options, args) {
  return parsedOpts(options, args)
    .filter(function(opt){return opt.def;})
    .map(function(opt){opt.value = opt.def.parser(opt.value); return opt;})
    .reduce(function(acc, val){
      acc[val.name] = val.value;
      return acc;
    }, {});
};

var parseMongoArgs = function(options, args) {
  var unknownOpts = parsedOpts(options, args).filter(function(opt){return !opt.def && opt.name != '_';});
  var accumulate = function(acc, opt) {
    if(opt.name.length > 1) {
      acc.push('--' + opt.name);
    } else {
      acc.push('-' + opt.name);
    }
    if(typeof opt.value !== 'boolean') {
      acc.push(opt.value);
    }
    return acc;
  };
  return _.reduce(unknownOpts, accumulate, []);
};

var parseDbCollection = function(args) {
  var db = null;
  var collection = null;
  if(args._.length > 0) {
    var split = args._[0].split('/');

    db = split.slice(0, split.length - 1).join('/');
    collection = split[split.length - 1];
  }
  return {'db':db, 'collection':collection};
};

var parse = function(argv) {
  var args = minimist(argv.slice(2));
  var ids = parseDbCollection(args);
  return {
    'db':ids.db,
    'collection':ids.collection,
    'params':parseVarietyArgs(options, args),
    'shellParams': parseMongoArgs(options, args)
  };
};

var help = function() {
  var maxOptionLength = _.max(options.map(function(opt){return opt.name.length;}));
  var optsDesc = options
    .map(function(option) {return '  --' + _.padEnd(option.name, maxOptionLength) + '  ' + option.desc;})
    .join('\n');

  var buf = fs.readFileSync(path.join(__dirname, 'MANPAGE.txt'), 'utf8');
  return buf.replace('{OPTIONS}', optsDesc);
};

module.exports = {
  'parse': parse,
  'help':help
};
<|endoftext|>


<commit_before>/*
 *  promise.js
 *
 *  David Janes
 *  IOTDB.org
 *  2017-02-15
 *
 *  Copyright [2013-2017] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

const Q = require("bluebird-q");
const async = require("async");

const assert = require("assert");

/**
 *  If the promise throws an error, it will be ignored
 */
const optional = (promise) => {
    const _optional = (self, done) => {
        Q(self)
            .then(promise)
            .then(sd => done(null, sd))
            .catch(error => done(null, self))
    };

    return Q.denodeify(_optional);
}

/**
 *  Condtionally chose something to run
 */
const conditional = (test, if_true, if_false) => {
    const _conditional = (self, done) => {
        let f = () => done(null, self);

        if (test(self)) {
            if (if_true) {
                f = if_true;
            }
        } else {
            if (if_false) {
                f = if_false;
            }
        }

        Q(self)
            .then(f)
            .then(sd => done(null, sd))
            .catch(error => done(error))
    }

    return Q.denodeify(_conditional)
}

/**
 *  Run the block of code, making sure that
 *  self becomes immutable and that exceptions
 *  are properly trapped
 *
 *  .then(_.promise.block(sd => { [some code]  }))
 */
const block = f => Q.denodeify((_self, done) => {
    const self = Object.assign({}, _self);

    f(self)

    done(null, self);
})

/**
 */
const ops_series = (_self, done) => {
    const self = Object.assign({}, _self);

    assert.ok(self.ops, "_.promise.ops_series: self.ops is required");

    async.series(self.ops, (error, results) => {
        if (error) {
            return done(error);
        }

        self.results = results; // phase out "results" in favor of "outputs"
        self.outputs = results;

        done(null, self);
    })
}

/**
 *  This will take each object in `self.inputs`,
 *  pull a value out of the input using `select.pre_selector`
 *  (typically) a string and then run the promise
 *  or function `f` on it
 */
const each = (_self, pre_selector, f, post_selector) => {
    const _ = {
        d: require("./d").d,
        is: require("./is").is,
    }
    const self = _.d.clone.shallow(_self)

    return new Promise((resolve, reject) => {
        const ops = self.inputs.map(item => inner_done => {
            Q(self)
                // .then(sd => _.d.add(sd, pre_selector, item))
                .then(sd => {
                    if (_.is.String(pre_selector)) {
                        sd[pre_selector] = item;
                    } else if (_.is.Function(pre_selector)) {
                        sd = Object.assign({}, sd, pre_selector(item))
                    }

                    return sd;
                })
                .then(f)
                .then(sd => {
                    if (_.is.String(post_selector)) {
                        inner_done(null, sd[post_selector])
                    } else if (_.is.Function(post_selector)) {
                        inner_done(null, post_selector(sd))
                    } else {
                        inner_done(null, sd)
                    }
                    return null;
                })
                .catch(inner_done)
        })

        async.series(ops, (error, outputs) => {
            if (error) {
                return reject(error)
                // return done(error);
            }

            self.outputs = outputs;

            // done(null, self);
            return resolve(self)
        })
    })

}

/**
 *  Wait delay seconds. If not set, 1 second.
 */
const delay = (_self, done) => {
    const self = Object.assign({}, _self);

    setTimeout(() => done(null, self), self.delay ? self.delay * 1000 : 1000)
}

/**
 *  Print the message and continue
 */
const log = (...rest) => sd => { console.log(...rest); return sd }
const timestamp = (...rest) => sd => { console.log((new Date()).toISOString(), ...rest); return sd }

/**
 *  Print the message AND the current _self and continue
 */
const spy = (...rest) => sd => { console.log(...rest, sd); return sd }

exports.promise = {
    optional: optional,
    conditional: conditional,
    block: block,
    each: each,
    ops: {
        clear: sd => { sd.ops = []; return sd },
        series: Q.denodeify(ops_series),
    },
    log: log,
    timestamp: timestamp,
    spy: spy,
    delay: Q.denodeify(delay),
    denodeify: Q.denodeify,
    make: Q,
};
<commit_msg>parameterized delay<commit_after>/*
 *  promise.js
 *
 *  David Janes
 *  IOTDB.org
 *  2017-02-15
 *
 *  Copyright [2013-2017] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

const Q = require("bluebird-q");
const async = require("async");

const assert = require("assert");

/**
 *  If the promise throws an error, it will be ignored
 */
const optional = (promise) => {
    const _optional = (self, done) => {
        Q(self)
            .then(promise)
            .then(sd => done(null, sd))
            .catch(error => done(null, self))
    };

    return Q.denodeify(_optional);
}

/**
 *  Condtionally chose something to run
 */
const conditional = (test, if_true, if_false) => {
    const _conditional = (self, done) => {
        let f = () => done(null, self);

        if (test(self)) {
            if (if_true) {
                f = if_true;
            }
        } else {
            if (if_false) {
                f = if_false;
            }
        }

        Q(self)
            .then(f)
            .then(sd => done(null, sd))
            .catch(error => done(error))
    }

    return Q.denodeify(_conditional)
}

/**
 *  Run the block of code, making sure that
 *  self becomes immutable and that exceptions
 *  are properly trapped
 *
 *  .then(_.promise.block(sd => { [some code]  }))
 */
const block = f => Q.denodeify((_self, done) => {
    const self = Object.assign({}, _self);

    f(self)

    done(null, self);
})

/**
 */
const ops_series = (_self, done) => {
    const self = Object.assign({}, _self);

    assert.ok(self.ops, "_.promise.ops_series: self.ops is required");

    async.series(self.ops, (error, results) => {
        if (error) {
            return done(error);
        }

        self.results = results; // phase out "results" in favor of "outputs"
        self.outputs = results;

        done(null, self);
    })
}

/**
 *  This will take each object in `self.inputs`,
 *  pull a value out of the input using `select.pre_selector`
 *  (typically) a string and then run the promise
 *  or function `f` on it
 */
const each = (_self, pre_selector, f, post_selector) => {
    const _ = {
        d: require("./d").d,
        is: require("./is").is,
    }
    const self = _.d.clone.shallow(_self)

    return new Promise((resolve, reject) => {
        const ops = self.inputs.map(item => inner_done => {
            Q(self)
                // .then(sd => _.d.add(sd, pre_selector, item))
                .then(sd => {
                    if (_.is.String(pre_selector)) {
                        sd[pre_selector] = item;
                    } else if (_.is.Function(pre_selector)) {
                        sd = Object.assign({}, sd, pre_selector(item))
                    }

                    return sd;
                })
                .then(f)
                .then(sd => {
                    if (_.is.String(post_selector)) {
                        inner_done(null, sd[post_selector])
                    } else if (_.is.Function(post_selector)) {
                        inner_done(null, post_selector(sd))
                    } else {
                        inner_done(null, sd)
                    }
                    return null;
                })
                .catch(inner_done)
        })

        async.series(ops, (error, outputs) => {
            if (error) {
                return reject(error)
                // return done(error);
            }

            self.outputs = outputs;

            // done(null, self);
            return resolve(self)
        })
    })

}

/**
 *  Wait delay seconds. If not set, 1 second.
 */
const delay = (_self, done) => {
    const self = Object.assign({}, _self);

    setTimeout(() => done(null, self), self.delay ? self.delay * 1000 : 1000)
}

const delay_p = delay => Q.denodeify((_self, done) => setTimeout(() => done(null, _self), (delay || 1) * 1000));

/**
 *  Print the message and continue
 */
const log = (...rest) => sd => { console.log(...rest); return sd }
const timestamp = (...rest) => sd => { console.log((new Date()).toISOString(), ...rest); return sd }

/**
 *  Print the message AND the current _self and continue
 */
const spy = (...rest) => sd => { console.log(...rest, sd); return sd }

exports.promise = {
    optional: optional,
    conditional: conditional,
    block: block,
    each: each,
    ops: {
        clear: sd => { sd.ops = []; return sd },
        series: Q.denodeify(ops_series),
    },
    log: log,
    timestamp: timestamp,
    spy: spy,
    delay: Q.denodeify(delay),
    denodeify: Q.denodeify,
    make: Q,
};

exports.promise.delay.p = delay_p;
<|endoftext|>


<commit_before>var rateLimit = require('./ratelimit');
var deepEquals = require('deep-is');
var arraydiff = require('arraydiff');
var projections = require('./projections');

module.exports = function(Livedb) {

  Livedb.prototype._sdcDbPrefix = function(options) {
    return 'livedb.db.' + ((options && options.backend) ? options.backend : 'default');
  };

  function projectResults(results, cName, projection) {
    if (!projection) return;
    var r = results.results ? results.results : results;
    for (var i = 0; i < r.length; i++) {
      var r = r[i];
      r.data = projections.projectSnapshot(r.type, projection.fields, r.data);
    }
  }

  Livedb.prototype._dbQuery = function(db, index, query, options, callback) {
    var projection = this.projections[index];

    if (projection) {
      if (db.queryProjected)
        db.queryProjected(this, projection.target, projection.fields, query, options, callback);
      else {
        db.query(this, projection.target, query, options, function(err, results) {
          if (results) projectResults(results, index, projection);
          callback(err, results);
        });
      }
    } else {
      db.query(this, index, query, options, callback);
    }
  };

  Livedb.prototype._dbQueryDoc = function(db, index, docName, query, callback) {
    var projection = this.projections[index];
    if (projection) {
      if (db.queryDocProjected) // What a mouthful!
        db.queryDocProjected(this, index, projection.target, docName, projection.fields, query, callback);
      else {
        db.queryDoc(this, index, projection.target, docName, query, function(err, result) {
          if (result) {
            result.data = projections.projectSnapshot(result.type, projection.fields, result.data);
          }
          callback(err, result);
        });
      }
    } else {
      db.queryDoc(this, index, index, docName, query, callback);
    }
  };

  Livedb.prototype.queryFetch = function(index, query, options, callback) {
    if (typeof options === 'function') {
      callback = options;
      options = null;
    }

    var start = Date.now();
    var livedb = this;

    var db;
    if (options && options.backend) {
      if (!this.extraDbs.hasOwnProperty(options.backend)) return callback('Backend not found');
      db = this.extraDbs[options.backend];
    } else {
      db = this.snapshotDb;
    }
    if (db.query.length < 5)
      throw Error("Livedb query backend " + (options.backend || 'default') + " is out of date " +
        "with spec (its probably missing the 'options' parameter). Update your livedb backend library");

    if (!this.snapshotDb.query) {
      return callback('Backend does not support queries');
    }

    this._dbQuery(db, index, query, {mode:'fetch'}, function(err, resultSet) {
      if (livedb.sdc) {
        var sdcPrefix = livedb._sdcDbPrefix(options);
        livedb.sdc.increment(sdcPrefix + '.query.fetch');
        livedb.sdc.timing(sdcPrefix + '.query.fetch', Date.now() - start);
      }

      if (err) {
        callback(err);
      } else if (Array.isArray(resultSet)) {
        callback(null, resultSet);
      } else {
        callback(null, resultSet.results, resultSet.extra);
      }
    });
  };

  Livedb.prototype.query = function(index, query, options, callback) {
    this.queryPoll(index, query, options, callback);
  };

  // For mongo, the index is just the collection itself. For something like
  // SOLR, the index refers to the core we're actually querying.
  //
  // Options can contain:
  // backend: the backend to use, or the name of the backend (if the backend
  //  is specified in the otherDbs when the livedb instance is created)
  // poll: true, false or undefined. Set true/false to force enable/disable
  //  polling mode. Undefined will let the database decide.
  // shouldPoll: function(collection, docName, opData, index, query) {return true or false; }
  //  this is a syncronous function which can be used as an early filter for
  //  operations going through the system to reduce the load on the backend.
  // pollDelay: Minimum delay between subsequent database polls. This is used
  //  to batch updates to reduce load on the database at the expense of
  //  liveness.
  Livedb.prototype.queryPoll = function(index, query, options, callback) {
    if (!this.driver.subscribeChannels) return callback("Driver does not support polling queries");

    if (typeof options === 'function') {
      callback = options;
      options = {};
    } else if (!options) {
      options = {};
    }

    var start = Date.now();
    var livedb = this;

    var db;
    if (options.backend) {
      if (!this.extraDbs.hasOwnProperty(options.backend)) return callback('Backend not found');
      db = this.extraDbs[options.backend];
    } else {
      db = this.snapshotDb;
    }

    if (db.disableSubscribe) {
      return callback('Backend does not support subscribe');
    }

    if (!this.snapshotDb.query) {
      return callback('Backend does not support queries');
    }

    var projection = this.projections[index];
    var collection = (projection) ? projection.target : index;
    var channels = [collection];
    // subscribe to collection firehose -> cache. The firehose isn't updated until after the db,
    // so if we get notified about an op here, the document's been saved.
    this.driver.subscribeChannels(channels, function(err, stream) {
      if (err) return callback(err);
      if (livedb.sdc) {
        var sdcPrefix = livedb._sdcDbPrefix(options);
        livedb.sdc.timing(sdcPrefix + '.query.driverSubscribe', Date.now() - start);
      }

      // Issue query on db to get our initial result set.
      livedb._dbQuery(db, index, query, {mode: 'initial'}, function(err, resultSet) {
        if (err) {
          stream.destroy();
          return callback(err);
        }
        if (livedb.sdc) {
          var sdcPrefix = livedb._sdcDbPrefix(options);
          livedb.sdc.increment(sdcPrefix + '.query.subscribe');
          livedb.sdc.timing(sdcPrefix + '.query.subscribe', Date.now() - start);
        }
        var results, extra;
        if (Array.isArray(resultSet)) {
          results = resultSet;
        } else {
          results = resultSet.results;
          extra = resultSet.extra;
        }
        var docNames = mapResults(results);
        var queryEmitter = new QueryEmitter(index, query, stream, docNames, extra);
        var pollQuery = getPollQuery(livedb, db, options, queryEmitter)
        startStream(livedb, db, options, queryEmitter, collection, pollQuery);
        callback(null, queryEmitter, results, extra);
      });
    });
  };
};

function startStream(livedb, db, options, queryEmitter, collection, pollQuery) {
  function readStream() {
    var data;
    while (data = queryEmitter.stream.read()) {
      readStreamItem(livedb, db, options, queryEmitter, collection, pollQuery, data);
    }
  }
  readStream();
  queryEmitter.stream.on('readable', readStream);
  return queryEmitter;
}

function getPollQuery(livedb, db, options, queryEmitter) {
  var poll = (!db.queryDoc) ? true :
    (options.poll != null) ? options.poll :
    (db.queryNeedsPollMode) ? db.queryNeedsPollMode(queryEmitter.index, queryEmitter.query) :
    true;
  if (!poll) return;

  // Default to 2 seconds
  var delay = (typeof options.pollDelay === 'number') ? options.pollDelay : 2000;
  return rateLimit(delay, function pollQuery() {
    // We need to do a full poll of the query, because the query uses limits or something.
    var start = Date.now();
    livedb._dbQuery(db, queryEmitter.index, queryEmitter.query, {mode: 'poll'}, function(err, resultSet) {
      if (err) return queryEmitter.emitError(err);

      if (livedb.sdc) {
        var sdcPrefix = livedb._sdcDbPrefix(options);
        livedb.sdc.timing(sdcPrefix + '.query.poll', Date.now() - start);
      }

      var results, extra;
      if (Array.isArray(resultSet)) {
        results = resultSet;
      } else {
        results = resultSet.results;
        extra = resultSet.extra;
      }
      queryEmitter.emitResults(results, extra);
    });
  });
}

function readStreamItem(livedb, db, options, queryEmitter, collection, pollQuery, data) {
  // Ignore if the user or database say we don't need to poll
  if (options.shouldPoll && !options.shouldPoll(collection, data.docName, data, queryEmitter.index, queryEmitter.query)) return;
  if (db.queryShouldPoll && !db.queryShouldPoll(this, collection, data.docName, data, queryEmitter.index, queryEmitter.query)) return;

  // Not sure whether the changed document should be in the result set
  if (pollQuery) return pollQuery();

  livedb._dbQueryDoc(db, queryEmitter.index, data.docName, queryEmitter.query, function(err, result) {
    if (err === 'Irrelevant') return;
    if (err) return queryEmitter.emitError(err);

    // Check if the document was in the previous results set
    var i = queryEmitter.docNames.indexOf(data.docName);

    if (i === -1 && result) {
      // Add doc to the collection. Order isn't important, so
      // we'll just whack it at the end.
      var index = queryEmitter.docNames.push(result.docName) - 1;
      var values = [result];
      queryEmitter.emitDiff([new arraydiff.InsertDiff(index, values)]);

    } else if (i !== -1 && !result) {
      queryEmitter.docNames.splice(i, 1);
      queryEmitter.emitDiff([new arraydiff.RemoveDiff(i, 1)]);
    }
  });
}

function QueryEmitter(index, query, stream, docNames, extra) {
  this.index = index;
  this.query = query;
  this.stream = stream;
  this.docNames = docNames;
  this.extra = extra;
}

QueryEmitter.prototype.destroy = function() {
  this.stream.destroy();
  this.onError = doNothing;
  this.onDiff = doNothing;
  this.onExtra = doNothing;
  this.emitError = doNothing;
  this.emitDiff = doNothing;
  this.emitExtra = doNothing;
};

QueryEmitter.prototype.emitResults = function(results, extra) {
  var docNames = mapResults(results);
  var docNamesDiff = arraydiff(this.docNames, docNames);
  if (docNamesDiff.length) {
    this.docNames = docNames;
    var diff = mapDiff(docNamesDiff, results);
    this.emitDiff(diff);
  }
  // Be nice to not have to do this in such a brute force way
  if (!deepEquals(this.extra, extra)) {
    this.extra = extra;
    this.emitExtra(extra);
  }
};

// These methods can be overriden to extend default behavior
QueryEmitter.prototype.emitError = function(err) {
  this.onError(err);
};
QueryEmitter.prototype.emitDiff = function(diff) {
  this.onDiff(diff);
};
QueryEmitter.prototype.emitExtra = function(extra) {
  this.onExtra(extra);
};

// Clients should define these functions
QueryEmitter.prototype.onError = doNothing;
QueryEmitter.prototype.onDiff = doNothing;
QueryEmitter.prototype.onExtra = doNothing;

function doNothing() {}

function mapResults(results) {
  var docNames = [];
  for (var i = 0; i < results.length; i++) {
    docNames.push(results[i].docName);
  }
  return docNames;
}

function mapDiff(docNamesDiff, results) {
  var diff = [];
  var resultsMap;
  for (var i = 0; i < docNamesDiff.length; i++) {
    var item = docNamesDiff[i];
    if (item instanceof arraydiff.InsertDiff) {
      if (!resultsMap) resultsMap = getResultsMap(results);
      var values = [];
      for (var j = 0; j < item.values.length; j++) {
        var docName = item.values[j];
        values.push(resultsMap[docName]);
      }
      diff.push(new arraydiff.InsertDiff(item.index, values));
    } else {
      diff.push(item);
    }
  }
  return diff;
}

function getResultsMap(results) {
  var resultsMap = {};
  for (var i = 0; i < results.length; i++) {
    var result = results[i];
    resultsMap[result.docName] = result;
  }
  return resultsMap;
}
<commit_msg>remove statsd increments that duplicate timers<commit_after>var rateLimit = require('./ratelimit');
var deepEquals = require('deep-is');
var arraydiff = require('arraydiff');
var projections = require('./projections');

module.exports = function(Livedb) {

  Livedb.prototype._sdcDbPrefix = function(options) {
    return 'livedb.db.' + ((options && options.backend) ? options.backend : 'default');
  };

  function projectResults(results, cName, projection) {
    if (!projection) return;
    var r = results.results ? results.results : results;
    for (var i = 0; i < r.length; i++) {
      var r = r[i];
      r.data = projections.projectSnapshot(r.type, projection.fields, r.data);
    }
  }

  Livedb.prototype._dbQuery = function(db, index, query, options, callback) {
    var projection = this.projections[index];

    if (projection) {
      if (db.queryProjected)
        db.queryProjected(this, projection.target, projection.fields, query, options, callback);
      else {
        db.query(this, projection.target, query, options, function(err, results) {
          if (results) projectResults(results, index, projection);
          callback(err, results);
        });
      }
    } else {
      db.query(this, index, query, options, callback);
    }
  };

  Livedb.prototype._dbQueryDoc = function(db, index, docName, query, callback) {
    var projection = this.projections[index];
    if (projection) {
      if (db.queryDocProjected) // What a mouthful!
        db.queryDocProjected(this, index, projection.target, docName, projection.fields, query, callback);
      else {
        db.queryDoc(this, index, projection.target, docName, query, function(err, result) {
          if (result) {
            result.data = projections.projectSnapshot(result.type, projection.fields, result.data);
          }
          callback(err, result);
        });
      }
    } else {
      db.queryDoc(this, index, index, docName, query, callback);
    }
  };

  Livedb.prototype.queryFetch = function(index, query, options, callback) {
    if (typeof options === 'function') {
      callback = options;
      options = null;
    }

    var start = Date.now();
    var livedb = this;

    var db;
    if (options && options.backend) {
      if (!this.extraDbs.hasOwnProperty(options.backend)) return callback('Backend not found');
      db = this.extraDbs[options.backend];
    } else {
      db = this.snapshotDb;
    }
    if (db.query.length < 5)
      throw Error("Livedb query backend " + (options.backend || 'default') + " is out of date " +
        "with spec (its probably missing the 'options' parameter). Update your livedb backend library");

    if (!this.snapshotDb.query) {
      return callback('Backend does not support queries');
    }

    this._dbQuery(db, index, query, {mode:'fetch'}, function(err, resultSet) {
      if (livedb.sdc) {
        var sdcPrefix = livedb._sdcDbPrefix(options);
        livedb.sdc.timing(sdcPrefix + '.query.fetch', Date.now() - start);
      }

      if (err) {
        callback(err);
      } else if (Array.isArray(resultSet)) {
        callback(null, resultSet);
      } else {
        callback(null, resultSet.results, resultSet.extra);
      }
    });
  };

  Livedb.prototype.query = function(index, query, options, callback) {
    this.queryPoll(index, query, options, callback);
  };

  // For mongo, the index is just the collection itself. For something like
  // SOLR, the index refers to the core we're actually querying.
  //
  // Options can contain:
  // backend: the backend to use, or the name of the backend (if the backend
  //  is specified in the otherDbs when the livedb instance is created)
  // poll: true, false or undefined. Set true/false to force enable/disable
  //  polling mode. Undefined will let the database decide.
  // shouldPoll: function(collection, docName, opData, index, query) {return true or false; }
  //  this is a syncronous function which can be used as an early filter for
  //  operations going through the system to reduce the load on the backend.
  // pollDelay: Minimum delay between subsequent database polls. This is used
  //  to batch updates to reduce load on the database at the expense of
  //  liveness.
  Livedb.prototype.queryPoll = function(index, query, options, callback) {
    if (!this.driver.subscribeChannels) return callback("Driver does not support polling queries");

    if (typeof options === 'function') {
      callback = options;
      options = {};
    } else if (!options) {
      options = {};
    }

    var start = Date.now();
    var livedb = this;

    var db;
    if (options.backend) {
      if (!this.extraDbs.hasOwnProperty(options.backend)) return callback('Backend not found');
      db = this.extraDbs[options.backend];
    } else {
      db = this.snapshotDb;
    }

    if (db.disableSubscribe) {
      return callback('Backend does not support subscribe');
    }

    if (!this.snapshotDb.query) {
      return callback('Backend does not support queries');
    }

    var projection = this.projections[index];
    var collection = (projection) ? projection.target : index;
    var channels = [collection];
    // subscribe to collection firehose -> cache. The firehose isn't updated until after the db,
    // so if we get notified about an op here, the document's been saved.
    this.driver.subscribeChannels(channels, function(err, stream) {
      if (err) return callback(err);
      if (livedb.sdc) {
        var sdcPrefix = livedb._sdcDbPrefix(options);
        livedb.sdc.timing(sdcPrefix + '.query.driverSubscribe', Date.now() - start);
      }

      // Issue query on db to get our initial result set.
      livedb._dbQuery(db, index, query, {mode: 'initial'}, function(err, resultSet) {
        if (err) {
          stream.destroy();
          return callback(err);
        }
        if (livedb.sdc) {
          var sdcPrefix = livedb._sdcDbPrefix(options);
          livedb.sdc.timing(sdcPrefix + '.query.subscribe', Date.now() - start);
        }
        var results, extra;
        if (Array.isArray(resultSet)) {
          results = resultSet;
        } else {
          results = resultSet.results;
          extra = resultSet.extra;
        }
        var docNames = mapResults(results);
        var queryEmitter = new QueryEmitter(index, query, stream, docNames, extra);
        var pollQuery = getPollQuery(livedb, db, options, queryEmitter)
        startStream(livedb, db, options, queryEmitter, collection, pollQuery);
        callback(null, queryEmitter, results, extra);
      });
    });
  };
};

function startStream(livedb, db, options, queryEmitter, collection, pollQuery) {
  function readStream() {
    var data;
    while (data = queryEmitter.stream.read()) {
      readStreamItem(livedb, db, options, queryEmitter, collection, pollQuery, data);
    }
  }
  readStream();
  queryEmitter.stream.on('readable', readStream);
  return queryEmitter;
}

function getPollQuery(livedb, db, options, queryEmitter) {
  var poll = (!db.queryDoc) ? true :
    (options.poll != null) ? options.poll :
    (db.queryNeedsPollMode) ? db.queryNeedsPollMode(queryEmitter.index, queryEmitter.query) :
    true;
  if (!poll) return;

  // Default to 2 seconds
  var delay = (typeof options.pollDelay === 'number') ? options.pollDelay : 2000;
  return rateLimit(delay, function pollQuery() {
    // We need to do a full poll of the query, because the query uses limits or something.
    var start = Date.now();
    livedb._dbQuery(db, queryEmitter.index, queryEmitter.query, {mode: 'poll'}, function(err, resultSet) {
      if (err) return queryEmitter.emitError(err);

      if (livedb.sdc) {
        var sdcPrefix = livedb._sdcDbPrefix(options);
        livedb.sdc.timing(sdcPrefix + '.query.poll', Date.now() - start);
      }

      var results, extra;
      if (Array.isArray(resultSet)) {
        results = resultSet;
      } else {
        results = resultSet.results;
        extra = resultSet.extra;
      }
      queryEmitter.emitResults(results, extra);
    });
  });
}

function readStreamItem(livedb, db, options, queryEmitter, collection, pollQuery, data) {
  // Ignore if the user or database say we don't need to poll
  if (options.shouldPoll && !options.shouldPoll(collection, data.docName, data, queryEmitter.index, queryEmitter.query)) return;
  if (db.queryShouldPoll && !db.queryShouldPoll(this, collection, data.docName, data, queryEmitter.index, queryEmitter.query)) return;

  // Not sure whether the changed document should be in the result set
  if (pollQuery) return pollQuery();

  livedb._dbQueryDoc(db, queryEmitter.index, data.docName, queryEmitter.query, function(err, result) {
    if (err === 'Irrelevant') return;
    if (err) return queryEmitter.emitError(err);

    // Check if the document was in the previous results set
    var i = queryEmitter.docNames.indexOf(data.docName);

    if (i === -1 && result) {
      // Add doc to the collection. Order isn't important, so
      // we'll just whack it at the end.
      var index = queryEmitter.docNames.push(result.docName) - 1;
      var values = [result];
      queryEmitter.emitDiff([new arraydiff.InsertDiff(index, values)]);

    } else if (i !== -1 && !result) {
      queryEmitter.docNames.splice(i, 1);
      queryEmitter.emitDiff([new arraydiff.RemoveDiff(i, 1)]);
    }
  });
}

function QueryEmitter(index, query, stream, docNames, extra) {
  this.index = index;
  this.query = query;
  this.stream = stream;
  this.docNames = docNames;
  this.extra = extra;
}

QueryEmitter.prototype.destroy = function() {
  this.stream.destroy();
  this.onError = doNothing;
  this.onDiff = doNothing;
  this.onExtra = doNothing;
  this.emitError = doNothing;
  this.emitDiff = doNothing;
  this.emitExtra = doNothing;
};

QueryEmitter.prototype.emitResults = function(results, extra) {
  var docNames = mapResults(results);
  var docNamesDiff = arraydiff(this.docNames, docNames);
  if (docNamesDiff.length) {
    this.docNames = docNames;
    var diff = mapDiff(docNamesDiff, results);
    this.emitDiff(diff);
  }
  // Be nice to not have to do this in such a brute force way
  if (!deepEquals(this.extra, extra)) {
    this.extra = extra;
    this.emitExtra(extra);
  }
};

// These methods can be overriden to extend default behavior
QueryEmitter.prototype.emitError = function(err) {
  this.onError(err);
};
QueryEmitter.prototype.emitDiff = function(diff) {
  this.onDiff(diff);
};
QueryEmitter.prototype.emitExtra = function(extra) {
  this.onExtra(extra);
};

// Clients should define these functions
QueryEmitter.prototype.onError = doNothing;
QueryEmitter.prototype.onDiff = doNothing;
QueryEmitter.prototype.onExtra = doNothing;

function doNothing() {}

function mapResults(results) {
  var docNames = [];
  for (var i = 0; i < results.length; i++) {
    docNames.push(results[i].docName);
  }
  return docNames;
}

function mapDiff(docNamesDiff, results) {
  var diff = [];
  var resultsMap;
  for (var i = 0; i < docNamesDiff.length; i++) {
    var item = docNamesDiff[i];
    if (item instanceof arraydiff.InsertDiff) {
      if (!resultsMap) resultsMap = getResultsMap(results);
      var values = [];
      for (var j = 0; j < item.values.length; j++) {
        var docName = item.values[j];
        values.push(resultsMap[docName]);
      }
      diff.push(new arraydiff.InsertDiff(item.index, values));
    } else {
      diff.push(item);
    }
  }
  return diff;
}

function getResultsMap(results) {
  var resultsMap = {};
  for (var i = 0; i < results.length; i++) {
    var result = results[i];
    resultsMap[result.docName] = result;
  }
  return resultsMap;
}
<|endoftext|>


<commit_before>'use strict';

const format = require('format-io');
const currify = require('currify');
const tryToCatch = require('try-to-catch');

const sortify = currify(require('@cloudcmd/sortify'));
const formatify = require('@cloudcmd/formatify');

const WIN = process.platform === 'win32';

const ifRaw = currify(_ifRaw);
const replaceProperty = currify(_replaceProperty);

const nicki = !WIN && require('nicki');

const readdir = require('./readdir');

module.exports = readify;

async function readify(path, options = {}) {
    const type = options.type;
    const order = options.order;
    const sort = options.sort || 'name';

    check(path, type);
    checkSort(sort, order);

    const names = await readdir(path);
    const sorted = sortify({sort,order}, names);
    const formated = ifRaw(type, formatify, sorted);

    return fillJSON(path, type, formated);
}

function check(path, type) {
    const isString = (a) => typeof a === 'string';

    const pathMsg = 'path should be string!';
    const typeMsg = 'type should be a string or not to be defined!';

    if (!isString(path))
        throw Error(pathMsg);

    if (type && !isString(type))
        throw Error(typeMsg);
}

function checkSort(sort, order) {
    if (sort && typeof sort !== 'string')
        throw Error('sort should be a string!');

    if (order && !/^(asc|desc)$/.test(order))
        throw Error('order can be "asc" or "desc" only!');
}

function _ifRaw(type, fn, a) {
    if (type === 'raw')
        return a;

    return fn(a);
}

async function fillJSON(dir, type, files) {
    const path = format.addSlashToEnd(dir);

    if (type === 'raw')
        return {
            path,
            files,
        };

    const newFiles = await changeUIDToName(files);

    return {
        path,
        files: newFiles,
    };
}

async function changeUIDToName(files) {
    if (!nicki)
        return files;

    const [e, names] = await tryToCatch(nicki);

    if (e)
        return names;

    const replaceOwner = replaceProperty(names, 'owner');

    return files.map(replaceOwner);
}

function _replaceProperty(obj, prop, item) {
    const n = item[prop];
    const data = obj[n];

    if (typeof data === 'undefined')
        return item;

    return {
        ...item,
        [prop]: data
    };
}

<commit_msg>chore(readify) add " "<commit_after>'use strict';

const format = require('format-io');
const currify = require('currify');
const tryToCatch = require('try-to-catch');

const sortify = currify(require('@cloudcmd/sortify'));
const formatify = require('@cloudcmd/formatify');

const WIN = process.platform === 'win32';

const ifRaw = currify(_ifRaw);
const replaceProperty = currify(_replaceProperty);

const nicki = !WIN && require('nicki');

const readdir = require('./readdir');

module.exports = readify;

async function readify(path, options = {}) {
    const type = options.type;
    const order = options.order;
    const sort = options.sort || 'name';

    check(path, type);
    checkSort(sort, order);

    const names = await readdir(path);
    const sorted = sortify({sort, order}, names);
    const formated = ifRaw(type, formatify, sorted);

    return fillJSON(path, type, formated);
}

function check(path, type) {
    const isString = (a) => typeof a === 'string';

    const pathMsg = 'path should be string!';
    const typeMsg = 'type should be a string or not to be defined!';

    if (!isString(path))
        throw Error(pathMsg);

    if (type && !isString(type))
        throw Error(typeMsg);
}

function checkSort(sort, order) {
    if (sort && typeof sort !== 'string')
        throw Error('sort should be a string!');

    if (order && !/^(asc|desc)$/.test(order))
        throw Error('order can be "asc" or "desc" only!');
}

function _ifRaw(type, fn, a) {
    if (type === 'raw')
        return a;

    return fn(a);
}

async function fillJSON(dir, type, files) {
    const path = format.addSlashToEnd(dir);

    if (type === 'raw')
        return {
            path,
            files,
        };

    const newFiles = await changeUIDToName(files);

    return {
        path,
        files: newFiles,
    };
}

async function changeUIDToName(files) {
    if (!nicki)
        return files;

    const [e, names] = await tryToCatch(nicki);

    if (e)
        return names;

    const replaceOwner = replaceProperty(names, 'owner');

    return files.map(replaceOwner);
}

function _replaceProperty(obj, prop, item) {
    const n = item[prop];
    const data = obj[n];

    if (typeof data === 'undefined')
        return item;

    return {
        ...item,
        [prop]: data
    };
}

<|endoftext|>


<commit_before>/*jshint -W058 */

import partial from 'lodash.partial';
import bind from 'component-bind';
import type from 'component-type';
import merge from 'lodash.merge';
import jsonp from 'jsonp';
import qs from 'qs';
import Emitter from 'component-emitter';
import errors from './errors';
import version from './version';
import bankAccount from './recurly/bank-account';
import {Bus} from './recurly/bus';
import {Message} from './recurly/message';
import {HostedFields} from './recurly/hosted-fields';
import FraudDataCollector from './recurly/fraud-data-collector';

const debug = require('debug')('recurly');

/**
 * Default configuration values.
 *
 * currency: ISO 4217
 * timeout: API request timeout in ms
 * publicKey: Recurly site public key
 * cors: Whether to use XHR2/XDR+CORS over jsonp for API requests
 * api: URL of API
 *
 * @private
 * @type {Object}
 */

const defaults = {
  currency: 'USD',
  timeout: 60000,
  publicKey: '',
  parent: true,
  cors: false,
  fraudDataCollector: false,
  litleSessionId: null,
  api: 'https://api.recurly.com/js/v1',
  style: {},
  fields: {
    number: '[data-recurly=number]',
    month: '[data-recurly=month]',
    year: '[data-recurly=year]',
    cvv: '[data-recurly=cvv]'
  }
};

/**
 * Initialize defaults.
 *
 * @param {Object} options
 * @constructor
 * @public
 */

export class Recurly extends Emitter {
  constructor (options) {
    super();
    this.id = 0;
    this.version = version;
    this.configured = false;
    this.readyState = 0;
    this.config = merge({}, defaults);
    if (options) this.configure(options);
    this.bankAccount = {
      token: bind(this, bankAccount.token),
      bankInfo: bind(this, bankAccount.bankInfo)
    };
  }

  ready (done) {
    if (this.readyState > 1) done();
    else this.once('ready', done);
  }

  /**
   * Configure settings.
   *
   * @param {String|Object} options Either publicKey or object containing
   *                                publicKey and other optional members
   * @param {String} options.publicKey
   * @param {String} [options.currency] sets a default currency
   * @param {String} [options.api]
   * @param {Boolean} [options.cors] Enables data transmission over XHR+CORS
   * @param {Array} [options.required] Adds additional field requirements for
   *                                   tokenization. ex: ['cvv']
   * @public
   */

  configure (options) {
    debug('configure');

    if (type(options) === 'string') options = { publicKey: options };

    if (options.publicKey) {
      this.config.publicKey = options.publicKey;
    } else if (!this.config.publicKey) {
      throw errors('config-missing-public-key');
    }

    if (options.api) {
      this.config.api = options.api;
    }

    if (options.currency) {
      this.config.currency = options.currency;
    }

    if ('cors' in options) {
      this.config.cors = options.cors;
    }

    if ('fraudDataCollector' in options) {
      this.config.fraudDataCollector = options.fraudDataCollector;
    }

    if ('parent' in options) {
      this.config.parent = options.parent;
    }

    if ('style' in options) {
      merge(this.config.style, options.style);
    }

    if (type(options.fields) === 'object') {
      merge(this.config.fields, options.fields);
    }

    this.config.required = options.required || this.config.required || [];

    // Begin parent role configuration and setup
    if (this.config.parent) this.parent();

    this.configured = true;

    if (this.config.fraudDataCollector) FraudDataCollector.addFields.call(this);
  };

  /**
   * Initialize the parent recurly instance concerns: hosted fields and message bus
   *
   * sets this.readyState
   *   0: unconfigured
   *   1: begun intializing hosted fields
   *   2: done intializing hosted fields
   *   3: done initializing (no hosted fields)
   *
   * @private
   */

  parent () {
    if (this.readyState > 0) {
      this.bus.send('hostedFields:configure', this.config);
      return;
    }

    this.bus = new Bus;
    this.bus.add(this);

    this.hostedFields = new HostedFields(this.config);

    if (this.hostedFields.errors.length === 0) {
      this.bus.add(this.hostedFields);
      this.once('hostedFields:ready', body => {
        this.readyState = 2;
        this.emit('ready');
      });
      this.on('hostedFields:state:change', body => this.emit('change', { fields: body }));
      this.on('hostedField:submit', () => this.emit('field:submit'));
      this.readyState = 1;
    } else {
      this.readyState = 3;
      this.emit('ready');
    }
  };

  /**
   * Assembles the API endpoint.
   *
   * @return {String} route
   * @private
   */

  url (route) {
    return this.config.api + route;
  };

  /**
   * Issues an API request.
   *
   * @param {String} method
   * @param {String} route
   * @param {Object} [data]
   * @param {Function} done
   * @throws {Error} If `configure` has not been called.
   * @private
   */

  request (method, route, data, done) {
    debug('request');

    if (!this.configured) {
      throw errors('not-configured');
    }

    if ('function' == type(data)) {
      done = data;
      data = {};
    }

    data.version = this.version;
    data.key = this.config.publicKey;

    if (this.config.cors) {
      return this.xhr(method, route, data, done);
    } else {
      return this.jsonp(route, data, done);
    }
  };

  /**
   * Issues an API request over xhr.
   *
   * @param {String} method
   * @param {String} route
   * @param {Object} [data]
   * @param {Function} done
   * @private
   */

  xhr (method, route, data, done) {
    debug('xhr');

    const XHR = (function () {
      const XHR = window.XMLHttpRequest;
      const XDM = window.XDomainRequest;
      if (XHR && 'withCredentials' in new XHR) return XHR;
      if (XDM) return XDM;
    })();

    var req = new XHR;
    var url = this.url(route);
    var payload = qs.stringify(data);

    if (method === 'get') {
      url += '?' + payload;
    }

    req.open(method, url);
    req.timeout = this.config.timeout;
    req.ontimeout = function () {
      done(errors('api-timeout'));
    };
    req.onerror = function () {
      done(errors('api-error'));
    };
    req.onprogress = function () {};
    req.onload = function () {
      var res;

      try {
        res = JSON.parse(this.responseText);
      } catch (e) {
        debug(this.responseText, e);
        return done(errors('api-error', { message: 'There was a problem parsing the API response.' }));
      }

      if (res && res.error) {
        done(errors('api-error', res.error));
      } else {
        done(null, res);
      }
    };

    // XDR requests will abort if too many are sent simultaneously
    setTimeout(send, 0);

    function send () {
      if (method === 'post') {
        // XDR cannot set Content-type
        if (req.setRequestHeader) {
          req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        }
        req.send(payload);
      } else {
        req.send();
      }
    }
  };

  /**
   * Issues an API request over jsonp.
   *
   * @param {String} route
   * @param {Object} [data]
   * @param {Function} done
   * @private
   */

  jsonp (route, data, done) {
    debug('jsonp');

    var url = this.url(route) + '?' + qs.stringify(data);

    jsonp(url, { timeout: this.config.timeout, prefix: '__rjs' }, function (err, res) {
      if (err) return done(err);
      if (res.error) {
        done(errors('api-error', res.error));
      } else {
        done(null, res);
      }
    });
  };
}

Recurly.prototype.open = require('./recurly/open');
Recurly.prototype.relay = require('./recurly/relay');
Recurly.prototype.coupon = require('./recurly/coupon');
Recurly.prototype.paypal = require('./recurly/paypal');
Recurly.prototype.plan = require('./recurly/plan');
Recurly.prototype.tax = require('./recurly/tax');
Recurly.prototype.token = require('./recurly/token');
Recurly.prototype.validate = require('./recurly/validate');
Recurly.prototype.Pricing = require('./recurly/pricing');
<commit_msg>set litle session id in config method<commit_after>/*jshint -W058 */

import partial from 'lodash.partial';
import bind from 'component-bind';
import type from 'component-type';
import merge from 'lodash.merge';
import jsonp from 'jsonp';
import qs from 'qs';
import Emitter from 'component-emitter';
import errors from './errors';
import version from './version';
import bankAccount from './recurly/bank-account';
import {Bus} from './recurly/bus';
import {Message} from './recurly/message';
import {HostedFields} from './recurly/hosted-fields';
import FraudDataCollector from './recurly/fraud-data-collector';

const debug = require('debug')('recurly');

/**
 * Default configuration values.
 *
 * currency: ISO 4217
 * timeout: API request timeout in ms
 * publicKey: Recurly site public key
 * cors: Whether to use XHR2/XDR+CORS over jsonp for API requests
 * api: URL of API
 *
 * @private
 * @type {Object}
 */

const defaults = {
  currency: 'USD',
  timeout: 60000,
  publicKey: '',
  parent: true,
  cors: false,
  fraudDataCollector: false,
  litleSessionId: null,
  api: 'https://api.recurly.com/js/v1',
  style: {},
  fields: {
    number: '[data-recurly=number]',
    month: '[data-recurly=month]',
    year: '[data-recurly=year]',
    cvv: '[data-recurly=cvv]'
  }
};

/**
 * Initialize defaults.
 *
 * @param {Object} options
 * @constructor
 * @public
 */

export class Recurly extends Emitter {
  constructor (options) {
    super();
    this.id = 0;
    this.version = version;
    this.configured = false;
    this.readyState = 0;
    this.config = merge({}, defaults);
    if (options) this.configure(options);
    this.bankAccount = {
      token: bind(this, bankAccount.token),
      bankInfo: bind(this, bankAccount.bankInfo)
    };
  }

  ready (done) {
    if (this.readyState > 1) done();
    else this.once('ready', done);
  }

  /**
   * Configure settings.
   *
   * @param {String|Object} options Either publicKey or object containing
   *                                publicKey and other optional members
   * @param {String} options.publicKey
   * @param {String} [options.currency] sets a default currency
   * @param {String} [options.api]
   * @param {Boolean} [options.cors] Enables data transmission over XHR+CORS
   * @param {Array} [options.required] Adds additional field requirements for
   *                                   tokenization. ex: ['cvv']
   * @public
   */

  configure (options) {
    debug('configure');

    if (type(options) === 'string') options = { publicKey: options };

    if (options.publicKey) {
      this.config.publicKey = options.publicKey;
    } else if (!this.config.publicKey) {
      throw errors('config-missing-public-key');
    }

    if (options.api) {
      this.config.api = options.api;
    }

    if (options.currency) {
      this.config.currency = options.currency;
    }

    if ('cors' in options) {
      this.config.cors = options.cors;
    }

    if ('fraudDataCollector' in options) {
      this.config.fraudDataCollector = options.fraudDataCollector;
    }

    if ('litleSessionId' in options) {
      this.config.litleSessionId = options.litleSessionId;
    }

    if ('parent' in options) {
      this.config.parent = options.parent;
    }

    if ('style' in options) {
      merge(this.config.style, options.style);
    }

    if (type(options.fields) === 'object') {
      merge(this.config.fields, options.fields);
    }

    this.config.required = options.required || this.config.required || [];

    // Begin parent role configuration and setup
    if (this.config.parent) this.parent();

    this.configured = true;

    if (this.config.fraudDataCollector) FraudDataCollector.addFields.call(this);
  };

  /**
   * Initialize the parent recurly instance concerns: hosted fields and message bus
   *
   * sets this.readyState
   *   0: unconfigured
   *   1: begun intializing hosted fields
   *   2: done intializing hosted fields
   *   3: done initializing (no hosted fields)
   *
   * @private
   */

  parent () {
    if (this.readyState > 0) {
      this.bus.send('hostedFields:configure', this.config);
      return;
    }

    this.bus = new Bus;
    this.bus.add(this);

    this.hostedFields = new HostedFields(this.config);

    if (this.hostedFields.errors.length === 0) {
      this.bus.add(this.hostedFields);
      this.once('hostedFields:ready', body => {
        this.readyState = 2;
        this.emit('ready');
      });
      this.on('hostedFields:state:change', body => this.emit('change', { fields: body }));
      this.on('hostedField:submit', () => this.emit('field:submit'));
      this.readyState = 1;
    } else {
      this.readyState = 3;
      this.emit('ready');
    }
  };

  /**
   * Assembles the API endpoint.
   *
   * @return {String} route
   * @private
   */

  url (route) {
    return this.config.api + route;
  };

  /**
   * Issues an API request.
   *
   * @param {String} method
   * @param {String} route
   * @param {Object} [data]
   * @param {Function} done
   * @throws {Error} If `configure` has not been called.
   * @private
   */

  request (method, route, data, done) {
    debug('request');

    if (!this.configured) {
      throw errors('not-configured');
    }

    if ('function' == type(data)) {
      done = data;
      data = {};
    }

    data.version = this.version;
    data.key = this.config.publicKey;

    if (this.config.cors) {
      return this.xhr(method, route, data, done);
    } else {
      return this.jsonp(route, data, done);
    }
  };

  /**
   * Issues an API request over xhr.
   *
   * @param {String} method
   * @param {String} route
   * @param {Object} [data]
   * @param {Function} done
   * @private
   */

  xhr (method, route, data, done) {
    debug('xhr');

    const XHR = (function () {
      const XHR = window.XMLHttpRequest;
      const XDM = window.XDomainRequest;
      if (XHR && 'withCredentials' in new XHR) return XHR;
      if (XDM) return XDM;
    })();

    var req = new XHR;
    var url = this.url(route);
    var payload = qs.stringify(data);

    if (method === 'get') {
      url += '?' + payload;
    }

    req.open(method, url);
    req.timeout = this.config.timeout;
    req.ontimeout = function () {
      done(errors('api-timeout'));
    };
    req.onerror = function () {
      done(errors('api-error'));
    };
    req.onprogress = function () {};
    req.onload = function () {
      var res;

      try {
        res = JSON.parse(this.responseText);
      } catch (e) {
        debug(this.responseText, e);
        return done(errors('api-error', { message: 'There was a problem parsing the API response.' }));
      }

      if (res && res.error) {
        done(errors('api-error', res.error));
      } else {
        done(null, res);
      }
    };

    // XDR requests will abort if too many are sent simultaneously
    setTimeout(send, 0);

    function send () {
      if (method === 'post') {
        // XDR cannot set Content-type
        if (req.setRequestHeader) {
          req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        }
        req.send(payload);
      } else {
        req.send();
      }
    }
  };

  /**
   * Issues an API request over jsonp.
   *
   * @param {String} route
   * @param {Object} [data]
   * @param {Function} done
   * @private
   */

  jsonp (route, data, done) {
    debug('jsonp');

    var url = this.url(route) + '?' + qs.stringify(data);

    jsonp(url, { timeout: this.config.timeout, prefix: '__rjs' }, function (err, res) {
      if (err) return done(err);
      if (res.error) {
        done(errors('api-error', res.error));
      } else {
        done(null, res);
      }
    });
  };
}

Recurly.prototype.open = require('./recurly/open');
Recurly.prototype.relay = require('./recurly/relay');
Recurly.prototype.coupon = require('./recurly/coupon');
Recurly.prototype.paypal = require('./recurly/paypal');
Recurly.prototype.plan = require('./recurly/plan');
Recurly.prototype.tax = require('./recurly/tax');
Recurly.prototype.token = require('./recurly/token');
Recurly.prototype.validate = require('./recurly/validate');
Recurly.prototype.Pricing = require('./recurly/pricing');
<|endoftext|>


<commit_before>'use strict';

module.exports = function (Terminal) {

  /**
  * Rendering Engine
  */

  // In the screen buffer, each character
  // is stored as a an array with a character
  // and a 32-bit integer.
  // First value: a utf-16 character.
  // Second value:
  // Next 9 bits: background color (0-511).
  // Next 9 bits: foreground color (0-511).
  // Next 14 bits: a mask for misc. flags:
  // 1=bold, 2=underline, 4=inverse

  Terminal.prototype.refresh = function(start, end) {
    var x, y, i, line, out, ch, width, data, attr, fgColor, bgColor, flags, row, parent;

    width = this.cols;
    y = start;

    // if (end > this.lines.length) {
    // end = this.lines.length;
    // }

    for (; y <= end; y++) {
      row = y + this.ydisp;

      line = this.lines[row];
      out = '';

      if (y === this.y && this.cursorState && this.ydisp === this.ybase && !this.cursorHidden) {
        x = this.x;
      } else {
        x = -1;
      }

      attr = this.defAttr;
      i = 0;

      for (; i < width; i++) {
        data = line[i][0];
        ch = line[i][1];

        if (i === x) data = -1;

        if (data !== attr) {
          if (attr !== this.defAttr) {
            out += '';
          }
          if (data !== this.defAttr) {
            if (data === -1) {
              out += '';
            } else {
              out += '> 9) & 0x1ff;
              flags = data >> 18;

              if (flags & 1) {
                if (!Terminal.brokenBold) {
                  out += 'font-weight:bold;';
                }
                // see: XTerm*boldColors
                if (fgColor < 8) fgColor += 8;
              }

              if (flags & 2) {
                out += 'text-decoration:underline;';
              }

              if (bgColor !== 256) {
                out += 'background-color:' + Terminal.colors[bgColor] + ';';
              }

              if (fgColor !== 257) {
                out += 'color:' + Terminal.colors[fgColor] + ';';
              }

              out += '">';
            }
          }
        }

        switch (ch) {
        case '&':
          out += '&';
          break;
        case '<':
          out += '<';
          break;
        case '>':
          out += '>';
          break;
        default:
          if (ch <= ' ') {
            out += ' ';
          } else {
            out += ch;
          }
          break;
        }

        attr = data;
      }

      if (attr !== this.defAttr) {
        out += '';
      }

      this.children[y].innerHTML = out;
    }

    if (parent) parent.appendChild(this.element);
  };
};
<commit_msg>cleaning and accepting text wrapping as ok for now<commit_after>'use strict';

module.exports = function (Terminal) {

  /**
  * Rendering Engine
  */

  // In the screen buffer, each character
  // is stored as a an array with a character
  // and a 32-bit integer.
  // First value: a utf-16 character.
  // Second value:
  // Next 9 bits: background color (0-511).
  // Next 9 bits: foreground color (0-511).
  // Next 14 bits: a mask for misc. flags:
  // 1=bold, 2=underline, 4=inverse

  Terminal.prototype.refresh = function(start, end) {
    var x, y, i, line, out, ch, width, data, attr, fgColor, bgColor, flags, row, parent;

    width = this.cols;
    y = start;

    for (; y <= end; y++) {
      row = y + this.ydisp;

      line = this.lines[row];
      out = '';

      if (y === this.y && this.cursorState && this.ydisp === this.ybase && !this.cursorHidden) {
        x = this.x;
      } else {
        x = -1;
      }

      attr = this.defAttr;
      i = 0;

      for (; i < width; i++) {
        data = line[i][0];
        ch = line[i][1];

        if (i === x) data = -1;

        if (data !== attr) {
          if (attr !== this.defAttr) {
            out += '';
          }
          if (data !== this.defAttr) {
            if (data === -1) {
              out += '';
            } else {
              out += '> 9) & 0x1ff;
              flags = data >> 18;

              if (flags & 1) {
                if (!Terminal.brokenBold) {
                  out += 'font-weight:bold;';
                }
                // see: XTerm*boldColors
                if (fgColor < 8) fgColor += 8;
              }

              if (flags & 2) {
                out += 'text-decoration:underline;';
              }

              if (bgColor !== 256) {
                out += 'background-color:' + Terminal.colors[bgColor] + ';';
              }

              if (fgColor !== 257) {
                out += 'color:' + Terminal.colors[fgColor] + ';';
              }

              out += '">';
            }
          }
        }

        switch (ch) {
        case '&':
          out += '&';
          break;
        case '<':
          out += '<';
          break;
        case '>':
          out += '>';
          break;
        default:
          if (ch <= ' ') {
            out += ' ';
          } else {
            out += ch;
          }
          break;
        }

        attr = data;
      }

      if (attr !== this.defAttr) {
        out += '';
      }

      this.children[y].innerHTML = out;
    }

    if (parent) parent.appendChild(this.element);
  };
};
<|endoftext|>


<commit_before>const request = require('request')
const debug = require('debug')('geohub:request')
const pkg = require('../package.json')
const apiBase = 'https://api.github.com'

/**
 * handles requests by geohub to the github API
 *
 * @param  {object}   options - url (string), qs (object)
 * @param  {Function} callback
 */
function geohubRequest (options, callback) {
  if (options.url.indexOf('https://') !== 0) {
    options.url = apiBase + options.url
  }

  options.headers = {
    'User-Agent': 'geohub/' + pkg.version
  }

  // delete null/undefined access token to avoid 401 from github
  if (options.qs && !options.qs.access_token) {
    delete options.qs.access_token
  }

  debug(options)

  request(options, function (err, res, body) {
    if (err) return callback(err)
    let json
    try {
      json = JSON.parse(body)
    } catch (e) {
      return callback(new Error(`Failed to parse JSON from ${options.url} (status code: ${res.statusCode}, body: ${body})`))
    }

    if (json.message) {
      return callback(new Error(res.statusCode + ' (github): ' + json.message))
    }

    callback(null, json)
  })
}

module.exports = geohubRequest
<commit_msg>Ack...remove const and let to maintain Node version compatibility.<commit_after>var request = require('request')
var debug = require('debug')('geohub:request')
var pkg = require('../package.json')
var apiBase = 'https://api.github.com'

/**
 * handles requests by geohub to the github API
 *
 * @param  {object}   options - url (string), qs (object)
 * @param  {Function} callback
 */
function geohubRequest (options, callback) {
  if (options.url.indexOf('https://') !== 0) {
    options.url = apiBase + options.url
  }

  options.headers = {
    'User-Agent': 'geohub/' + pkg.version
  }

  // delete null/undefined access token to avoid 401 from github
  if (options.qs && !options.qs.access_token) {
    delete options.qs.access_token
  }

  debug(options)

  request(options, function (err, res, body) {
    if (err) return callback(err)

    try {
      var json = JSON.parse(body)
    } catch (e) {
      var msg = 'Failed to parse JSON from ' + options.url
      msg += ' (status code: ' + res.statusCode + ', body: ' + body + ')'
      return callback(new Error(msg))
    }

    if (json.message) {
      return callback(new Error(res.statusCode + ' (github): ' + json.message))
    }

    callback(null, json)
  })
}

module.exports = geohubRequest
<|endoftext|>