<commit_before>
/*
 * Main Pieze constructor
 * Process options
 * Tell the board to set pin mode
 */
var Piezo = function (options) {
  if (!options || !options.board) throw new Error('Must supply required options to Piezo');
  this.board = options.board;
  this.pin = options.pin || 13;
  this.board.pinMode(this.pin, 'out');
}

/*
 * Send a square wave to the speaker
 *
 * timeHigh = period / 2 = 1 / (2 * toneFrequency)
 *
 * note   frequency   period   timeHigh
 *  c       261hz      3830      1915
 *  d       294hz      3400      1700
 *  e       329hz      3038      1519
 *  f       349hz      2854      1432
 *  g       392hz      2550      1275
 *  a       440hz      2272      1136
 *  b       493hz      2028      1014
 *  c       523hz      1912       956
 */
Piezo.prototype.tone = function (note, length) {
  var start = +new Date();
  var end = start + length;
  for (i = start; i < end; i++) {
    this.board.digitalWrite(this.pin, this.board.HIGH);
    this.board.digitalWrite(this.pin, this.board.LOW);
  }
}

/*
 * Turn the Piezo on
 */
Piezo.prototype.on = function () {
  this.board.digitalWrite(this.pin, this.board.HIGH);
}

/*
 * Turn the LED off
 */
Piezo.prototype.off = function () {
  this.board.digitalWrite(this.pin, this.board.LOW);
}

module.exports = Piezo;
<commit_msg>[major] add note and reimplment tone in piezo<commit_after>
/*
 * Main Pieze constructor
 * Process options
 * Tell the board to set pin mode
 */
var Piezo = function (options) {
  if (!options || !options.board) throw new Error('Must supply required options to Piezo');
  this.board = options.board;
  this.pin = options.pin || 13;
  this.bright = false;
  this.board.pinMode(this.pin, 'out');
}

/*
 * Send a square wave to the speaker for a given duration
 */
Piezo.prototype.tone = function (tone, duration) {
  this.board.log('info', 'starting tone ' + (tone * 1000).toString().green + ' for ' + duration.toString().green + ' milliseconds');

  var self = this,
      tone = Math.floor(tone / 1000); // timeHigh is in microseconds and our delay() function is in milliseconds
      i = 0;

  setInterval(function(){
    if (self.bright) {
      self.board.digitalWrite(self.pin, self.board.LOW);
    } else {
      self.board.digitalWrite(self.pin, self.board.HIGH);
    }

    if (i++ >= duration) {
      self.board.log('info', 'tone end');
      clearInterval(this);
    }
  }, tone);

}

/*
 * Play a tone for a given duration to create a note
 *
 * timeHigh = period / 2 = 1 / (2 * toneFrequency)
 *
 * note   frequency   period   timeHigh
 *  c       261hz      3830      1915
 *  d       294hz      3400      1700
 *  e       329hz      3038      1519
 *  f       349hz      2854      1432
 *  g       392hz      2550      1275
 *  a       440hz      2272      1136
 *  b       493hz      2028      1014
 *  c       523hz      1912       956
 */
Piezo.prototype.note = function (note, duration) {
  this.board.log('info', 'playing note ' + note.green + ' for ' + duration.toString().green + ' milliseconds');
  var notes = {
    'c': 1915,
    'd': 1700,
    'e': 1519,
    'f': 1432,
    'g': 1275,
    'a': 1136,
    'b': 1014,
    'c': 956
  };
  this.tone(notes[note], duration);
}

/*
 * Turn the Piezo on
 */
Piezo.prototype.on = function () {
  this.board.digitalWrite(this.pin, this.board.HIGH);
}

/*
 * Turn the LED off
 */
Piezo.prototype.off = function () {
  this.board.digitalWrite(this.pin, this.board.LOW);
}

module.exports = Piezo;
<|endoftext|>


<commit_before>var piwikTracker = require('piwik-tracker')
var onFinished = require('on-finished')

function getClientIP (req) {
  var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
  if (ip) return ip
  if (req.ip) return req.ip
  if (req._remoteAddress) return req._remoteAddress
  var sock = req.socket
  if (sock.socket) return sock.socket.remoteAddress
  return sock.remoteAddress
}

function getFullUrl (req) {
  var forwardedProtocol = req.get('X-Forwarded-Proto')
  var protocol = forwardedProtocol || req.protocol
  var fullUrl = protocol + '://' + req.get('host') + req.originalUrl
  return fullUrl
}

module.exports = function (options) {
  return function (req, res, next) {
    req.startTime = Date.now()
    onFinished(res, function (err, res) {
      var piwik = piwikTracker(options.siteid, options.url)
      var action_result = (!err && res.statusCode < 400) ? 'success' : 'failure'
      var response_time = Date.now() - req.startTime
      var piwikData = {
        url: getFullUrl(req),
        action_name: req.route_object.function_name,
        ua: req.header('User-Agent'),
        lang: req.header('Accept-Language'),
        gt_ms: response_time,
        method: req.method,
        action_result: action_result,
        token_auth: options.token,
        cip: getClientIP(req)
      }
      piwik.track(piwikData)
    })
    next()
  }
}
<commit_msg>Piwik: add user identifier as custom dimension<commit_after>var piwikTracker = require('piwik-tracker')
var onFinished = require('on-finished')

function getClientIP (req) {
  var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
  if (ip) return ip
  if (req.ip) return req.ip
  if (req._remoteAddress) return req._remoteAddress
  var sock = req.socket
  if (sock.socket) return sock.socket.remoteAddress
  return sock.remoteAddress
}

function getFullUrl (req) {
  var forwardedProtocol = req.get('X-Forwarded-Proto')
  var protocol = forwardedProtocol || req.protocol
  var fullUrl = protocol + '://' + req.get('host') + req.originalUrl
  return fullUrl
}

module.exports = function (options) {
  return function (req, res, next) {
    req.startTime = Date.now()
    onFinished(res, function (err, res) {
      var piwik = piwikTracker(options.siteid, options.url)
      var action_result = (!err && res.statusCode < 400) ? 'success' : 'failure'
      var response_time = Date.now() - req.startTime
      var piwikData = {
        url: getFullUrl(req),
        action_name: req.route_object.function_name,
        ua: req.header('User-Agent'),
        lang: req.header('Accept-Language'),
        gt_ms: response_time,
        method: req.method,
        user_indentifier: req.user_identifier,
        action_result: action_result,
        token_auth: options.token,
        cip: getClientIP(req)
      }
      piwik.track(piwikData)
    })
    next()
  }
}
<|endoftext|>


<commit_before>var fs        = require('fs');
var protobuf  = require('node-protobuf');

var desc = fs.readFileSync(__dirname + '/cast_channel.desc');
var schema = new protobuf(desc);

var package_ = 'extensions.api.cast_channel';

var messages = [
  'CastMessage',
  'AuthChallenge',
  'AuthResponse',
  'AuthError',
  'DeviceAuthMessage'
];

messages.forEach(function(message) {
  var packagename = package_ + '.' + message;
  module.exports[message] = {
  	serialize: function(data) {
  		console.log(data);
  		return schema.serialize(data, packagename);
  	},
  	parse: function(data) {
  		return schema.parse(data, packagename);
  	}
  };
});<commit_msg>Removed console log<commit_after>var fs        = require('fs');
var protobuf  = require('node-protobuf');

var desc = fs.readFileSync(__dirname + '/cast_channel.desc');
var schema = new protobuf(desc);

var package_ = 'extensions.api.cast_channel';

var messages = [
  'CastMessage',
  'AuthChallenge',
  'AuthResponse',
  'AuthError',
  'DeviceAuthMessage'
];

messages.forEach(function(message) {
  var packagename = package_ + '.' + message;
  module.exports[message] = {
  	serialize: function(data) {
  		return schema.serialize(data, packagename);
  	},
  	parse: function(data) {
  		return schema.parse(data, packagename);
  	}
  };
});<|endoftext|>


