<commit_before>/**
 * Module dependencies
 */

var git = require('git-node');
var parseurl = require('url').parse;
var formaturl = require('url').format;
var mkdirp = require('mkdirp');
var exec = require('child_process').exec;

/**
 * Create a GitHub hook
 *
 * @param {Object} config
 * @return {Server}
 */

module.exports = function(config) {
  config = config || {};

  var secret = config.secret;
  var key = config.token;

  if (!key) throw new Error('missing github token')

  return function(app) {
    app.hook('github', '/github', hook);
  };

  function hook(task, log, fn) {
    // TODO verify secret matches

    var body = task.body;
    var headers = task.headers;

    var event = headers['x-github-event'];

    if (event === 'ping') return fn();

    var url = body.repository.url;
    var name = body.repository.name;
    var ref = body.ref;
    var branch = ref.replace('refs/heads/', '');
    var sha = body.after;

    var dir = task.dir;

    if (event === 'delete') return fn(null, name, branch, sha, event);

    log('cloning ' + url + ' to ' + dir);
    clone(url, dir, ref, key, log, function(err) {
      log('ready to deploy');
      fn(err, name, branch, sha, event);
    });
  };
};

/**
 * Clone a repo
 *
 * @param {String} url
 * @param {String} target
 * @param {String} ref
 * @param {String} key
 * @param {Function} log
 * @param {Function} fn
 */

function clone(url, target, ref, key, log, fn) {
  var urlObj = parseurl(url);
  urlObj.auth = key + ':x-oauth-basic';
  var authurl = formaturl(urlObj) + '.git';

  var dir = target + '/.git';

  log('creating dir ' + dir);
  mkdirp(dir, function(err) {
    if (err) return fn(err);

    var remote = git.remote(authurl);
    var repo = git.repo(dir);
    var opts = {};
    opts.want = ref;
    log('fetching ' + url);
    repo.fetch(remote, opts, function(err) {
      if (err) return fn(err);
      log('checking out ' + ref);
      repo.resolveHashish(ref, function(err, hash) {
        if (err) return fn(err);
        log('updating head to ' + hash);
        repo.updateHead(hash, function(err) {
          if (err) return fn(err);
          exec('git checkout ' + hash, {cwd: target}, function(err, stdout, stderr) {
            fn(err);
          });
        });
      });
    });
  });
}
<commit_msg>use the latest grappler api<commit_after>/**
 * Module dependencies
 */

var git = require('git-node');
var parseurl = require('url').parse;
var formaturl = require('url').format;
var mkdirp = require('mkdirp');
var exec = require('child_process').exec;

/**
 * Create a GitHub hook
 *
 * @param {Object} config
 * @return {Server}
 */

module.exports = function(config) {
  config = config || {};

  var secret = config.secret;
  var key = config.token;

  if (!key) throw new Error('missing github token')

  return function(app) {
    app.hook('github', '/github', hook);
    app.on('task', function(task) {
      task.on('gh:parsed', function() {
        fetch(key, task);
      });

      task.on('ready', handleStatus('pending', task));
      task.on('error', handleStatus('error', task));
      task.on('success', handleStatus('success', task));
      task.on('success', handleSuccess(task));
    });
  };

  function hook(req, log, fn) {
    // TODO verify secret matches
    var event = req.headers['x-github-event'];
    if (event === 'push') return handlePush(key, req, log, fn);
    if (event === 'pull_request') return handlePullRequest(key, req, log, fn);
    if (event === 'deployment') return handleDeployment(key, req, log, fn);
    return fn('pass');
  };
};

/**
 * Handle a pull request event
 *
 * steps:
 *   * check mergability (https://developer.github.com/v3/pulls/#mergability)
 *   * merge the commit (https://developer.github.com/v3/repos/merging/)
 *
 * @doc https://developer.github.com/v3/activity/events/types/#pullrequestevent
 */

function handlePullRequest(key, task, log, fn) {
  var body = task.body;

}

/**
 * Handle a push event
 *
 * steps:
 *   * git clone sha
 *   * deploy the sha
 *   * listen for success/failure and update the repo status (https://developer.github.com/v3/repos/statuses/)
 *   * create a deployment (https://developer.github.com/v3/repos/deployments/#create-a-deployment)
 */

function handlePush(key, req, log, fn) {
  var body = req.body;
  if (!body) return fn(new Error('missing body'));

  var url = body.repository.url;
  var name = body.repository.name;
  var ref = body.ref;
  var branch = ref.replace('refs/heads/', '');
  var sha = body.after;

  var info = {
    url: url,
    name: name,
    ref: ref,
    branch: branch,
    sha: sha,
    body: body
  };

  var event = body.deleted ? 'branch-deleted' : 'gh:parsed';
  fn(null, info, event);
}

/**
 * Handle a deployment event
 *
 * @doc https://developer.github.com/v3/activity/events/types/#deploymentevent
 */

function handleDeployment() {

}

function handleStatus(event, task) {

}

/**
 * Create a deployment
 */

function handleSuccess(task) {

}

function fetch(key, task) {
  task.clone('github', function(dir, log) {
    var url = task.info.url;
    var ref = task.info.ref;
    log('cloning ' + url + ' to ' + dir);
    clone(url, dir, ref, key, log, function(err) {
      if (err) return task.emit('error', err);
      log('ready to deploy');
      task.ready();
    });
  });
}

/**
 * Clone a repo
 *
 * @param {String} url
 * @param {String} target
 * @param {String} ref
 * @param {String} key
 * @param {Function} log
 * @param {Function} fn
 */

function clone(url, target, ref, key, log, fn) {
  var urlObj = parseurl(url);
  urlObj.auth = key + ':x-oauth-basic';
  var authurl = formaturl(urlObj) + '.git';

  var dir = target + '/.git';

  log('creating dir ' + dir);
  mkdirp(dir, function(err) {
    if (err) return fn(err);

    var remote = git.remote(authurl);
    var repo = git.repo(dir);
    var opts = {};
    opts.want = ref;
    log('fetching ' + url);
    repo.fetch(remote, opts, function(err) {
      if (err) return fn(err);
      log('checking out ' + ref);
      repo.resolveHashish(ref, function(err, hash) {
        if (err) return fn(err);
        log('updating head to ' + hash);
        repo.updateHead(hash, function(err) {
          if (err) return fn(err);
          exec('git checkout ' + hash, {cwd: target}, function(err, stdout, stderr) {
            fn(err);
          });
        });
      });
    });
  });
}
<|endoftext|>


<commit_before>var io = require('socket.io'),
    fs = require('fs'),
    path = require('path');

exports.attach = function (server) {

    // Store all the request listeners already defined on this server.
    var oldListeners = server.listeners('request').splice(0);

    // Remove all the request listeners already defined on this server.
    server.removeAllListeners('request');

    // Add our own request listener.
    server.on('request', function (req, res) {

        // If the request URL does not match the one we want to handle then invoke the pre-existing request listeners.
        if (req.url !== '/shotgun/shotgun.client.js') {
            for (var i = 0, l = oldListeners.length; i < l; i++) {
                oldListeners[i].call(server, req, res);
            }
        }
        // If the URL does match then serve up the following scripts:
        // - socket.io.js
        // - shotgun.client.js
        // - jquery.cooltype.js
        // - jquery.shotgunConsole.js
        else {
            try {
                fs.readFile(path.join(__dirname, '/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js'), function (err, socketIoClient) {
                    fs.readFile(path.join(__dirname, '/client/shotgun.client.js'), function (err, shotgunClient) {
                        fs.readFile(path.join(__dirname, '/client/jquery.cooltype.js'), function (err, jqueryCoolType) {
                            fs.readFile(path.join(__dirname, '/client/jquery.shotgunConsole.js'), function (err, jqueryShotgunConsole) {
                                res.writeHead(200, { 'Content-Type': 'application/javascript' });
                                res.end(socketIoClient + '\n\n' + shotgunClient + '\n\n' + jqueryCoolType + '\n\n' + jqueryShotgunConsole);
                            });
                        });
                    });
                });
            }
            catch (e) {
            }
        }

    });

    // Instantiate socket.io server.
    var sockets = io.listen(server, { log: false });

    // Create an array of all arguments passed in except the first one.
    // The first argument was the http server and all other arguments are expected to be shotgun hell instances.
    var shells = [].splice.call(arguments,1);

    // Iterate over each shell and associate a socket.io namespace with each shell instance passed in.
    shells.forEach(function (shell) {

        // Add io to the shell for advanced users.
        shell.socketIo = io;

        // Create a shell helper function for setting cookies on the client.
        shell.setCookie = function (name, value, days) {
            var newCookies = shell.getVar('newCookies') || {};
            newCookies[shell.settings.namespace + '|' + name] = { value: value, days: days };
            return shell.setVar('newCookies', newCookies);
        };

        // Setup socket.io namespace for the current shell.
        sockets.of('/' + shell.settings.namespace)
            .on('connection', function (socket) {

                // Listen for our custom "execute" socket.io event.
                socket.on('execute', function (cmdStr, context, options) {

                    // Add current socket to context for advanced users.
                    context.socket = socket;

                    // If the shell has its debug setting enabled then write out user input to console.
                    if (shell.settings.debug) console.log('%s: %s', shell.settings.namespace, cmdStr);

                    // Configure the shell for this execution.
                    shell
                        // If shotgun modifies the context then send it to the client via this client's
                        // socket connection so it can be stored in the browser.
                        .onContextSave(function (contextToSave) {
                            socket.emit('saveContext', contextToSave);
                        })
                        // If shotgun sends any data then send it to the client to be handled.
                        .onData(function (data) {
                            socket.emit('data', data);
                        })
                        // Execute the shell.
                        .execute(cmdStr, context, options);
                });

            });
    });

    // Return any relevant internals for shotgun-client.
    return {
        sockets: sockets
    };
};<commit_msg>Fixing circular reference issue when trying to send context object to browser with socket attached to it.<commit_after>var io = require('socket.io'),
    fs = require('fs'),
    path = require('path');

