<commit_before>"use strict";
/* -------------------------------------------------------------------
 * Require Statements << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

var coback = require('coback');
var Tedious = require('tedious');
var TdmBulkLoad = require('./TdmBulkLoad');
var TdmTransaction = require('./TdmTransaction');

/* =============================================================================
 *
 * TdmConnection
 *
 * ========================================================================== */

module.exports = TdmConnection;

function TdmConnection (id, tediousConn)
{
	this.id = id;
	/** @member {TdmConnectionPool} */
	this.pool = null;
	this.tediousConnection = tediousConn;
	this.lastActivity = Date.now();
}

/* -------------------------------------------------------------------
 * Prototype Methods << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

TdmConnection.prototype.bulkLoad = function (table)
{
	return new TdmBulkLoad(this, table);
};

TdmConnection.prototype.request = function * (sql, params, options)
{
	this.lastActivity = Date.now();
	if (!options)
		options = {};

	var cb = coback();
	var req = new Tedious.Request(sql, cb);

	if (params)
	{
		for (let i in params)
		{
			let p = params[i];
			req.addParameter(i, p.type, p.value, p);
		}
	}

  var colNames = [];
  var recordsets = [];
  var recordset = [];

  req.on('columnMetadata', function (metadata)
  {
    colNames = columnNamesFromMetadata(metadata);
  });

  function done(rowCount, more)
  {
    if (colNames.length === 0) return;

    recordsets.push(recordset);
    recordset = [];
    colNames = [];
  }

  req.on('done', done);
  req.on('doneInProc', done);

  req.on('row', function (columns)
  {
    var row = {};
    for (var i = 0, l = columns.length; i < l; ++i)
      row[colNames[i]] = columns[i].value;
    recordset.push(row);
  });

	if (options.batch)
		this.tediousConnection.execSqlBatch(req);
	else
		this.tediousConnection.execSql(req);

	var sqlResult = yield cb.result;

	var result = {
		rowCount: null,
		rows: null
	};

	this.lastActivity = Date.now();
	if (sqlResult instanceof Array)
	{
		let rowCount = sqlResult[0];
		if (!recordsets || (recordsets.length === 0 && rowCount !== 0))
			return rowCount;

		result.rowCount = rowCount;

    result.rows = options.multiple
      ? recordsets
      : recordsets[0];
	}

	return result;
};

TdmConnection.prototype.usingTransaction = function * (isolationLevel, name, scope)
{
	if (typeof scope !== 'function')
	{
		if (typeof name === 'function')
		{
			scope = name;
			name = undefined;
		}
		else
		{
			scope = isolationLevel;
			name = undefined;
			isolationLevel = undefined;
		}
	}

	/** @type {TdmTransaction} */
	let tran = yield TdmTransaction.createTransaction(this, isolationLevel, name);
	let error = null;

	try
	{
		yield scope(tran);
	}
	catch (ex)
	{
		error = ex;
	}

	if (tran.open)
		yield tran.rollback();

	if (error)
		throw error;
};

function columnNamesFromMetadata (metadata)
{
  var names = new Array(metadata.length);
  for (var i = 0, l = metadata.length; i < l; ++i)
    names[i] = metadata[i].colName;
  return names;
}
<commit_msg>formatting<commit_after>"use strict";
/* -------------------------------------------------------------------
 * Require Statements << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

var coback = require('coback');
var Tedious = require('tedious');
var TdmBulkLoad = require('./TdmBulkLoad');
var TdmTransaction = require('./TdmTransaction');

/* =============================================================================
 *
 * TdmConnection
 *
 * ========================================================================== */

module.exports = TdmConnection;

function TdmConnection (id, tediousConn)
{
	this.id = id;
	/** @member {TdmConnectionPool} */
	this.pool = null;
	this.tediousConnection = tediousConn;
	this.lastActivity = Date.now();
}

/* -------------------------------------------------------------------
 * Prototype Methods << Keep in alphabetical order >>
 * ---------------------------------------------------------------- */

TdmConnection.prototype.bulkLoad = function (table)
{
	return new TdmBulkLoad(this, table);
};

TdmConnection.prototype.request = function * (sql, params, options)
{
	this.lastActivity = Date.now();
	if (!options)
		options = {};

	var cb = coback();
	var req = new Tedious.Request(sql, cb);

	if (params)
	{
		for (let i in params)
		{
			let p = params[i];
			req.addParameter(i, p.type, p.value, p);
		}
	}

	var colNames = [];
	var recordsets = [];
	var recordset = [];

	req.on('columnMetadata', function (metadata)
	{
		colNames = columnNamesFromMetadata(metadata);
	});

	function done(rowCount, more)
	{
		if (colNames.length === 0) return;

		recordsets.push(recordset);
		recordset = [];
		colNames = [];
	}

	req.on('done', done);
	req.on('doneInProc', done);

	req.on('row', function (columns)
	{
		var row = {};
		for (var i = 0, l = columns.length; i < l; ++i)
			row[colNames[i]] = columns[i].value;
		recordset.push(row);
	});

	if (options.batch)
		this.tediousConnection.execSqlBatch(req);
	else
		this.tediousConnection.execSql(req);

	var sqlResult = yield cb.result;

	var result = {
		rowCount: null,
		rows: null
	};

	this.lastActivity = Date.now();
	if (sqlResult instanceof Array)
	{
		let rowCount = sqlResult[0];
		if (!recordsets || (recordsets.length === 0 && rowCount !== 0))
			return rowCount;

		result.rowCount = rowCount;

		result.rows = options.multiple
			? recordsets
			: recordsets[0];
	}

	return result;
};

TdmConnection.prototype.usingTransaction = function * (isolationLevel, name, scope)
{
	if (typeof scope !== 'function')
	{
		if (typeof name === 'function')
		{
			scope = name;
			name = undefined;
		}
		else
		{
			scope = isolationLevel;
			name = undefined;
			isolationLevel = undefined;
		}
	}

	/** @type {TdmTransaction} */
	let tran = yield TdmTransaction.createTransaction(this, isolationLevel, name);
	let error = null;

	try
	{
		yield scope(tran);
	}
	catch (ex)
	{
		error = ex;
	}

	if (tran.open)
		yield tran.rollback();

	if (error)
		throw error;
};

function columnNamesFromMetadata (metadata)
{
	var names = new Array(metadata.length);
	for (var i = 0, l = metadata.length; i < l; ++i)
		names[i] = metadata[i].colName;
	return names;
}
<|endoftext|>


<commit_before>
var MediaModel = require('./models/mediaModel.js'),
    PlayModel = require('./models/playModel.js');

var DubAPIError = require('./errors/error.js'),
    DubAPIRequestError = require('./errors/requestError.js');

var endpoints = require('./data/endpoints.js'),
    events = require('./data/events.js'),
    utils = require('./utils.js');

function ActionHandler(dubAPI, auth) {
    this.doLogin = doLogin.bind(dubAPI, auth);
    this.clearPlay = clearPlay.bind(dubAPI);
    this.updatePlay = updatePlay.bind(dubAPI);
}

function doLogin(auth, callback) {
    var that = this;

    this._.reqHandler.queue({method: 'POST', url: endpoints.authDubtrack, form: auth}, function(code, body) {
        if ([200, 400].indexOf(code) === -1) {
            return callback(new DubAPIRequestError(code, that._.reqHandler.endpoint(endpoints.authDubtrack)));
        } else if (code === 400) {
            return callback(new DubAPIError('Authentication Failed: ' + body.data.details.message));
        }

        callback(undefined);
    });
}

function clearPlay() {
    clearTimeout(this._.room.playTimeout);

    var message = {type: events.roomPlaylistUpdate};

    if (this._.room.play) {
        message.lastPlay = {
            id: this._.room.play.id,
            media: utils.clone(this._.room.play.media),
            user: utils.clone(this._.room.users.findWhere({id: this._.room.play.user})),
            score: this._.room.play.getScore()
        };
    }

    this._.room.play = undefined;
    this._.room.users.set({dub: undefined});

    this.emit('*', message);
    this.emit(events.roomPlaylistUpdate, message);
}