<commit_before>
/*!
 * Connect - HTTPServer
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var http = require('http')
  , utils = require('./utils')
  , debug = require('debug')('connect:dispatcher');

// prototype

var app = module.exports = {};

// environment

var env = process.env.NODE_ENV || 'development';

/**
 * Utilize the given middleware `handle` to the given `route`,
 * defaulting to _/_. This "route" is the mount-point for the
 * middleware, when given a value other than _/_ the middleware
 * is only effective when that segment is present in the request's
 * pathname.
 *
 * For example if we were to mount a function at _/admin_, it would
 * be invoked on _/admin_, and _/admin/settings_, however it would
 * not be invoked for _/_, or _/posts_.
 *
 * Examples:
 *
 *      var app = connect();
 *      app.use(connect.favicon());
 *      app.use(connect.logger());
 *      app.use(connect.static(__dirname + '/public'));
 *
 * If we wanted to prefix static files with _/public_, we could
 * "mount" the `static()` middleware:
 *
 *      app.use('/public', connect.static(__dirname + '/public'));
 *
 * This api is chainable, so the following is valid:
 *
 *      connect()
 *        .use(connect.favicon())
 *        .use(connect.logger())
 *        .use(connect.static(__dirname + '/public'))
 *        .listen(3000);
 *
 * @param {String|Function|Server} route, callback or server
 * @param {Function|Server} callback or server
 * @return {Server} for chaining
 * @api public
 */

app.use = function(route, fn){
  // default route to '/'
  if ('string' != typeof route) {
    fn = route;
    route = '/';
  }

  // wrap sub-apps
  if ('function' == typeof fn.handle) {
    var server = fn;
    fn.route = route;
    fn = function(req, res, next){
      server.handle(req, res, next);
    };
  }

  // wrap vanilla http.Servers
  if (fn instanceof http.Server) {
    fn = fn.listeners('request')[0];
  }

  // strip trailing slash
  if ('/' == route[route.length - 1]) {
    route = route.slice(0, -1);
  }

  // add the middleware
  debug('use %s %s', route || '/', fn.name || 'anonymous');
  this.stack.push({ route: route, handle: fn });

  return this;
};

/**
 * Handle server requests, punting them down
 * the middleware stack.
 *
 * @api private
 */

app.handle = function(req, res, out) {
  var stack = this.stack
    , fqdn = ~req.url.indexOf('://')
    , removed = ''
    , slashAdded = false
    , index = 0;

  function next(err) {
    var layer, path, status, c;

    if (slashAdded) {
      req.url = req.url.substr(1);
      slashAdded = false;
    }

    req.url = removed + req.url;
    req.originalUrl = req.originalUrl || req.url;
    removed = '';

    // next callback
    layer = stack[index++];

    // all done
    if (!layer || res.headerSent) {
      // delegate to parent
      if (out) return out(err);

      // unhandled error
      if (err) {
        // default to 500
        if (res.statusCode < 400) res.statusCode = 500;
        debug('default %s', res.statusCode);

        // respect err.status
        if (err.status) res.statusCode = err.status;

        // production gets a basic error message
        var msg = 'production' == env
          ? http.STATUS_CODES[res.statusCode]
          : err.stack || err.toString();

        // log to stderr in a non-test env
        if ('test' != env) console.error(err.stack || err.toString());
        if (res.headerSent) return req.socket.destroy();
        res.setHeader('Content-Type', 'text/plain');
        res.setHeader('Content-Length', Buffer.byteLength(msg));
        if ('HEAD' == req.method) return res.end();
        res.end(msg);
      } else {
        debug('default 404');
        res.statusCode = 404;
        res.setHeader('Content-Type', 'text/plain');
        if ('HEAD' == req.method) return res.end();
        res.end('Cannot ' + req.method + ' ' + utils.escape(req.originalUrl));
      }
      return;
    }

    try {
      path = utils.parseUrl(req).pathname;
      if (undefined == path) path = '/';

      // skip this layer if the route doesn't match.
      if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) return next(err);

      c = path[layer.route.length];
      if (c && '/' != c && '.' != c) return next(err);

      // Call the layer handler
      // Trim off the part of the url that matches the route
      removed = layer.route;
      req.url = req.url.substr(removed.length);

      // Ensure leading slash
      if (!fqdn && '/' != req.url[0]) {
        req.url = '/' + req.url;
        slashAdded = true;
      }

      debug('%s', layer.handle.name || 'anonymous');
      var arity = layer.handle.length;
      if (err) {
        if (arity === 4) {
          layer.handle(err, req, res, next);
        } else {
          next(err);
        }
      } else if (arity < 4) {
        layer.handle(req, res, next);
      } else {
        next();
      }
    } catch (e) {
      next(e);
    }
  }
  next();
};

/**
 * Listen for connections.
 *
 * This method takes the same arguments
 * as node's `http.Server#listen()`.
 *
 * HTTP and HTTPS:
 *
 * If you run your application both as HTTP
 * and HTTPS you may wrap them individually,
 * since your Connect "server" is really just
 * a JavaScript `Function`.
 *
 *      var connect = require('connect')
 *        , http = require('http')
 *        , https = require('https');
 *
 *      var app = connect();
 *
 *      http.createServer(app).listen(80);
 *      https.createServer(options, app).listen(443);
 *
 * @return {http.Server}
 * @api public
 */

app.listen = function(){
  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};
<commit_msg>fix: escape req.method in 404 response<commit_after>
/*!
 * Connect - HTTPServer
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var http = require('http')
  , utils = require('./utils')
  , debug = require('debug')('connect:dispatcher');

// prototype

var app = module.exports = {};

// environment

var env = process.env.NODE_ENV || 'development';

/**
 * Utilize the given middleware `handle` to the given `route`,
 * defaulting to _/_. This "route" is the mount-point for the
 * middleware, when given a value other than _/_ the middleware
 * is only effective when that segment is present in the request's
 * pathname.
 *
 * For example if we were to mount a function at _/admin_, it would
 * be invoked on _/admin_, and _/admin/settings_, however it would
 * not be invoked for _/_, or _/posts_.
 *
 * Examples:
 *
 *      var app = connect();
 *      app.use(connect.favicon());
 *      app.use(connect.logger());
 *      app.use(connect.static(__dirname + '/public'));
 *
 * If we wanted to prefix static files with _/public_, we could
 * "mount" the `static()` middleware:
 *
 *      app.use('/public', connect.static(__dirname + '/public'));
 *
 * This api is chainable, so the following is valid:
 *
 *      connect()
 *        .use(connect.favicon())
 *        .use(connect.logger())
 *        .use(connect.static(__dirname + '/public'))
 *        .listen(3000);
 *
 * @param {String|Function|Server} route, callback or server
 * @param {Function|Server} callback or server
 * @return {Server} for chaining
 * @api public
 */

app.use = function(route, fn){
  // default route to '/'
  if ('string' != typeof route) {
    fn = route;
    route = '/';
  }

  // wrap sub-apps
  if ('function' == typeof fn.handle) {
    var server = fn;
    fn.route = route;
    fn = function(req, res, next){
      server.handle(req, res, next);
    };
  }

  // wrap vanilla http.Servers
  if (fn instanceof http.Server) {
    fn = fn.listeners('request')[0];
  }

  // strip trailing slash
  if ('/' == route[route.length - 1]) {
    route = route.slice(0, -1);
  }

  // add the middleware
  debug('use %s %s', route || '/', fn.name || 'anonymous');
  this.stack.push({ route: route, handle: fn });

  return this;
};

/**
 * Handle server requests, punting them down
 * the middleware stack.
 *
 * @api private
 */