exports.attach = function (server) {

    // Store all the request listeners already defined on this server.
    var oldListeners = server.listeners('request').splice(0);

    // Remove all the request listeners already defined on this server.
    server.removeAllListeners('request');

    // Add our own request listener.
    server.on('request', function (req, res) {

        // If the request URL does not match the one we want to handle then invoke the pre-existing request listeners.
        if (req.url !== '/shotgun/shotgun.client.js') {
            for (var i = 0, l = oldListeners.length; i < l; i++) {
                oldListeners[i].call(server, req, res);
            }
        }
        // If the URL does match then serve up the following scripts:
        // - socket.io.js
        // - shotgun.client.js
        // - jquery.cooltype.js
        // - jquery.shotgunConsole.js
        else {
            try {
                fs.readFile(path.join(__dirname, '/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js'), function (err, socketIoClient) {
                    fs.readFile(path.join(__dirname, '/client/shotgun.client.js'), function (err, shotgunClient) {
                        fs.readFile(path.join(__dirname, '/client/jquery.cooltype.js'), function (err, jqueryCoolType) {
                            fs.readFile(path.join(__dirname, '/client/jquery.shotgunConsole.js'), function (err, jqueryShotgunConsole) {
                                res.writeHead(200, { 'Content-Type': 'application/javascript' });
                                res.end(socketIoClient + '\n\n' + shotgunClient + '\n\n' + jqueryCoolType + '\n\n' + jqueryShotgunConsole);
                            });
                        });
                    });
                });
            }
            catch (e) {
            }
        }

    });

    // Instantiate socket.io server.
    var sockets = io.listen(server, { log: false });

    // Create an array of all arguments passed in except the first one.
    // The first argument was the http server and all other arguments are expected to be shotgun hell instances.
    var shells = [].splice.call(arguments,1);

    // Iterate over each shell and associate a socket.io namespace with each shell instance passed in.
    shells.forEach(function (shell) {

        // Add io to the shell for advanced users.
        shell.socketIo = io;

        // Create a shell helper function for setting cookies on the client.
        shell.setCookie = function (name, value, days) {
            var newCookies = shell.getVar('newCookies') || {};
            newCookies[shell.settings.namespace + '|' + name] = { value: value, days: days };
            return shell.setVar('newCookies', newCookies);
        };

        // Setup socket.io namespace for the current shell.
        sockets.of('/' + shell.settings.namespace)
            .on('connection', function (socket) {

                // Listen for our custom "execute" socket.io event.
                socket.on('execute', function (cmdStr, context, options) {

                    // Add current socket to context for advanced users.
                    context.socket = socket;

                    // If the shell has its debug setting enabled then write out user input to console.
                    if (shell.settings.debug) console.log('%s: %s', shell.settings.namespace, cmdStr);

                    // Configure the shell for this execution.
                    shell
                        // If shotgun modifies the context then send it to the client via this client's
                        // socket connection so it can be stored in the browser.
                        .onContextSave(function (contextToSave) {
                            if (contextToSave.hasOwnProperty('socket')) delete contextToSave.socket;
                            socket.emit('saveContext', contextToSave);
                        })
                        // If shotgun sends any data then send it to the client to be handled.
                        .onData(function (data) {
                            socket.emit('data', data);
                        })
                        // Execute the shell.
                        .execute(cmdStr, context, options);
                });

            });
    });

    // Return any relevant internals for shotgun-client.
    return {
        sockets: sockets
    };
};<|endoftext|>


<commit_before>module.exports = function matcher(obj) {
  "use strict";
  var props = Object.getOwnPropertyNames(obj);
  var re = new RegExp(props.reduce(function(p, c) {
    if(c.indexOf("_") === 0) return p + obj[c];
    else return p + "(" + obj[c] + ")";
  }, ""));
  props = props.filter(function(x) { return !x.startsWith("_"); });
  return function(pattern) {
      var o = {};
      var res = re.exec(pattern);
      if(res === null) return null;
      for(var i = 0; i < res.length; i++) {
         o[props[i]] = res[i + 1];
      }
      return o;
  };
};
<commit_msg>expose re of variable<commit_after>module.exports = function matcher(obj) {
  "use strict";
  var props = Object.getOwnPropertyNames(obj);
  var re = new RegExp(props.reduce(function(p, c) {
    if(c.indexOf("_") === 0) return p + obj[c];
    else return p + "(" + obj[c] + ")";
  }, ""));
  props = props.filter(function(x) { return !x.startsWith("_"); });
  var parser = function(pattern) {
      var o = {};
      var res = re.exec(pattern);
      if(res === null) return null;
      for(var i = 0; i < res.length; i++) {
         o[props[i]] = res[i + 1];
      }
      return o;
  };
  parser.re = re; // expose regexp
  return parser;
};
<|endoftext|>


<commit_before>/* jshint ignore:start */
'use strict';

const BbPromise = require('bluebird');
const fse = require('fs-extra');
const {addVendorHelper, removeVendorHelper, packRequirements} = require('./lib/zip');
const {installRequirements} = require('./lib/pip');
const {pipfileToRequirements} = require('./lib/pipenv');
const {linkRequirements, unlinkRequirements} = require('./lib/link');
const {cleanup} = require('./lib/clean');

BbPromise.promisifyAll(fse);

/**
 * Plugin for Serverless 1.x that bundles python requirements!
 */
class ServerlessPythonRequirements {
  /**
   * get the custom.pythonRequirements contents, with defaults set
   * @return {Object}
   */
  get options() {
    const options = Object.assign({
      zip: false,
      cleanupZipHelper: true,
      invalidateCaches: false,
      fileName: 'requirements.txt',
      usePipenv: true,
      pythonBin: this.serverless.service.provider.runtime || 'python',
      dockerizePip: false,
      dockerSsh: false,
      dockerImage: null,
      dockerFile: null,
      pipCmdExtraArgs: [],
      noDeploy: [
        'boto3',
        'botocore',
        'docutils',
        'jmespath',
        'python-dateutil',
        's3transfer',
        'six',
        'pip',
        'setuptools',
      ],
    }, this.serverless.service.custom && this.serverless.service.custom.pythonRequirements || {});
    if (options.dockerizePip === 'non-linux') {
      options.dockerizePip = process.platform !== 'linux';
    }
    if (options.dockerImage && options.dockerFile) {
      throw new Error('You can provide a dockerImage or a dockerFile option, not both.');
    } else if (!options.dockerFile) {
      // If no dockerFile is provided, use default image
      const defaultImage = `lambci/lambda:build-${this.serverless.service.provider.runtime}`;
      options.dockerImage = options.dockerImage || defaultImage;
    }
    return options;
  }

  /**
   * The plugin constructor
   * @param {Object} serverless
   * @param {Object} options
   * @return {undefined}
   */
  constructor(serverless, options) {
    this.serverless = serverless;
    this.servicePath = this.serverless.config.servicePath;

    this.commands = {
      requirements: {
        commands: {
          clean: {
            usage: 'Remove .requirements and requirements.zip',
            lifecycleEvents: [
              'clean',
            ],
          },
          install: {
            usage: 'install requirements manually',
            lifecycleEvents: [
              'install',
            ],
          },
        },
      },
    };

    const before = () => BbPromise.bind(this)
      .then(pipfileToRequirements)
      .then(addVendorHelper)
      .then(installRequirements)
      .then(packRequirements)
      .then(linkRequirements);

    const after = () => BbPromise.bind(this)
      .then(removeVendorHelper)
      .then(unlinkRequirements);

    const invalidateCaches = () => {
      if (this.options.invalidateCaches) {
        return BbPromise.bind(this)
          .then(cleanup)
          .then(removeVendorHelper);
      }
      return BbPromise.resolve();
    };

    this.hooks = {
      'after:package:cleanup': invalidateCaches,
      'before:package:createDeploymentArtifacts': before,
      'after:package:createDeploymentArtifacts': after,
      'before:deploy:function:packageFunction': before,
      'after:deploy:function:packageFunction': after,
      'requirements:install:install': () => BbPromise.bind(this)
        .then(pipfileToRequirements)
        .then(addVendorHelper)
        .then(installRequirements)
        .then(packRequirements),
      'requirements:clean:clean': () => BbPromise.bind(this)
        .then(cleanup)
        .then(removeVendorHelper),
    };
  }
}

module.exports = ServerlessPythonRequirements;
<commit_msg>Add warning for docker related options<commit_after>/* jshint ignore:start */
'use strict';

const BbPromise = require('bluebird');
const fse = require('fs-extra');
const {addVendorHelper, removeVendorHelper, packRequirements} = require('./lib/zip');
const {installRequirements} = require('./lib/pip');
const {pipfileToRequirements} = require('./lib/pipenv');
const {linkRequirements, unlinkRequirements} = require('./lib/link');
const {cleanup} = require('./lib/clean');

BbPromise.promisifyAll(fse);

/**
 * Plugin for Serverless 1.x that bundles python requirements!
 */
class ServerlessPythonRequirements {
  /**
   * get the custom.pythonRequirements contents, with defaults set
   * @return {Object}
   */
  get options() {
    const options = Object.assign({
      zip: false,
      cleanupZipHelper: true,
      invalidateCaches: false,
      fileName: 'requirements.txt',
      usePipenv: true,
      pythonBin: this.serverless.service.provider.runtime || 'python',
      dockerizePip: false,
      dockerSsh: false,
      dockerImage: null,
      dockerFile: null,
      pipCmdExtraArgs: [],
      noDeploy: [
        'boto3',
        'botocore',
        'docutils',
        'jmespath',
        'python-dateutil',
        's3transfer',
        'six',
        'pip',
        'setuptools',
      ],
    }, this.serverless.service.custom && this.serverless.service.custom.pythonRequirements || {});
    if (options.dockerizePip === 'non-linux') {
      options.dockerizePip = process.platform !== 'linux';
    }
    if (options.dockerImage && options.dockerFile) {
      throw new Error(
        'Python Requirements: you can provide a dockerImage or a dockerFile option, not both.'
      );
    } else if (!options.dockerFile) {
      // If no dockerFile is provided, use default image
      const defaultImage = `lambci/lambda:build-${this.serverless.service.provider.runtime}`;
      options.dockerImage = options.dockerImage || defaultImage;
    }
    if (!options.dockerizePip && (options.dockerSsh || options.dockerImage || options.dockerFile)) {
      if (!this.warningLogged) {
          this.serverless.cli.log(
            'WARNING: You provided a docker related option but dockerizePip is set to false.'
          );
          this.warningLogged = true;
      }
    }
    return options;
  }

  /**
   * The plugin constructor
   * @param {Object} serverless
   * @param {Object} options
   * @return {undefined}
   */
  constructor(serverless, options) {
    this.serverless = serverless;
    this.servicePath = this.serverless.config.servicePath;
    this.warningLogged = false;

    this.commands = {
      requirements: {
        commands: {
          clean: {
            usage: 'Remove .requirements and requirements.zip',
            lifecycleEvents: [
              'clean',
            ],
          },
          install: {
            usage: 'install requirements manually',
            lifecycleEvents: [
              'install',
            ],
          },
        },
      },
    };

    const before = () => BbPromise.bind(this)
      .then(pipfileToRequirements)
      .then(addVendorHelper)
      .then(installRequirements)
      .then(packRequirements)
      .then(linkRequirements);

    const after = () => BbPromise.bind(this)
      .then(removeVendorHelper)
      .then(unlinkRequirements);

    const invalidateCaches = () => {
      if (this.options.invalidateCaches) {
        return BbPromise.bind(this)
          .then(cleanup)
          .then(removeVendorHelper);
      }
      return BbPromise.resolve();
    };

    this.hooks = {
      'after:package:cleanup': invalidateCaches,
      'before:package:createDeploymentArtifacts': before,
      'after:package:createDeploymentArtifacts': after,
      'before:deploy:function:packageFunction': before,
      'after:deploy:function:packageFunction': after,
      'requirements:install:install': () => BbPromise.bind(this)
        .then(pipfileToRequirements)
        .then(addVendorHelper)
        .then(installRequirements)
        .then(packRequirements),
      'requirements:clean:clean': () => BbPromise.bind(this)
        .then(cleanup)
        .then(removeVendorHelper),
    };
  }
}