function updatePlay() {
    var that = this;

    clearTimeout(that._.room.playTimeout);

    that._.reqHandler.queue({method: 'GET', url: endpoints.roomPlaylistActive}, function(code, body) {
        if ([200, 404].indexOf(code) === -1) {
            that.emit('error', new DubAPIRequestError(code, that._.reqHandler.endpoint(endpoints.roomPlaylistActive)));
            return;
        } else if (code === 404) {
            clearPlay();
            return;
        }

        var message = {type: events.roomPlaylistUpdate},
            newPlay = new PlayModel(body.data.song),
            curPlay = that._.room.play;

        if (curPlay && newPlay.id === curPlay.id) {
            if (Date.now() - newPlay.played > newPlay.songLength) clearPlay();
            return;
        }

        newPlay.media = new MediaModel(body.data.songInfo);

        message.raw = body.data;

        if (that._.room.play) {
            message.lastPlay = {
                id: curPlay.id,
                media: utils.clone(curPlay.media),
                user: utils.clone(that._.room.users.findWhere({id: curPlay.user})),
                score: curPlay.getScore()
            };
        }

        message.id = newPlay.id;
        message.media = utils.clone(newPlay.media);
        message.user = utils.clone(that._.room.users.findWhere({id: newPlay.user}));

        that._.reqHandler.queue({method: 'GET', url: endpoints.roomPlaylistActiveDubs}, function(code, body) {
            that._.room.play = newPlay;
            that._.room.playTimeout = setTimeout(that._.actHandler.updatePlay, newPlay.getTimeRemaining() + 15000);

            that._.room.users.set({dub: undefined});

            if (code === 200) {
                body.data.currentSong = new PlayModel(body.data.currentSong);

                if (newPlay.id === body.data.currentSong.id) {
                    newPlay.updubs = body.data.currentSong.updubs;
                    newPlay.downdubs = body.data.currentSong.downdubs;

                    body.data.upDubs.forEach(function(dub) {
                        newPlay.dubs[dub.userid] = 'updub';

                        var user = that._.room.users.findWhere({id: dub.userid});
                        if (user) user.set({dub: 'updub'});
                    });

                    body.data.downDubs.forEach(function(dub) {
                        newPlay.dubs[dub.userid] = 'downdub';

                        var user = that._.room.users.findWhere({id: dub.userid});
                        if (user) user.set({dub: 'downdub'});
                    });
                }
            } else {
                that.emit('error', new DubAPIRequestError(code, that._.reqHandler.endpoint(endpoints.roomPlaylistActiveDubs)));
            }

            that.emit('*', message);
            that.emit(events.roomPlaylistUpdate, message);
        });
    });
}

module.exports = ActionHandler;
<commit_msg>Fixed a TypeError<commit_after>
var MediaModel = require('./models/mediaModel.js'),
    PlayModel = require('./models/playModel.js');

var DubAPIError = require('./errors/error.js'),
    DubAPIRequestError = require('./errors/requestError.js');

var endpoints = require('./data/endpoints.js'),
    events = require('./data/events.js'),
    utils = require('./utils.js');

function ActionHandler(dubAPI, auth) {
    this.doLogin = doLogin.bind(dubAPI, auth);
    this.clearPlay = clearPlay.bind(dubAPI);
    this.updatePlay = updatePlay.bind(dubAPI);
}

function doLogin(auth, callback) {
    var that = this;

    this._.reqHandler.queue({method: 'POST', url: endpoints.authDubtrack, form: auth}, function(code, body) {
        if ([200, 400].indexOf(code) === -1) {
            return callback(new DubAPIRequestError(code, that._.reqHandler.endpoint(endpoints.authDubtrack)));
        } else if (code === 400) {
            return callback(new DubAPIError('Authentication Failed: ' + body.data.details.message));
        }

        callback(undefined);
    });
}

function clearPlay() {
    clearTimeout(this._.room.playTimeout);

    var message = {type: events.roomPlaylistUpdate};

    if (this._.room.play) {
        message.lastPlay = {
            id: this._.room.play.id,
            media: utils.clone(this._.room.play.media),
            user: utils.clone(this._.room.users.findWhere({id: this._.room.play.user})),
            score: this._.room.play.getScore()
        };
    }

    this._.room.play = undefined;
    this._.room.users.set({dub: undefined});

    this.emit('*', message);
    this.emit(events.roomPlaylistUpdate, message);
}

function updatePlay() {
    var that = this;

    clearTimeout(that._.room.playTimeout);

    that._.reqHandler.queue({method: 'GET', url: endpoints.roomPlaylistActive}, function(code, body) {
        if ([200, 404].indexOf(code) === -1) {
            that.emit('error', new DubAPIRequestError(code, that._.reqHandler.endpoint(endpoints.roomPlaylistActive)));
            return;
        } else if (code === 404) {
            that._.actHandler.clearPlay();
            return;
        }

        var message = {type: events.roomPlaylistUpdate},
            newPlay = new PlayModel(body.data.song),
            curPlay = that._.room.play;

        if (curPlay && newPlay.id === curPlay.id) {
            if (Date.now() - newPlay.played > newPlay.songLength) that._.actHandler.clearPlay();
            return;
        }

        newPlay.media = new MediaModel(body.data.songInfo);

        message.raw = body.data;

        if (that._.room.play) {
            message.lastPlay = {
                id: curPlay.id,
                media: utils.clone(curPlay.media),
                user: utils.clone(that._.room.users.findWhere({id: curPlay.user})),
                score: curPlay.getScore()
            };
        }

        message.id = newPlay.id;
        message.media = utils.clone(newPlay.media);
        message.user = utils.clone(that._.room.users.findWhere({id: newPlay.user}));

        that._.reqHandler.queue({method: 'GET', url: endpoints.roomPlaylistActiveDubs}, function(code, body) {
            that._.room.play = newPlay;
            that._.room.playTimeout = setTimeout(that._.actHandler.updatePlay, newPlay.getTimeRemaining() + 15000);

            that._.room.users.set({dub: undefined});

            if (code === 200) {
                body.data.currentSong = new PlayModel(body.data.currentSong);

                if (newPlay.id === body.data.currentSong.id) {
                    newPlay.updubs = body.data.currentSong.updubs;
                    newPlay.downdubs = body.data.currentSong.downdubs;

                    body.data.upDubs.forEach(function(dub) {
                        newPlay.dubs[dub.userid] = 'updub';

                        var user = that._.room.users.findWhere({id: dub.userid});
                        if (user) user.set({dub: 'updub'});
                    });

                    body.data.downDubs.forEach(function(dub) {
                        newPlay.dubs[dub.userid] = 'downdub';

                        var user = that._.room.users.findWhere({id: dub.userid});
                        if (user) user.set({dub: 'downdub'});
                    });
                }
            } else {
                that.emit('error', new DubAPIRequestError(code, that._.reqHandler.endpoint(endpoints.roomPlaylistActiveDubs)));
            }

            that.emit('*', message);
            that.emit(events.roomPlaylistUpdate, message);
        });
    });
}

module.exports = ActionHandler;
<|endoftext|>


<commit_before>
module.exports = devices;
devices.list = list;

devices.usage = "\nfhc devices list"
             +"\nfhc devices create <device-id> <description> <make> <model>"
             +"\nfhc devices delete <device-id>"
             +"\nfhc devices read <device-id>"
             +"\nfhc devices update <device-id> <description> <make> <model> <enabled> <blocked>"
             +"\nfhc devices addusers <device-id> <user-email>*"
             +"\nfhc devices removeusers <device-id> <user-email>*"
             +"\nfhc devices approvals <device-id>"

var log = require("./utils/log");
var fhc = require("./fhc");
var fhreq = require("./utils/request");
var common = require("./common");
var util = require('util');
var async = require('async');
var path = require('path');
var ini = require('./utils/ini');
var Table = require('cli-table');

// Main devices entry point
function devices (args, cb) {
  if (args.length == 0){
    return list(cb);
  }

  var action = args[0];
  if (action == 'list') {
    return list(cb);
  }else if (action === 'create'){
    if (args.length !== 5) return cb("Invalid arguments for 'create':" + devices.usage);
    return create(args[1], args[2], args[3], args[4], cb);
  }else if (action === 'read'){
    if (args.length !== 2) return cb("Invalid arguments for 'read':" + devices.usage);
    return read(args[1], cb);
  }else if (action === 'update'){
    if (args.length !== 7) return cb("Invalid arguments for 'update':" + devices.usage);
    return update(args[1], args[2], args[3], args[4], args[5], args[6], cb);
  }else if (action === 'delete'){
    if (args.length !== 2) return cb("Invalid arguments for 'delete':" + devices.usage);
    return deleteDevice(args[1], cb);
  }else if (action === 'addusers'){
    if (args.length <= 2) return cb("Invalid arguments for 'addusers':" + devices.usage);
    var act = args.shift();
    var id = args.shift();
    return addusers(id, args, cb);
  }else if (action === 'removeusers'){
    if (args.length <= 2) return cb("Invalid arguments for 'removeusers':" + devices.usage);
    var act = args.shift();
    var id = args.shift();
    return removeusers(id, args, cb);
  }else if (action === 'approvals'){
    if (args.length !== 1) return cb("Invalid arguments for 'approvals':" + devices.usage);
    return approvals(cb);
  }else if (args.length == 1){
    var appId = fhc.appId(args[0]);
    return read(appId, cb);
  }else{
    return cb(devices.usage);
  }
}

// list devices
function list(cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/arm/device/list", {}, "Error listing devices: ", function(err, devices){
    if(err) return cb(err);
    return cb(undefined, devices);
  });
}