app.handle = function(req, res, out) {
  var stack = this.stack
    , fqdn = ~req.url.indexOf('://')
    , removed = ''
    , slashAdded = false
    , index = 0;

  function next(err) {
    var layer, path, status, c;

    if (slashAdded) {
      req.url = req.url.substr(1);
      slashAdded = false;
    }

    req.url = removed + req.url;
    req.originalUrl = req.originalUrl || req.url;
    removed = '';

    // next callback
    layer = stack[index++];

    // all done
    if (!layer || res.headerSent) {
      // delegate to parent
      if (out) return out(err);

      // unhandled error
      if (err) {
        // default to 500
        if (res.statusCode < 400) res.statusCode = 500;
        debug('default %s', res.statusCode);

        // respect err.status
        if (err.status) res.statusCode = err.status;

        // production gets a basic error message
        var msg = 'production' == env
          ? http.STATUS_CODES[res.statusCode]
          : err.stack || err.toString();

        // log to stderr in a non-test env
        if ('test' != env) console.error(err.stack || err.toString());
        if (res.headerSent) return req.socket.destroy();
        res.setHeader('Content-Type', 'text/plain');
        res.setHeader('Content-Length', Buffer.byteLength(msg));
        if ('HEAD' == req.method) return res.end();
        res.end(msg);
      } else {
        debug('default 404');
        res.statusCode = 404;
        res.setHeader('Content-Type', 'text/plain');
        if ('HEAD' == req.method) return res.end();
        res.end('Cannot ' + utils.escape(req.method) + ' ' + utils.escape(req.originalUrl));
      }
      return;
    }

    try {
      path = utils.parseUrl(req).pathname;
      if (undefined == path) path = '/';

      // skip this layer if the route doesn't match.
      if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) return next(err);

      c = path[layer.route.length];
      if (c && '/' != c && '.' != c) return next(err);

      // Call the layer handler
      // Trim off the part of the url that matches the route
      removed = layer.route;
      req.url = req.url.substr(removed.length);

      // Ensure leading slash
      if (!fqdn && '/' != req.url[0]) {
        req.url = '/' + req.url;
        slashAdded = true;
      }

      debug('%s', layer.handle.name || 'anonymous');
      var arity = layer.handle.length;
      if (err) {
        if (arity === 4) {
          layer.handle(err, req, res, next);
        } else {
          next(err);
        }
      } else if (arity < 4) {
        layer.handle(req, res, next);
      } else {
        next();
      }
    } catch (e) {
      next(e);
    }
  }
  next();
};

/**
 * Listen for connections.
 *
 * This method takes the same arguments
 * as node's `http.Server#listen()`.
 *
 * HTTP and HTTPS:
 *
 * If you run your application both as HTTP
 * and HTTPS you may wrap them individually,
 * since your Connect "server" is really just
 * a JavaScript `Function`.
 *
 *      var connect = require('connect')
 *        , http = require('http')
 *        , https = require('https');
 *
 *      var app = connect();
 *
 *      http.createServer(app).listen(80);
 *      https.createServer(options, app).listen(443);
 *
 * @return {http.Server}
 * @api public
 */

app.listen = function(){
  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};
<|endoftext|>


<commit_before>var proxies = {};

var _check_string = function(str){

	if(typeof str !== "string")
		throw "parameter must be a string";
}

var _keys= function(obj){

	var keys =[];
	for(var k in obj){
		keys.push(k);
	}
	return keys;
}

var _values = function(obj){

	return _keys(obj).map(function(key){
		return obj[key];
	});
}

var _isSync = function(proc_name,f){

	return _values(proxies[proc_name].sync).indexOf(f) !== -1;
}

/*
 * Returns installed proxies as an array for the procedure name proc_name.
 */
var _list_proxies  = function(proc_name){

	var p = [];
	for(var i=1; i <= size(proc_name); i++ ){

		p.push(	proxies[proc_name].sync[i.toString()] ||
				proxies[proc_name].async[i.toString()] );
	}
	return p;
};

var clear = exports.clear = function(){

	proxies = {};
}

/*
 * Returns the number of installed proxies for the procedure name proc_name.
 */
var size = exports.size  = function(proc_name){

	_check_string(proc_name);
	return _keys(proxies[proc_name].sync).length + _keys(proxies[proc_name].async).length;
};

/*
 * Removes proxy functions.
 */
exports.uninject = function(modulee, proc_name){

	proc_name && _check_string(proc_name);

	if(proc_name){
		modulee[proc_name] = proxies[proc_name].func;
		delete proxies[proc_name];
	}else{
		for(var key in proxies){
			modulee[key] = proxies[key].func
			delete proxies[key];
		}
	}

}

/*
 * Adds a synchronous proxy to the function proc_name.
 */
exports.add_proxy_sync = function(proc_name, handler){

	if(!proxies[proc_name]){
		proxies[proc_name] = {sync:{},async:{},err:null,func:null};
	}

	var nextIndex = size( proc_name ) + 1;
	proxies[proc_name].sync[ nextIndex.toString() ] = handler;
	return this;
};

/*
 * Add an asynchronous proxy to the function proc_name.
 */
exports.add_proxy_async = function(proc_name, handler){

	if(!proxies[proc_name]){
		proxies[proc_name] = {sync:{},async:{},err:null,func:null};
	}

	var nextIndex = size(proc_name) + 1;
	proxies[proc_name].async[ nextIndex.toString() ] = handler;
	return this;
};

/*
 * Adds an error handler for async proxies.
 */
exports.add_proxy_err = function(proc_name, handler){

	if(!proxies[proc_name]){
		proxies[proc_name] = {sync:{},async:{},err:null,func:null};
	}
	proxies[proc_name].err = handler;
	return this;
}

/*
 * Inject proxies into module.
 */
exports.inject = function(modulee){

	for(var key in proxies){
		(function(){

			var scopekey = key;
			proxies[scopekey].func = modulee[scopekey];
			var handlers =  _list_proxies(scopekey);
			modulee[scopekey] = function(){

				var args = Array.prototype.slice.call(arguments);
				var loop = function(err){
					if(!err){
						var handler = handlers.shift();
						if(handler){
							if(_isSync(scopekey,handler)){
								handler.apply(this,args);
								loop();
							}else{
								handler.apply(this,args.concat(loop));
							}

						}else{
							proxies[scopekey].func && proxies[scopekey].func.apply(this,args);
						}
					}else if(proxies[scopekey].err){
						proxies[scopekey].err(err);
					}
				};
				loop();
			};
		})();
	}
};
<commit_msg>internal refactoring and added function clear.<commit_after>var proxies = {};

var _check_string = function(str){

	if(typeof str !== "string")
		throw "parameter must be a string";
}

var _check_function = function(f){

	if(typeof f !== "function")
		throw "parameter must be a function";
}

var _keys= function(obj){

	var keys =[];
	for(var k in obj){
		keys.push(k);
	}
	return keys;
}

var _values = function(obj){

	return _keys(obj).map(function(key){
		return obj[key];
	});
}

var _isSync = function(proc_name,f){

	_check_string(proc_name);
	return _values(proxies[proc_name].sync).indexOf(f) !== -1;
}

/*
 * Returns installed proxies as an array for the procedure name proc_name.
 */
var _list_proxies  = function(proc_name){

	_check_string(proc_name);
	var p = [];
	for(var i=1; i <= size(proc_name); i++ ){

		p.push(	proxies[proc_name].sync[i.toString()] ||
				proxies[proc_name].async[i.toString()] );
	}
	return p;
};

var clear = exports.clear = function(){

	for(var key in proxies){
		proxies[key].modulee[key] = proxies[key].func;
		delete proxies[key];
	}

}

/*
 * Returns the number of installed proxies for the procedure name proc_name.
 */
var size = exports.size  = function(proc_name){

	_check_string(proc_name);
	return _keys(proxies[proc_name].sync).length + _keys(proxies[proc_name].async).length;
};

/*
 * Removes proxy functions.
 */
exports.uninject = function(modulee, proc_name){

	proc_name && _check_string(proc_name);
	if(proc_name){
		modulee[proc_name] = proxies[proc_name].func;
		delete proxies[proc_name];
	}else{
		for(var key in proxies){
			modulee[key] = proxies[key].func
			delete proxies[key];
		}
	}

}

/*
 * Adds a synchronous proxy to the function proc_name.
 */