module.exports = ServerlessPythonRequirements;
<|endoftext|>


<commit_before>import colors, { fg, reset as colorEnd } from 'ansi-256-colors';

const {
    getRgb: rgb
} = fg;

const SPACER = rgb(1, 1, 1) + '┈' + colorEnd;
const GET_LEVEL = responseTime => Math.floor(responseTime / 50) - 1;

function join(strings, ...values) {
    const indent = strings[0].match(/\n( *)/)[1];

    let result = '';

    for (let i = 0; i < strings.length; i++) {
        const split = strings[i].split(indent);

        result += (split[1] || '') + (values[i] || '');

        if (i !== strings.length - 1) {
            result += ' ';
        }
    }

    return result;
}

function chars(character, num) {
    let string = '';

    for (let i = 0; i < num; i++) {
        string += character;
    }

    return string;
}

function breakLines(message, messageWidth, map) {
    const lines = [];

    for (let i = 0; i < message.length; i = i + messageWidth) {
        let line = message.substr(i, messageWidth);

        const lineBreak = line.indexOf('\n');

        if (lineBreak >= 0) {
            line = line.substr(0, lineBreak);
            i = i - messageWidth + lineBreak + 1;
        }

        lines.push(line);
    }

    for (let i = 0; i < lines.length; i++) {
        map(lines[i], i, lines);
    }
}

function colorize(color = 0) {
    if (typeof color === 'number') {
        if (color <= 0) {
            return character => character;
        }

        let green = 6 - color;

        if (green < 0) {
            green = 0;
        }

        return character => rgb(5, green, 0) + character + colorEnd;
    } else {
        let format;

        switch (color) {
        case 'info':
            format = colors.fg.standard[4];
            break;
        case 'warning':
            format = rgb(5, 5, 0);
            break;
        case 'error':
            format = rgb(5, 2, 0);
            break;
        case 'fatal':
            format = rgb(5, 0, 0);
            break;
        }

        if (format) {
            return character => format + character + colorEnd;
        } else {
            return character => character;
        }
    }
}

function printToConsole(maxLocaleTimeLength, width, slim, slots, slot, colorizer) {
    return (meta = () => false, format, formatLine, char, separator = SPACER) => {
        return (...args) => {
            if (!formatLine) {
                if (format) {
                    formatLine = format;
                } else {
                    formatLine = string => string;
                }
            }

            const message = args.map(arg => {
                if (arg instanceof Error) {
                    return arg.stack;
                }

                if (arg instanceof Object) {
                    return JSON.stringify(arg, null, 2).replace(/\\n/g, '\n');
                }

                return arg;
            }).join(' ');

            const timeLength = maxLocaleTimeLength();

            const now = new Date;

            const _slots = slots.map(slot =>
                slot ? colorizer(now - slot)('│') : separator
            );

            let messageWidth;

            if (width) {
                messageWidth = (
                    width - 4 - timeLength - 6 - slots.length * 2 - 1
                );
            } else {
                messageWidth = message.length;
            }

            breakLines(message, messageWidth, (line, i, lines) => {
                let $meta = meta(i, lines.length);

                if (!$meta) {
                    $meta = chars(' ', 4 + timeLength + 5);
                }

                _slots[slot] = (
                    format ? (
                        format(char(i, lines.length))
                    ) : (
                        colorizer(now - slots[slot])(char(i, lines.length))
                    )
                );

                const $slots = _slots.join(slim ? '' : separator);

                // eslint-disable-next-line no-console
                console.log(join`
                    ${$meta}
                    ${$slots}
                    ${formatLine(line)}
                `);
            });
        };
    };
}

export default function createLogger(options = {}) {
    const {
        minSlots = 1,
        getLevel = GET_LEVEL,
        width = 80,
        timestamp: showTimestamp = false,
        slim = false,
        req = context => context.originalUrl,
        res = context => context.originalUrl
    } = options;

    const slots = new Array(minSlots).fill(null);

    const colorizer = responseTime => {
        const level = getLevel(responseTime);

        return colorize(level);
    };

    let maxLocaleTimeLength;

    if (showTimestamp) {
        maxLocaleTimeLength = (new Date).toLocaleTimeString().length;
    } else {
        maxLocaleTimeLength = 5;
    }

    return async function logger(context, next) {
        const start = new Date;

        let slot;
        for (let i = 0; i < slots.length; i++) {
            if (!slots[i]) {
                slot = i;
                break;
            }
        }

        if (slot === undefined) {
            slots.push(null);
            slot = slots.length - 1;
        }

        slots[slot] = +start;

        const printer = printToConsole(
            () => maxLocaleTimeLength,
            width,
            slim,
            slots,
            slot,
            colorizer
        );

        const log = printer(undefined, undefined, undefined, () => '╎', ' ');
        log.info = printer(undefined, colorize('info'), undefined, () => '╎', ' ');
        log.error = printer(undefined, colorize('fatal'), undefined, () => '╎', ' ');

        context.log = log;

        const {
            method
        } = context;

        let $method = method.substr(0, 4);

        if ($method.length < 4) {
            $method += chars(SPACER, 4 - method.length);
        }

        {
            let $time;

            if (showTimestamp) {
                $time = start.toLocaleTimeString();

                if ($time.length > maxLocaleTimeLength) {
                    maxLocaleTimeLength = $time.length;
                } else if ($time.length < maxLocaleTimeLength) {
                    $time += (
                        chars(SPACER, maxLocaleTimeLength - $time.length)
                    );
                }
            } else {
                $time = chars(SPACER, maxLocaleTimeLength);
            }

            const meta = i => !i && `⟶   ${$time} ${$method}`;

            const print = printer(meta, undefined, undefined, i => i ? '│' : '┬');

            print(req(context));
        }

        try {
            await next();
        } catch(error) {
            context.status = 500;
            log.error(error);
        }

        const end = new Date;
        const duration = end - start;

        let $duration = `${duration}ms`;

        const durationLength = $duration.length;

        $duration = colorizer(duration)($duration);

        if (durationLength < maxLocaleTimeLength) {
            $duration = (
                chars(SPACER, maxLocaleTimeLength - durationLength) + $duration
            );
        }

        const {
            status
        } = context;

        let $status;

        if (status >= 100 && status < 200) {
            $status = colorize('info')(status);
        } else if (status < 300) {
            $status = status;
        } else if (status >= 300 && status < 400) {
            $status = colorize('warning')(status);
        } else if (status < 500) {
            $status = colorize('error')(status);
        } else {
            $status = colorize('fatal')(status);
        }

        {
            const meta = (i, length) => i === length - 1 && `${$status} ${$duration} ${$method}`;

            const print = printer(meta, undefined, undefined, (i, length) => i === length - 1 ? '┴' : '│');

            print(res(context));
        }

        slots[slot] = null;
    };
}
<commit_msg>Change to object based API for optional arguments / for functions with large argument list<commit_after>import colors, { fg, reset as colorEnd } from 'ansi-256-colors';

const {
    getRgb: rgb
} = fg;

const SPACER = rgb(1, 1, 1) + '┈' + colorEnd;
const GET_LEVEL = responseTime => Math.floor(responseTime / 50) - 1;

function join(strings, ...values) {
    const indent = strings[0].match(/\n( *)/)[1];

    let result = '';

    for (let i = 0; i < strings.length; i++) {
        const split = strings[i].split(indent);

        result += (split[1] || '') + (values[i] || '');

        if (i !== strings.length - 1) {
            result += ' ';
        }
    }

    return result;
}

function chars(character, num) {
    let string = '';

    for (let i = 0; i < num; i++) {
        string += character;
    }

    return string;
}

function breakLines(message, messageWidth, map) {
    const lines = [];

    for (let i = 0; i < message.length; i = i + messageWidth) {
        let line = message.substr(i, messageWidth);

        const lineBreak = line.indexOf('\n');

        if (lineBreak >= 0) {
            line = line.substr(0, lineBreak);
            i = i - messageWidth + lineBreak + 1;
        }

        lines.push(line);
    }

    for (let i = 0; i < lines.length; i++) {
        map(lines[i], i, lines);
    }
}

function colorize(color = 0) {
    if (typeof color === 'number') {
        if (color <= 0) {
            return character => character;
        }

        let green = 6 - color;

        if (green < 0) {
            green = 0;
        }

        return character => rgb(5, green, 0) + character + colorEnd;
    } else {
        let format;

        switch (color) {
        case 'info':
            format = colors.fg.standard[4];
            break;
        case 'warning':
            format = rgb(5, 5, 0);
            break;
        case 'error':
            format = rgb(5, 2, 0);
            break;
        case 'fatal':
            format = rgb(5, 0, 0);
            break;
        }

        if (format) {
            return character => format + character + colorEnd;
        } else {
            return character => character;
        }
    }
}

function printToConsole({
    colorizer,
    maxLocaleTimeLength,
    slim,
    slot,
    slots,
    width
}) {
    return ({
        char,
        format,
        formatLine,
        meta = () => false,
        separator = SPACER
    }) => {
        return (...messages) => {
            if (!formatLine) {
                if (format) {
                    formatLine = format;
                } else {
                    formatLine = string => string;
                }
            }

            const message = messages.map(arg => {
                if (arg instanceof Error) {
                    return arg.stack;
                }

                if (arg instanceof Object) {
                    return JSON.stringify(arg, null, 2).replace(/\\n/g, '\n');
                }

                return arg;
            }).join(' ');

            const timeLength = maxLocaleTimeLength();

            const now = new Date;

            const _slots = slots.map(slot =>
                slot ? colorizer(now - slot)('│') : separator
            );

            let messageWidth;

            if (width) {
                messageWidth = (
                    width - 4 - timeLength - 6 - slots.length * 2 - 1
                );
            } else {
                messageWidth = message.length;
            }

            breakLines(message, messageWidth, (line, i, lines) => {
                let $meta = meta(i, lines.length);

                if (!$meta) {
                    $meta = chars(' ', 4 + timeLength + 5);
                }

                _slots[slot] = (
                    format ? (
                        format(char(i, lines.length))
                    ) : (
                        colorizer(now - slots[slot])(char(i, lines.length))
                    )
                );

                const $slots = _slots.join(slim ? '' : separator);

                // eslint-disable-next-line no-console
                console.log(join`
                    ${$meta}
                    ${$slots}
                    ${formatLine(line)}
                `);
            });
        };
    };
}