// create device
function create(id, desc, make, model, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/arm/device/create", {"payload":{"device":id, "deviceDesc": desc, "make": make, "model": model}}, "Error creating device: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

// delete device
function deleteDevice(id, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/arm/device/delete", {"payload":{"device": id}}, "Error deleting device: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

// update user
function update(id, desc, make, model, enabled, blocked, cb) {
  if (typeof enabled === 'string') {
    enabled = (enabled === 'true');
  }

  if (typeof blocked === 'string') {
    blocked = (blocked === 'true');
  }

  var payload = {
    "device": id,
    "deviceDesc": desc,
    "make": make,
    "model": model,
    "enabled": enabled,
    "blocked": blocked
  };

  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/arm/device/update", {"payload": payload}, "Error updating device: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

// read user
function read(id, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/arm/device/read", {"payload":{"device": id}}, "Error reading device: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

// add users to a device
function addusers(id, users, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/arm/device/addusers", {"payload":{"device": id, "owner": users}}, "Error adding users: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

// remove users from a group
function removeusers(id, users, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/arm/device/removeusers", {"payload":{"device": id, "owner": users}}, "Error removing users: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

// list approvals
function approvals(cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/arm/device/listApprovals", {}, "Error listing device approvals: ", function(err, approvals){
    if(err) return cb(err);
    return cb(undefined, approvals);
  });
}

// bash completion
devices.completion = function (opts, cb) {
  var argv = opts.conf.argv.remain;
  if (argv[1] !== "devices") argv.unshift("devices");
  if (argv.length === 2) {
    var cmds = ["list", "read", "create", "update", "delete", "addusers", "removeusers", "approvals"];
    if (opts.partialWord !== "l") cmds.push("list");
    return cb(undefined, cmds);
  }

/*
  var action = argv[2];
  switch (action) {
    case "update":
    case "read":
    case "delete":
      // get devices list
      break;
    case "list":
      return cb(null, []);
    default: return cb(null, []);
  }
*/
};
<commit_msg>update device admin commands<commit_after>
module.exports = devices;
devices.list = list;

devices.usage = "\nfhc devices list"
              + "\nfhc devices read <device-id>"
              + "\nfhc devices update <device-id> <label>"
              + "\nfhc devices enable <device-id> <true|false>"
              + "\nfhc devices purgedata <device-id> <true|false>"
              + "\nfhc devices listusers <device-id>"
              + "\nfhc devices listapps <device-id>"

var log = require("./utils/log");
var fhc = require("./fhc");
var fhreq = require("./utils/request");
var common = require("./common");
var util = require('util');
var async = require('async');
var path = require('path');
var ini = require('./utils/ini');
var Table = require('cli-table');

// Main devices entry point
function devices (args, cb) {
  if (args.length == 0){
    return list(cb);
  }

  var action = args[0];
  if (action === 'list') {
    return list(cb);
  }else if (action === 'read'){
    if (args.length !== 2) return cb("Invalid arguments for 'read':" + devices.usage);
    return read(args[1], cb);
  }else if (action === 'update'){
    if (args.length !== 3) return cb("Invalid arguments for 'update':" + devices.usage);
    return update(args[1], args[2], cb);
  }else if (action === 'enable'){
    if (args.length !== 3) return cb("Invalid arguments for 'enable':" + devices.usage);
    return enabledDevice(args[1], args[2], cb);
  }else if (action === 'purgedata'){
    if (args.length !== 3) return cb("Invalid arguments for 'purgedata':" + devices.usage);
    return purgedataDevice(args[1], args[2], cb);
  }else if (action === 'listusers'){
    if (args.length !== 2) return cb("Invalid arguments for 'listusers':" + devices.usage);
    return listusers(args[1], cb);
  }else if (action === 'listapps'){
    if (args.length !== 2) return cb("Invalid arguments for 'listapps':" + devices.usage);
    return listapps(args[1], cb);
  }else if (args.length == 1){
    var deviceId = args[0]
    return read(deviceId, cb);
  }else{
    return cb(devices.usage);
  }
}

// list devices
function list(cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/admin/device/list", {}, "Error listing devices: ", function(err, devices){
    if(err) return cb(err);
    return cb(undefined, devices);
  });
}

function update(id, label, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/admin/device/update", {"cuid": id, "name": label}, "Error updating device: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

function read(id, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/admin/device/read", {"cuid": id}, "Error reading device: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

function enabledDevice(id, enabled, cb) {
  var disabled = false;
  if(enabled === "false"){
    disabled = true;
  }
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/admin/device/update", {"cuid": id, "disabled": disabled}, "Error updating device: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

function purgedataDevice(id, purgedata, cb) {
  var doPurge = false;
  if(purgedata === "true"){
    doPurge = true;
  }
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/admin/device/update", {"cuid": id, "blacklisted": doPurge}, "Error updating device: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

function listusers(id, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/admin/device/listusers", {"cuid": id}, "Error listing device users: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

function listapps(id, cb) {
  common.doApiCall(fhreq.getFeedHenryUrl(), "/box/srv/1.1/admin/device/listapps", {"cuid": id}, "Error listing device apps: ", function(err, data){
    if(err) return cb(err);
    return cb(undefined, data);
  });
}

// bash completion
devices.completion = function (opts, cb) {
  var argv = opts.conf.argv.remain;
  if (argv[1] !== "devices") argv.unshift("devices");
  if (argv.length === 2) {
    var cmds = ["list", "read", "update", "enabled", "purgedata", "listusers", "listapps"];
    if (opts.partialWord !== "l") cmds.push("list");
    return cb(undefined, cmds);
  }

/*
  var action = argv[2];
  switch (action) {
    case "update":
    case "read":
    case "delete":
      // get devices list
      break;
    case "list":
      return cb(null, []);
    default: return cb(null, []);
  }
*/
};
<|endoftext|>


<commit_before>// WARNING:
// The following global constants must be set before instantiation:
//             DEEZER_APP_ID and DEEZER_CHANNEL_URL

window.showMessage = window.showMessage || function(msg) {
  console.warn("[showMessage]", msg);
};

window.$ = window.$ || function(){return window.$};
$.getScript = $.getScript || function(js,cb){loader.includeJS(js,cb);};
$.append = $.append || function(html){document.write(html);};

function DeezerPlayer(){
  return DeezerPlayer.super_.apply(this, arguments);
}

(function(){

  // CONSTANTS
  var SDK_URL = 'https://cdns-files.deezer.com/js/min/dz.js',
      SDK_LOADED = false,
      IS_LOGGED = false,
      URL_REG = /(?:https?:)?\/\/(?:www\.)deezer\.com\/track\/(\d+)/i,
      EVENT_MAP = {
        player_play: 'onPlaying',
        player_paused: 'onPaused',
        player_position: 'onTrackInfo'
      };

  //============================================================================
  function Player(eventHandlers) {

    var self = this;

    this.label = 'Deezer';
    this.eventHandlers = eventHandlers || {};
    this.currentTrack = {position: 0, duration: 0};

    loadSDK(function() {
      init(function() {
        //console.log('DeezerPlayer ready');
        //DZ.getLoginStatus = function(cb) {cb && cb({userID: null})}
        DZ.getLoginStatus(function(response) {
          DZ.player.setRepeat(0);
          IS_LOGGED = response.userID;
          self.isReady = true;
          hookHandlers(self);
        });
      });
    });

  }

  //============================================================================
  Player.prototype.isLogged = function() {
    return IS_LOGGED;
  }

  //============================================================================
  Player.prototype.getEid = function(url, cb) {
    cb(URL_REG.test(url) ? RegExp.$1 : null, this);
  }

  //============================================================================
  Player.prototype.play = function(id) {
    var self = this;
    if (IS_LOGGED) {
      DZ.player.playTracks([id], 0);
    } else {
      DZ.api('/track/' + id, function(data) {
        showMessage(
          'This is a 30 secs preview. ' +
          '' +
          'Connect to Deezer to listen to the full track.'
        );
        self.sound = createSound(self, data.preview)
      });
    }
  }

  //============================================================================
  Player.prototype.pause = function() {
    if (this.sound) {
      this.sound.pause();
    } else {
      DZ.player.pause();
    }
  }

  //============================================================================
  Player.prototype.stop = function() {
    if (this.sound) {
      this.sound.stop();
      this.sound.destruct();
      this.sound = null;
    } else {
      DZ.player.pause();
    }
  }

  //============================================================================
  Player.prototype.resume = function() {
    if (this.sound) {
      this.sound.resume();
    } else {
      DZ.player.play();
    }
  }

  //============================================================================
  // pos: seconds
  Player.prototype.setTrackPosition = function(pos) {
    if (this.sound)
      this.sound.setPosition(Math.round(pos * 1000));
    else
      DZ.player.seek(Math.round(100 * pos / this.currentTrack.duration));
  }

  //============================================================================
  // vol: float between 0 and 1
  Player.prototype.setVolume = function(vol) {
    if (this.sound)
      this.sound.setVolume(Math.round(vol * 100));
    else
      DZ.player.setVolume(Math.round(vol * 100));
  }

  //============================================================================
  function loadSDK(cb) {
    if (!SDK_LOADED) {
      //$('body').append('

');
      var dz = document.createElement('div'); dz.id = 'dz-root';
      document.getElementsByTagName("body")[0].appendChild(dz);
      $.getScript(SDK_URL, function() {
        SDK_LOADED = true;
        cb();
      });
    } else {
      cb();
    }
  }

  //============================================================================
  function init(onload) {
    DZ.init({
      appId: DEEZER_APP_ID,
      channelUrl: DEEZER_CHANNEL_URL,
      player: {
        onload: onload
      }
    });
  }

  //============================================================================
  function hookHandlers(self) {

    function createHandler(e) {
      if (e === 'player_position') {
        return function(eventObject) {
          var onTrackInfoHandler = self.eventHandlers.onTrackInfo,
              onEndedHandler = self.eventHandlers.onEnded,
              position = eventObject[0],
              duration = eventObject[1];
          if (onTrackInfoHandler) {
            self.currentTrack = {position: position, duration: duration};
            onTrackInfoHandler(self.currentTrack);
          }
          if ((duration - position <= 1.5) && onEndedHandler)
            onEndedHandler(self);
        };
      }
      return function() {
        var handler = self.eventHandlers[EVENT_MAP[e]];
        handler && handler(self);
      };
    }

    for (var e in EVENT_MAP)
      DZ.Event.suscribe(e, createHandler(e));
    self.eventHandlers.onApiReady && self.eventHandlers.onApiReady(self);
  }

  //============================================================================
  function createSound(self, url) {
    return soundManager.createSound({
      id: 'deezerSound' + Date.now(),
      url: url,
      autoLoad: true,
      autoPlay: true,
      whileplaying: function() {
        self.currentTrack = {
          position: self.sound.position / 1000,
          duration: self.sound.duration / 1000
        };
        if (self.eventHandlers.onTrackInfo)
          self.eventHandlers.onTrackInfo(self.currentTrack);
      },
      onplay: function() {
        if (self.eventHandlers.onPlaying)
          self.eventHandlers.onPlaying(self);
      },
      onresume: function() {
        if (self.eventHandlers.onPlaying)
          self.eventHandlers.onPlaying(self);
      },
      onfinish: function() {
        if (self.eventHandlers.onEnded)
          self.eventHandlers.onEnded(self);
      }
    });
  }

  //============================================================================
  Player.login = function() {
    DZ.login(function(response) {
      if (response.userID) {
        IS_LOGGED = true;
        showMessage('Login successful. Your Deezer tracks will be full length from now on!');
      } else {
        showMessage('Deezer login unsuccesful.', true);
      }
    }, {perms: 'email'});
  }

  //============================================================================
  //return Player;
  //inherits(DeezerPlayer, Player);
  DeezerPlayer.prototype = Player.prototype;
  DeezerPlayer.super_ = Player;
})();
<commit_msg>bugfix: login() function should be attached to DeezerPlayer class instead of Player class<commit_after>// WARNING:
// The following global constants must be set before instantiation:
//             DEEZER_APP_ID and DEEZER_CHANNEL_URL

window.showMessage = window.showMessage || function(msg) {
  console.warn("[showMessage]", msg);
};

window.$ = window.$ || function(){return window.$};
$.getScript = $.getScript || function(js,cb){loader.includeJS(js,cb);};
$.append = $.append || function(html){document.write(html);};

function DeezerPlayer(){
  return DeezerPlayer.super_.apply(this, arguments);
}

(function(){

  // CONSTANTS
  var SDK_URL = 'https://cdns-files.deezer.com/js/min/dz.js',
      SDK_LOADED = false,
      IS_LOGGED = false,
      URL_REG = /(?:https?:)?\/\/(?:www\.)deezer\.com\/track\/(\d+)/i,
      EVENT_MAP = {
        player_play: 'onPlaying',
        player_paused: 'onPaused',
        player_position: 'onTrackInfo'
      };

  //============================================================================
  function Player(eventHandlers) {

    var self = this;

    this.label = 'Deezer';
    this.eventHandlers = eventHandlers || {};
    this.currentTrack = {position: 0, duration: 0};

    loadSDK(function() {
      init(function() {
        //console.log('DeezerPlayer ready');
        //DZ.getLoginStatus = function(cb) {cb && cb({userID: null})}
        DZ.getLoginStatus(function(response) {
          DZ.player.setRepeat(0);
          IS_LOGGED = response.userID;
          self.isReady = true;
          hookHandlers(self);
        });
      });
    });

  }

  //============================================================================
  Player.prototype.isLogged = function() {
    return IS_LOGGED;
  }

  //============================================================================
  Player.prototype.getEid = function(url, cb) {
    cb(URL_REG.test(url) ? RegExp.$1 : null, this);
  }

  //============================================================================
  Player.prototype.play = function(id) {
    var self = this;
    if (IS_LOGGED) {
      DZ.player.playTracks([id], 0);
    } else {
      DZ.api('/track/' + id, function(data) {
        showMessage(
          'This is a 30 secs preview. ' +
          '' +
          'Connect to Deezer to listen to the full track.'
        );
        self.sound = createSound(self, data.preview)
      });
    }
  }

  //============================================================================
  Player.prototype.pause = function() {
    if (this.sound) {
      this.sound.pause();
    } else {
      DZ.player.pause();
    }
  }

  //============================================================================
  Player.prototype.stop = function() {
    if (this.sound) {
      this.sound.stop();
      this.sound.destruct();
      this.sound = null;
    } else {
      DZ.player.pause();
    }
  }

  //============================================================================
  Player.prototype.resume = function() {
    if (this.sound) {
      this.sound.resume();
    } else {
      DZ.player.play();
    }
  }

  //============================================================================
  // pos: seconds
  Player.prototype.setTrackPosition = function(pos) {
    if (this.sound)
      this.sound.setPosition(Math.round(pos * 1000));
    else
      DZ.player.seek(Math.round(100 * pos / this.currentTrack.duration));
  }

  //============================================================================
  // vol: float between 0 and 1
  Player.prototype.setVolume = function(vol) {
    if (this.sound)
      this.sound.setVolume(Math.round(vol * 100));
    else
      DZ.player.setVolume(Math.round(vol * 100));
  }

  //============================================================================
  function loadSDK(cb) {
    if (!SDK_LOADED) {
      //$('body').append('

');
      var dz = document.createElement('div'); dz.id = 'dz-root';
      document.getElementsByTagName("body")[0].appendChild(dz);
      $.getScript(SDK_URL, function() {
        SDK_LOADED = true;
        cb();
      });
    } else {
      cb();
    }
  }

  //============================================================================
  function init(onload) {
    DZ.init({
      appId: DEEZER_APP_ID,
      channelUrl: DEEZER_CHANNEL_URL,
      player: {
        onload: onload
      }
    });
  }

  //============================================================================
  function hookHandlers(self) {

    function createHandler(e) {
      if (e === 'player_position') {
        return function(eventObject) {
          var onTrackInfoHandler = self.eventHandlers.onTrackInfo,
              onEndedHandler = self.eventHandlers.onEnded,
              position = eventObject[0],
              duration = eventObject[1];
          if (onTrackInfoHandler) {
            self.currentTrack = {position: position, duration: duration};
            onTrackInfoHandler(self.currentTrack);
          }
          if ((duration - position <= 1.5) && onEndedHandler)
            onEndedHandler(self);
        };
      }
      return function() {
        var handler = self.eventHandlers[EVENT_MAP[e]];
        handler && handler(self);
      };
    }

    for (var e in EVENT_MAP)
      DZ.Event.suscribe(e, createHandler(e));
    self.eventHandlers.onApiReady && self.eventHandlers.onApiReady(self);
  }

  //============================================================================
  function createSound(self, url) {
    return soundManager.createSound({
      id: 'deezerSound' + Date.now(),
      url: url,
      autoLoad: true,
      autoPlay: true,
      whileplaying: function() {
        self.currentTrack = {
          position: self.sound.position / 1000,
          duration: self.sound.duration / 1000
        };
        if (self.eventHandlers.onTrackInfo)
          self.eventHandlers.onTrackInfo(self.currentTrack);
      },
      onplay: function() {
        if (self.eventHandlers.onPlaying)
          self.eventHandlers.onPlaying(self);
      },
      onresume: function() {
        if (self.eventHandlers.onPlaying)
          self.eventHandlers.onPlaying(self);
      },
      onfinish: function() {
        if (self.eventHandlers.onEnded)
          self.eventHandlers.onEnded(self);
      }
    });
  }

  //============================================================================
  DeezerPlayer.login = function() {
    DZ.login(function(response) {
      if (response.userID) {
        IS_LOGGED = true;
        showMessage('Login successful. Your Deezer tracks will be full length from now on!');
      } else {
        showMessage('Deezer login unsuccesful.', true);
      }
    }, {perms: 'email'});
  }

  //============================================================================
  //return Player;
  //inherits(DeezerPlayer, Player);
  DeezerPlayer.prototype = Player.prototype;
  DeezerPlayer.super_ = Player;
})();
<|endoftext|>


<commit_before>module.exports = {
    id: "bada",
    initialize: function() {},
    objects: {
        device: {
            path: 'cordova/plugin/bada/device'
        },
        navigator: {
            children: {
                accelerometer: {
                    path: "cordova/plugin/bada/Accelerometer"
                }
            }
        },
    },
    merges: {
        navigator: {
            children: {
                device: {
                    path: "cordova/plugin/bada/device"
                },
                camera: {
                    path: "cordova/plugin/bada/Camera"
                },
                capture: {
                    path: "cordova/plugin/bada/Capture"
                }
            }
        }
    }
};
<commit_msg>overriding notification object<commit_after>module.exports = {
    id: "bada",
    initialize: function() {},
    objects: {
        device: {
            path: 'cordova/plugin/bada/device'
        },
        navigator: {
            children: {
                accelerometer: {
                    path: "cordova/plugin/bada/Accelerometer"
                },
                notification: {
                    path: "cordova/plugin/bada/Notification"
                }
            }
        }
    },
    merges: {
        navigator: {
            children: {
                device: {
                    path: "cordova/plugin/bada/device"
                },
                camera: {
                    path: "cordova/plugin/bada/Camera"
                },
                capture: {
                    path: "cordova/plugin/bada/Capture"
                }
            }
        }
    }
};
<|endoftext|>


<commit_before>var request = require("request");
var dns = require("dns");

function GeoIPPlugin(bot) {
	var self = this;
	self.name = "geoip";
	self.help = "GeoIP plugin";
	self.depend = ["cmd", "bitly"];

	self.formatPair = function(key, value) {
		if (value !== undefined)
			return key + ": \x02" + value + "\x02";
		else
			return "\x02" + key + "\x02";
	};

	self.geoip = function(ip, callback) {
		request("http://ipinfo.io/" + ip + "/json", function(err, res, body) {
			if (!err && res.statusCode == 200) {
				var j = JSON.parse(body);
				var bits = [];

				var locstr = "";
				if (j.city)
					locstr += j.city + ", ";
				if (j.region)
					locstr += j.region + ", ";
				if (j.country)
					locstr += j.country;
				if (locstr != "")
					bits.push(["location", locstr]);

				var loc = j.loc && j.loc != "";
				if (loc)
					bits.push(["coords", j.loc]);

				if (j.org)
					bits.push(["organization", j.org]);
				if (j.postal)
					bits.push(["postal code", j.postal]);
				if (j.bogon)
					bits.push(["bogon"]);

				var func;
				var mapsurl = "http://www.google.com/maps/place/" + j.loc + "/@" + j.loc + ",9z";
				if (loc)
					func = bot.plugins.bitly.shorten;
				else {
					func = function(_, callback) {
						callback();
					};
				}

				func(mapsurl, function(shorturl) {
					if (loc) {
						for (var i = 0; i < bits.length; i++) {
							if (bits[i][0] == "coords") {
								bits[i][1] += " \x02(" + shorturl + ")\x02";
								break;
							}
						}
					}

					var hoststr = (j.hostname !== undefined && j.hostname != "No Hostname") ? " \x02(" + j.hostname + ")\x02" : "";
					var str = "\x02" + j.ip + hoststr + ": \x02";
					for (var i = 0; i < bits.length; i++) {
						str += self.formatPair(bits[i][0], bits[i][1]);
						if (i != bits.length - 1)
							str += ", ";
					}

					(callback || function(){})(str);
				});
			}
			else if (!err && res.statusCode == 404) {
				(callback || function(){})(null);
			}
		});
	};

	self.events = {
		"cmd#geoip": function(nick, to, args) {
			self.geoip(args[1], function(str) {
				if (str === null) {
					dns.resolve4(args[1], function(err, ips) {
						if (!err) {
							var i = args[2] || 1;
							if (i - 1 < 0 || i - 1 >= ips.length) {
								bot.say(to, "\x02" + args[1] + "\x02 [" + i + "/" + ips.length + "] invalid resolve index");
								return;
							}

							var ip = ips[i - 1];
							self.geoip(ip, function(str) {
								if (str === null) {
									bot.say(to, "\x02" + args[1] + "\x02 [" + i + "/" + ips.length + "] = \x02" + ip + "\x02 is invalid IP");
								}
								else {
									bot.say(to, "\x02" + args[1] + "\x02 [" + i + "/" + ips.length + "] = " + str);
								}
							});
						}
						else
							bot.say(to, "\x02" + args[1] + "\x02 is invalid IP and domain");
					});
				}
				else {
					bot.say(to, str);
				}
			});
		}
	}
}

module.exports = GeoIPPlugin;
<commit_msg>Strip ASN from geoip organization<commit_after>var request = require("request");
var dns = require("dns");

function GeoIPPlugin(bot) {
	var self = this;
	self.name = "geoip";
	self.help = "GeoIP plugin";
	self.depend = ["cmd", "bitly"];

	self.formatPair = function(key, value) {
		if (value !== undefined)
			return key + ": \x02" + value + "\x02";
		else
			return "\x02" + key + "\x02";
	};

	self.geoip = function(ip, callback) {
		request("http://ipinfo.io/" + ip + "/json", function(err, res, body) {
			if (!err && res.statusCode == 200) {
				var j = JSON.parse(body);
				var bits = [];

				var locstr = "";
				if (j.city)
					locstr += j.city + ", ";
				if (j.region)
					locstr += j.region + ", ";
				if (j.country)
					locstr += j.country;
				if (locstr != "")
					bits.push(["location", locstr]);

				var loc = j.loc && j.loc != "";
				if (loc)
					bits.push(["coords", j.loc]);

				if (j.org)
					bits.push(["organization", j.org.replace(/^AS\d+ /, "")]);
				if (j.postal)
					bits.push(["postal code", j.postal]);
				if (j.bogon)
					bits.push(["bogon"]);

				var func;
				var mapsurl = "http://www.google.com/maps/place/" + j.loc + "/@" + j.loc + ",9z";
				if (loc)
					func = bot.plugins.bitly.shorten;
				else {
					func = function(_, callback) {
						callback();
					};
				}

				func(mapsurl, function(shorturl) {
					if (loc) {
						for (var i = 0; i < bits.length; i++) {
							if (bits[i][0] == "coords") {
								bits[i][1] += " \x02(" + shorturl + ")\x02";
								break;
							}
						}
					}

					var hoststr = (j.hostname !== undefined && j.hostname != "No Hostname") ? " \x02(" + j.hostname + ")\x02" : "";
					var str = "\x02" + j.ip + hoststr + ": \x02";
					for (var i = 0; i < bits.length; i++) {
						str += self.formatPair(bits[i][0], bits[i][1]);
						if (i != bits.length - 1)
							str += ", ";
					}

					(callback || function(){})(str);
				});
			}
			else if (!err && res.statusCode == 404) {
				(callback || function(){})(null);
			}
		});
	};

	self.events = {
		"cmd#geoip": function(nick, to, args) {
			self.geoip(args[1], function(str) {
				if (str === null) {
					dns.resolve4(args[1], function(err, ips) {
						if (!err) {
							var i = args[2] || 1;
							if (i - 1 < 0 || i - 1 >= ips.length) {
								bot.say(to, "\x02" + args[1] + "\x02 [" + i + "/" + ips.length + "] invalid resolve index");
								return;
							}

							var ip = ips[i - 1];
							self.geoip(ip, function(str) {
								if (str === null) {
									bot.say(to, "\x02" + args[1] + "\x02 [" + i + "/" + ips.length + "] = \x02" + ip + "\x02 is invalid IP");
								}
								else {
									bot.say(to, "\x02" + args[1] + "\x02 [" + i + "/" + ips.length + "] = " + str);
								}
							});
						}
						else
							bot.say(to, "\x02" + args[1] + "\x02 is invalid IP and domain");
					});
				}
				else {
					bot.say(to, str);
				}
			});
		}
	}
}

module.exports = GeoIPPlugin;
<|endoftext|>


<commit_before>// Batch Request

var _ = require('lodash'),
    check = require('validator').check,
    methods = require('methods'),
    Promise = require('bluebird'),
    request = Promise.promisify(require('request')),
    url = require('url'),
    template = require('es6-template-strings'),
    logger = require('tracer').colorConsole();

function debug() {
    var util = require('util');
    console.log( util.inspect( arguments, { depth: null, colors: true } ) );
}

function getFinalUrl(req, r) {
    // Accept either uri or url (this is what request does, we just mirror)
    r.url = r.url || r.uri;

    // Convert relative paths to full paths
    if (typeof r.url === 'string' && /^\//.test(r.url) === true) {
        return req.protocol + '://' + req.get('host') + r.url;
    }

    return r.url;
}

var batchRequest = function(params) {

    // Set default option values
    params = params || {};
    params.localOnly = (typeof params.localOnly === 'undefined') ? true : params.localOnly;
    params.httpsAlways = (typeof params.localOnly === 'undefined') ? false : params.localOnly;
    params.max = (typeof params.max === 'undefined') ? 20 : params.max;
    params.validateRespond = (typeof params.validateRespond === 'undefined') ? true : params.validateRespond;
    params.allowedHosts = (typeof params.allowedHosts === 'undefined') ? null : params.allowedHosts;
    params.defaultHeaders = (typeof params.defaultHeaders === 'undefined') ? {} : params.defaultHeaders;
    params.forwardHeaders = (typeof params.forwardHeaders === 'undefined') ? [] : params.forwardHeaders;

    var batch = function(req, res, next) {
        // Here we assume it the request has already been validated, either by
        // our included middleware or otherwise by the app developer.

        // We also assume it has been run through some middleware like
        // express.bodyParser() or express.json() to parse the requests

        var requests = req.body;

        var requestPromise = function(r) {
            r.headers = r.headers || {};

            r.url = getFinalUrl(req, r);

            _.each(params.defaultHeaders, function(headerV, headerK) {
                if (!(headerK in r.headers)) { // copy defaults if not already exposed
                    r.headers[headerK] = headerV;
                }
            });
            _.each(params.forwardHeaders, function(headerK) {
                if (!(headerK in r.headers) && headerK in req.headers) { // copy forward if not already exposed
                    var forwardValue = req.headers[headerK];
                    r.headers[headerK] = forwardValue;
                }
            });
            return request(r).spread(function(response, body) {
                if ( response.headers['content-type'].indexOf( 'application/json' ) > -1 ) {
                    body = JSON.parse( body );
                }
                return {
                    'statusCode': response.statusCode,
                    'body': body,
                    'headers': response.headers
                };
            });
        };

        // First, let's fire off all calls without any dependencies, accumulate their promises
        var requestPromises = _.reduce(requests, function(promises, r, key) {
            if (!r.dependency || r.dependency === 'none') {
                promises[key] = requestPromise(r);
            }
            // And while we do that, build the dependency object with those items as keys
            // { key: Promise }
            return promises;
        }, {});

        // Then recursively iterate over all items with dependencies, resolving some at each pass
        var recurseDependencies = function (reqs) {

            debug( 'reqs', reqs );
            debug( 'requestPromises', requestPromises );

            // @todo somewhere here i need to account for a dependency array

            // End state hit when the number of promises we have matches the number
            // of request objects we started with.
            if (_.size(requestPromises) >= _.size(reqs)) {
                return;
            } else {
                _.each(requestPromises, function(rp, key) {
                    debug( 'rp', rp ); // the request's promise
                    debug( 'key', key ); // the request's key - ex. "uploadFile", "emailLink"
                    var dependentKey = null;
                    var dependent = _.find(reqs, function(request, dKey) {
                        debug( 'request', request );
                        debug( 'dKey', dKey ); // this is the job key - ex. "uploadFile", "emailLink"
                        dependentKey = dKey;
                        return request.dependency === key && (typeof requestPromises[dKey] === 'undefined');
                    });
                    if (dependent) {
                        requestPromises[dependentKey] = rp.then(function( dependencyResponse ) {
                            console.log( dependencyResponse ); // This is the JSON response from the dependency
                            console.log( dependent ); // This is the JSON request from the dependent

                            // This could break if the data that's being swapped in contains quotes or other JSON-breaking characters
                            // @todo Check out es6-template-strings/resolve / customTags
                            var jsonRequest = JSON.stringify( dependent );
                            jsonRequest = template( jsonRequest, { dependency: dependencyResponse } );
                            dependent = JSON.parse( jsonRequest );

                            console.log( dependent );

                            return requestPromise(dependent);
                        });
                    }
                });
                recurseDependencies(reqs);
            }
        };

        debug( 'requests', requests );

        // Recurse dependencies
        recurseDependencies(requests);

        // Wait for all to complete before responding
        Promise.props(requestPromises).then(function(result) {

            // remove all properties, except status, body, and headers
            var output = {};
            for(var prop in result){
                output[prop] = { statusCode: result[prop].statusCode, body: result[prop].body, headers: result[prop].headers};
            }
            res.json(output);
            // next(); // this line is causing the response to be 0
        });
    };

    batch.validate = function(req, res, next) {
        var err = null,
            requests = req.body,
            requestHost;

        // Validation on Request object as a whole
        try {
            check(_.size(requests), 'Cannot make a batch request with an empty request object').min(1);
            check(_.size(requests), 'Over the max request limit. Please limit batches to ' + params.max + ' requests').max(params.max);
            if (req.method === 'POST' && !req.is('json')) {
                throw new Error('Batch Request will only accept body as json');
            }
        } catch (e) {
            err = {
                error: {
                    'message': e.message,
                    'type': 'ValidationError'
                }
            };
        }

        // Validation on each request object
        _.each(requests, function(r, key) {

            // If no method provided, default to GET
            r.method = (typeof r.method === 'string') ? r.method.toLowerCase() : 'get';

            r.url = getFinalUrl(req, r);

            try {
                check(r.url, 'Invalid URL').isUrl();
                check(r.method, 'Invalid method').isIn(methods);
                if (r.body !== undefined) {
                    check(r.method.toLowerCase(), 'Request body not allowed for this method').isIn(['put', 'post', 'options']);
                }
            } catch (e) {
                err = {
                    error: {
                        'message': e.message,
                        'request': key,
                        'type': 'ValidationError'
                    }
                };
            }

            if (params.allowedHosts !== null) {
                requestHost = url.parse(r.url).host;
                if (params.allowedHosts.indexOf(requestHost) === -1) {
                    err = {
                        error: {
                            'message': 'Cannot make batch request to a host which is not allowed',
                            'host': requestHost,
                            'type': 'ValidationError'
                        }
                    };
                }
            }
        });

        if (err !== null) {
            res.status(400).send(err);
            next(err);
        } else {
            next();
        }
    };

    return batch;
};

module.exports = batchRequest;
<commit_msg>Working with a single element dependency array<commit_after>// Batch Request

var _ = require('lodash'),
    check = require('validator').check,
    methods = require('methods'),
    Promise = require('bluebird'),
    request = Promise.promisify(require('request')),
    url = require('url'),
    template = require('es6-template-strings'),
    logger = require('tracer').colorConsole();

function debug() {
    var util = require('util');
    console.log( util.inspect( arguments, { depth: null, colors: true } ) );
}

function getFinalUrl(req, r) {
    // Accept either uri or url (this is what request does, we just mirror)
    r.url = r.url || r.uri;

    // Convert relative paths to full paths
    if (typeof r.url === 'string' && /^\//.test(r.url) === true) {
        return req.protocol + '://' + req.get('host') + r.url;
    }

    return r.url;
}

var batchRequest = function(params) {

    // Set default option values
    params = params || {};
    params.localOnly = (typeof params.localOnly === 'undefined') ? true : params.localOnly;
    params.httpsAlways = (typeof params.localOnly === 'undefined') ? false : params.localOnly;
    params.max = (typeof params.max === 'undefined') ? 20 : params.max;
    params.validateRespond = (typeof params.validateRespond === 'undefined') ? true : params.validateRespond;
    params.allowedHosts = (typeof params.allowedHosts === 'undefined') ? null : params.allowedHosts;
    params.defaultHeaders = (typeof params.defaultHeaders === 'undefined') ? {} : params.defaultHeaders;
    params.forwardHeaders = (typeof params.forwardHeaders === 'undefined') ? [] : params.forwardHeaders;

    var batch = function(req, res, next) {
        // Here we assume it the request has already been validated, either by
        // our included middleware or otherwise by the app developer.

        // We also assume it has been run through some middleware like
        // express.bodyParser() or express.json() to parse the requests

        var requests = req.body;

        var requestPromise = function(r) {
            r.headers = r.headers || {};

            r.url = getFinalUrl(req, r);

            _.each(params.defaultHeaders, function(headerV, headerK) {
                if (!(headerK in r.headers)) { // copy defaults if not already exposed
                    r.headers[headerK] = headerV;
                }
            });
            _.each(params.forwardHeaders, function(headerK) {
                if (!(headerK in r.headers) && headerK in req.headers) { // copy forward if not already exposed
                    var forwardValue = req.headers[headerK];
                    r.headers[headerK] = forwardValue;
                }
            });
            return request(r).spread(function(response, body) {
                if ( response.headers['content-type'].indexOf( 'application/json' ) > -1 ) {
                    body = JSON.parse( body );
                }
                return {
                    'statusCode': response.statusCode,
                    'body': body,
                    'headers': response.headers
                };
            });
        };

        // First, let's fire off all calls without any dependencies, accumulate their promises
        var requestPromises = _.reduce(requests, function(promises, r, key) {
            if (!r.dependency || r.dependency === 'none') {
                promises[key] = requestPromise(r);
            }
            // And while we do that, build the dependency object with those items as keys
            // { key: Promise }
            return promises;
        }, {});

        // Then recursively iterate over all items with dependencies, resolving some at each pass
        var recurseDependencies = function (reqs) {

            debug( 'reqs', reqs );
            debug( 'requestPromises', requestPromises );

            // @todo somewhere here i need to account for a dependency array

            // End state hit when the number of promises we have matches the number
            // of request objects we started with.
            if (_.size(requestPromises) >= _.size(reqs)) {
                return;
            } else {
                _.each(requestPromises, function(rp, key) {
                    debug( 'rp', rp ); // the request's promise
                    debug( 'key', key ); // the request's key - ex. "uploadFile", "emailLink"

                    var dependentKey = null;
                    var dependent = _.filter(reqs, function(request, dKey) {
                        debug( 'request', request );
                        debug( 'dKey', dKey ); // the request's key - ex. "uploadFile", "emailLink"
                        dependentKey = dKey;

                        var isDependency = false;

                        debug( 'requestPromises[dKey]', requestPromises[dKey] );
                        debug( 'request.dependency', request.dependency );

                        if ( typeof requestPromises[dKey] === 'undefined' ) {
                            if ( Array.isArray( request.dependency ) ) {
                                if ( request.dependency.indexOf( key ) > -1 ) {
                                    isDependency = true;
                                }
                            }
                            else {
                                if ( request.dependency === key ) {
                                    isDependency = true;
                                }
                            }
                        }

                        return isDependency;

                        // return request.dependency === key && (typeof requestPromises[dKey] === 'undefined');
                    });

                    debug( 'dependent', dependent );
                    dependent = dependent[0];

                    if (dependent) {
                        requestPromises[dependentKey] = rp.then(function( dependencyResponse ) {
                            console.log( dependencyResponse ); // This is the JSON response from the dependency
                            console.log( dependent ); // This is the JSON request from the dependent

                            // This could break if the data that's being swapped in contains quotes or other JSON-breaking characters
                            // @todo Check out es6-template-strings/resolve / customTags
                            var jsonRequest = JSON.stringify( dependent );
                            jsonRequest = template( jsonRequest, { dependency: dependencyResponse } );
                            dependent = JSON.parse( jsonRequest );

                            console.log( dependent );

                            return requestPromise(dependent);
                        });
                    }
                });
                recurseDependencies(reqs);
            }
        };

        debug( 'requests', requests );

        // Recurse dependencies
        recurseDependencies(requests);

        // Wait for all to complete before responding
        Promise.props(requestPromises).then(function(result) {

            // remove all properties, except status, body, and headers
            var output = {};
            for(var prop in result){
                output[prop] = { statusCode: result[prop].statusCode, body: result[prop].body, headers: result[prop].headers};
            }
            res.json(output);
            // next(); // this line is causing the response to be 0
        });
    };

    batch.validate = function(req, res, next) {
        var err = null,
            requests = req.body,
            requestHost;

        // Validation on Request object as a whole
        try {
            check(_.size(requests), 'Cannot make a batch request with an empty request object').min(1);
            check(_.size(requests), 'Over the max request limit. Please limit batches to ' + params.max + ' requests').max(params.max);
            if (req.method === 'POST' && !req.is('json')) {
                throw new Error('Batch Request will only accept body as json');
            }
        } catch (e) {
            err = {
                error: {
                    'message': e.message,
                    'type': 'ValidationError'
                }
            };
        }

        // Validation on each request object
        _.each(requests, function(r, key) {

            // If no method provided, default to GET
            r.method = (typeof r.method === 'string') ? r.method.toLowerCase() : 'get';

            r.url = getFinalUrl(req, r);

            try {
                check(r.url, 'Invalid URL').isUrl();
                check(r.method, 'Invalid method').isIn(methods);
                if (r.body !== undefined) {
                    check(r.method.toLowerCase(), 'Request body not allowed for this method').isIn(['put', 'post', 'options']);
                }
            } catch (e) {
                err = {
                    error: {
                        'message': e.message,
                        'request': key,
                        'type': 'ValidationError'
                    }
                };
            }

            if (params.allowedHosts !== null) {
                requestHost = url.parse(r.url).host;
                if (params.allowedHosts.indexOf(requestHost) === -1) {
                    err = {
                        error: {
                            'message': 'Cannot make batch request to a host which is not allowed',
                            'host': requestHost,
                            'type': 'ValidationError'
                        }
                    };
                }
            }
        });

        if (err !== null) {
            res.status(400).send(err);
            next(err);
        } else {
            next();
        }
    };

    return batch;
};

module.exports = batchRequest;
<|endoftext|>


<commit_before>// Batch Request

var _ = require('lodash'),
    check = require('validator').check,
    methods = require('methods'),
    Promise = require('bluebird'),
    request = Promise.promisify(require('request')),
    url = require('url'),
    template = require('es6-template-strings'),
    resolve = require( 'es6-template-strings/resolve' ),
    compile = require('es6-template-strings/compile')
    ;

function debug() {
    var util = require('util');
    console.log( util.inspect( arguments, { depth: null, colors: true } ) );
    console.log( '' );
}

function getFinalUrl(req, r) {
    // Accept either uri or url (this is what request does, we just mirror)
    r.url = r.url || r.uri;

    // Convert relative paths to full paths
    if (typeof r.url === 'string' && /^\//.test(r.url) === true) {
        return req.protocol + '://' + req.get('host') + r.url;
    }

    return r.url;
}

var batchRequest = function(params) {

    // Set default option values
    params = params || {};
    params.localOnly = (typeof params.localOnly === 'undefined') ? true : params.localOnly;
    params.httpsAlways = (typeof params.localOnly === 'undefined') ? false : params.localOnly;
    params.max = (typeof params.max === 'undefined') ? 20 : params.max;
    params.validateRespond = (typeof params.validateRespond === 'undefined') ? true : params.validateRespond;
    params.allowedHosts = (typeof params.allowedHosts === 'undefined') ? null : params.allowedHosts;
    params.defaultHeaders = (typeof params.defaultHeaders === 'undefined') ? {} : params.defaultHeaders;
    params.forwardHeaders = (typeof params.forwardHeaders === 'undefined') ? [] : params.forwardHeaders;

    var batch = function(req, res, next) {
        // Here we assume the request has already been validated, either by
        // our included middleware or otherwise by the app developer.

        // We also assume it has been run through some middleware like
        // express.bodyParser() or express.json() to parse the requests

        var requests = req.body;

        var requestPromise = function(r) {
            r.headers = r.headers || {};

            r.url = getFinalUrl(req, r);

            _.each(params.defaultHeaders, function(headerV, headerK) {
                if (!(headerK in r.headers)) { // copy defaults if not already exposed
                    r.headers[headerK] = headerV;
                }
            });
            _.each(params.forwardHeaders, function(headerK) {
                if (!(headerK in r.headers) && headerK in req.headers) { // copy forward if not already exposed
                    var forwardValue = req.headers[headerK];
                    r.headers[headerK] = forwardValue;
                }
            });
            return request(r).spread(function(response, body) {
                if ( response.headers && response.headers['content-type'] && response.headers['content-type'].indexOf( 'application/json' ) > -1 ) {
                    try {
                        body = JSON.parse( body );
                    }
                    catch( e ) {
                        // nop
                    }
                }
                return {
                    'statusCode': response.statusCode,
                    'body': body,
                    'headers': response.headers
                };
            });
        };

        // First, let's fire off all calls without any dependencies, accumulate their promises
        var requestPromises = _.reduce(requests, function(promises, r, key) {
            if (!r.dependency || r.dependency === 'none') {
                promises[key] = requestPromise(r);
            }
            // And while we do that, build the dependency object with those items as keys
            // { key: Promise }
            return promises;
        }, {});

        // The documentation for es6-template-strings suggests using the spread operator (...),
        // but I'm avoiding it for compatibility with older node versions
        var escapeSubstitutions = function(/* literals, ...substitutions */) {
            var literals = arguments[0];
            var substitutions = Array.prototype.slice.call(arguments, 1);

            var resolvedString = '';
            for (var i = 0; i < literals.length; i++) {
                resolvedString += literals[i];
                if (typeof substitutions[i] !== 'undefined' && substitutions[i] !== null) {
                    resolvedString += substitutions[i].replace(/"/gi, '\\"');
                }
            }
            return resolvedString;
        };

        // Then recursively iterate over all items with dependencies, resolving some at each pass
        var recurseDependencies = function(reqs) {

            // End state hit when the number of promises we have matches the number
            // of request objects we started with.
            if (_.size(requestPromises) >= _.size(reqs)) {
                return;
            } else {
                _.each(requestPromises, function(rp, key) {
                    // rp = the request's promise
                    // key = the request's key/name

                    var dependencyPromises = [];
                    var dependentKey = null;
                    var dependent = _.find(reqs, function(request, dKey) {
                        // dKey = the request's key/name
                        dependentKey = dKey;

                        var isDependency = false;

                        if (typeof requestPromises[dKey] === 'undefined') {
                            if (Array.isArray(request.dependency)) {
                                if (request.dependency.indexOf(key) > -1) {
                                    isDependency = true;
                                }
                            }
                            else {
                                if (request.dependency === key) {
                                    isDependency = true;
                                }
                            }
                        }

                        return isDependency;
                    });

                    if (dependent) {
                        if (!Array.isArray(dependent.dependency)) {
                            dependent.dependency = [dependent.dependency];
                        }
                        _.each(dependent.dependency, function(dependencyKey) {
                            dependencyPromises.push(requestPromises[dependencyKey]);
                        });

                        requestPromises[dependentKey] = Promise.all(dependencyPromises).then(function(dependencyResponses) {
                            // Looking good here.  dependencyResponses is an array of responses from the dependencyPromises

                            var jsonRequest = JSON.stringify(dependent),
                                compiled = compile(jsonRequest),
                                resolved = resolve(compiled, { dependency: dependencyResponses }),
                                parsedJsonRequest = escapeSubstitutions.apply(null, resolved),
                                parsedDependent = JSON.parse(parsedJsonRequest)
                                ;

                            return requestPromise(parsedDependent);
                        });
                    }
                });

                recurseDependencies(reqs);
            }
        };

        // Recurse dependencies
        recurseDependencies(requests);

        // Wait for all to complete before responding
        Promise.props(requestPromises).then(function(result) {

            // remove all properties, except status, body, and headers
            var output = {};
            for(var prop in result){
                output[prop] = { statusCode: result[prop].statusCode, body: result[prop].body, headers: result[prop].headers};
            }
            res.json(output);
            // next(); // this line is causing the response to be 0
        });
    };

    batch.validate = function(req, res, next) {
        var err = null,
            requests = req.body,
            requestHost;

        // Validation on Request object as a whole
        try {
            check(_.size(requests), 'Cannot make a batch request with an empty request object').min(1);
            check(_.size(requests), 'Over the max request limit. Please limit batches to ' + params.max + ' requests').max(params.max);
            if (req.method === 'POST' && !req.is('json')) {
                throw new Error('Batch Request will only accept body as json');
            }
        } catch (e) {
            err = {
                error: {
                    'message': e.message,
                    'type': 'ValidationError'
                }
            };
        }

        // Validation on each request object
        _.each(requests, function(r, key) {

            // If no method provided, default to GET
            r.method = (typeof r.method === 'string') ? r.method.toLowerCase() : 'get';

            r.url = getFinalUrl(req, r);

            try {
                check(r.url, 'Invalid URL').isUrl();
                check(r.method, 'Invalid method').isIn(methods);
                if (r.body !== undefined) {
                    check(r.method.toLowerCase(), 'Request body not allowed for this method').isIn(['put', 'post', 'options']);
                }
            } catch (e) {
                err = {
                    error: {
                        'message': e.message,
                        'request': key,
                        'type': 'ValidationError'
                    }
                };
            }

            if (params.allowedHosts !== null) {
                requestHost = url.parse(r.url).host;
                if (params.allowedHosts.indexOf(requestHost) === -1) {
                    err = {
                        error: {
                            'message': 'Cannot make batch request to a host which is not allowed',
                            'host': requestHost,
                            'type': 'ValidationError'
                        }
                    };
                }
            }
        });

        if (err !== null) {
            res.status(400).send(err);
            next(err);
        } else {
            next();
        }
    };

    return batch;
};

module.exports = batchRequest;
<commit_msg>Renamed ambiguous variables<commit_after>// Batch Request

var _                         = require('lodash'),
    check                     = require('validator').check,
    methods                   = require('methods'),
    Promise                   = require('bluebird'),
    request                   = Promise.promisify(require('request')),
    url                       = require('url'),
    es6TemplateStringsResolve = require( 'es6-template-strings/resolve' ),
    es6TemplateStringsCompile = require('es6-template-strings/compile')
    ;

function debug() {
    var util = require('util');
    console.log( util.inspect( arguments, { depth: null, colors: true } ) );
    console.log( '' );
}

function getFinalUrl(req, r) {
    // Accept either uri or url (this is what request does, we just mirror)
    r.url = r.url || r.uri;

    // Convert relative paths to full paths
    if (typeof r.url === 'string' && /^\//.test(r.url) === true) {
        return req.protocol + '://' + req.get('host') + r.url;
    }

    return r.url;
}

var batchRequest = function(params) {

    // Set default option values
    params = params || {};
    params.localOnly = (typeof params.localOnly === 'undefined') ? true : params.localOnly;
    params.httpsAlways = (typeof params.localOnly === 'undefined') ? false : params.localOnly;
    params.max = (typeof params.max === 'undefined') ? 20 : params.max;
    params.validateRespond = (typeof params.validateRespond === 'undefined') ? true : params.validateRespond;
    params.allowedHosts = (typeof params.allowedHosts === 'undefined') ? null : params.allowedHosts;
    params.defaultHeaders = (typeof params.defaultHeaders === 'undefined') ? {} : params.defaultHeaders;
    params.forwardHeaders = (typeof params.forwardHeaders === 'undefined') ? [] : params.forwardHeaders;

    var batch = function(req, res, next) {
        // Here we assume the request has already been validated, either by
        // our included middleware or otherwise by the app developer.

        // We also assume it has been run through some middleware like
        // express.bodyParser() or express.json() to parse the requests

        var requests = req.body;

        var requestPromise = function(r) {
            r.headers = r.headers || {};

            r.url = getFinalUrl(req, r);

            _.each(params.defaultHeaders, function(headerV, headerK) {
                if (!(headerK in r.headers)) { // copy defaults if not already exposed
                    r.headers[headerK] = headerV;
                }
            });
            _.each(params.forwardHeaders, function(headerK) {
                if (!(headerK in r.headers) && headerK in req.headers) { // copy forward if not already exposed
                    var forwardValue = req.headers[headerK];
                    r.headers[headerK] = forwardValue;
                }
            });
            return request(r).spread(function(response, body) {
                if ( response.headers && response.headers['content-type'] && response.headers['content-type'].indexOf( 'application/json' ) > -1 ) {
                    try {
                        body = JSON.parse( body );
                    }
                    catch( e ) {
                        // nop
                    }
                }
                return {
                    'statusCode': response.statusCode,
                    'body': body,
                    'headers': response.headers
                };
            });
        };

        // First, let's fire off all calls without any dependencies, accumulate their promises
        var requestPromises = _.reduce(requests, function(promises, r, key) {
            if (!r.dependency || r.dependency === 'none') {
                promises[key] = requestPromise(r);
            }
            // And while we do that, build the dependency object with those items as keys
            // { key: Promise }
            return promises;
        }, {});

        // The documentation for es6-template-strings suggests using the spread operator (...),
        // but I'm avoiding it for compatibility with older node versions
        var escapeSubstitutions = function(/* literals, ...substitutions */) {
            var literals = arguments[0];
            var substitutions = Array.prototype.slice.call(arguments, 1);

            var resolvedString = '';
            for (var i = 0; i < literals.length; i++) {
                resolvedString += literals[i];
                if (typeof substitutions[i] !== 'undefined' && substitutions[i] !== null) {
                    resolvedString += substitutions[i].replace(/"/gi, '\\"');
                }
            }
            return resolvedString;
        };

        // Then recursively iterate over all items with dependencies, resolving some at each pass
        var recurseDependencies = function(reqs) {

            // End state hit when the number of promises we have matches the number
            // of request objects we started with.
            if (_.size(requestPromises) >= _.size(reqs)) {
                return;
            } else {
                _.each(requestPromises, function(rp, key) {
                    // rp = the request's promise
                    // key = the request's key/name

                    var dependencyPromises = [];
                    var dependentKey = null;
                    var dependent = _.find(reqs, function(request, dKey) {
                        // dKey = the request's key/name
                        dependentKey = dKey;

                        var isDependency = false;

                        if (typeof requestPromises[dKey] === 'undefined') {
                            if (Array.isArray(request.dependency)) {
                                if (request.dependency.indexOf(key) > -1) {
                                    isDependency = true;
                                }
                            }
                            else {
                                if (request.dependency === key) {
                                    isDependency = true;
                                }
                            }
                        }

                        return isDependency;
                    });

                    if (dependent) {
                        if (!Array.isArray(dependent.dependency)) {
                            dependent.dependency = [dependent.dependency];
                        }
                        _.each(dependent.dependency, function(dependencyKey) {
                            dependencyPromises.push(requestPromises[dependencyKey]);
                        });

                        requestPromises[dependentKey] = Promise.all(dependencyPromises).then(function(dependencyResponses) {
                            // Looking good here.  dependencyResponses is an array of responses from the dependencyPromises

                            var jsonRequest = JSON.stringify(dependent),
                                compiled = es6TemplateStringsCompile(jsonRequest),
                                resolved = es6TemplateStringsResolve(compiled, { dependency : dependencyResponses }),
                                parsedJsonRequest = escapeSubstitutions.apply(null, resolved),
                                parsedDependent = JSON.parse(parsedJsonRequest)
                                ;

                            return requestPromise(parsedDependent);
                        });
                    }
                });

                recurseDependencies(reqs);
            }
        };

        // Recurse dependencies
        recurseDependencies(requests);

        // Wait for all to complete before responding
        Promise.props(requestPromises).then(function(result) {

            // remove all properties, except status, body, and headers
            var output = {};
            for(var prop in result){
                output[prop] = { statusCode: result[prop].statusCode, body: result[prop].body, headers: result[prop].headers};
            }
            res.json(output);
            // next(); // this line is causing the response to be 0
        });
    };

    batch.validate = function(req, res, next) {
        var err = null,
            requests = req.body,
            requestHost;

        // Validation on Request object as a whole
        try {
            check(_.size(requests), 'Cannot make a batch request with an empty request object').min(1);
            check(_.size(requests), 'Over the max request limit. Please limit batches to ' + params.max + ' requests').max(params.max);
            if (req.method === 'POST' && !req.is('json')) {
                throw new Error('Batch Request will only accept body as json');
            }
        } catch (e) {
            err = {
                error: {
                    'message': e.message,
                    'type': 'ValidationError'
                }
            };
        }

        // Validation on each request object
        _.each(requests, function(r, key) {

            // If no method provided, default to GET
            r.method = (typeof r.method === 'string') ? r.method.toLowerCase() : 'get';

            r.url = getFinalUrl(req, r);

            try {
                check(r.url, 'Invalid URL').isUrl();
                check(r.method, 'Invalid method').isIn(methods);
                if (r.body !== undefined) {
                    check(r.method.toLowerCase(), 'Request body not allowed for this method').isIn(['put', 'post', 'options']);
                }
            } catch (e) {
                err = {
                    error: {
                        'message': e.message,
                        'request': key,
                        'type': 'ValidationError'
                    }
                };
            }

            if (params.allowedHosts !== null) {
                requestHost = url.parse(r.url).host;
                if (params.allowedHosts.indexOf(requestHost) === -1) {
                    err = {
                        error: {
                            'message': 'Cannot make batch request to a host which is not allowed',
                            'host': requestHost,
                            'type': 'ValidationError'
                        }
                    };
                }
            }
        });

        if (err !== null) {
            res.status(400).send(err);
            next(err);
        } else {
            next();
        }
    };

    return batch;
};

module.exports = batchRequest;
<|endoftext|>