exports.add_proxy_sync = function(proc_name, handler){

	_check_string(proc_name) && _check_function(handler);
	if(!proxies[proc_name]){
		proxies[proc_name] = {sync:{},async:{},err:null,func:null,modulee:null};
	}

	var nextIndex = size( proc_name ) + 1;
	proxies[proc_name].sync[ nextIndex.toString() ] = handler;
	return this;
};

/*
 * Add an asynchronous proxy to the function proc_name.
 */
exports.add_proxy_async = function(proc_name, handler){

	_check_string(proc_name) && _check_function(handler);
	if(!proxies[proc_name]){
		proxies[proc_name] = {sync:{},async:{},err:null,func:null,modulee:null};
	}

	var nextIndex = size(proc_name) + 1;
	proxies[proc_name].async[ nextIndex.toString() ] = handler;
	return this;
};

/*
 * Adds an error handler for async proxies.
 */
exports.add_proxy_err = function(proc_name, handler){

	_check_string(proc_name) && _check_function(handler);
	if(!proxies[proc_name]){
		proxies[proc_name] = {sync:{},async:{},err:null,func:null,modulee:null};
	}
	proxies[proc_name].err = handler;
	return this;
}

/*
 * Inject proxies into module.
 */
exports.inject = function(modulee){

	for(var key in proxies){
		(function(){

			var scopekey = key;
			if(proxies[scopekey].modulee)
				throw "Proxy " + scopekey + " is injected in other module";

			proxies[scopekey].func = modulee[scopekey];
			proxies[scopekey].modulee = modulee;
			var handlers =  _list_proxies(scopekey);
			modulee[scopekey] = function(){

				var args = Array.prototype.slice.call(arguments);
				var loop = function(err){
					if(!err){
						var handler = handlers.shift();
						if(handler){
							if(_isSync(scopekey,handler)){
								handler.apply(this,args);
								loop();
							}else{
								handler.apply(this,args.concat(loop));
							}

						}else{
							proxies[scopekey].func && proxies[scopekey].func.apply(this,args);
						}
					}else if(proxies[scopekey].err){
						proxies[scopekey].err(err);
					}
				};
				loop();
			};
		})();
	}
};
<|endoftext|>


<commit_before>let express = require('express');
let fs = require('fs');
let superAgent = require('superagent');

function firstLetterToLowerCase(world) {
	return world.charAt(0).toLowerCase() + world.slice(1);
}

function firstLetterToUpperCase(world) {
	return world.charAt(0).toUpperCase() + world.slice(1);
}

function parseSetCookieHeader(cookieString) {
	let cookiePairs = cookieString.split('; ');

	let cookieName = null;
	let cookieValue = null;
	let cookieOptions = {
		path: '/',
		secure: false,
		expires: new Date('Fri, 31 Dec 9999 23:59:59 UTC'),
		httpOnly: false,
		'max-Age': null
	};

	cookiePairs.forEach((pair) => {
		let separatorIndexEqual = pair.indexOf('=');
		let name = decodeURIComponent(firstLetterToLowerCase(pair.substr(0, separatorIndexEqual)).trim());
		let value = decodeURIComponent(pair.substr(separatorIndexEqual + 1).trim());

		if (name === '') {
			name = firstLetterToLowerCase(value);
			value = true;
		}

		if (cookieOptions.hasOwnProperty(name)) {

			if (name === 'expires') {
				cookieOptions[name] = new Date(value);
			} else {
				cookieOptions[name] = value;
			}

		} else {
			cookieName = name;
			cookieValue = value;
		}
	});

	return {
		name: cookieName,
		value: cookieValue,
		options: cookieOptions
	};
}

function createHttpRequest(method, proxyUrl, clientRequest) {
	let httpRequest = null;
	let body = clientRequest.body;

	switch (method) {
		case 'POST':
			httpRequest = superAgent.post(proxyUrl);
			let contentType = clientRequest.get('Content-Type');
			if (/^multipart\/form-data;\s+/i.test(contentType)) {
				for (let fieldName of Object.keys(body)) {
					httpRequest.field(fieldName, body[fieldName]);
				}
				for (let fieldName of Object.keys(clientRequest.files || {})) {
					let files = clientRequest.files[fieldName];
					for (let file of files) {
						let { fieldname, path, originalname } = file;
						httpRequest.attach(fieldname, path, originalname);
					}
				}
			} else {
				httpRequest.send(body);
			}
			break;
		case 'PUT':
			httpRequest = superAgent
				.put(proxyUrl)
				.send(body);
			break;
		case 'PATCH':
			httpRequest = superAgent
				.patch(proxyUrl)
				.send(body);
			break;
		case 'DELETE':
			httpRequest = superAgent
				.del(proxyUrl)
				.send(body);
			break;
		case 'GET':
			httpRequest = superAgent
				.get(proxyUrl);
			break;
		default:
			console.warn(`Unknown HTTP request method: ${method}`);
			break;
	}

	return httpRequest;
}

function setCommonRequestHeaders(httpRequest, headers) {
	Object
		.keys(headers)
		.filter((key) => {
			return !['host', 'Cookie'].includes(key);
		})
		.forEach((header) => {
			httpRequest.set(header, headers[header]);
		});

	return httpRequest;
}

function cleanUpRequest(clientRequest) {
	if (clientRequest.method !== 'POST') {
		return;
	}
	let contentType = clientRequest.get('Content-Type');
	if (!/^multipart\/form-data;\s+/i.test(contentType)) {
		return;
	}

	for (let fieldName of Object.keys(clientRequest.files || {})) {
		for (let { path } of clientRequest.files[fieldName]) {
			fs.unlink(path, () => {});
		}
	}
}

module.exports = (environment, logger) => {

	function getResponseData(error, response) {
		let status = 0;
		let body = {};
		let text = '';

		if (error) {
			status = error.status || 500;
			text = error.response.text;
		}

		if (!error && response) {
			status = response.status || 200;
			body = response.body;
			text = response.text;
		}

		if (
			(
				!body ||
				typeof body === 'object' &&
				Object.keys(body).length === 0
			) &&
			typeof(text) === 'string' &&
			text !== ''
		) {
			try {
				logger.warn(
					'The API sent invalid Content-Type header. More info ' +
					'about how you can to fix this: ' +
					'http://visionmedia.github.io/superagent/#parsing-response bodies'
				);
				body = JSON.parse(text);
			} catch (error) {
				logger.error('API response is invalid JSON.', { error });
				body = {};
			}
		}

		return { status, body };
	}

	function sendJSONResponse(req, res, error, response) {
		let { status, body } = getResponseData(error, response);

		if (!Object.keys(body).length) {
			body = { Error: 'API error' };
		}

		res.status(status).json(body);
	}

	return (proxyServer) => {
		let router = express.Router();

		let _callRemoteServer = (req, res) => {
			let url = req.url;

			if (url.length && (url[url.length - 1] === '/')) {
				url = url.substr(0, url.length - 1);
			}

			let proxyUrl = proxyServer + url;

			logger.log(
				'debug',
				`API proxy: ${req.method} ${proxyUrl} query: ` +
				JSON.stringify(req.query)
			);

			let httpRequest = createHttpRequest(req.method, proxyUrl, req);
			httpRequest = setCommonRequestHeaders(httpRequest, req.headers);

			if (req.get('Cookie') && req.get('Cookie') !== '') {
				httpRequest = httpRequest.set('Cookie', req.get('Cookie'));
			}

			httpRequest
				.end((error, response) => {
					cleanUpRequest(req);

					if (error) {
						logger.error(
							`API ERROR: ${req.method} ${proxyUrl} query: ` +
							JSON.stringify(req.query),
							{ error }
						);

						sendJSONResponse(req, res, error, response);
					} else if (response) {
						let settedCookies = response.header['set-cookie'];

						Object
							.keys(response.header)
							.filter((key) => {
								return !['set-cookie', 'content-encoding', 'content-type', 'content-length', 'transfer-encoding'].includes(key);
							})
							.map((key) => {
								return ({
									headerName: key
											.split('-')
											.map(firstLetterToUpperCase)
											.join('-'),
									key: key
								});
							})
							.forEach((item) => {
								res.set(item.headerName, response.header[item.key]);
							});

						if (settedCookies) {
							settedCookies.forEach((cookieString) => {
								let cookie = parseSetCookieHeader(cookieString);
								res.cookie(cookie.name, cookie.value, cookie.options);
							});
						}

						sendJSONResponse(req, res, error, response);
					}
				});
		};

		router.all('*', (req, res) => {
			_callRemoteServer(req, res);
		});

		return router;
	}
};