export default function createLogger(options = {}) {
    const {
        minSlots = 1,
        getLevel = GET_LEVEL,
        width = 80,
        timestamp: showTimestamp = false,
        slim = false,
        req = context => context.originalUrl,
        res = context => context.originalUrl
    } = options;

    const slots = new Array(minSlots).fill(null);

    const colorizer = responseTime => {
        const level = getLevel(responseTime);

        return colorize(level);
    };

    let maxLocaleTimeLength;

    if (showTimestamp) {
        maxLocaleTimeLength = (new Date).toLocaleTimeString().length;
    } else {
        maxLocaleTimeLength = 5;
    }

    return async function logger(context, next) {
        const start = new Date;

        let slot;
        for (let i = 0; i < slots.length; i++) {
            if (!slots[i]) {
                slot = i;
                break;
            }
        }

        if (slot === undefined) {
            slots.push(null);
            slot = slots.length - 1;
        }

        slots[slot] = +start;

        const printer = printToConsole({
            maxLocaleTimeLength: () => maxLocaleTimeLength,
            width,
            slim,
            slots,
            slot,
            colorizer
        });

        const log = printer({
            char: () => '╎',
            separator: ' '
        });

        log.info = printer({
            char: () => '╎',
            format: colorize('info'),
            separator: ' '
        });

        log.error = printer({
            char: () => '╎',
            format: colorize('fatal'),
            separator: ' '
        });

        context.log = log;

        const {
            method
        } = context;

        let $method = method.substr(0, 4);

        if ($method.length < 4) {
            $method += chars(SPACER, 4 - method.length);
        }

        {
            let $time;

            if (showTimestamp) {
                $time = start.toLocaleTimeString();

                if ($time.length > maxLocaleTimeLength) {
                    maxLocaleTimeLength = $time.length;
                } else if ($time.length < maxLocaleTimeLength) {
                    $time += (
                        chars(SPACER, maxLocaleTimeLength - $time.length)
                    );
                }
            } else {
                $time = chars(SPACER, maxLocaleTimeLength);
            }

            const print = printer({
                char: i => i ? '│' : '┬',
                meta: i => !i && `⟶   ${$time} ${$method}`
            });

            print(req(context));
        }

        try {
            await next();
        } catch(error) {
            context.status = 500;
            log.error(error);
        }

        const end = new Date;
        const duration = end - start;

        let $duration = `${duration}ms`;

        const durationLength = $duration.length;

        $duration = colorizer(duration)($duration);

        if (durationLength < maxLocaleTimeLength) {
            $duration = (
                chars(SPACER, maxLocaleTimeLength - durationLength) + $duration
            );
        }

        const {
            status
        } = context;

        let $status;

        if (status >= 100 && status < 200) {
            $status = colorize('info')(status);
        } else if (status < 300) {
            $status = status;
        } else if (status >= 300 && status < 400) {
            $status = colorize('warning')(status);
        } else if (status < 500) {
            $status = colorize('error')(status);
        } else {
            $status = colorize('fatal')(status);
        }

        {
            const print = printer({
                meta: (i, length) => i === length - 1 && (
                    `${$status} ${$duration} ${$method}`
                ),
                char: (i, length) => i === length - 1 ? '┴' : '│'
            });

            print(res(context));
        }

        slots[slot] = null;
    };
}
<|endoftext|>


<commit_before>Clients = new Mongo.Collection('clients');

ClientSchema = new SimpleSchema({
	name : {
		type: String,
	},
});

Clients.attachSchema( ClientSchema );<commit_msg>Delete Clients.js<commit_after><|endoftext|>


<commit_before>'use strict';

var htmlparser = require('htmlparser2');

/**
 * Parse html to PostHTMLTree
 * @param  {String} html
 * @return {Object}
 */
module.exports = function postHTMLParser(html) {
    var bufArray = [],
        results = [];

    bufArray.last = function() {
        return this[this.length - 1];
    };

    var parser = new htmlparser.Parser({
        onprocessinginstruction: function(name, data) {
            if (name.toLowerCase() === '!doctype') {
                results.push('<' + data + '>');
            }
        },
        oncomment: function(data) {
            var comment = '<!--' + data + '-->',
                last = bufArray.last();

            if (!last) {
                results.push(comment);
                return;
            }

            last.content || (last.content = []);
            last.content.push(comment);
        },
        onopentag: function(tag, attrs) {
            var buf = {};

            buf.tag = tag;

            if (Object.keys(attrs).length) {
                buf.attrs = attrs;
            }

            bufArray.push(buf);
        },
        onclosetag: function() {
            var buf = bufArray.pop();

            if (bufArray.length === 0) {
                results.push(buf);
                return;
            }

            var last = bufArray.last();
            if (!(last.content instanceof Array)) {
                last.content = [];
            }
            last.content.push(buf);
        },
        ontext: function(text) {
            var last = bufArray.last();
            if (!last) {
                results.push(text);
                return;
            }

            last.content || (last.content = []);
            last.content.push(text);
        }
    }, {lowerCaseTags: false});

    parser.write(html);
    parser.end();

    return results;
};
<commit_msg>minor improvements<commit_after>'use strict';

var htmlparser = require('htmlparser2');

/**
 * Parse html to PostHTMLTree
 * @param  {String} html
 * @return {Object}
 */
module.exports = function postHTMLParser(html) {
    var bufArray = [],
        results = [];

    bufArray.last = function() {
        return this[this.length - 1];
    };

    var parser = new htmlparser.Parser({
        onprocessinginstruction: function(name, data) {
            if (name.toLowerCase() === '!doctype') {
                results.push('<' + data + '>');
            }
        },
        oncomment: function(data) {
            var comment = '<!--' + data + '-->',
                last = bufArray.last();

            if (!last) {
                results.push(comment);
                return;
            }

            last.content || (last.content = []);
            last.content.push(comment);
        },
        onopentag: function(tag, attrs) {
            var buf = { tag: tag };

            if (Object.keys(attrs).length) {
                buf.attrs = attrs;
            }

            bufArray.push(buf);
        },
        onclosetag: function() {
            var buf = bufArray.pop();

            if (!bufArray.length) {
                results.push(buf);
                return;
            }

            var last = bufArray.last();
            if (!Array.isArray(last.content)) {
                last.content = [];
            }

            last.content.push(buf);
        },
        ontext: function(text) {
            var last = bufArray.last();
            if (!last) {
                results.push(text);
                return;
            }

            last.content || (last.content = []);
            last.content.push(text);
        }
    }, {lowerCaseTags: false});

    parser.write(html);
    parser.end();

    return results;
};
<|endoftext|>


<commit_before>var express         = require('express');
var path            = require('path');
var swig            = require('swig');

var app             = express();
var config          = require('./package').config;
var db              = require('./db');

// Establecemos la configuración de la plantillas Swig.
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, 'views'));
app.set('view cache', !config.debug);
swig.setDefaults({ cache: config.debug ? false : 'memory' });

// Estableciendo las rutas

var router = express.Router();

var homeController = require('./controllers/home-controller');
var authController = require('./controllers/auth-controller');
var userController = require('./controllers/user-controller');
var friendController = require('./controllers/friend-controller');
var wallController = require('./controllers/wall-controller');

router.route('/')
	.get(homeController.index);

router.route('/auth')
	.get(authController.login)
	.post(authController.login);

router.route('/auth/logout')
	.get(authController.logout);

router.route('/user/:id')
	.get(userController.index)
	.post(userController.add);

router.route('/user/:id/modify')
	.get(userController.modify);

router.route('/user/:id/delete')
	.get(userController.delete);

router.route('/friends')
	.get(friendController.index)
	.post(friendController.add);

router.route('/friends/:id/accept')
	.get(friendController.accept);

router.route('/friends/:id/ignore')
	.get(friendController.ignore);

router.route('/friends/:id/delete')
	.get(friendController.delete);

router.route('/wall')
	.get(wallController.index)
	.post(wallController.addPost);

router.route('/wall/:id')
	.get(wallController.getPost);

router.route('/wall/:id/delete')
	.get(wallController.deletePost);

app.use(router);

// Conectamos con la base de datos
db.connect();

// Iniciamos el servidor
app.listen(config.port, function() {
	console.log("INFO (index.js) - Servidor web iniciado (Puerto: " + config.port + ").");
});

process.on('SIGINT', function() {
	console.log("INFO (index.js) - Apagando servidor web...");
	db.disconnect();
	process.exit(0);
});
<commit_msg>Añadido soporte para archivos estáticos<commit_after>var express         = require('express');
var path            = require('path');
var swig            = require('swig');

var app             = express();
var config          = require('./package').config;
var db              = require('./db');

// Establecemos la configuración de la plantillas Swig.
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, 'views'));
app.set('view cache', !config.debug);
swig.setDefaults({ cache: config.debug ? false : 'memory' });

// Estableciendo las rutas
var router = express.Router();

//var fileController = require('./controllers/file-controller');
var homeController = require('./controllers/home-controller');
var authController = require('./controllers/auth-controller');
var userController = require('./controllers/user-controller');
var friendController = require('./controllers/friend-controller');
var wallController = require('./controllers/wall-controller');

router.route('/')
	.get(homeController.index);

router.route('/auth')
	.get(authController.login)
	.post(authController.login);

router.route('/auth/logout')
	.get(authController.logout);

router.route('/user/:id')
	.get(userController.index)
	.post(userController.add);

router.route('/user/:id/modify')
	.get(userController.modify);

router.route('/user/:id/delete')
	.get(userController.delete);

router.route('/friends')
	.get(friendController.index)
	.post(friendController.add);

router.route('/friends/:id/accept')
	.get(friendController.accept);

router.route('/friends/:id/ignore')
	.get(friendController.ignore);

router.route('/friends/:id/delete')
	.get(friendController.delete);

router.route('/wall')
	.get(wallController.index)
	.post(wallController.addPost);

router.route('/wall/:id')
	.get(wallController.getPost);

router.route('/wall/:id/delete')
	.get(wallController.deletePost);

app.use(router);

// Establecemos la carpeta de archivos estaticos
app.use('/static', express.static(path.join(__dirname, 'public')));

// Conectamos con la base de datos
db.connect();

// Iniciamos el servidor
app.listen(config.port, function() {
	console.log("INFO (index.js) - Servidor web iniciado (Puerto: " + config.port + ").");
});

process.on('SIGINT', function() {
	console.log("INFO (index.js) - Apagando servidor web...");
	db.disconnect();
	process.exit(0);
});
<|endoftext|>


<commit_before>var parseArgs = require('./lib/parse-args')
var budo = require('./lib/budo')
var color = require('term-color')

module.exports = budo
module.exports.cli = budoCLI

function budoCLI (args, opts) {
  var argv = parseArgs(args, opts)

  // default to stdout
  if (argv.stream !== false) {
    argv.stream = process.stdout
  }

  var entries = argv._
  delete argv._

  argv.browserifyArgs = argv['--']
  delete argv['--']

  if (argv.version) {
    console.log(require('./package.json').version)
    return null
  }

  if (argv.help) {
    var help = require('path').join(__dirname, 'bin', 'help.txt')
    require('fs').createReadStream(help)
      .pipe(process.stdout)
    return null
  }

  if (argv.outfile) {
    console.error(color.yellow('WARNING'), '--outfile has been removed in budo@3.0')
    // ensure we don't pass to watchify
    delete argv.outfile
  }

  // opts.live can be a glob or a boolean
  if (typeof argv.live === 'string' && /(true|false)/.test(argv.live)) {
    argv.live = argv.live === 'true'
  }

  return budo(entries, argv).on('error', exit)
}