module.exports.parseSetCookieHeader = parseSetCookieHeader;
module.exports.firstLetterToLowerCase = firstLetterToLowerCase;
module.exports.firstLetterToUpperCase = firstLetterToUpperCase;
module.exports.createHttpRequest = createHttpRequest;
module.exports.setCommonRequestHeaders = setCommonRequestHeaders;
<commit_msg>#! code style<commit_after>let express = require('express');
let fs = require('fs');
let superAgent = require('superagent');

function firstLetterToLowerCase(world) {
	return world.charAt(0).toLowerCase() + world.slice(1);
}

function firstLetterToUpperCase(world) {
	return world.charAt(0).toUpperCase() + world.slice(1);
}

function parseSetCookieHeader(cookieString) {
	let cookiePairs = cookieString.split('; ');

	let cookieName = null;
	let cookieValue = null;
	let cookieOptions = {
		path: '/',
		secure: false,
		expires: new Date('Fri, 31 Dec 9999 23:59:59 UTC'),
		httpOnly: false,
		'max-Age': null
	};

	cookiePairs.forEach((pair) => {
		let separatorIndexEqual = pair.indexOf('=');
		let name = decodeURIComponent(firstLetterToLowerCase(pair.substr(0, separatorIndexEqual)).trim());
		let value = decodeURIComponent(pair.substr(separatorIndexEqual + 1).trim());

		if (name === '') {
			name = firstLetterToLowerCase(value);
			value = true;
		}

		if (cookieOptions.hasOwnProperty(name)) {

			if (name === 'expires') {
				cookieOptions[name] = new Date(value);
			} else {
				cookieOptions[name] = value;
			}

		} else {
			cookieName = name;
			cookieValue = value;
		}
	});

	return {
		name: cookieName,
		value: cookieValue,
		options: cookieOptions
	};
}

function createHttpRequest(method, proxyUrl, clientRequest) {
	let httpRequest = null;
	let body = clientRequest.body;

	switch (method) {
		case 'POST':
			httpRequest = superAgent.post(proxyUrl);
			let contentType = clientRequest.get('Content-Type');

			if (/^multipart\/form-data;\s+/i.test(contentType)) {
				for (let fieldName of Object.keys(body)) {
					httpRequest.field(fieldName, body[fieldName]);
				}

				for (let fieldName of Object.keys(clientRequest.files || {})) {
					let files = clientRequest.files[fieldName];
					for (let file of files) {
						let { fieldname, path, originalname } = file;
						httpRequest.attach(fieldname, path, originalname);
					}
				}
			} else {
				httpRequest.send(body);
			}
			break;
		case 'PUT':
			httpRequest = superAgent
				.put(proxyUrl)
				.send(body);
			break;
		case 'PATCH':
			httpRequest = superAgent
				.patch(proxyUrl)
				.send(body);
			break;
		case 'DELETE':
			httpRequest = superAgent
				.del(proxyUrl)
				.send(body);
			break;
		case 'GET':
			httpRequest = superAgent
				.get(proxyUrl);
			break;
		default:
			console.warn(`Unknown HTTP request method: ${method}`);
			break;
	}

	return httpRequest;
}

function setCommonRequestHeaders(httpRequest, headers) {
	Object
		.keys(headers)
		.filter((key) => {
			return !['host', 'Cookie'].includes(key);
		})
		.forEach((header) => {
			httpRequest.set(header, headers[header]);
		});

	return httpRequest;
}

function cleanUpRequest(clientRequest) {
	if (clientRequest.method !== 'POST') {
		return;
	}

	let contentType = clientRequest.get('Content-Type');
	if (!/^multipart\/form-data;\s+/i.test(contentType)) {
		return;
	}

	for (let fieldName of Object.keys(clientRequest.files || {})) {
		for (let { path } of clientRequest.files[fieldName]) {
			fs.unlink(path, () => {});
		}
	}
}

module.exports = (environment, logger) => {

	function getResponseData(error, response) {
		let status = 0;
		let body = {};
		let text = '';

		if (error) {
			status = error.status || 500;
			text = error.response.text;
		}

		if (!error && response) {
			status = response.status || 200;
			body = response.body;
			text = response.text;
		}

		if (
			(
				!body ||
				typeof body === 'object' &&
				Object.keys(body).length === 0
			) &&
			typeof(text) === 'string' &&
			text !== ''
		) {
			try {
				logger.warn(
					'The API sent invalid Content-Type header. More info ' +
					'about how you can to fix this: ' +
					'http://visionmedia.github.io/superagent/#parsing-response bodies'
				);
				body = JSON.parse(text);
			} catch (error) {
				logger.error('API response is invalid JSON.', { error });
				body = {};
			}
		}

		return { status, body };
	}

	function sendJSONResponse(req, res, error, response) {
		let { status, body } = getResponseData(error, response);

		if (!Object.keys(body).length) {
			body = { Error: 'API error' };
		}

		res.status(status).json(body);
	}

	return (proxyServer) => {
		let router = express.Router();

		let _callRemoteServer = (req, res) => {
			let url = req.url;

			if (url.length && (url[url.length - 1] === '/')) {
				url = url.substr(0, url.length - 1);
			}

			let proxyUrl = proxyServer + url;

			logger.log(
				'debug',
				`API proxy: ${req.method} ${proxyUrl} query: ` +
				JSON.stringify(req.query)
			);

			let httpRequest = createHttpRequest(req.method, proxyUrl, req);
			httpRequest = setCommonRequestHeaders(httpRequest, req.headers);

			if (req.get('Cookie') && req.get('Cookie') !== '') {
				httpRequest = httpRequest.set('Cookie', req.get('Cookie'));
			}

			httpRequest
				.end((error, response) => {
					cleanUpRequest(req);

					if (error) {
						logger.error(
							`API ERROR: ${req.method} ${proxyUrl} query: ` +
							JSON.stringify(req.query),
							{ error }
						);

						sendJSONResponse(req, res, error, response);
					} else if (response) {
						let settedCookies = response.header['set-cookie'];

						Object
							.keys(response.header)
							.filter((key) => {
								return !['set-cookie', 'content-encoding', 'content-type', 'content-length', 'transfer-encoding'].includes(key);
							})
							.map((key) => {
								return ({
									headerName: key
											.split('-')
											.map(firstLetterToUpperCase)
											.join('-'),
									key: key
								});
							})
							.forEach((item) => {
								res.set(item.headerName, response.header[item.key]);
							});

						if (settedCookies) {
							settedCookies.forEach((cookieString) => {
								let cookie = parseSetCookieHeader(cookieString);
								res.cookie(cookie.name, cookie.value, cookie.options);
							});
						}

						sendJSONResponse(req, res, error, response);
					}
				});
		};

		router.all('*', (req, res) => {
			_callRemoteServer(req, res);
		});

		return router;
	}
};

module.exports.parseSetCookieHeader = parseSetCookieHeader;
module.exports.firstLetterToLowerCase = firstLetterToLowerCase;
module.exports.firstLetterToUpperCase = firstLetterToUpperCase;
module.exports.createHttpRequest = createHttpRequest;
module.exports.setCommonRequestHeaders = setCommonRequestHeaders;
<|endoftext|>


<commit_before>(function (module, process) {
    'use strict';
    var colors = require('colors'),
        request = require('./request/main'),
        _ = require('underscore'),
        Q = require('q'),
        events = require('events');

    colors.setTheme({
        silly:'rainbow',
        input:'grey',
        verbose:'cyan',
        prompt:'grey',
        info:'green',
        data:'grey',
        help:'cyan',
        warn:'yellow',
        debug:'blue',
        error:'red'
    });

    var translateOptions2Arguments = function (options) {
        //used to translate property to cmd line arg
        var argMap = {
            'ignoreSslErrors':'ignore-ssl-errors',
            'localToRemoteUrlAccessEnabled':'local-to-remote-url-access',
            'cookiesFile':'cookies-file',
            'diskCache':'disk-cache',
            'loadImages':'load-images',
            'maxDiskCache':'max-disk-cache',
            'outputEncoding':'output-encoding',
            'proxy':'proxy',
            'proxyType':'proxy-type',
            'scriptEncoding':'script-encoding',
            'version':'version',
            'webSecurity':'web-security',
            'port':'port'
        };

        //may integrate in future
        var defaultoptions = {
            'ignoreSslErrors':true,
            'localToRemoteUrlAccessEnabled':true,
            'cookiesFile':'cookies.txt',
            'diskCache':'yes',
            'loadImages':'yes',
            'localToRemoteUrlAccess':'no',
            'maxDiskCache':'50000',
            'outputEncoding':'utf8',
            'proxy':'0',
            'proxyType':'yes',
            'scriptEncoding':'yes',
            'webSecurity':'no',
            'port':1061
        };

        //map options props to cmd line args for phantom process
        return Object.keys(options).map(function (value) {
            return '--' + argMap[value] + '=' + options[value];
        });

    };

//    //on exit loop through process array and kill everything
//    process.on('exit', function () {
//        processArray.forEach(function (proc) {
//            proc.kill('SIGHUP');
//        });
//    });

    //creates a new phantomjs process
    var createServer = function (options, callbackFn) {
            var Webpage = require('./webpage'),
                Phantom = require('./phantom'),
                self = this,
                streamPosition = 0,

//            //pass proxy to callbackFn
//            callbackFn.call(self, self.proxy);

            //parses a line from phantoms event stream
                parseResponse = function (response) {
                    var parsedEvent;

                    self.options.debug && console.log('buffer :%s'.grey, response);

                    try {
                        parsedEvent = JSON.parse(response);
                    }
                    catch (exception) {
                        console.error(exception.toString().red.bold);
                        console.error('attempted to parse %s', response);
                        return;
                    }

                    var args = parsedEvent.args;
                    args.unshift(parsedEvent.type);

                    self.options.debug && console.log('emitting %s event on %s'.grey, parsedEvent.type, parsedEvent.source);

                    switch (parsedEvent.source) {
                        //phantomJs server module started and is listening or failed
                        case 'phantom' :
                            self.proxy.phantom.emit.apply(self.proxy.phantom, args);
                            break;
                        case 'page' :
                            self.proxy.page.emit.apply(self.proxy.page, args);
                            break;
                        case 'server' :
                            self.proxy.phantom.emit.apply(self.proxy.phantom, args);
                            break;
                        default :
                            throw new Error('unexpected eventsource:' + parsedEvent.source);

                    }

                };

            var spawnNewProcess = function () {
                var spawn = require('child_process').spawn,
                    serverPath = __dirname + '/' + require('path').normalize('./server/index.js');

                var processArgs = translateOptions2Arguments(options);

                processArgs.unshift(JSON.stringify(options));
                processArgs.unshift(serverPath);

                //spawn new process
                var phantomjs = spawn('phantomjs',
                    processArgs,
                    {
                        detatched:false,
                        stdio:
                            [
                                process.stdin,
                                process.stdout,
                                process.stderr
                            ]
                    });

                //  phantomjs.unref && phantomjs.unref();
            };

            var ensureServerRunning = function () {
                pingServer(options, function (result) {
                    self.options.debug && console.log('pinged server and got back %s', result);

                    if (result) {
                        self.options.debug && console.log('server already running... proxy value %s', JSON.stringify(self.proxy));
                        callbackFn(self.proxy);

                    }
                    else {
                        self.options.debug && console.log('creating a new server, waiting for servercreated event on %s', self.proxy.phantom);

                        self.proxy.phantom.on('serverCreated', function (result) {
                            self.options.debug && console.log('server created callback fired with value:%s'.yellow.bold, result);
                            callbackFn(self.proxy);
                        });

                        spawnNewProcess();
                    }
                });
            };

            var socketio = require('socket.io');
            var http = require('http');
            this.server = http.createServer(function (request, response) {
                response.writeHead(200, {"Content-Type":"text/html"});
                response.end('');
            }).listen();

            options.clientPort = this.server.address().port;
            var io = socketio.listen(this.server, {'log level':1});

            io.sockets.on('connection', function (socket) {
                options.debug && console.log('connection'.green);
                socket.on('res', function (response) {
                    var data = JSON.stringify(response);
                    options.debug && console.log('response: %s'.green, data);
                    parseResponse(data);
                });
            });

            //create proxy object
            self.proxy = {
                page:new Webpage(options),
                phantom:new Phantom(options),
                end:function (endCallback) {
                    self.end(function () {
                        endCallback(true);
                    });
                }
            };

            ensureServerRunning();
        },
//use to see if  phantom server already runnings
        pingServer = function (options, callbackFn) {

            var self = this;
            request.get(options.hostAndPort + '/ping',
                function (error, response) {

                    if (response && response.statusCode === 200) {    //server up

                        callbackFn && callbackFn.call(self, true);
                    }
                    else {    //server down
                        callbackFn.call(self, false);
                    }
                });
            return this;
        };

    module.exports = {
        //terminates phantomjs process
        end:function (callbackFn) {
            var self = this;
            request.post(this.options.hostAndPort + '/phantom/functions/exit', {
                    form:{
                    }
                },
                function (error, response, body) {

                    if (response && response.statusCode === 200) {    //server up
                        self.server.close();
                        callbackFn && callbackFn.call(self, true);
                    }
                    else {    //server down
                        callbackFn.call(self, false);
                    }
                });
        },
        //creates a new proxy session - creates phantomjs process and webserver module
        create:function (options, callbackFn) {
            var self = this;

            //compensate for optional options parm
            if (typeof options === 'function') {
                callbackFn = options;
                options = {};
            }

            //assign default port
            options.port = options.port || 1061;
            options.host = options.host || 'localhost';
            options.hostAndPort = 'http://' + options.host + ':' + options.port;
            options.eventStreamPath = require('path').normalize(__dirname + '/../temp/events.txt');

            options.debug && console.log('creating proxy to %s', options.hostAndPort);

            this.options = options;

            //try starting server
            createServer.call(self, options, function (proxy) {
                callbackFn.call(self, proxy);
            });

            return this;//return this to chain end
        }};
}
    (module, process)
    )
;

<commit_msg>fix issue #20, remove alerts code, give attribution to node-phantom for socket.io impl.<commit_after>(function (module, process) {
    'use strict';
    var colors = require('colors'),
        request = require('./request/main'),
        _ = require('underscore'),
        Q = require('q'),
        events = require('events');

    colors.setTheme({
        silly:'rainbow',
        input:'grey',
        verbose:'cyan',
        prompt:'grey',
        info:'green',
        data:'grey',
        help:'cyan',
        warn:'yellow',
        debug:'blue',
        error:'red'
    });

    var translateOptions2Arguments = function (options) {
        //used to translate property to cmd line arg
        var argMap = {
            'ignoreSslErrors':'ignore-ssl-errors',
            'localToRemoteUrlAccessEnabled':'local-to-remote-url-access',
            'cookiesFile':'cookies-file',
            'diskCache':'disk-cache',
            'loadImages':'load-images',
            'maxDiskCache':'max-disk-cache',
            'outputEncoding':'output-encoding',
            'proxy':'proxy',
            'proxyType':'proxy-type',
            'scriptEncoding':'script-encoding',
            'version':'version',
            'webSecurity':'web-security',
            'port':'port'
        };

        //may integrate in future
        var defaultoptions = {
            'ignoreSslErrors':true,
            'localToRemoteUrlAccessEnabled':true,
            'cookiesFile':'cookies.txt',
            'diskCache':'yes',
            'loadImages':'yes',
            'localToRemoteUrlAccess':'no',
            'maxDiskCache':'50000',
            'outputEncoding':'utf8',
            'proxy':'0',
            'proxyType':'yes',
            'scriptEncoding':'yes',
            'webSecurity':'no',
            'port':1061
        };

        //map options props to cmd line args for phantom process
        return Object.keys(options).map(function (value) {
            return '--' + argMap[value] + '=' + options[value];
        });

    };