function exit (err) {
  console.log(color.red('ERROR'), err.message)
  process.exit(1)
}
<commit_msg>testing onupdate exec events<commit_after>var parseArgs = require('./lib/parse-args')
var budo = require('./lib/budo')
var color = require('term-color')
var exec = require('child_process').exec

module.exports = budo
module.exports.cli = budoCLI

function budoCLI (args, opts) {
  var argv = parseArgs(args, opts)

  // default to stdout
  if (argv.stream !== false) {
    argv.stream = process.stdout
  }

  var entries = argv._
  delete argv._

  argv.browserifyArgs = argv['--']
  delete argv['--']

  if (argv.version) {
    console.log(require('./package.json').version)
    return null
  }

  if (argv.help) {
    var help = require('path').join(__dirname, 'bin', 'help.txt')
    require('fs').createReadStream(help)
      .pipe(process.stdout)
    return null
  }

  if (argv.outfile) {
    console.error(color.yellow('WARNING'), '--outfile has been removed in budo@3.0')
    // ensure we don't pass to watchify
    delete argv.outfile
  }

  // opts.live can be a glob or a boolean
  if (typeof argv.live === 'string' && /(true|false)/.test(argv.live)) {
    argv.live = argv.live === 'true'
  }

  var instance = budo(entries, argv).on('error', exit)
  var onUpdates = [].concat(argv.onupdate).filter(Boolean)
  onUpdates.forEach(function (cmd) {
    instance.on('update', execFunc(cmd))
  })

  return instance
}

function execFunc (cmd) {
  return function run () {
    var p = exec(cmd)
    p.stderr.pipe(process.stderr)
    p.stdout.pipe(process.stdout)
  }
}

function exit (err) {
  console.log(color.red('ERROR'), err.message)
  process.exit(1)
}
<|endoftext|>


<commit_before>var events = require('events');
var fs = require('fs');
var path = require('path'), basename = path.basename;
var util = require('util');
var camelcase = require('cli-util').camelcase;

var mutators = {
  cmd: {
    commands: false,
    arguments: false,
    names: false,
    key: true,
    name: true,
    id: true,
    description: true,
    action: true
  },
  arg: {
    names: false,
    key: true,
    name: true,
    id: true,
    optional: true,
    multiple: true,
    value: true,
    converter: true,
    extra: true,
    description: true,
    action: true
  },
  prg: {
    converter: true
  }
}

var k, keys;
var delimiter = /[ ,|]+/;
var required = /^</;
var multiple = /\.\.\./;

function initialize(options, properties) {
  for(var z in options) {
    if(~properties.indexOf(z) && options[z]) this[z](options[z]);
  }
}

/**
 *  Retrieve the key for an option.
 *
 *  Scope is the option. Alternatively you may pass a
 *  string of the raw name passed when instantiating the options.
 *
 *  @param names Array of names or raw string name (optional).
 */
function getKey(names) {
  var k, names = names || this._names;
  var name = this._name;
  if(typeof names == 'string') {
    name = names;
    names = names.split(delimiter);
  }
  if(!names.length || !names[0]) {
    throw new Error('Invalid option name \'' + name + '\'');
  }

  var k = names.reduce(
    function (a, b) { return a.length > b.length ? a : b; });
  k = k.replace(/^-+/, '');
  return camelcase(k.toLowerCase());
}

var EventProxy = {
  setMaxListeners: function() {
    return this._emitter.setMaxListeners.apply(this, arguments);
  },
  emit: function() {
    return this._emitter.emit.apply(this, arguments);
  },
  addListener: function() {
    return this._emitter.addListener.apply(this, arguments);
  },
  on: function() {
    return this._emitter.on.apply(this, arguments);
  },
  once: function() {
    return this._emitter.once.apply(this, arguments);
  },
  removeListener: function() {
    return this._emitter.removeListener.apply(this, arguments);
  },
  removeAllListeners: function() {
    return this._emitter.removeAllListeners.apply(this, arguments);
  },
  listeners: function() {
    return this._emitter.listeners.apply(this, arguments);
  }
}

var enumerable = process.env.CLI_TOOLKIT_DEBUG ? true : false;

function toString(delimiter) {
  if(!arguments.length) return Object.prototype.toString.call(this);
  delimiter = delimiter || ' | ';
  var names = this.names() || [];
  return names.join(delimiter);
}

function define(obj, name, value, writable) {
  writable = writable || false;
  Object.defineProperty(obj, name,
    {
      enumerable: enumerable,
      configurable: false,
      writable: writable,
      value: value
    }
  );
}

/**
 *  Abstract super class.
 *
 *  @param name The argument name.
 *  @param description The argument description.
 *  @param options The argument options or conversion function.
 */