//    //on exit loop through process array and kill everything
//    process.on('exit', function () {
//        processArray.forEach(function (proc) {
//            proc.kill('SIGHUP');
//        });
//    });

    //creates a new phantomjs process
    var createServer = function (options, callbackFn) {
            var Webpage = require('./webpage'),
                Phantom = require('./phantom'),
                self = this,
                streamPosition = 0,

//            //pass proxy to callbackFn
//            callbackFn.call(self, self.proxy);

            //parses a line from phantoms event stream
                parseResponse = function (response) {
                    var parsedEvent;

                    self.options.debug && console.log('buffer :%s'.grey, response);

                    try {
                        parsedEvent = JSON.parse(response);
                    }
                    catch (exception) {
                        console.error(exception.toString().red.bold);
                        console.error('attempted to parse %s', response);
                        return;
                    }

                    var args = parsedEvent.args;
                    args.unshift(parsedEvent.type);

                    self.options.debug && console.log('emitting %s event on %s'.grey, parsedEvent.type, parsedEvent.source);

                    switch (parsedEvent.source) {
                        //phantomJs server module started and is listening or failed
                        case 'phantom' :
                            self.proxy.phantom.emit.apply(self.proxy.phantom, args);
                            break;
                        case 'page' :
                            self.proxy.page.emit.apply(self.proxy.page, args);
                            break;
                        case 'server' :
                            self.proxy.phantom.emit.apply(self.proxy.phantom, args);
                            break;
                        default :
                            throw new Error('unexpected eventsource:' + parsedEvent.source);

                    }

                };

            var spawnNewProcess = function () {
                var spawn = require('child_process').spawn,
                    serverPath = __dirname + '/' + require('path').normalize('./server/index.js');

                var processArgs = translateOptions2Arguments(options);

                processArgs.unshift(JSON.stringify(options));
                processArgs.unshift(serverPath);

                //spawn new process
                var phantomjs = spawn('phantomjs',
                    processArgs,
                    {
                        detatched:false,
                        stdio:
                            [
                                process.stdin,
                                process.stdout,
                                process.stderr
                            ]
                    });

                //  phantomjs.unref && phantomjs.unref();
            };

            var ensureServerRunning = function () {
                pingServer(options, function (result) {
                    self.options.debug && console.log('pinged server and got back %s', result);

                    if (result) {
                        self.options.debug && console.log('server already running... proxy value %s', JSON.stringify(self.proxy));
                        callbackFn(self.proxy);

                    }
                    else {
                        self.options.debug && console.log('creating a new server, waiting for servercreated event on %s', self.proxy.phantom);

                        self.proxy.phantom.on('serverCreated', function (result) {
                            self.options.debug && console.log('server created callback fired with value:%s'.yellow.bold, result);
                            callbackFn(self.proxy);
                        });

                        spawnNewProcess();
                    }
                });
            };

            //socket io implementation - credit to node-phantom
            var socketio = require('socket.io');
            var http = require('http');
            this.server = http.createServer(function (request, response) {
                response.writeHead(200, {"Content-Type":"text/html"});
                response.end('');
            }).listen();

            options.clientPort = this.server.address().port;
            var io = socketio.listen(this.server, {'log level':1});

            io.sockets.on('connection', function (socket) {
                options.debug && console.log('connection'.green);
                socket.on('res', function (response) {
                    var data = JSON.stringify(response);
                    options.debug && console.log('response: %s'.green, data);
                    parseResponse(data);
                });
            });

            //create proxy object
            self.proxy = {
                page:new Webpage(options),
                phantom:new Phantom(options),
                end:function (endCallback) {
                    self.end(function () {
                        endCallback(true);
                    });
                }
            };

            ensureServerRunning();
        },
//use to see if  phantom server already runnings
        pingServer = function (options, callbackFn) {

            var self = this;
            request.get(options.hostAndPort + '/ping',
                function (error, response) {

                    if (response && response.statusCode === 200) {    //server up

                        callbackFn && callbackFn.call(self, true);
                    }
                    else {    //server down
                        callbackFn.call(self, false);
                    }
                });
            return this;
        };

    module.exports = {
        //terminates phantomjs process
        end:function (callbackFn) {
            var self = this;
            request.post(this.options.hostAndPort + '/phantom/functions/exit', {
                    form:{
                    }
                },
                function (error, response, body) {

                    if (response && response.statusCode === 200) {    //server up
                        self.server.close();
                        callbackFn && callbackFn.call(self, true);
                    }
                    else {    //server down
                        callbackFn.call(self, false);
                    }
                });
        },
        //creates a new proxy session - creates phantomjs process and webserver module
        create:function (options, callbackFn) {
            var self = this;

            //compensate for optional options parm
            if (typeof options === 'function') {
                callbackFn = options;
                options = {};
            }

            //assign default port
            options.port = options.port || 1061;
            options.host = options.host || 'localhost';
            options.hostAndPort = 'http://' + options.host + ':' + options.port;
            options.eventStreamPath = require('path').normalize(__dirname + '/../temp/events.txt');

            options.debug && console.log('creating proxy to %s', options.hostAndPort);

            this.options = options;

            //try starting server
            createServer.call(self, options, function (proxy) {
                callbackFn.call(self, proxy);
            });

            return this;//return this to chain end
        }};
}
    (module, process)
    )
;

<|endoftext|>


<commit_before>/**
 * @copyright Maichong Software Ltd. 2016 http://maichong.it
 * @date 2016-12-26
 * @author Liang <liang@maichong.it>
 */

function Query(path, client) {
  var me = this;
  me._client = client;
  me._conditions = { data: {} };
  me._lastCondition = null;
  me._op = 'find';
  me._path = path;
  me._promise = null;

  me.where = function (conditions, value) {
    if (!me._conditions.data.params) {
      me._conditions.data.params = {};
    }
    if (typeof conditions === 'object') {
      if (conditions && conditions.params) {
        me._conditions.data = Object.assign({}, me._conditions.data, conditions);
      } else {
        me._conditions.data.params = Object.assign({}, me._conditions.data.params, conditions);
      }
    } else {
      if (value === undefined) {
        me._lastCondition = conditions;
      } else {
        me._conditions.data.params[conditions] = value;
      }
    }
    return me;
  };

  me._compute = function (type, value) {
    if (!me._conditions.data.params) {
      me._conditions.data.params = {};
    }
    if (type.indexOf('$') >= 0) {
      if (me._lastCondition) {
        if (!me._conditions.data.params.filters) {
          me._conditions.data.params.filters = {};
        }
        if (!me._conditions.data.params.filters[me._lastCondition]) {
          me._conditions.data.params.filters[me._lastCondition] = {};
        }
        if (type === '$eq') {
          me._conditions.data.params.filters[me._lastCondition] = value;
        } else {
          me._conditions.data.params.filters[me._lastCondition][type.split('$')[1]] = value;
        }
      }
    } else {
      me._conditions.data.params[type] = value;
    }
    me._lastCondition = null;
    return me;
  };

  me.eq = function (value) {

    return me._compute('$eq', value);
  };
  me.equals = function (value) {
    return me._compute('$eq', value);
  };

  me.lt = function (value) {
    return me._compute('$lt', value);
  };

  me.lte = function (value) {
    return me._compute('$lte', value);
  };

  me.gt = function (value) {
    return me._compute('$gt', value);
  };

  me.gte = function (value) {
    return me._compute('$gte', value);
  };

  me.limit = function (size) {
    return me._compute('limit', size);
  };

  me.page = function (size) {
    return me._compute('page', size);
  };

  me.sort = function (sortBy) {
    return me._compute('sort', sortBy);
  };

  me.create = function (data) {
    me._op = 'create';
    if (data && data.body) {
      me._conditions.data = data;
    } else {
      me._conditions.data = { body: data };
    }
    return me;
  };

  me.update = function (id, data) {
    me._op = 'update';
    var newData = {};
    if (typeof id === 'object') {
      newData = id;
      id = null;
    } else {
      newData = data;
    }
    if (newData && newData.body) {
      me._conditions.data = newData;
    } else {
      me._conditions.data = { body: newData };
    }
    if (id) {
      me._conditions.id = id;
    }

    return me;
  };

  me.remove = function (conditions) {
    me._op = 'remove';
    if (typeof conditions === 'object') {
      if (conditions && conditions.body) {
        me._conditions.data = conditions;
      } else {
        me._conditions.data = { body: conditions };
      }
    } else {
      me._conditions.id = conditions;
    }
    return me;
  };

  me.count = function (conditions) {
    me._op = 'count';
    if (conditions && conditions.body) {
      me._conditions.data = conditions;
    } else {
      me._conditions.data = { body: conditions };
    }
    return me;
  };

  me.find = function (conditions) {
    me._op = 'find';
    if (conditions && conditions.params) {
      me._conditions.data = conditions;
    } else {
      me._conditions.data = { params: conditions };
    }
    return me;
  };

  me.findOne = function (conditions) {
    me._op = 'find';
    if (typeof conditions === 'object') {
      if (conditions && conditions.params) {
        me._conditions.data = conditions;
      } else {
        me._conditions.data = { params: conditions };
      }
    } else {
      me._conditions.id = conditions;
    }
    return me;
  };

  me.findAll = function () {
    me._op = 'find';
    me._conditions.data = {};
    return me;
  };

  me.exec = function () {
    if (!me._promise) {
      var url = me._path;
      var data;
      if (me._conditions && me._conditions.data) {
        data = me._conditions.data;
      }
      if (me._conditions && me._conditions.id) {
        url += '/' + me._conditions.id;
      }
      me._conditions = { data: {} };
      var p;
      switch (me._op) {
        case 'create':
          p = me._client.post(url, data);
          break;
        case 'update':
          p = me._client.put(url, data);
          break;
        case 'remove':
          p = me._client.delete(url, data);
          break;
        case 'count':
          p = me._client.get(url, data);
          break;
        case 'find':
          p = me._client.get(url, data);
          break;
        default:
          p = new Promise;
      }
      me._promise = p;
    }
    return me._promise;
  };

  me.then = function (onSuccess, onFail) {

    return me.exec().then(onSuccess, onFail);
  };

  me.catch = function (onFail) {
    return me.exec().catch(onFail);
  };
}

module.exports = Query;
<commit_msg>count    body to params<commit_after>/**
 * @copyright Maichong Software Ltd. 2016 http://maichong.it
 * @date 2016-12-26
 * @author Liang <liang@maichong.it>
 */

function Query(path, client) {
  var me = this;
  me._client = client;
  me._conditions = { data: {} };
  me._lastCondition = null;
  me._op = 'find';
  me._path = path;
  me._promise = null;

  me.where = function (conditions, value) {
    if (!me._conditions.data.params) {
      me._conditions.data.params = {};
    }
    if (typeof conditions === 'object') {
      if (conditions && conditions.params) {
        me._conditions.data = Object.assign({}, me._conditions.data, conditions);
      } else {
        me._conditions.data.params = Object.assign({}, me._conditions.data.params, conditions);
      }
    } else {
      if (value === undefined) {
        me._lastCondition = conditions;
      } else {
        me._conditions.data.params[conditions] = value;
      }
    }
    return me;
  };

  me._compute = function (type, value) {
    if (!me._conditions.data.params) {
      me._conditions.data.params = {};
    }
    if (type.indexOf('$') >= 0) {
      if (me._lastCondition) {
        if (!me._conditions.data.params.filters) {
          me._conditions.data.params.filters = {};
        }
        if (!me._conditions.data.params.filters[me._lastCondition]) {
          me._conditions.data.params.filters[me._lastCondition] = {};
        }
        if (type === '$eq') {
          me._conditions.data.params.filters[me._lastCondition] = value;
        } else {
          me._conditions.data.params.filters[me._lastCondition][type.split('$')[1]] = value;
        }
      }
    } else {
      me._conditions.data.params[type] = value;
    }
    me._lastCondition = null;
    return me;
  };

  me.eq = function (value) {

    return me._compute('$eq', value);
  };
  me.equals = function (value) {
    return me._compute('$eq', value);
  };

  me.lt = function (value) {
    return me._compute('$lt', value);
  };

  me.lte = function (value) {
    return me._compute('$lte', value);
  };

  me.gt = function (value) {
    return me._compute('$gt', value);
  };

  me.gte = function (value) {
    return me._compute('$gte', value);
  };

  me.limit = function (size) {
    return me._compute('limit', size);
  };

  me.page = function (size) {
    return me._compute('page', size);
  };

  me.sort = function (sortBy) {
    return me._compute('sort', sortBy);
  };

  me.create = function (data) {
    me._op = 'create';
    if (data && data.body) {
      me._conditions.data = data;
    } else {
      me._conditions.data = { body: data };
    }
    return me;
  };

  me.update = function (id, data) {
    me._op = 'update';
    var newData = {};
    if (typeof id === 'object') {
      newData = id;
      id = null;
    } else {
      newData = data;
    }
    if (newData && newData.body) {
      me._conditions.data = newData;
    } else {
      me._conditions.data = { body: newData };
    }
    if (id) {
      me._conditions.id = id;
    }

    return me;
  };

  me.remove = function (conditions) {
    me._op = 'remove';
    if (typeof conditions === 'object') {
      if (conditions && conditions.body) {
        me._conditions.data = conditions;
      } else {
        me._conditions.data = { body: conditions };
      }
    } else {
      me._conditions.id = conditions;
    }
    return me;
  };

  me.count = function (conditions) {
    me._op = 'count';
    if (conditions && conditions.params) {
      me._conditions.data = conditions;
    } else {
      me._conditions.data = { params: conditions };
    }
    return me;
  };

  me.find = function (conditions) {
    me._op = 'find';
    if (conditions && conditions.params) {
      me._conditions.data = conditions;
    } else {
      me._conditions.data = { params: conditions };
    }
    return me;
  };

  me.findOne = function (conditions) {
    me._op = 'find';
    if (typeof conditions === 'object') {
      if (conditions && conditions.params) {
        me._conditions.data = conditions;
      } else {
        me._conditions.data = { params: conditions };
      }
    } else {
      me._conditions.id = conditions;
    }
    return me;
  };

  me.findAll = function () {
    me._op = 'find';
    me._conditions.data = {};
    return me;
  };

  me.exec = function () {
    if (!me._promise) {
      var url = me._path;
      var data;
      if (me._conditions && me._conditions.data) {
        data = me._conditions.data;
      }
      if (me._conditions && me._conditions.id) {
        url += '/' + me._conditions.id;
      }
      me._conditions = { data: {} };
      var p;
      switch (me._op) {
        case 'create':
          p = me._client.post(url, data);
          break;
        case 'update':
          p = me._client.put(url, data);
          break;
        case 'remove':
          p = me._client.delete(url, data);
          break;
        case 'count':
          p = me._client.get(url, data);
          break;
        case 'find':
          p = me._client.get(url, data);
          break;
        default:
          p = new Promise;
      }
      me._promise = p;
    }
    return me._promise;
  };

  me.then = function (onSuccess, onFail) {

    return me.exec().then(onSuccess, onFail);
  };

  me.catch = function (onFail) {
    return me.exec().catch(onFail);
  };
}

module.exports = Query;
<|endoftext|>