var Argument = function(name, description, options) {
  if(typeof name == 'object') options = name;
  define(this, '_name', name || '', true);
  define(this, '_description', description || '', true);
  define(this, '_key', '', true);
  define(this, '_id', '', true);
  define(this, '_optional', true, true);
  define(this, '_multiple', false, true);
  define(this, '_value', undefined, true);
  define(this, '_converter', undefined, true);
  define(this, '_action', undefined, true);
  define(this, '_extra', undefined, true);
  define(this, '_names', undefined, true);

  // event emitter
  define(this, '_emitter', new events.EventEmitter(), false);
  define(this, '_events', undefined, true);
  define(this, '_maxListeners', undefined, true);
  define(this, 'domain', undefined, true);

  if(options === JSON) {
    this._converter = JSON;
  }else if(options && (typeof options == 'object') && !Array.isArray(options)) {
    initialize.call(this, options, Object.keys(mutators.arg));
  }else if((typeof options == 'function') || this.isFunctionArray(options)){
    this._converter = options;
    if(arguments.length > 3 && this._value === undefined) {
      this._value = arguments[3];
    }
  }else {
    this._value = options;
    if(arguments.length > 3
      && (typeof(arguments[3]) == 'function'
      || this.isFunctionArray(options))) {
      this._converter = arguments[3];
    }
  }
  this._names = this._name.split(delimiter);
  for(var i = 0;i < this._names.length;i++) {
    if(/^(\[|<)/.test(this._names[i])) {
      this._extra = this._names.slice(i).join(' ');
      this._names = this._names.slice(0, i);
      break;
    }
  }
  if(required.test(this._extra)) {
    this._optional = false;
  }
  if(multiple.test(this._extra)) {
    this._multiple = true;
  }
  this._key = getKey.call(this);
}

define(Argument.prototype, 'toString', toString, false);

for(k in EventProxy) {
  define(Argument.prototype, k, EventProxy[k], false);
}

/**
 *  Determines whether an array consists solely of functions
 *  allowing for the special case JSON.
 *
 *  @param arr The array candidate.
 */
Argument.prototype.isFunctionArray = function(arr) {
  if(!Array.isArray(arr)) return false;
  var i, item;
  for(i = 0;i < arr.length;i++) {
    item = arr[i];
    if(item !== JSON && !(typeof item == 'function')) return false;
  }
  return true;
}

keys = Object.keys(mutators.arg);
keys.forEach(function(name) {
  var read = function() {
    return this['_' + name];
  }
  var write = function(value) {
    var key = '_' + name;
    if(!arguments.length) return this[key];
    this[key] = value;
    return this;
  }
  define(Argument.prototype, name, mutators.arg[name] ? write : read, false);
})

/**
 *  Represents an option argument.
 */
var Option = function() {
  Argument.apply(this, arguments);
}

util.inherits(Option, Argument);

/**
 *  Represents a flag argument.
 */
var Flag = function() {
  Argument.apply(this, arguments);
  //console.log('Flag %s %s', this._name, this._description);
  this._value = false;
}

util.inherits(Flag, Argument);

/**
 *  Represents a command argument.
 */
var Command = function(name, description, options) {
  //events.EventEmitter.call(this);
  if(typeof name == 'object') options = name;

  // private
  define(this, '_commands', {}, true);
  define(this, '_arguments', {}, true);
  define(this, '_name', name || '', true);
  define(this, '_description', description || '', true);
  define(this, '_key', '', true);
  define(this, '_id', '', true);
  define(this, '_action', undefined, true);
  define(this, '_names', undefined, true);
  define(this, '_package', undefined, true);

  // event emitter
  define(this, '_emitter', new events.EventEmitter(), false);
  define(this, '_events', undefined, true);
  define(this, '_maxListeners', undefined, true);
  define(this, 'domain', undefined, true);

  // public
  define(this, 'args', undefined, true);

  if((typeof options == 'object')) {
    initialize.call(this, options, Object.keys(mutators.cmd));
  }
  this._names = this._name.split(delimiter);
  this._key = getKey.call(this);
}

define(Command.prototype, 'toString', toString, false);

for(k in EventProxy) {
  define(Command.prototype, k, EventProxy[k], false);
}

keys = Object.keys(mutators.cmd);
keys.forEach(function(name) {
  var read = function() {
    return this['_' + name];
  }
  var write = function(value) {
    var key = '_' + name;
    if(value === undefined) return this[key];
    this[key] = value;
    return this;
  }
  define(Command.prototype, name, mutators.cmd[name] ? write : read, false);
})

/**
 *  Define a command argument.
 */
function command(name, description, options) {
  var opt = (name instanceof Command) ? name
    : new Command(name, description, options);
  this._commands[opt.key()] = opt;
  return description ? this : opt;
}
define(Command.prototype, 'command', command, false);

/**
 *  Define an option argument.
 */
function option(name, description, options, coerce, value) {
  var clazz = Option;
  if(typeof name == 'string' && !/[<\[]/.test(name)) {
    clazz = Flag;
  }
  var opt = (name instanceof clazz) ? name
    : new clazz(name, description, options, coerce, value);
  this._arguments[opt.key()] = opt;
  return this;
}
define(Command.prototype, 'option', option, false);

/**
 *  Define a flag argument explicitly.
 */
function flag(name, description, options, coerce, value) {
  var opt = (name instanceof Flag) ? name
    : new Flag(name, description, options, coerce, value);
  this._arguments[opt.key()] = opt;
  return this;
}
define(Command.prototype, 'flag', flag, false);

/**
 *  Represents the program.
 */
var Program = function() {
  Command.apply(this, arguments);
  define(this, '_version', '0.0.1', true);
  define(this, '_package', undefined, true);
  define(this, '_converter', undefined, true);
  define(this, '_author', undefined, true);
  define(this, '_usage', undefined, true);
}

util.inherits(Program, Command);

keys = Object.keys(mutators.prg);
keys.forEach(function(name) {
  var write = function(value) {
    var key = '_' + name;
    if(!arguments.length) return this[key];
    this[key] = value;
    return this;
  }
  define(Program.prototype, name, write, false);
})

/**
 *  Set the program package descriptor.
 *
 *  @param path The path to the package descriptor.
 */
function package(path) {
  if(!arguments.length && this._package) return this._package;
  if(path && fs.existsSync(path)) {
    try {
      var pkg = this._package = require(path);
      this._version = pkg.version;
      if(pkg.author) this._author = pkg.author;
      if(pkg.description) this._description = pkg.description;
    }catch(e) {
      throw new Error(util.format(
        'package parse error %s (malformed json)', path));
    }
  }else if(path) {
    throw new Error(util.format(
      'package descriptor %s does not exist', path));
  }
  return this;
}
define(Program.prototype, 'package', package, false);

/**
 *  Set the program usage string.
 *
 *  @param usage The program usage string.
 */
function usage(usage) {
  if(!arguments.length && this._usage) return this._usage;
  this._usage = usage;
  return this;
}
define(Program.prototype, 'usage', usage, false);

/**
 *  Initialize the program from a package.json
 *  project descriptor, optionally overriding
 *  the name, description and class to instantiate.
 *
 *  @param package The path to package.json.
 *  @param name A specific name for the root command (optional).
 *  @param description A specific description for the root command (optional).
 *  @param clazz A specific class to instantiate.
 */
function create(package, name, description, clazz) {
  clazz = clazz || Program;
  var program = new clazz(basename(process.argv[1]));
  program.package(package);
  if(name) program.name(name);
  if(description) program.description(description);
  return program;
}

module.exports = create;
module.exports.define = define;
module.exports.key = getKey;
module.exports.Program = Program;
module.exports.Command = Command;
module.exports.Option = Option;
module.exports.Flag = Flag;
<commit_msg>Remove _author property.<commit_after>var events = require('events');
var fs = require('fs');
var path = require('path'), basename = path.basename;
var util = require('util');
var camelcase = require('cli-util').camelcase;

var mutators = {
  cmd: {
    commands: false,
    arguments: false,
    names: false,
    key: true,
    name: true,
    id: true,
    description: true,
    action: true
  },
  arg: {
    names: false,
    key: true,
    name: true,
    id: true,
    optional: true,
    multiple: true,
    value: true,
    converter: true,
    extra: true,
    description: true,
    action: true
  },
  prg: {
    converter: true
  }
}

var k, keys;
var delimiter = /[ ,|]+/;
var required = /^</;
var multiple = /\.\.\./;

function initialize(options, properties) {
  for(var z in options) {
    if(~properties.indexOf(z) && options[z]) this[z](options[z]);
  }
}

/**
 *  Retrieve the key for an option.
 *
 *  Scope is the option. Alternatively you may pass a
 *  string of the raw name passed when instantiating the options.
 *
 *  @param names Array of names or raw string name (optional).
 */
function getKey(names) {
  var k, names = names || this._names;
  var name = this._name;
  if(typeof names == 'string') {
    name = names;
    names = names.split(delimiter);
  }
  if(!names.length || !names[0]) {
    throw new Error('Invalid option name \'' + name + '\'');
  }

  var k = names.reduce(
    function (a, b) { return a.length > b.length ? a : b; });
  k = k.replace(/^-+/, '');
  return camelcase(k.toLowerCase());
}

var EventProxy = {
  setMaxListeners: function() {
    return this._emitter.setMaxListeners.apply(this, arguments);
  },
  emit: function() {
    return this._emitter.emit.apply(this, arguments);
  },
  addListener: function() {
    return this._emitter.addListener.apply(this, arguments);
  },
  on: function() {
    return this._emitter.on.apply(this, arguments);
  },
  once: function() {
    return this._emitter.once.apply(this, arguments);
  },
  removeListener: function() {
    return this._emitter.removeListener.apply(this, arguments);
  },
  removeAllListeners: function() {
    return this._emitter.removeAllListeners.apply(this, arguments);
  },
  listeners: function() {
    return this._emitter.listeners.apply(this, arguments);
  }
}

var enumerable = process.env.CLI_TOOLKIT_DEBUG ? true : false;

function toString(delimiter) {
  if(!arguments.length) return Object.prototype.toString.call(this);
  delimiter = delimiter || ' | ';
  var names = this.names() || [];
  return names.join(delimiter);
}

function define(obj, name, value, writable) {
  writable = writable || false;
  Object.defineProperty(obj, name,
    {
      enumerable: enumerable,
      configurable: false,
      writable: writable,
      value: value
    }
  );
}

/**
 *  Abstract super class.
 *
 *  @param name The argument name.
 *  @param description The argument description.
 *  @param options The argument options or conversion function.
 */
var Argument = function(name, description, options) {
  if(typeof name == 'object') options = name;
  define(this, '_name', name || '', true);
  define(this, '_description', description || '', true);
  define(this, '_key', '', true);
  define(this, '_id', '', true);
  define(this, '_optional', true, true);
  define(this, '_multiple', false, true);
  define(this, '_value', undefined, true);
  define(this, '_converter', undefined, true);
  define(this, '_action', undefined, true);
  define(this, '_extra', undefined, true);
  define(this, '_names', undefined, true);

  // event emitter
  define(this, '_emitter', new events.EventEmitter(), false);
  define(this, '_events', undefined, true);
  define(this, '_maxListeners', undefined, true);
  define(this, 'domain', undefined, true);

  if(options === JSON) {
    this._converter = JSON;
  }else if(options && (typeof options == 'object') && !Array.isArray(options)) {
    initialize.call(this, options, Object.keys(mutators.arg));
  }else if((typeof options == 'function') || this.isFunctionArray(options)){
    this._converter = options;
    if(arguments.length > 3 && this._value === undefined) {
      this._value = arguments[3];
    }
  }else {
    this._value = options;
    if(arguments.length > 3
      && (typeof(arguments[3]) == 'function'
      || this.isFunctionArray(options))) {
      this._converter = arguments[3];
    }
  }
  this._names = this._name.split(delimiter);
  for(var i = 0;i < this._names.length;i++) {
    if(/^(\[|<)/.test(this._names[i])) {
      this._extra = this._names.slice(i).join(' ');
      this._names = this._names.slice(0, i);
      break;
    }
  }
  if(required.test(this._extra)) {
    this._optional = false;
  }
  if(multiple.test(this._extra)) {
    this._multiple = true;
  }
  this._key = getKey.call(this);
}

define(Argument.prototype, 'toString', toString, false);

for(k in EventProxy) {
  define(Argument.prototype, k, EventProxy[k], false);
}

/**
 *  Determines whether an array consists solely of functions
 *  allowing for the special case JSON.
 *
 *  @param arr The array candidate.
 */
Argument.prototype.isFunctionArray = function(arr) {
  if(!Array.isArray(arr)) return false;
  var i, item;
  for(i = 0;i < arr.length;i++) {
    item = arr[i];
    if(item !== JSON && !(typeof item == 'function')) return false;
  }
  return true;
}

keys = Object.keys(mutators.arg);
keys.forEach(function(name) {
  var read = function() {
    return this['_' + name];
  }
  var write = function(value) {
    var key = '_' + name;
    if(!arguments.length) return this[key];
    this[key] = value;
    return this;
  }
  define(Argument.prototype, name, mutators.arg[name] ? write : read, false);
})

/**
 *  Represents an option argument.
 */
var Option = function() {
  Argument.apply(this, arguments);
}

util.inherits(Option, Argument);

/**
 *  Represents a flag argument.
 */
var Flag = function() {
  Argument.apply(this, arguments);
  //console.log('Flag %s %s', this._name, this._description);
  this._value = false;
}

util.inherits(Flag, Argument);

/**
 *  Represents a command argument.
 */
var Command = function(name, description, options) {
  //events.EventEmitter.call(this);
  if(typeof name == 'object') options = name;

  // private
  define(this, '_commands', {}, true);
  define(this, '_arguments', {}, true);
  define(this, '_name', name || '', true);
  define(this, '_description', description || '', true);
  define(this, '_key', '', true);
  define(this, '_id', '', true);
  define(this, '_action', undefined, true);
  define(this, '_names', undefined, true);
  define(this, '_package', undefined, true);

  // event emitter
  define(this, '_emitter', new events.EventEmitter(), false);
  define(this, '_events', undefined, true);
  define(this, '_maxListeners', undefined, true);
  define(this, 'domain', undefined, true);

  // public
  define(this, 'args', undefined, true);

  if((typeof options == 'object')) {
    initialize.call(this, options, Object.keys(mutators.cmd));
  }
  this._names = this._name.split(delimiter);
  this._key = getKey.call(this);
}

define(Command.prototype, 'toString', toString, false);

for(k in EventProxy) {
  define(Command.prototype, k, EventProxy[k], false);
}

keys = Object.keys(mutators.cmd);
keys.forEach(function(name) {
  var read = function() {
    return this['_' + name];
  }
  var write = function(value) {
    var key = '_' + name;
    if(value === undefined) return this[key];
    this[key] = value;
    return this;
  }
  define(Command.prototype, name, mutators.cmd[name] ? write : read, false);
})

/**
 *  Define a command argument.
 */
function command(name, description, options) {
  var opt = (name instanceof Command) ? name
    : new Command(name, description, options);
  this._commands[opt.key()] = opt;
  return description ? this : opt;
}
define(Command.prototype, 'command', command, false);

/**
 *  Define an option argument.
 */
function option(name, description, options, coerce, value) {
  var clazz = Option;
  if(typeof name == 'string' && !/[<\[]/.test(name)) {
    clazz = Flag;
  }
  var opt = (name instanceof clazz) ? name
    : new clazz(name, description, options, coerce, value);
  this._arguments[opt.key()] = opt;
  return this;
}
define(Command.prototype, 'option', option, false);

/**
 *  Define a flag argument explicitly.
 */
function flag(name, description, options, coerce, value) {
  var opt = (name instanceof Flag) ? name
    : new Flag(name, description, options, coerce, value);
  this._arguments[opt.key()] = opt;
  return this;
}
define(Command.prototype, 'flag', flag, false);

/**
 *  Represents the program.
 */
var Program = function() {
  Command.apply(this, arguments);
  define(this, '_version', '0.0.1', true);
  define(this, '_package', undefined, true);
  define(this, '_converter', undefined, true);
  define(this, '_usage', undefined, true);
}

util.inherits(Program, Command);

keys = Object.keys(mutators.prg);
keys.forEach(function(name) {
  var write = function(value) {
    var key = '_' + name;
    if(!arguments.length) return this[key];
    this[key] = value;
    return this;
  }
  define(Program.prototype, name, write, false);
})

/**
 *  Set the program package descriptor.
 *
 *  @param path The path to the package descriptor.
 */
function package(path) {
  if(!arguments.length && this._package) return this._package;
  if(path && fs.existsSync(path)) {
    try {
      var pkg = this._package = require(path);
      this._version = pkg.version;
      if(pkg.description) this._description = pkg.description;
    }catch(e) {
      throw new Error(util.format(
        'package parse error %s (malformed json)', path));
    }
  }else if(path) {
    throw new Error(util.format(
      'package descriptor %s does not exist', path));
  }
  return this;
}
define(Program.prototype, 'package', package, false);

/**
 *  Set the program usage string.
 *
 *  @param usage The program usage string.
 */
function usage(usage) {
  if(!arguments.length && this._usage) return this._usage;
  this._usage = usage;
  return this;
}
define(Program.prototype, 'usage', usage, false);

/**
 *  Initialize the program from a package.json
 *  project descriptor, optionally overriding
 *  the name, description and class to instantiate.
 *
 *  @param package The path to package.json.
 *  @param name A specific name for the root command (optional).
 *  @param description A specific description for the root command (optional).
 *  @param clazz A specific class to instantiate.
 */
function create(package, name, description, clazz) {
  clazz = clazz || Program;
  var program = new clazz(basename(process.argv[1]));
  program.package(package);
  if(name) program.name(name);
  if(description) program.description(description);
  return program;
}

module.exports = create;
module.exports.define = define;
module.exports.key = getKey;
module.exports.Program = Program;
module.exports.Command = Command;
module.exports.Option = Option;
module.exports.Flag = Flag;
<|endoftext|>


<commit_before>/*
	Copyright 2013-2014, Marten de Vries

	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";

//TODO: call http equivalent if http adapter.

var Promise = require("bluebird");
var extend = require("extend");

var couchdb_objects = require("../couchdb-objects");
var render = require("../utils/couchrender.js");
var addCallback = require("../utils/promisewrapper.js");

exports.list = function (listPath, options, callback) {
  var db = this;

  if (typeof options === "function") {
    callback = options;
    options = {};
  }
  var designDocName = listPath.split("/")[0];
  var listName = listPath.split("/")[1];
  var viewName = listPath.split("/")[2];

  //build request object
  var infoPromise = db.info();
  var pathPromise = infoPromise.then(function (info) {
    var path = [info.db_name, "_design", designDocName, "_list", listName];
    if (viewName) {
      path.push(viewName);
    }
    return path;
  });
  var reqPromise = couchdb_objects.buildRequestObject(options, pathPromise, infoPromise, db);

  //get the data involved.
  var ddocPromise = db.get("_design/" + designDocName).then(function (designDoc) {
    if (!(designDoc.lists || {}).hasOwnProperty(listName)) {
      throw {
        status: 404,
        error: "not_found",
        reason: "missing list function " + listName + " on design doc _design/" + designDocName
      };
    }
    return designDoc;
  });
  var viewPromise = db.query(designDocName + "/" + viewName, options);

  var promise = Promise.all([ddocPromise, viewPromise, reqPromise]).then(function (args) {
    var designDoc = args[0];
    var viewResp = args[1];
    var req = args[2];

    var head = {
      offset: viewResp.offset,
      total_rows: viewResp.total_rows
    };

    var respInfo;
    var chunks = [];

    var listApi = {
      getRow: function () {
        listApi.start({});
        return viewResp.rows.shift() || null;
      },
      send: function (chunk) {
        listApi.start({});
        chunks.push(chunk);
      },
      start: function (respBegin) {
        if (!respInfo) {
          respInfo = respBegin;
        }
      }
    };

    var resp = render(designDoc.lists[listName], designDoc, head, req, listApi);
    if (respInfo) {
      extend(resp, respInfo || {});
      resp.body = chunks.join("") + resp.body;
      resp.headers["Transfer-Encoding"] = "chunked";
    }
    return resp;
  });
  addCallback(promise, callback);
  return promise;
};
<commit_msg>All JS are now Node modules of their own, that could even be published to the registry if necessary. For now just there's a script that links them locally (and installs all their dependencies).<commit_after>/*
	Copyright 2013-2014, Marten de Vries

	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";

//TODO: call http equivalent if http adapter.

var Promise = require("bluebird");
var extend = require("extend");

var couchdb_objects = require("couchdb-objects");
var render = require("couchdb-render");
var nodify = require("promise-nodify");

exports.list = function (listPath, options, callback) {
  var db = this;

  if (typeof options === "function") {
    callback = options;
    options = {};
  }
  var designDocName = listPath.split("/")[0];
  var listName = listPath.split("/")[1];
  var viewName = listPath.split("/")[2];

  //build request object
  var infoPromise = db.info();
  var pathPromise = infoPromise.then(function (info) {
    var path = [info.db_name, "_design", designDocName, "_list", listName];
    if (viewName) {
      path.push(viewName);
    }
    return path;
  });
  var reqPromise = couchdb_objects.buildRequestObject(options, pathPromise, infoPromise, db);

  //get the data involved.
  var ddocPromise = db.get("_design/" + designDocName).then(function (designDoc) {
    if (!(designDoc.lists || {}).hasOwnProperty(listName)) {
      throw {
        status: 404,
        error: "not_found",
        reason: "missing list function " + listName + " on design doc _design/" + designDocName
      };
    }
    return designDoc;
  });
  var viewPromise = db.query(designDocName + "/" + viewName, options);

  var promise = Promise.all([ddocPromise, viewPromise, reqPromise]).then(function (args) {
    var designDoc = args[0];
    var viewResp = args[1];
    var req = args[2];

    var head = {
      offset: viewResp.offset,
      total_rows: viewResp.total_rows
    };

    var respInfo;
    var chunks = [];

    var listApi = {
      getRow: function () {
        listApi.start({});
        return viewResp.rows.shift() || null;
      },
      send: function (chunk) {
        listApi.start({});
        chunks.push(chunk);
      },
      start: function (respBegin) {
        if (!respInfo) {
          respInfo = respBegin;
        }
      }
    };

    var resp = render(designDoc.lists[listName], designDoc, head, req, listApi);
    if (respInfo) {
      extend(resp, respInfo || {});
      resp.body = chunks.join("") + resp.body;
      resp.headers["Transfer-Encoding"] = "chunked";
    }
    return resp;
  });
  nodify(promise, callback);
  return promise;
};
<|endoftext|>


<commit_before>var https = require('https');
var crypto = require('crypto');
var url = require('url');
var fs = require('fs');
var basic = require('basic-auth');

/**
 * Two parameters mode
 *  If a is undefined, return b else a
 * Three parameters mode
 *  If a is undefined, return c else b
 * @param {*} a
 * @param {*} b
 * @param {*=} c
 * @returns {*}
 */
function ifnotundef(a, b, c) {
    return (typeof c == 'undefined') ? ((typeof a != 'undefined' && a != null) ? a : b) : ((typeof a != 'undefined' && a != null) ? b : c);
}

/**
 * Generates a random Xrf key of a given size within a set of given chars
 * @param {integer=} [size=16]
 * @param {string=} [chars=abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789]
 * @returns {string}
 */
function generateXrfkey(size, chars) {
    size = size || 16;
    chars = chars || 'abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789';

    var rnd = crypto.randomBytes(size), value = new Array(size), len = chars.length;

    for (var i = 0; i < size; i++) {
        value[i] = chars[rnd[i] % len]
    }

    return value.join('');
}

/**
 * Makes a request on a Qlik Sense API endpoint defined in the options object, posting the params object
 * @param {Object} params the parameters to post to the API endpoint
 * @param {Object} options the options to connect to the API endpoint
 * @returns {Promise}
 */
function request(params, options) {

    var xrfkey = generateXrfkey();
    var restUri = url.parse(options.restUri);

    var headers = {
        'X-Qlik-Xrfkey': xrfkey,
        'Content-Type': 'application/json'
    };

    if(typeof options.UserDirectory != 'undefined' || typeof options.UserId != 'undefined')
        headers['X-Qlik-User'] = 'UserDirectory= ' + ifnotundef(options.UserDirectory, '.') + '; UserId= ' + ifnotundef(options.UserId, 'qlikservice');

    if(typeof options.session != 'undefined')
        headers['Cookie'] = options.session;

    var settings = {
        protocol: restUri.protocol,
        host: restUri.hostname,
        port: restUri.port,
        path: restUri.pathname + '?' + ifnotundef(restUri.query, restUri.query + '&', '') + 'xrfkey=' + xrfkey,
        method: ifnotundef(options.method, 'POST'),
        headers: headers,
        pfx: ifnotundef(options.pfx, null),
        passphrase: ifnotundef(options.passPhrase, null),
        rejectUnauthorized: false,
        agent: false
    };

    return new Promise(function(resolve, reject) {

        if(settings.protocol != 'https:') reject('https is needed to make API call');
        else {

            var apireq = https.request(settings, function (apires) {

                var body = "";
                apires.on('data', function (d) {
                    body += d.toString()
                });

                apires.on('end', function (d) {
                    resolve(JSON.parse(body));
                });

            });

            if(params) {
                apireq.write(JSON.stringify(params));
            }

            apireq.end();

            apireq.on('error', function (e) {
                reject(e);
            });

        }

    });

};

/**
 * Generates a ticket on Qlik Sense QRS Api
 * @param {Object} params the ticket parameters
 * @param {Object} options the options to connect to the ticket API endpoint
 * @returns {Promise}
 */
function getTicket(params, options) {

    var restUri = url.parse(options.restUri);

    var ticketOptions = {
        restUri: restUri.protocol + '//' + restUri.host + '/qps/ticket',
        method: 'POST',
        pfx: options.pfx,
        passPhrase: options.passPhrase
    };

    return request(params, ticketOptions);

}

/**
 * Opens a session on the Qlik Sense Hub with the given ticket and returns the session cookie
 * @param {Object} ticket the generated ticket
 * @param {Object} options parsed url of the Qlik Sense Hub
 * @returns {Promise}
 */
function openSession(ticket, options) {

    var p = new Promise(function(resolve, reject) {

        var settings = {
            host: options.hostname,
            port: options.port,
            path: options.pathname + '?' + ifnotundef(options.query, options.query + '&', '') + 'qlikTicket=' + ticket.Ticket,
            method: 'GET',
            rejectUnauthorized: false,
            agent: false
        };

        var prot = (options.protocol == 'https:') ? https : http;

        var req = prot.request(settings, function (response) {
            response.on('data', function (d) {
                var cookies = response.headers['set-cookie'];
                resolve(cookies[0]);
            });
        });
        req.on('error', function(e) {
            reject(e);
        });
        req.end();
    });

    return p;
}

/**
 * Adds the given ip address to the websocket whitelist of the given virtual proxy
 * @param  {string} ip the ip to add
 * @param  {Object} options the endpoint to add the ip to
 * @returns {Promise}
 */
function addToWhiteList(ip, options) {

    var restUri = url.parse(options.restUri);

    return request(null, {
        restUri: restUri.protocol + '//' + restUri.host + '/qrs/proxyservice/local',
        method: 'GET',
        pfx: options.pfx,
        passPhrase: options.passPhrase,
        UserId: options.UserId,
        UserDirectory: options.UserDirectory
    }).then(function(settings) {

        var vpsettings = settings.settings.virtualProxies[0];

        return request(null, {
            restUri: restUri.protocol + '//' + restUri.host + '/qrs/virtualproxyconfig/' + vpsettings.id,
            method: 'GET',
            pfx: options.pfx,
            passPhrase: options.passPhrase,
            UserId: options.UserId,
            UserDirectory: options.UserDirectory
        })

    }).then(function(settings) {

        if(settings.websocketCrossOriginWhiteList.indexOf(ip) == -1) {

            settings.websocketCrossOriginWhiteList.push(ip);

            var currDate = new Date();
            var oldDate = new Date(settings.modifiedDate);
            var newDate;

            if (currDate > oldDate) {
                newDate = currDate;
            } else {
                newDate = oldDate;
                newDate.setSeconds(newDate.getSeconds() + 1);
            }

            settings.modifiedDate = newDate.toISOString();

            return request(settings, {
                restUri: restUri.protocol + '//' + restUri.host + '/qrs/virtualproxyconfig/' + settings.id,
                method: 'PUT',
                pfx: options.pfx,
                passPhrase: options.passPhrase,
                UserId: options.UserId,
                UserDirectory: options.UserDirectory
            });

        } else {
            return 'already in whitelist!'
        }

    })

}

/**
 * Simple basic auth middleware for use with Express 4.x.
 *
 * @example
 * app.use('/api-requiring-auth', utils.basicAuth([{user: 'username', pass: 'password'}]));
 *
 * @param   {Object}   username list of usernames & passwords
 * @returns {function} Express 4 middleware requiring the given credentials
 */
function basicAuth(users) {
    return function(req, res, next) {
        var user = basic(req);

        if(
            !user || users.filter(function(item) {
                return item.user == user.name && item.pass == user.pass;
            }).length == 0
        ) {
            res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
            return res.send(401);
        }

        req.authUser = user.name;
        next();
    };
};

module.exports = {
    request: request,
    getTicket: getTicket,
    openSession: openSession,
    addToWhiteList: addToWhiteList,
    basicAuth: basicAuth
}
<commit_msg>ifnotundef<commit_after>var https = require('https');
var crypto = require('crypto');
var url = require('url');
var fs = require('fs');
var basic = require('basic-auth');

/**
 * Two parameters mode
 *  If a is undefined, return b else a
 * Three parameters mode
 *  If a is undefined, return c else b
 *
 * @example
 * var myHost = ifnotundef(options.host, options.hostname);
 *
 * @example
 * var myHost = ifnotundef(options.host, options.hostname, 'localhost');
 *
 * @param {*} a
 * @param {*} b
 * @param {*=} c
 * @returns {*}
 */
function ifnotundef(a, b, c) {
    return (typeof c == 'undefined') ? ((typeof a != 'undefined' && a != null) ? a : b) : ((typeof a != 'undefined' && a != null) ? b : c);
}

/**
 * Generates a random Xrf key of a given size within a set of given chars
 *
 * @example
 * var xrf = generateXrfkey(8);
 *
 * @param {integer=} [size=16]
 * @param {string=} [chars=abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789]
 * @returns {string}
 */
function generateXrfkey(size, chars) {
    size = size || 16;
    chars = chars || 'abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789';

    var rnd = crypto.randomBytes(size), value = new Array(size), len = chars.length;

    for (var i = 0; i < size; i++) {
        value[i] = chars[rnd[i] % len]
    }

    return value.join('');
}

/**
 * Makes a request on a Qlik Sense API endpoint defined in the options object, posting the params object
 *
 * @example
 * request({
 *      'UserId': 'qlikservice',
 *      'UserDirectory': '2008R2-0',
 *      'Attributes': []
 * }, {
 *      restUri: 'https://10.76.224.72:4243/qps/ticket',
 *      pfx: pfx,
 *      passPhrase: ''
 * }).then(function(retVal) {
 *      console.log(retVal);
 * });
 *
 * @param {Object} params the parameters to post to the API endpoint
 * @param {Object} options the options to connect to the API endpoint
 * @returns {Promise}
 */
function request(params, options) {

    var xrfkey = generateXrfkey();
    var restUri = url.parse(options.restUri);

    var headers = {
        'X-Qlik-Xrfkey': xrfkey,
        'Content-Type': 'application/json'
    };

    if(typeof options.UserDirectory != 'undefined' || typeof options.UserId != 'undefined')
        headers['X-Qlik-User'] = 'UserDirectory= ' + ifnotundef(options.UserDirectory, '.') + '; UserId= ' + ifnotundef(options.UserId, 'qlikservice');

    if(typeof options.session != 'undefined')
        headers['Cookie'] = options.session;

    var settings = {
        protocol: restUri.protocol,
        host: restUri.hostname,
        port: restUri.port,
        path: restUri.pathname + '?' + ifnotundef(restUri.query, restUri.query + '&', '') + 'xrfkey=' + xrfkey,
        method: ifnotundef(options.method, 'POST'),
        headers: headers,
        pfx: ifnotundef(options.pfx, null),
        passphrase: ifnotundef(options.passPhrase, null),
        rejectUnauthorized: false,
        agent: false
    };

    return new Promise(function(resolve, reject) {

        if(settings.protocol != 'https:') reject('https is needed to make API call');
        else {

            var apireq = https.request(settings, function (apires) {

                var body = "";
                apires.on('data', function (d) {
                    body += d.toString()
                });

                apires.on('end', function (d) {
                    resolve(JSON.parse(body));
                });

            });

            if(params) {
                apireq.write(JSON.stringify(params));
            }

            apireq.end();

            apireq.on('error', function (e) {
                reject(e);
            });

        }

    });

};

/**
 * Generates a ticket on Qlik Sense QRS Api
 *
 * @example
 * getTicket({
 *      'UserId': 'qlikservice',
 *      'UserDirectory': '2008R2-0',
 *      'Attributes': []
 * }, {
 *      restUri: 'https://10.76.224.72:4243',
 *      pfx: pfx,
 *      passPhrase: ''
 * }).then(function(retVal) {
 *      console.log(retVal);
 * });
 *
 * @param {Object} params the ticket parameters
 * @param {Object} options the options to connect to the ticket API endpoint
 * @returns {Promise}
 */
function getTicket(params, options) {

    var restUri = url.parse(options.restUri);

    var ticketOptions = {
        restUri: restUri.protocol + '//' + restUri.host + '/qps/ticket',
        method: 'POST',
        pfx: options.pfx,
        passPhrase: options.passPhrase
    };

    return request(params, ticketOptions);

}

/**
 * Opens a session on the Qlik Sense Hub with the given ticket and returns the session cookie
 *
 * @example
 * openSession({
 *      UserDirectory: '2008R2-0',
 *      UserId: 'qlikservice',
 *      Attributes: [],
 *      Ticket: 'QzSPXzBmJKjhucPF',
 *      TargetUri: null
 * }, url.parse('https://localhost/hub')).then(function(retVal) {
 *      console.log(retVal);
 * });
 *
 * @param {Object} ticket the generated ticket
 * @param {Object} options parsed url of the Qlik Sense Hub
 * @returns {Promise}
 */
function openSession(ticket, options) {

    var p = new Promise(function(resolve, reject) {

        var settings = {
            host: options.hostname,
            port: options.port,
            path: options.pathname + '?' + ifnotundef(options.query, options.query + '&', '') + 'qlikTicket=' + ticket.Ticket,
            method: 'GET',
            rejectUnauthorized: false,
            agent: false
        };

        var prot = (options.protocol == 'https:') ? https : http;

        var req = prot.request(settings, function (response) {
            response.on('data', function (d) {
                var cookies = response.headers['set-cookie'];
                resolve(cookies[0]);
            });
        });
        req.on('error', function(e) {
            reject(e);
        });
        req.end();
    });

    return p;
}

/**
 * Adds the given ip address to the websocket whitelist of the given virtual proxy
 *
 * @example
 * readFile('./client.pfx').then(function(certif) {
 *
 *      return utils.addToWhiteList('10.76.224.72', {
 *          restUri: 'https://10.76.224.72:4242',
 *          pfx: certif,
 *          passPhrase: '',
 *          UserId: 'qlikservice',
 *          UserDirectory: '2008R2-0'
 *      });
 *
 * }).then(function(ret) {
 *      console.log(ret);
 * }, function(ret) {
 *      console.log(ret);
 * });
 *
 * @param  {string} ip the ip to add
 * @param  {Object} options the endpoint to add the ip to
 * @returns {Promise}
 */
function addToWhiteList(ip, options) {

    var restUri = url.parse(options.restUri);

    return request(null, {
        restUri: restUri.protocol + '//' + restUri.host + '/qrs/proxyservice/local',
        method: 'GET',
        pfx: options.pfx,
        passPhrase: options.passPhrase,
        UserId: options.UserId,
        UserDirectory: options.UserDirectory
    }).then(function(settings) {

        var vpsettings = settings.settings.virtualProxies[0];

        return request(null, {
            restUri: restUri.protocol + '//' + restUri.host + '/qrs/virtualproxyconfig/' + vpsettings.id,
            method: 'GET',
            pfx: options.pfx,
            passPhrase: options.passPhrase,
            UserId: options.UserId,
            UserDirectory: options.UserDirectory
        })

    }).then(function(settings) {

        if(settings.websocketCrossOriginWhiteList.indexOf(ip) == -1) {

            settings.websocketCrossOriginWhiteList.push(ip);

            var currDate = new Date();
            var oldDate = new Date(settings.modifiedDate);
            var newDate;

            if (currDate > oldDate) {
                newDate = currDate;
            } else {
                newDate = oldDate;
                newDate.setSeconds(newDate.getSeconds() + 1);
            }

            settings.modifiedDate = newDate.toISOString();

            return request(settings, {
                restUri: restUri.protocol + '//' + restUri.host + '/qrs/virtualproxyconfig/' + settings.id,
                method: 'PUT',
                pfx: options.pfx,
                passPhrase: options.passPhrase,
                UserId: options.UserId,
                UserDirectory: options.UserDirectory
            });

        } else {
            return 'already in whitelist!'
        }

    })

}

/**
 * Simple basic auth middleware for use with Express 4.x.
 *
 * @example
 * app.use('/api-requiring-auth', utils.basicAuth([{user: 'username', pass: 'password'}]));
 *
 * @param   {Object}   username list of usernames & passwords
 * @returns {function} Express 4 middleware requiring the given credentials
 */
function basicAuth(users) {
    return function(req, res, next) {
        var user = basic(req);

        if(
            !user || users.filter(function(item) {
                return item.user == user.name && item.pass == user.pass;
            }).length == 0
        ) {
            res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
            return res.send(401);
        }

        req.authUser = user.name;
        next();
    };
};

module.exports = {
    ifnotundef: ifnotundef,
    request: request,
    getTicket: getTicket,
    openSession: openSession,
    addToWhiteList: addToWhiteList,
    basicAuth: basicAuth
}
<|endoftext|>


<commit_before>require('babel-register');
require('./main');
// exports.default = require('./lib');
<commit_msg>fix entry point<commit_after>// require('babel-register');
// require('./main');
exports.default = require('./lib');
<|endoftext|>