<commit_before>module.exports.Vec2 = require('./lib/Vec2');
module.exports.Vec3 = require('./lib/Vec3');
module.exports.Vec4 = require('./lib/Vec4');
module.exports.Mat4 = require('./lib/Mat4');
module.exports.Quat = require('./lib/Quat');
module.exports.Path = require('./lib/Path');
module.exports.Rect = require('./lib/Rect');
module.exports.Spline3D = require('./lib/Spline3D');
module.exports.Spline2D = require('./lib/Spline2D');
module.exports.Spline1D = require('./lib/Spline1D');
module.exports.Ray = require('./lib/Ray');
module.exports.Plane = require('./lib/Plane');
module.exports.Geometry = require('./lib/Geometry');
module.exports.Random = require('./lib/Random');

//unpack Random methods to geom package
for(var funcName in module.exports.Random) {
  module.exports[funcName] = module.exports.Random[funcName];
}<commit_msg>Added new classes to index<commit_after>module.exports.Vec2 = require('./lib/Vec2');
module.exports.Vec3 = require('./lib/Vec3');
module.exports.Vec4 = require('./lib/Vec4');
module.exports.Mat4 = require('./lib/Mat4');
module.exports.Quat = require('./lib/Quat');
module.exports.Path = require('./lib/Path');
module.exports.Rect = require('./lib/Rect');
module.exports.Spline3D = require('./lib/Spline3D');
module.exports.Spline2D = require('./lib/Spline2D');
module.exports.Spline1D = require('./lib/Spline1D');
module.exports.Ray = require('./lib/Ray');
module.exports.Plane = require('./lib/Plane');
module.exports.Geometry = require('./lib/Geometry');
module.exports.Random = require('./lib/Random');
module.exports.BoundingBox = require('./lib/BoundingBox');
module.exports.Triangle2D = require('./lib/Triangle2D');

//unpack Random methods to geom package
for(var funcName in module.exports.Random) {
  module.exports[funcName] = module.exports.Random[funcName];
}<|endoftext|>


<commit_before>;(function(window, $) {

	var Riptide = function(element, options){
			this.element  = element;
			this.$element = $(element);
			this.options  = options;
			// To dynamically set the context
			this.context = {
				grid: '',
				ripple: '',
				blocks: ''
			};
			// Grid array that will store all the grid positions
			this.grid = [];
			// Some globals
			this.radius = 0;
			this.rectanglePosX = 0;
			this.rectanglePosY = 0;
			this.ripplePosX = 0;
			this.ripplePosY = 0;
			this.requestAnimationFrame = window.requestAnimationFrame ||
			                            window.mozRequestAnimationFrame ||
			                            window.webkitRequestAnimationFrame ||
			                            window.msRequestAnimationFrame;

			self = this;
		};

	// Plugin defaults
	Riptide.prototype.defaults = {
		// Canvas options
		canvasLayoutClasses: {
			grid: 'grid',
			ripple: 'ripple',
			blocks: 'blocks'
		},
		canvasFullSize: false,
		canvasWidth: 300,
		canvasHeight: 300,
		canvasStyle: 'border:1px solid #D3D3D3;',
		// Grid options
		gridStrokeStyle: '#D3D3D3',
		gridLineWidth: 1,
		// Block options
		blockFillStyle: '#D3D3D3',
		blockStrokeStyle: '#C8C8C8',
		blockLineWidth: 1,
		blockType: 'fill', // fill or stroke
		blockExcludeGridLines: false,
		blockProbability: 90,
		// Ripple options
		rippleStyle: 'rgba(0,0,0,0.0)',
		rippleSpeed: 1
	};

	Riptide.prototype.init = function() {
		// Extend default with user options
		self.config = $.extend(true, {}, self.defaults, self.options);
		self.generateCanvas();
	};

	/**
	 * Creates the needed 3 layer canvas setup and applies the styles
	 *
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.generateCanvas = function() {
		var count = 1;
		if (self.config.canvasFullSize) {
			self.config.canvasWidth = self.$element.width();
			self.config.canvasHeight = self.$element.height();
		}
		for (layout in self.config.canvasLayoutClasses) {
			$('<canvas id="' + layout + '"></canvas>').attr({
				width: self.config.canvasWidth,
				height: self.config.canvasHeight,
				style: self.config.canvasStyle
			}).css({
				'position': 'absolute',
				'z-index': count++
			}).appendTo(this.$element);

			self.context[layout] = document.getElementById(layout).getContext("2d");
		};

		self.drawGrid();
	};

	/**
	 * Iterates the x columns and y rows for the canvas, drawing out all
	 * the grid block and saving them in self.grid
	 *
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.drawGrid = function() {
		this.complete = false;

		while (self.rectanglePosY < self.config.canvasHeight) {
			while (self.rectanglePosX < self.config.canvasWidth) {
				self.context.grid.rect(self.rectanglePosX,self.rectanglePosY,20,20);

				self.grid.push({
					x: self.rectanglePosX,
					y: self.rectanglePosY,
					w: 20,
					h: 20
				});
				self.rectanglePosX = self.rectanglePosX + 20;
			}
			self.rectanglePosX = 0;
			self.rectanglePosY = self.rectanglePosY + 20;
		};

		self.context.grid.strokeStyle = self.config.gridStrokeStyle;
		self.context.grid.lineWidth = self.config.gridLineWidth;
		self.context.grid.stroke();

		self.calcRipplePos();
		self.drawRipple();
	}

	/**
	 * Calculates a random position for the circle to the sides of the canvas
	 *
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.calcRipplePos = function() {
		if (Math.random() > 0.5) {
			self.ripplePosX = self.config.canvasWidth - (self.config.canvasWidth * Math.random())/3;
			self.ripplePosY = self.config.canvasHeight - (self.config.canvasHeight * Math.random());
		} else {
			self.ripplePosX = 0 + (self.config.canvasWidth * Math.random())/3;
			self.ripplePosY = 0 + (self.config.canvasHeight * Math.random());
		}
	}

	/**
	 * Repeatedly draws a circle with an increased radius on every iteration.
	 * Circle has a random new location everytime the radius surpasses the canvas size
	 *
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.drawRipple = function() {
	    self.context.ripple.clearRect(0, 0, self.config.canvasWidth, self.config.canvasHeight);

	    self.context.ripple.beginPath();
	    self.context.ripple.arc(self.ripplePosX, self.ripplePosY, self.radius, 0, Math.PI * 2, false);
	    self.context.ripple.closePath();
	    // Making the ripple invisible before we stroke
	    self.context.ripple.strokeStyle = self.config.rippleStyle;
	    // draw the Ripple
	    self.context.ripple.stroke();
	    // Run the collisions check
		self.collisionCheck();

	    self.radius += self.config.rippleSpeed;

	    if (self.radius/1.8 > self.config.canvasWidth || self.radius/1.8 > self.config.canvasHeight) {
	    	self.radius = 0;
	    	self.calcRipplePos();
	    	self.context.blocks.clearRect(0,0,self.config.canvasWidth,self.config.canvasHeight);
	    }

	    requestAnimationFrame(self.drawRipple);
	}

	/**
	 * Draws the active blocks
	 * Style depends on options
	 *
	 * @param  object rect Rectangle that will be drawn
	 * @return mixed Return when blockType == 'stroke' or blockExcludeGridLines == true
	 * @author Johan du Plessis
	 */
	Riptide.prototype.drawBlock = function(rect) {
		if (self.config.blockType == 'stroke') {
			if (self.options.gridLineWidth != undefined && self.options.blocksLineWidth == undefined) {
				self.config.blocksLineWidth = self.options.gridLineWidth;
			}
			self.context.blocks.lineWidth = self.config.blocksLineWidth;
			self.context.blocks.strokeStyle = self.config.blockStrokeStyle;
			self.context.blocks.strokeRect(rect.x,rect.y,rect.w,rect.h);
			return;
		}

		// This will keep the grid visible while filling the blocks
		if (self.config.blockExcludeGridLines) {
			self.context.blocks.fillStyle = self.config.blockFillStyle;
			self.context.blocks.fillRect(
					rect.x + self.config.gridLineWidth/2,
					rect.y + self.config.gridLineWidth/2,
					rect.w - self.config.gridLineWidth,
					rect.h - self.config.gridLineWidth
				);
			return;
		}

		// Default fillRect
		self.context.blocks.fillStyle = self.config.blockFillStyle;
		self.context.blocks.fillRect(rect.x,rect.y,rect.w,rect.h);
	};

	/**
	 * Detect collision between grid blocks and ripple
	 * Iterates through grid array to compare all the block objects
	 * This should be called on every iteration of the ripple
	 *
	 * @param  object rectangle with x,y,w,z
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.collisionCheck = function() {
		var rcx, rcy, dist;

		$.each(self.grid, function(key, rect) {
			rcx = Math.pow(Math.floor(rect.x) - Math.floor(self.ripplePosX),2);
			rcy = Math.pow(Math.floor(rect.y) - Math.floor(self.ripplePosY),2);
			dist = Math.sqrt(rcx + rcy);

			if (self.radius > dist && Math.random()*100 > self.config.blockProbability) {
				self.drawBlock(rect);
			}
		});
	}

	$.fn.riptide = function(options) {
		return this.each(function() {
			new Riptide(this, options).init();
		});
	};

	window.Riptide = Riptide;

})(window, jQuery);<commit_msg>Taste the rainbow<commit_after>;(function(window, $) {

	var Riptide = function(element, options){
			this.element  = element;
			this.$element = $(element);
			this.options  = options;
			// To dynamically set the context
			this.context = {
				grid: '',
				ripple: '',
				blocks: ''
			};
			// Grid array that will store all the grid positions
			this.grid = [];
			// Some globals
			this.radius = 0;
			this.rectanglePosX = 0;
			this.rectanglePosY = 0;
			this.ripplePosX = 0;
			this.ripplePosY = 0;
			this.requestAnimationFrame = window.requestAnimationFrame ||
			                            window.mozRequestAnimationFrame ||
			                            window.webkitRequestAnimationFrame ||
			                            window.msRequestAnimationFrame;

			self = this;
		};

	// Plugin defaults
	Riptide.prototype.defaults = {
		// Canvas options
		canvasLayoutClasses: {
			grid: 'grid',
			ripple: 'ripple',
			blocks: 'blocks'
		},
		canvasFullSize: false,
		canvasWidth: 300,
		canvasHeight: 300,
		canvasStyle: 'border:1px solid #D3D3D3;',
		// Grid options
		gridStrokeStyle: '#D3D3D3',
		gridLineWidth: 1,
		// Block options
		blockWidth: 10,
		blockHeight: 10,
		blockFillStyle: '#D3D3D3',
		blockStrokeStyle: '#C8C8C8',
		blockLineWidth: 1,
		blockType: 'fill', // fill or stroke
		blockExcludeGridLines: false,
		blockProbability: 90,
		// Ripple options
		rippleStyle: 'rgba(0,0,0,0.0)',
		rippleSpeed: 1,
		// Taste the rainbow
		tasteTheRainbow: false
	};

	Riptide.prototype.init = function() {
		// Extend default with user options
		self.config = $.extend(true, {}, self.defaults, self.options);
		self.generateCanvas();
	};

	/**
	 * Creates the needed 3 layer canvas setup and applies the styles
	 *
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.generateCanvas = function() {
		var count = 1;
		if (self.config.canvasFullSize) {
			self.config.canvasWidth = self.$element.width();
			self.config.canvasHeight = self.$element.height();
		}
		for (layout in self.config.canvasLayoutClasses) {
			$('<canvas id="' + layout + '"></canvas>').attr({
				width: self.config.canvasWidth,
				height: self.config.canvasHeight,
				style: self.config.canvasStyle
			}).css({
				'position': 'absolute',
				'z-index': count++
			}).appendTo(this.$element);

			self.context[layout] = document.getElementById(layout).getContext("2d");
		};

		self.drawGrid();
	};

	/**
	 * Iterates the x columns and y rows for the canvas, drawing out all
	 * the grid block and saving them in self.grid
	 *
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.drawGrid = function() {
		this.complete = false;

		while (self.rectanglePosY < self.config.canvasHeight) {
			while (self.rectanglePosX < self.config.canvasWidth) {
				self.context.grid.rect(self.rectanglePosX,self.rectanglePosY,self.config.blockWidth,self.config.blockHeight);

				self.grid.push({
					x: self.rectanglePosX,
					y: self.rectanglePosY,
					w: self.config.blockWidth,
					h: self.config.blockHeight,
					active: false
				});
				self.rectanglePosX = self.rectanglePosX + self.config.blockWidth;
			}
			self.rectanglePosX = 0;
			self.rectanglePosY = self.rectanglePosY + self.config.blockHeight;
		};

		self.context.grid.strokeStyle = self.config.gridStrokeStyle;
		self.context.grid.lineWidth = self.config.gridLineWidth;
		self.context.grid.stroke();

		self.calcRipplePos();
		self.drawRipple();
	}

	/**
	 * Calculates a random position for the circle to the sides of the canvas
	 *
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.calcRipplePos = function() {
		if (Math.random() > 0.5) {
			self.ripplePosX = self.config.canvasWidth - (self.config.canvasWidth * Math.random())/3;
			self.ripplePosY = self.config.canvasHeight - (self.config.canvasHeight * Math.random());
		} else {
			self.ripplePosX = 0 + (self.config.canvasWidth * Math.random())/3;
			self.ripplePosY = 0 + (self.config.canvasHeight * Math.random());
		}
	}

	/**
	 * Repeatedly draws a circle with an increased radius on every iteration.
	 * Circle has a random new location everytime the radius surpasses the canvas size
	 *
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.drawRipple = function() {
	    self.context.ripple.clearRect(0, 0, self.config.canvasWidth, self.config.canvasHeight);

	    self.context.ripple.beginPath();
	    self.context.ripple.arc(self.ripplePosX, self.ripplePosY, self.radius, 0, Math.PI * 2, false);
	    self.context.ripple.closePath();
	    // Making the ripple invisible before we stroke
	    self.context.ripple.strokeStyle = self.config.rippleStyle;
	    // draw the Ripple
	    self.context.ripple.stroke();
	    // Run the collisions check
		self.collisionCheck();

	    self.radius += self.config.rippleSpeed;

	    if (self.radius/1.8 > self.config.canvasWidth || self.radius/1.8 > self.config.canvasHeight) {
	    	self.radius = 0;
	    	self.clearActiveRectangles();
	    	self.calcRipplePos();
	    	self.context.blocks.clearRect(0,0,self.config.canvasWidth,self.config.canvasHeight);
	    }

	    requestAnimationFrame(self.drawRipple);
	}

	/**
	 * Draws the active blocks
	 * Style depends on options
	 *
	 * @param  object rect Rectangle that will be drawn
	 * @return mixed Return when blockType == 'stroke' or blockExcludeGridLines == true
	 * @author Johan du Plessis
	 */
	Riptide.prototype.drawBlock = function(rect) {

		if (self.config.tasteTheRainbow) {
			self.context.blocks.fillStyle = self.tasteTheRainbow();
		} else {
			self.context.blocks.fillStyle = self.config.blockFillStyle;
		}

		if (self.config.blockType == 'stroke') {
			if (self.options.gridLineWidth != undefined && self.options.blocksLineWidth == undefined) {
				self.config.blocksLineWidth = self.options.gridLineWidth;
			}
			self.context.blocks.lineWidth = self.config.blocksLineWidth;
			self.context.blocks.strokeStyle = self.config.blockStrokeStyle;
			self.context.blocks.strokeRect(rect.x,rect.y,rect.w,rect.h);
			return;
		}

		// This will keep the grid visible while filling the blocks
		if (self.config.blockExcludeGridLines) {
			self.context.blocks.fillRect(
					rect.x + self.config.gridLineWidth/2,
					rect.y + self.config.gridLineWidth/2,
					rect.w - self.config.gridLineWidth,
					rect.h - self.config.gridLineWidth
				);
			return;
		}

		// Default fillRect
		self.context.blocks.fillRect(rect.x,rect.y,rect.w,rect.h);
	};

	/**
	 * Taste the rainbow
	 * @return string random color
	 */
	Riptide.prototype.tasteTheRainbow = function() {
		var color = '#';
		var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		for( var i=0; i < 6; i++ ) {
	        color += possible.charAt(Math.floor(Math.random() * possible.length));
	    }

	    return color;
	};

	/**
	 * Detect collision between grid blocks and ripple
	 * Iterates through grid array to compare all the block objects
	 * This should be called on every iteration of the ripple
	 *
	 * @param  object rectangle with x,y,w,z
	 * @return void
	 * @author Johan du Plessis
	 */
	Riptide.prototype.collisionCheck = function() {
		var rcx, rcy, dist;

		$.each(self.grid, function(key, rect) {
			rcx = Math.pow(Math.floor(rect.x) - Math.floor(self.ripplePosX),2);
			rcy = Math.pow(Math.floor(rect.y) - Math.floor(self.ripplePosY),2);
			dist = Math.sqrt(rcx + rcy);

			if (!rect.active && self.radius > dist && Math.random()*100 > self.config.blockProbability) {
				self.drawBlock(rect);
				self.grid[key].active = true;
			}
		});
	}

	Riptide.prototype.clearActiveRectangles = function() {
		$.each(self.grid, function(key, rect) {
			self.grid[key].active = false;
		});
	};

	$.fn.riptide = function(options) {
		return this.each(function() {
			new Riptide(this, options).init();
		});
	};

	window.Riptide = Riptide;

})(window, jQuery);<|endoftext|>


<commit_before>var crypto = require('crypto');
var assert = require('assert');
var LdapAuth = require('ldapauth-fork');
var parseDN = require('ldapjs').parseDN;

module.exports = Auth;

function Auth(config, stuff) {
  var self = Object.create(Auth.prototype);
  self._users = {};

  // config for this module
  self._config = config;

  // verdaccio logger
  self._logger = stuff.logger;

  // TODO: Set more defaults
  self._config.groupNameAttribute = self._config.groupNameAttribute || 'cn';

  return self;
}

//
// Attempt to authenticate user against LDAP backend
//
Auth.prototype.authenticate = function (user, password, callback) {
  var self = this;
  var LdapClient = new LdapAuth(self._config.client_options);

  LdapClient.authenticate(user, password, function (err, ldap_user) {
    if (err) {
      // 'No such user' is reported via error
      self._logger.warn({
        user: user,
        err: err,
      }, 'LDAP error @{err}');

      LdapClient.close(function (err) {
        if (err) {
          self._logger.warn({
            err: err
          }, 'LDAP error on close @{err}');
        }
      });

      return callback(null, false);
    }

    var groups;
    if (ldap_user) {
      groups = [user];
      if ('memberOf' in ldap_user) {
        if (!Array.isArray(ldap_user.memberOf)) {
          ldap_user.memberOf = [ldap_user.memberOf];
        }
        for (var i = 0; i < ldap_user.memberOf.length; i++) {
          groups.push("%" + parseDN(ldap_user.memberOf[i]).rdns[0][self._config.groupNameAttribute]);
        }
      }
    }

    callback(null, groups);

    LdapClient.close(function (err) {
      if (err) {
        self._logger.warn({
          err: err
        }, 'LDAP error on close @{err}');
      }
    });

  });
};
<commit_msg>fix(index): correct jshint errors<commit_after>var crypto = require('crypto');
var assert = require('assert');
var LdapAuth = require('ldapauth-fork');
var parseDN = require('ldapjs').parseDN;

function Auth(config, stuff) {
  var self = Object.create(Auth.prototype);
  self._users = {};

  // config for this module
  self._config = config;

  // verdaccio logger
  self._logger = stuff.logger;

  // TODO: Set more defaults
  self._config.groupNameAttribute = self._config.groupNameAttribute || 'cn';

  return self;
}

//
// Attempt to authenticate user against LDAP backend
//
Auth.prototype.authenticate = function (user, password, callback) {
  var self = this;
  var LdapClient = new LdapAuth(self._config.client_options);

  LdapClient.authenticate(user, password, function (err, ldapUser) {
    if (err) {
      // 'No such user' is reported via error
      self._logger.warn({
        user: user,
        err: err,
      }, 'LDAP error @{err}');

      LdapClient.close(function (err) {
        if (err) {
          self._logger.warn({
            err: err
          }, 'LDAP error on close @{err}');
        }
      });

      return callback(null, false);
    }

    var groups;
    if (ldapUser) {
      groups = [user];
      if ('memberOf' in ldapUser) {
        if (!Array.isArray(ldapUser.memberOf)) {
          ldapUser.memberOf = [ldapUser.memberOf];
        }
        for (var i = 0; i < ldapUser.memberOf.length; i++) {
          groups.push('%' + parseDN(ldapUser.memberOf[i]).rdns[0][self._config.groupNameAttribute]);
        }
      }
    }

    callback(null, groups);

    LdapClient.close(function (err) {
      if (err) {
        self._logger.warn({
          err: err
        }, 'LDAP error on close @{err}');
      }
    });

  });
};

module.exports = Auth;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015-2016 PointSource, LLC.
 * MIT Licensed
 */
var path = require('path'),
    _ = require('lodash'),
    async = require('async'),
    cluster = require('cluster'),
    semver = require('semver');

var loader = require('./lib/loader');

var serviceLoader = loader();
var project = require('./lib/project')(serviceLoader);

global.services = serviceLoader.getRegistry();

//set the app root to the directory the main module was executed from
global.__appDir = path.normalize(path.join(process.mainModule.filename, '../'));

var workerNumberMap = {}; //map a worker pid to a worker number

//Opts is optional
module.exports.init = function (opts, callback) {

    if (typeof opts === 'function') {
        callback = opts;
        opts = {};
    }

    if (opts.appDir) {
        global.__appDir = opts.appDir;
    }

    //Load the bootstrap services first (config and logging) since they're only needed for the master
    initServices({bootstrap: true}, function (err) {
        if (err) {
            if (cluster.isMaster) {
                return callback(err);
            } else {
                //TODO: Don't like having to duplicate the startupComplete message
                var message = {cmd: 'startupComplete', pid: process.pid};
                message.error = err.message;
                process.send(message);
            }
        }

        if (cluster.isMaster) {

            var clusterConfig = serviceLoader.get('config').get('cluster');
            var logger = serviceLoader.get('logger');

            process.on('uncaughtException', function(err) {
                console.log(err.stack);
                logger.dumpBuffer(err);
                process.exit(1); //default behavior
            });

            printVersion(logger);
            checkNodeVersion(logger);

            // Either set to maxWorkers, or if < 0, use the count of machine's CPUs
            var workerCount = clusterConfig.maxWorkers < 0 ? require('os').cpus().length : clusterConfig.maxWorkers;

            //If there's only one worker defined, then it's easier to just run everything on the master
            //That avoid issues with trying to connect a debugger during development
            if (clusterConfig.maxWorkers === 1) {
                logger.info('Clustering is disabled');
                process.env.decryptionKey = serviceLoader.get('config').decryptionKey;
                return initServices(function (err) {
                    if (err) {
                        console.warn(err.stack);
                    }
                    return callback(err);
                });
            } else {

                //on exit, attempt to restart a worker process
                cluster.on('exit', handleClusterWorkerExit);

                async.timesSeries(workerCount, function(n, next) {
                    forkWorker(n, next);
                }, function(err, result) {
                    return callback(err);
                });
            }

        } else {
            initWorker();
        }

    });
};

function handleClusterWorkerExit(worker, code, signal) {
    var logger = serviceLoader.get('logger');

    if (worker.suicide === true) {
        //no need to fork.  We wanted the worker to die.
    } else {
        logger.info('Worker %d stopped (%s). Restarting', worker.process.pid, signal || code);
        var workerNumber = workerNumberMap[worker.process.pid];
        forkWorker(workerNumber, function () {
            //restarted
            logger.info('Restarted worker process');
        });
    }

}

function forkWorker(workerNumber, callback) {
    var logger = serviceLoader.get('logger');
    var worker = cluster.fork({decryptionKey: serviceLoader.get('config').decryptionKey});
    workerNumberMap[worker.process.pid] = workerNumber;
    worker.on('message', function(msg) {

        try {
            var obj = JSON.parse(msg);
            logger[obj.level].apply(logger, obj.args);
        } catch (err) {
            logger.info(msg);
        }

        if (msg.cmd === 'startupComplete') {
            if (msg.error) {
                //Callback with the error
                return callback(new Error(msg.error));
            } else {
                return callback();
            }
        }
    });
}

//master will send a 'stop' message to all the workers when it's time to stop
process.on('message', function(msg) {
    var data = JSON.parse(msg);
    if (data.cmd === 'stop') {

        module.exports.stop(false, function() {
            process.send(data);
        });
    }
});

//gracefully handle ctrl+c
process.on('SIGINT', function() {
    module.exports.stop(true, function() {
        //Just in case there's anything still running, shut it down
        if (cluster.isMaster) {
            process.exit(0);
        }
    });
});

/*
 * On SIGHUP (restart) if we're in a clustered setup, we restart each worker process in sequence.
 * This will give us better uptime since there will always be a worker process available.
 * We also wait for a graceful shutdown of each worker so that existing requests are handled.
 */
process.on('SIGHUP', function() {
    var logger = serviceLoader.get('logger');

    if (isClusteredMaster()) {
        logger.info('Restarting worker processes.');
        var ids = _.map(cluster.workers, function(key, val) {
            return val;
        });

        //kill and restart each worker in series
        //This should give us 100% uptime as there will always be a worker available
        async.eachSeries(ids, function(id, next) {
            var workerNumber = workerNumberMap[cluster.workers[id].process.pid];

            sendCommand(cluster.workers[id], 'stop', function() {
                cluster.workers[id].kill(0);
                forkWorker(workerNumber, next);
            });

        }, function(err, result) {
            if (err) {
                logger.info(err);
            }

            logger.info('Restart complete');
        });
    } else if (cluster.isMaster) {
        logger.warn('Ignoring SIGHUP');
    }

});

function sendCommand(worker, command, callback) {
    var payload = {
        cmd: command,
        id: worker.id
    };

    var listener = function(msg) {
        var data = null;
        if (typeof msg === 'object') {
            data = msg;
        } else {
            data = JSON.parse(msg);
        }
        if (data.cmd === 'stop' && data.id === worker.id) {
            worker.removeListener('message', arguments.callee);
            return callback();
        }
    };

    worker.on('message', listener);
    worker.send(JSON.stringify(payload));

}

//Stop the server
//if force, don't bother restarting.  We were probably stopped by a ctrl+c
module.exports.stop = function (force, callback) {
    if (!callback) {
        callback = function() {};
    }

    if (isClusteredMaster()) {
        async.each(Object.keys(cluster.workers), function(id, next) {
            var worker = cluster.workers[id];
            sendCommand(worker, 'stop', function() {
                if (force) {
                    worker.kill();
                } else {
                    worker.process.exit(0);
                }
                next();
            });
        }, function(err) {
            callback(err);
        });
    } else {
        worker_stopServices(function() {
            callback();
        });
    }
};

function worker_stopServices(callback) {
    //TODO: we should have a generic way of stopping all services

    //stop services on workers, or a master if it's a 1-worker cluster
    if (!isClusteredMaster()) {
        //try to do a graceful shutdown, note the express shutdown is async since it waits for requests to complete
        global.services.get('express').stop(function() {

            var cache = global.services.get('cache');
            if (cache && cache.stop) { //might not exist if server didn't finish starting
                cache.stop();
            }

            var monitor = global.services.get('monitor');
            if (monitor) {
                monitor.stop();
            }
            callback();
        });
    } else {
        return callback();
    }
}

/*
 * Returns true if this is a master server that has clustered workers.
 * Otherwise return false, i.e. for worker processes or single-process masters.
 */
function isClusteredMaster() {
    return cluster.isMaster && serviceLoader.get('config').get('cluster').maxWorkers !== 1;
}

function initWorker() {

    //Use this callback to notify back to the cluster master that we're started, either successfully or with error
    var callback = function (err) {
        var message = {cmd: 'startupComplete', pid: process.pid};
        if (err) {
            console.warn(err.stack);
            message.error = err.message;
        }
        process.send(message);
    };

    initServices(function (err) {
        return callback(err);
    });
}

/**
 * @param opts
 * @param callback
 * @returns {*}
 */
function initServices(opts, callback) {

    if (!callback) {
        callback = opts;
        opts = {};
    }

    var bootstrap = opts.bootstrap || false;

    if (bootstrap) {
        project.bootstrap(function(err) {
            callback(err);
        });
    } else {
        project.initProject(function(err) {
            callback(err);
        });
    }

}

function printVersion(logger) {
    var pkg = require('./package.json');
    logger.info('Starting %s v%s in %s mode using Node.js %s', pkg.name, pkg.version,
        process.env.NODE_ENV || 'development', process.version); //the config loader defaults to development
}

function checkNodeVersion(logger) {
    var nodeCfg = serviceLoader.get('config').get('node');
    var minVersionRange = nodeCfg.version.min;
    var recommendedVersion = nodeCfg.version.recommended;
    if (!semver.satisfies(process.version, minVersionRange)) {
        logger.warn('Unsupported Node.js. Consider upgrading to at least v%s', recommendedVersion);
    }

}
/*
 * testUtility must be explicitly called in order to gain access to utility methods that are
 * helpful for testing BO Server projects.  Not intended for use in non-test environments.
 */
module.exports.testUtility = function () {
    return require('./testlib/util');
};

<commit_msg>Handle IPC messages that aren't JSON formatted<commit_after>/*
 * Copyright (c) 2015-2016 PointSource, LLC.
 * MIT Licensed
 */
var path = require('path'),
    _ = require('lodash'),
    async = require('async'),
    cluster = require('cluster'),
    semver = require('semver');

var loader = require('./lib/loader');

var serviceLoader = loader();
var project = require('./lib/project')(serviceLoader);

global.services = serviceLoader.getRegistry();

//set the app root to the directory the main module was executed from
global.__appDir = path.normalize(path.join(process.mainModule.filename, '../'));

var workerNumberMap = {}; //map a worker pid to a worker number

//Opts is optional
module.exports.init = function (opts, callback) {

    if (typeof opts === 'function') {
        callback = opts;
        opts = {};
    }

    if (opts.appDir) {
        global.__appDir = opts.appDir;
    }

    //Load the bootstrap services first (config and logging) since they're only needed for the master
    initServices({bootstrap: true}, function (err) {
        if (err) {
            if (cluster.isMaster) {
                return callback(err);
            } else {
                //TODO: Don't like having to duplicate the startupComplete message
                var message = {cmd: 'startupComplete', pid: process.pid};
                message.error = err.message;
                process.send(message);
                return; //return so that we don't attempt to initialize the worker
            }
        }

        if (cluster.isMaster) {

            var clusterConfig = serviceLoader.get('config').get('cluster');
            var logger = serviceLoader.get('logger');

            process.on('uncaughtException', function(err) {
                console.log(err.stack);
                logger.dumpBuffer(err);
                process.exit(1); //default behavior
            });

            printVersion(logger);
            checkNodeVersion(logger);

            // Either set to maxWorkers, or if < 0, use the count of machine's CPUs
            var workerCount = clusterConfig.maxWorkers < 0 ? require('os').cpus().length : clusterConfig.maxWorkers;

            //If there's only one worker defined, then it's easier to just run everything on the master
            //That avoid issues with trying to connect a debugger during development
            if (clusterConfig.maxWorkers === 1) {
                logger.info('Clustering is disabled');
                process.env.decryptionKey = serviceLoader.get('config').decryptionKey;
                return initServices(function (err) {
                    if (err) {
                        console.warn(err.stack);
                    }
                    return callback(err);
                });
            } else {

                //on exit, attempt to restart a worker process
                cluster.on('exit', handleClusterWorkerExit);

                async.timesSeries(workerCount, function(n, next) {
                    forkWorker(n, next);
                }, function(err, result) {
                    return callback(err);
                });
            }

        } else {
            initWorker();
        }

    });
};

function handleClusterWorkerExit(worker, code, signal) {
    var logger = serviceLoader.get('logger');

    if (worker.suicide === true) {
        //no need to fork.  We wanted the worker to die.
    } else {
        logger.info('Worker %d stopped (%s). Restarting', worker.process.pid, signal || code);
        var workerNumber = workerNumberMap[worker.process.pid];
        forkWorker(workerNumber, function () {
            //restarted
            logger.info('Restarted worker process');
        });
    }

}

function forkWorker(workerNumber, callback) {
    var logger = serviceLoader.get('logger');
    var worker = cluster.fork({decryptionKey: serviceLoader.get('config').decryptionKey});
    workerNumberMap[worker.process.pid] = workerNumber;
    worker.on('message', function(msg) {

        try {
            var obj = JSON.parse(msg);
            logger[obj.level].apply(logger, obj.args);
        } catch (err) {
            logger.info(msg);
        }

        if (msg.cmd === 'startupComplete') {
            if (msg.error) {

                //kill worker
                worker.kill();

                //Callback with the error
                return callback(new Error(msg.error));
            } else {
                return callback();
            }
        }
    });
}

//master will send a 'stop' message to all the workers when it's time to stop
process.on('message', function(msg) {
    var data = null;
    try {
        data = JSON.parse(msg);
    } catch (err) {
        //wasn't json data
    }

    if (data && data.cmd === 'stop') {
        module.exports.stop(false, function() {
            process.send(data);
        });
    }
});

//gracefully handle ctrl+c
process.on('SIGINT', function() {
    module.exports.stop(true, function() {
        //Just in case there's anything still running, shut it down
        if (cluster.isMaster) {
            process.exit(0);
        }
    });
});

/*
 * On SIGHUP (restart) if we're in a clustered setup, we restart each worker process in sequence.
 * This will give us better uptime since there will always be a worker process available.
 * We also wait for a graceful shutdown of each worker so that existing requests are handled.
 */
process.on('SIGHUP', function() {
    var logger = serviceLoader.get('logger');

    if (isClusteredMaster()) {
        logger.info('Restarting worker processes.');
        var ids = _.map(cluster.workers, function(key, val) {
            return val;
        });

        //kill and restart each worker in series
        //This should give us 100% uptime as there will always be a worker available
        async.eachSeries(ids, function(id, next) {
            var workerNumber = workerNumberMap[cluster.workers[id].process.pid];

            sendCommand(cluster.workers[id], 'stop', function() {
                cluster.workers[id].kill(0);
                forkWorker(workerNumber, next);
            });

        }, function(err, result) {
            if (err) {
                logger.info(err);
            }

            logger.info('Restart complete');
        });
    } else if (cluster.isMaster) {
        logger.warn('Ignoring SIGHUP');
    }

});

function sendCommand(worker, command, callback) {
    var payload = {
        cmd: command,
        id: worker.id
    };

    var listener = function(msg) {
        var data = null;
        if (typeof msg === 'object') {
            data = msg;
        } else {
            data = JSON.parse(msg);
        }
        if (data.cmd === 'stop' && data.id === worker.id) {
            worker.removeListener('message', arguments.callee);
            return callback();
        }
    };

    worker.on('message', listener);
    worker.send(JSON.stringify(payload));

}

//Stop the server
//if force, don't bother restarting.  We were probably stopped by a ctrl+c
module.exports.stop = function (force, callback) {
    if (!callback) {
        callback = function() {};
    }

    if (isClusteredMaster()) {
        async.each(Object.keys(cluster.workers), function(id, next) {
            var worker = cluster.workers[id];
            sendCommand(worker, 'stop', function() {
                if (force) {
                    worker.kill();
                } else {
                    worker.process.exit(0);
                }
                next();
            });
        }, function(err) {
            callback(err);
        });
    } else {
        worker_stopServices(function() {
            callback();
        });
    }
};

function worker_stopServices(callback) {
    //TODO: we should have a generic way of stopping all services

    //stop services on workers, or a master if it's a 1-worker cluster
    if (!isClusteredMaster()) {
        //try to do a graceful shutdown, note the express shutdown is async since it waits for requests to complete
        global.services.get('express').stop(function() {

            var cache = global.services.get('cache');
            if (cache && cache.stop) { //might not exist if server didn't finish starting
                cache.stop();
            }

            var monitor = global.services.get('monitor');
            if (monitor) {
                monitor.stop();
            }
            callback();
        });
    } else {
        return callback();
    }
}

/*
 * Returns true if this is a master server that has clustered workers.
 * Otherwise return false, i.e. for worker processes or single-process masters.
 */
function isClusteredMaster() {
    return cluster.isMaster && serviceLoader.get('config').get('cluster').maxWorkers !== 1;
}

function initWorker() {

    //Use this callback to notify back to the cluster master that we're started, either successfully or with error
    var callback = function (err) {
        var message = {cmd: 'startupComplete', pid: process.pid};
        if (err) {
            console.warn(err.stack);
            message.error = err.message;
        }
        process.send(message);
    };

    initServices(function (err) {
        return callback(err);
    });
}

/**
 * @param opts
 * @param callback
 * @returns {*}
 */
function initServices(opts, callback) {

    if (!callback) {
        callback = opts;
        opts = {};
    }

    var bootstrap = opts.bootstrap || false;

    if (bootstrap) {
        project.bootstrap(function(err) {
            callback(err);
        });
    } else {
        project.initProject(function(err) {
            callback(err);
        });
    }

}

function printVersion(logger) {
    var pkg = require('./package.json');
    logger.info('Starting %s v%s in %s mode using Node.js %s', pkg.name, pkg.version,
        process.env.NODE_ENV || 'development', process.version); //the config loader defaults to development
}

function checkNodeVersion(logger) {
    var nodeCfg = serviceLoader.get('config').get('node');
    var minVersionRange = nodeCfg.version.min;
    var recommendedVersion = nodeCfg.version.recommended;
    if (!semver.satisfies(process.version, minVersionRange)) {
        logger.warn('Unsupported Node.js. Consider upgrading to at least v%s', recommendedVersion);
    }

}
/*
 * testUtility must be explicitly called in order to gain access to utility methods that are
 * helpful for testing BO Server projects.  Not intended for use in non-test environments.
 */
module.exports.testUtility = function () {
    return require('./testlib/util');
};

<|endoftext|>


<commit_before>module.exports = LevelCommonFormProject

var asap = require('asap')
var compareEdition = require('reviewers-edition-compare')
var decode = require('bytewise/encoding/hex').decode
var encode = require('bytewise/encoding/hex').encode
var isDigest = require('is-sha-256-hex-digest')
var parseEdition = require('reviewers-edition-parse')

function LevelCommonFormProject(levelup) {
  if (!(this instanceof LevelCommonFormProject)) {
    return new LevelCommonFormProject(levelup) }
  this.levelup = levelup }

var prototype = LevelCommonFormProject.prototype

prototype.putProject = function(publisher, project, edition, data, callback) {
  var parsedEdition = parseEdition(edition)
  if (parsedEdition === false) {
    return asap(function() {
      callback(new Error('Invalid edition')) }) }

  if (!validPublisher(publisher)) {
    return asap(function() {
      callback(new Error('Invalid publisher name')) }) }

  if (!validProject(project)) {
    return asap(function() {
      callback(new Error('Invalid project name')) }) }

  if (!validForm(data)) {
    return asap(function() {
      callback(new Error('Invalid form')) }) }

  var key = projectKey(publisher, project, edition)
  var levelup = this.levelup
  this.exists(key, function(error, exists) {
    if (error) {
      callback(error) }
    else {
      if (exists) {
        callback(new Error('Already exists')) }
      else {
        levelup.put(key, data, callback) } } }) }

prototype.exists = function(key, callback) {
  this.levelup.get(key, function(error) {
    if (error) {
      if (error.notFound) {
        callback(null, false) }
      else {
        callback(error) } }
    else {
      callback(null, true) } }) }

function validForm(argument) {
  return isDigest(argument) }

function validPublisher(argument) {
  return (
    ( typeof argument === 'string' ) &&
    argument.length > 0 &&
    /^[a-z]+$/.test(argument) ) }

function validProject(argument) {
  return validPublisher(argument) }

prototype.getProject = function(publisher, project, edition, callback) {
  var key = projectKey(publisher, project, edition)
  this.levelup.get(key, function(error, data) {
    if (error) {
      if (error.notFound) {
        callback(null, false) }
      else {
        callback(error) } }
    else {
      var result = {
        publisher: publisher,
        project: project,
        edition: edition,
        form: data }
      callback(null, result) } }) }

prototype.getCurrentEdition = function(publisher, project, callback) {
  var editions = [ ]
  this.levelup.createReadStream({
    gte: projectKey(publisher, project, null),
    lte: projectKey(publisher, project, undefined) })
    .on('data', function(item) {
      var decodedKey = decode(item.key)
      editions.push({
        publisher: decodedKey[0],
        project: decodedKey[1],
        edition: decodedKey[2],
        form: item.value }) })
    .on('error', function(error) {
      callback(error) })
    .on('end', function() {
      editions = editions
        .sort(function(a, b) {
          return compareEdition(a.edition, b.edition) })
        .filter(function(element) {
          return !parseEdition(element.edition).hasOwnProperty('draft') })
      callback(null, editions[editions.length - 1]) }) }

prototype.getLatestEdition = function(publisher, project, callback) {
  var editions = [ ]
  this.levelup.createReadStream({
    gte: projectKey(publisher, project, null),
    lte: projectKey(publisher, project, undefined) })
    .on('data', function(item) {
      var decodedKey = decode(item.key)
      editions.push({
        publisher: decodedKey[0],
        project: decodedKey[1],
        edition: decodedKey[2],
        form: item.value }) })
    .on('error', function(error) {
      callback(error) })
    .on('end', function() {
      editions = editions
        .sort(function(a, b) {
          return compareEdition(a.edition, b.edition) })
      callback(null, editions[editions.length - 1]) }) }

function projectKey(publisher, project, edition) {
  return encode([ publisher, project, edition ]) }
<commit_msg>Refactor `.getCurrentEdition()` and `.getLatestEdition()`<commit_after>module.exports = LevelCommonFormProject

var asap = require('asap')
var compareEdition = require('reviewers-edition-compare')
var decode = require('bytewise/encoding/hex').decode
var encode = require('bytewise/encoding/hex').encode
var isDigest = require('is-sha-256-hex-digest')
var parseEdition = require('reviewers-edition-parse')

function LevelCommonFormProject(levelup) {
  if (!(this instanceof LevelCommonFormProject)) {
    return new LevelCommonFormProject(levelup) }
  this.levelup = levelup }

var prototype = LevelCommonFormProject.prototype

prototype.putProject = function(publisher, project, edition, data, callback) {
  var parsedEdition = parseEdition(edition)
  if (parsedEdition === false) {
    return asap(function() {
      callback(new Error('Invalid edition')) }) }

  if (!validPublisher(publisher)) {
    return asap(function() {
      callback(new Error('Invalid publisher name')) }) }

  if (!validProject(project)) {
    return asap(function() {
      callback(new Error('Invalid project name')) }) }

  if (!validForm(data)) {
    return asap(function() {
      callback(new Error('Invalid form')) }) }

  var key = projectKey(publisher, project, edition)
  var levelup = this.levelup
  this.exists(key, function(error, exists) {
    if (error) {
      callback(error) }
    else {
      if (exists) {
        callback(new Error('Already exists')) }
      else {
        levelup.put(key, data, callback) } } }) }

prototype.exists = function(key, callback) {
  this.levelup.get(key, function(error) {
    if (error) {
      if (error.notFound) {
        callback(null, false) }
      else {
        callback(error) } }
    else {
      callback(null, true) } }) }

function validForm(argument) {
  return isDigest(argument) }

function validPublisher(argument) {
  return (
    ( typeof argument === 'string' ) &&
    argument.length > 0 &&
    /^[a-z]+$/.test(argument) ) }

function validProject(argument) {
  return validPublisher(argument) }

prototype.getProject = function(publisher, project, edition, callback) {
  var key = projectKey(publisher, project, edition)
  this.levelup.get(key, function(error, data) {
    if (error) {
      if (error.notFound) {
        callback(null, false) }
      else {
        callback(error) } }
    else {
      var result = {
        publisher: publisher,
        project: project,
        edition: edition,
        form: data }
      callback(null, result) } }) }

prototype.getCurrentEdition = function(publisher, project, callback) {
  this._getSortedEditions(publisher, project, function(error, editions) {
    editions = editions.filter(function(element) {
      return !parseEdition(element.edition).hasOwnProperty('draft') })
    callback(null, editions[editions.length - 1]) }) }

prototype.getLatestEdition = function(publisher, project, callback) {
  this._getSortedEditions(publisher, project, function(error, editions) {
    callback(null, editions[editions.length - 1]) }) }

prototype._getSortedEditions = function(publisher, project, callback) {
  var editions = [ ]
  this.levelup.createReadStream({
    gte: projectKey(publisher, project, null),
    lte: projectKey(publisher, project, undefined) })
    .on('data', function(item) {
      var decodedKey = decode(item.key)
      editions.push({
        publisher: decodedKey[0],
        project: decodedKey[1],
        edition: decodedKey[2],
        form: item.value }) })
    .on('error', function(error) {
      callback(error) })
    .on('end', function() {
      editions.sort(function(a, b) {
        return compareEdition(a.edition, b.edition) })
      callback(null, editions) }) }

function projectKey(publisher, project, edition) {
  return encode([ publisher, project, edition ]) }
<|endoftext|>


<commit_before>'use strict';

var RSVP = require('rsvp'),
  fs = require('fs'),
  path = require('path');

/**
 * Walk the input tree, calling visitor#visit for every file in the path.
 *
 * `vistor.visit` can return nothing, or a promise if it's behaving asynchronously.
 *
 * @param inputTree - input tree or path
 * @param visitor - an object
 * @return {TreeTraverser}
 * @constructor
 * @alias module:index
 */
function TreeTraverser(inputTree, visitor) {
  if (!(this instanceof TreeTraverser)) return new TreeTraverser(inputTree, visitor);

  this.inputTree = inputTree;
  this.visitor = visitor;
}

/**
 *
 * Read the directory, and stat the files it contains. Returns a promise
 * that will be resolved with the result of statFiles
 *
 * @param srcDir {string} the directory to read
 * @return {RSVP.Promise}
 */
TreeTraverser.prototype.readDir = function (srcDir) {
  var self = this;
  //make a promise to read the directory.
  return new RSVP.Promise(function (resolve, reject) {
    fs.readdir(srcDir, function (err, files) {
      //Resolve with all files or err
      if (err) { reject(err); }
      else {
        resolve(self.statFiles(srcDir, files));
      }
    });
  });
};

/**
 * Stat all the files in `parentPath`, calling `readDir` for directories,
 * and deferring to the visitor for plain files.
 * The resulting promise will be resolved with an array of promises.
 *
 * @param parentPath {string} the parent directory for the files
 * @param files {array} the list of files in the directory
 * @return {RSVP.Promise}
 */
TreeTraverser.prototype.statFiles = function statFiles(parentPath, files) {
  var self = this;

  //make a promise to stat all files, which is resolved
  return RSVP.all(files.map(function (file) {
    //when each file is statted
    return new RSVP.Promise(function (resolve, reject) {
      var filePath = path.join(parentPath, file);
      //read the file
      fs.lstat(filePath, function (err, stat) {
        if (err) { reject(err)}
        else {
          if (stat.isDirectory()) {
            //and resolve it with the promise to read the directory
            resolve(self.readDir(filePath))
          } else {
            //or a visit to the filepath
            resolve(self.visitor.visit(filePath));
          }
        }
      });
    });
  }));
};

/**
 * Implementation of Brocolli's required `read` method for a tree
 *
 * Read the input tree, then read read the src dir
 *
 * @param readTree
 * @return {RSVP.Promise}
 */
TreeTraverser.prototype.read = function (readTree) {
  var self = this;

  return readTree(self.inputTree)
    .then(this.readDir.bind(this))
    .then(function () {
      return self.inputTree;
    });
};

TreeTraverser.prototype.cleanup = function () {

};

/**
 *
 * @type {TreeTraverser}
 */
module.exports = TreeTraverser;<commit_msg>cleared up documentation<commit_after>'use strict';

var RSVP = require('rsvp'),
  fs = require('fs'),
  path = require('path');

/**
 * Walk the input tree, calling visitor#visit for every file in the path.
 *
 * `vistor.visit` can return nothing, or a promise if it's behaving asynchronously.
 *
 * @param inputTree - path - relative path do the source dir
 * @param visitor - an object
 * @return {TreeTraverser}
 * @constructor
 * @alias module:index
 */
function TreeTraverser(inputTree, visitor) {
  if (!(this instanceof TreeTraverser)) return new TreeTraverser(inputTree, visitor);

  this.inputTree = inputTree;
  this.visitor = visitor;
}

/**
 *
 * Read the directory, and stat the files it contains. Returns a promise
 * that will be resolved with the result of statFiles
 *
 * @param srcDir {string} the directory to read
 * @return {RSVP.Promise}
 */
TreeTraverser.prototype.readDir = function (srcDir) {
  var self = this;
  //make a promise to read the directory.
  return new RSVP.Promise(function (resolve, reject) {
    fs.readdir(srcDir, function (err, files) {
      //Resolve with all files or err
      if (err) { reject(err); }
      else {
        resolve(self.statFiles(srcDir, files));
      }
    });
  });
};

/**
 * Stat all the files in `parentPath`, calling `readDir` for directories,
 * and deferring to the visitor for plain files.
 * The resulting promise will be resolved with an array of promises.
 *
 * @param parentPath {string} the parent directory for the files
 * @param files {array} the list of files in the directory
 * @return {RSVP.Promise}
 */
TreeTraverser.prototype.statFiles = function statFiles(parentPath, files) {
  var self = this;

  //make a promise to stat all files, which is resolved
  return RSVP.all(files.map(function (file) {
    //when each file is statted
    return new RSVP.Promise(function (resolve, reject) {
      var filePath = path.join(parentPath, file);
      //read the file
      fs.lstat(filePath, function (err, stat) {
        if (err) { reject(err)}
        else {
          if (stat.isDirectory()) {
            //and resolve it with the promise to read the directory
            resolve(self.readDir(filePath))
          } else {
            //or a visit to the filepath
            resolve(self.visitor.visit(filePath));
          }
        }
      });
    });
  }));
};

/**
 * Implementation of Brocolli's required `read` method for a tree
 *
 * Read the input tree, then read read the src dir
 *
 * @param readTree
 * @return {RSVP.Promise}
 */
TreeTraverser.prototype.read = function (readTree) {
  var self = this;

  return readTree(self.inputTree)
    .then(this.readDir.bind(this))
    .then(function () {
      return self.inputTree;
    });
};

TreeTraverser.prototype.cleanup = function () {

};

/**
 *
 * @type {TreeTraverser}
 */
module.exports = TreeTraverser;<|endoftext|>


<commit_before>'use strict';
var redisLib = require('redis');
var AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN;
var inherits = require('util').inherits;
var url = require('url');

var RDIterator = require('./iterator');
var scriptsloader = require('./scriptsloader');

/**
 * @param location prefix for the database.
 */
function RedisDown(location) {
  if (!(this instanceof RedisDown)) {
    return new RedisDown(location);
  }
	AbstractLevelDOWN.call(this, location);
}

module.exports = RedisDown;

// default number of items fetched at once during by an iterator
RedisDown.defaultHighWaterMark = 128;

// our new prototype inherits from AbstractLevelDOWN
inherits(RedisDown, AbstractLevelDOWN);

// host:port -> { db: client, locations: [] }
RedisDown.dbs = {};

/**
 * @param options: either one of
 *  - redis-client instance.
 *  - object with { redis: redis-client}
 *  - object with { port: portNumber, host: host, ... other options passed to node-redis }
 *
 * When a client is created it is reused across instances of
 * RedisDOWN unless the option `ownClient` is truthy.
 * For a client to be reused, it requires the same port, host and options.
 */
RedisDown.prototype._open = function (options, callback) {
  this.highWaterMark   = options.highWaterMark   || RedisDown.defaultHighWaterMark;
  if (typeof options.hget === 'function') {
    this.db = options.hget;
    this.quitDbOnClose = false;
  } else if (options.redis && typeof options.redis.hget === 'function') {
    this.db = options.redis;
    this.quitDbOnClose = false;
  } else if (!options.ownClient) {
    this.redisId = _makeRedisId(options);
    var dbDesc = RedisDown.dbs[this.redisId];
    if (dbDesc) {
      this.db = dbDesc.db;
      dbDesc.locations.push(this.location);
    }
  } else {
    this.quitDbOnClose = true;
  }
  if (!this.db) {
    if (options.url) {
      var redisURL = url.parse(options.url);
      this.db = redis.createClient(redisURL.port, redisURL.hostname, options);
      if (redisURL.auth) this.db.auth(redisURL.auth.split(":")[1]);
    } else if (options.port || options.host) {
      this.db = redisLib.createClient(options.port, options.host, options);
    } else {
      this.db = redisLib.createClient();
    }
    if (!options.ownClient) {
      RedisDown.dbs[this.redisId] = { db: this.db, locations: [ this.location ] };
    }
  }
  var self = this;

  if (options && options.destroyOnOpen) {
    return this.destroy(false, function() {
      setImmediate(function () { callback(null, self); });
    });
  }
  scriptsloader.preload(this.db, function() {
    setImmediate(function () { callback(null, self); });
  });
};

RedisDown.prototype._get = function (key, options, cb) {
	this.db.hget(this.location+':h', key, function(e, v) {
		if (e) { return cb(e); }
		if (!v) { return cb(new Error('NotFound error ' + key)); }
		var json;
		try {
			json = JSON.parse(v);
		} catch(e) {
			return cb(e);
		}
	  var asBuffer = true;
	  if (options.asBuffer === false || options.raw) {
	    cb(null, json);
	  } else {
			cb(null, new Buffer(json));
		}
	});
};

RedisDown.prototype._put = function (key, rawvalue, opt, cb) {
	this.__exec(this.__appendPutCmd([], key, rawvalue), cb);
};

RedisDown.prototype._del = function (key, opt, cb) {
	this.__exec(this.__appendDelCmd([], key), cb);
};
RedisDown.prototype._batch = function (array, options, callback) {
	var cmds = [];
	for (var i = 0; i < array.length; i++) {
		var op = array[i];
		if (op.type === 'put') {
      this.__appendPutCmd(cmds, op.key, op.value);
		} else if (op.type === 'del') {
      this.__appendDelCmd(cmds, op.key);
		} else {
			return callback(new Error('Unknow type of operation ' + JSON.stringify(op)));
		}
	}
  this.__exec(cmds, callback);
};

RedisDown.prototype.__appendPutCmd = function(cmds, key, value) {
	cmds.push(['hset', this.location+':h', key, JSON.stringify(value) ]);
	cmds.push(['zadd', this.location+':z', 0, key ]);
  return cmds;
};
RedisDown.prototype.__appendDelCmd = function(cmds, key) {
	cmds.push(['hdel', this.location+':h', key ]);
	cmds.push(['zrem', this.location+':z', key ]);
  return cmds;
};
RedisDown.prototype.__exec = function(cmds, callback) {
	this.db.multi(cmds).exec(callback);
};

RedisDown.prototype._close = function (callback) {
  this.closed = true;
  if (this.quitDbOnClose === false) {
    return setImmediate(callback);
  }
  if (this.quitDbOnClose !== true) {
    // close the client only if it is not used by others:
    var dbDesc = RedisDown.dbs[this.redisId];
    if (dbDesc) {
      var location = this.location;
      dbDesc.locations = dbDesc.locations.filter(function(loc) {
        return loc !== location;
      });
      if (dbDesc.locations.length !== 0) {
        // a still used by another RedisDOWN
        return setImmediate(callback);
      }
      delete RedisDown.dbs[this.redisId];
    }
  }
	try {
  	this.db.quit();
	} catch(x) {
		console.log('Error attempting to quit the redis client', x);
	}
	setImmediate(callback);
};

RedisDown.prototype._iterator = function (options) {
  return new RDIterator(this, options);
};

// Special operations
/**
 * Opens a new redis client del the hset.
 * Quit the client.
 * Callbacks
 */
RedisDown.destroy = function (location, options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  var client = redisLib.createClient(options.post, options.host, options);
  client.del(location+':h', location+':z', function(e) {
    client.quit();
    callback(e);
  });
};
/**
 * @param doClose: optional parameter, by default true to close the client
 */
RedisDown.prototype.destroy = function (doClose, callback) {
  if (!callback && typeof doClose === 'function') {
    callback = doClose;
    doClose = true;
  }
  var self = this;
  this.db.del(this.location+':h', this.location+':z', function(e) {
    if (doClose) {
      self.close(callback);
    } else {
      callback();
    }
  });
};

/**
 * Internal:
 * create an identifier for a redis client from the options passed to _open.
 * when the identifier is identical, it is safe to reuse the same client.
 */
function _makeRedisId(options) {
  var redisIdOptions = [ 'host', 'port',
    'parser', 'return_buffers', 'detect_buffers', 'socket_nodelay', 'no_ready_check',
    'enable_offline_queue', 'retry_max_delay', 'connect_timeout', 'max_attempts' ];
  var redisOptions = {};
  redisIdOptions.forEach(function(opt) {
    if (options[opt] !== undefined && options[opt] !== null) {
      redisOptions[opt] = options[opt];
    }
  });
  return JSON.stringify(redisOptions);
}

RedisDown.reset = function(callback) {
  for (var k in RedisDown.dbs) {
    if (RedisDown.dbs.hasOwnProperty(k)) {
      try {
        var db = RedisDown.dbs[k].db;
        db.quit();
      } catch(x) {
      }
    }
  }
  if (callback) {
    return callback();
  }
};
<commit_msg>Support for options.url: Trivial error and linting<commit_after>'use strict';
var redisLib = require('redis');
var AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN;
var inherits = require('util').inherits;
var url = require('url');

var RDIterator = require('./iterator');
var scriptsloader = require('./scriptsloader');

/**
 * @param location prefix for the database.
 */
function RedisDown(location) {
  if (!(this instanceof RedisDown)) {
    return new RedisDown(location);
  }
	AbstractLevelDOWN.call(this, location);
}

module.exports = RedisDown;

// default number of items fetched at once during by an iterator
RedisDown.defaultHighWaterMark = 128;

// our new prototype inherits from AbstractLevelDOWN
inherits(RedisDown, AbstractLevelDOWN);

// host:port -> { db: client, locations: [] }
RedisDown.dbs = {};

/**
 * @param options: either one of
 *  - redis-client instance.
 *  - object with { redis: redis-client}
 *  - object with { port: portNumber, host: host, ... other options passed to node-redis }
 *
 * When a client is created it is reused across instances of
 * RedisDOWN unless the option `ownClient` is truthy.
 * For a client to be reused, it requires the same port, host and options.
 */
RedisDown.prototype._open = function (options, callback) {
  this.highWaterMark   = options.highWaterMark   || RedisDown.defaultHighWaterMark;
  if (typeof options.hget === 'function') {
    this.db = options.hget;
    this.quitDbOnClose = false;
  } else if (options.redis && typeof options.redis.hget === 'function') {
    this.db = options.redis;
    this.quitDbOnClose = false;
  } else if (!options.ownClient) {
    this.redisId = _makeRedisId(options);
    var dbDesc = RedisDown.dbs[this.redisId];
    if (dbDesc) {
      this.db = dbDesc.db;
      dbDesc.locations.push(this.location);
    }
  } else {
    this.quitDbOnClose = true;
  }
  if (!this.db) {
    if (options.url) {
      var redisURL = url.parse(options.url);
      if (redisURL.auth) {
        options.auth_pass = redisURL.auth.split(':')[1];
      }
      this.db = redisLib.createClient(redisURL.port, redisURL.hostname, options);
    } else if (options.port || options.host) {
      this.db = redisLib.createClient(options.port, options.host, options);
    } else {
      this.db = redisLib.createClient();
    }
    if (!options.ownClient) {
      RedisDown.dbs[this.redisId] = { db: this.db, locations: [ this.location ] };
    }
  }
  var self = this;

  if (options && options.destroyOnOpen) {
    return this.destroy(false, function() {
      setImmediate(function () { callback(null, self); });
    });
  }
  scriptsloader.preload(this.db, function() {
    setImmediate(function () { callback(null, self); });
  });
};

RedisDown.prototype._get = function (key, options, cb) {
	this.db.hget(this.location+':h', key, function(e, v) {
		if (e) { return cb(e); }
		if (!v) { return cb(new Error('NotFound error ' + key)); }
		var json;
		try {
			json = JSON.parse(v);
		} catch(e) {
			return cb(e);
		}
	  var asBuffer = true;
	  if (options.asBuffer === false || options.raw) {
	    cb(null, json);
	  } else {
			cb(null, new Buffer(json));
		}
	});
};

RedisDown.prototype._put = function (key, rawvalue, opt, cb) {
	this.__exec(this.__appendPutCmd([], key, rawvalue), cb);
};

RedisDown.prototype._del = function (key, opt, cb) {
	this.__exec(this.__appendDelCmd([], key), cb);
};
RedisDown.prototype._batch = function (array, options, callback) {
	var cmds = [];
	for (var i = 0; i < array.length; i++) {
		var op = array[i];
		if (op.type === 'put') {
      this.__appendPutCmd(cmds, op.key, op.value);
		} else if (op.type === 'del') {
      this.__appendDelCmd(cmds, op.key);
		} else {
			return callback(new Error('Unknow type of operation ' + JSON.stringify(op)));
		}
	}
  this.__exec(cmds, callback);
};

RedisDown.prototype.__appendPutCmd = function(cmds, key, value) {
	cmds.push(['hset', this.location+':h', key, JSON.stringify(value) ]);
	cmds.push(['zadd', this.location+':z', 0, key ]);
  return cmds;
};
RedisDown.prototype.__appendDelCmd = function(cmds, key) {
	cmds.push(['hdel', this.location+':h', key ]);
	cmds.push(['zrem', this.location+':z', key ]);
  return cmds;
};
RedisDown.prototype.__exec = function(cmds, callback) {
	this.db.multi(cmds).exec(callback);
};

RedisDown.prototype._close = function (callback) {
  this.closed = true;
  if (this.quitDbOnClose === false) {
    return setImmediate(callback);
  }
  if (this.quitDbOnClose !== true) {
    // close the client only if it is not used by others:
    var dbDesc = RedisDown.dbs[this.redisId];
    if (dbDesc) {
      var location = this.location;
      dbDesc.locations = dbDesc.locations.filter(function(loc) {
        return loc !== location;
      });
      if (dbDesc.locations.length !== 0) {
        // a still used by another RedisDOWN
        return setImmediate(callback);
      }
      delete RedisDown.dbs[this.redisId];
    }
  }
	try {
  	this.db.quit();
	} catch(x) {
		console.log('Error attempting to quit the redis client', x);
	}
	setImmediate(callback);
};

RedisDown.prototype._iterator = function (options) {
  return new RDIterator(this, options);
};

// Special operations
/**
 * Opens a new redis client del the hset.
 * Quit the client.
 * Callbacks
 */
RedisDown.destroy = function (location, options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  var client = redisLib.createClient(options.post, options.host, options);
  client.del(location+':h', location+':z', function(e) {
    client.quit();
    callback(e);
  });
};
/**
 * @param doClose: optional parameter, by default true to close the client
 */
RedisDown.prototype.destroy = function (doClose, callback) {
  if (!callback && typeof doClose === 'function') {
    callback = doClose;
    doClose = true;
  }
  var self = this;
  this.db.del(this.location+':h', this.location+':z', function(e) {
    if (doClose) {
      self.close(callback);
    } else {
      callback();
    }
  });
};

/**
 * Internal:
 * create an identifier for a redis client from the options passed to _open.
 * when the identifier is identical, it is safe to reuse the same client.
 */
function _makeRedisId(options) {
  var redisIdOptions = [ 'host', 'port',
    'parser', 'return_buffers', 'detect_buffers', 'socket_nodelay', 'no_ready_check',
    'enable_offline_queue', 'retry_max_delay', 'connect_timeout', 'max_attempts' ];
  var redisOptions = {};
  redisIdOptions.forEach(function(opt) {
    if (options[opt] !== undefined && options[opt] !== null) {
      redisOptions[opt] = options[opt];
    }
  });
  return JSON.stringify(redisOptions);
}

RedisDown.reset = function(callback) {
  for (var k in RedisDown.dbs) {
    if (RedisDown.dbs.hasOwnProperty(k)) {
      try {
        var db = RedisDown.dbs[k].db;
        db.quit();
      } catch(x) {
      }
    }
  }
  if (callback) {
    return callback();
  }
};
<|endoftext|>


<commit_before>var redis = require('redis');
var scoreRange = require('./lib/redis-scripts/score-range-to-hash.js')();
var zahd = require('./lib/redis-scripts/zadd-hdel.js')();
var hshd = require('./lib/redis-scripts/hset-hdel.js')();
var hmz = require('./lib/redis-scripts/hmovez.js')();
var queryDomain = require('getaaaaarr');
var equal = require('./lib/arrset.js').equal;

module.exports = function dnsmonctor(cfg, cb) {
  // The function to process newly-retrieved records with (if any).
  var process = cfg.process;
  // The function to process record retrival failures with (if any).
  var notfoundHandler = cfg.notfound;

  // TTL in seconds to set for records
  var ttl = cfg.ttl === 0 ? 0 : cfg.ttl || 300;

  var db = redis.createClient(cfg.redis.port, cfg.redis.hostname,
    {no_ready_check: true});
  if (cfg.redis.password) db.auth(cfg.redis.password);

  // Callback wrapper for final callbacks so as to not leak retvals
  function next(err){if (err) return cb(err); else cb();}

  // Handle the record response from a query
  function finishQuerying(domain, err, records) {
    // Set time until our next query
    var expiration = Date.now() + ttl * 1000;

    // If there was an error querying the domain
    if (err) {
      // If the domain was not found
      if (err.code == 'ENOTFOUND') {
        // If we have a function to handle missing domains
        if (notfoundHandler) {
          // Call it with a callback that lets it decide how to proceed
          return notfoundHandler(domain, function(remove) {
            // Remove the domain from circulation if requested
            if (remove) return db.hdel('querying_domains', domain, next);
            // Otherwise, keep it in circulation
            else completeQuery();
          });
        // If there's no function to handle missing domains
        } else {
          // Just return the domain to the query queue
          return completeQuery();
        }
      // If it was some other kind of error
      } else {
        // Spit it up
        return cb(err);
      }
    }

    // Set TTLs on the records
    records = records.map(function(record){record.ttl = ttl; return record});

    // If we process new records
    if (process) {

      // Set the new records and get the old ones
      db.getset('records:' + domain, JSON.stringify(records),
        function(err, oldrecords) { if (err) return cb(err);

        // If the old ones aren't the same as the new ones
        if (!equal(records,JSON.parse(oldrecords))) {

          // Mark this domain as processing
          db.eval(hshd,2,'processing_domains','querying_domains',
            domain, expiration, function(err, res) {
              if (err) return cb(err);

              // Process the new records
              process(domain,records,finishProcessing);
            });
        // If the old ones were the same,
        // just advance as if we weren't processing
        } else completeQuery();
      });
    } else {
      db.set('records:' + domain, JSON.stringify(records), completeQuery);
    }

    // Mark that we've set the records (if any) and finish
    function completeQuery(err) {
      if (err) return cb(err);
      db.eval(zahd,2,'expiring_domains','querying_domains',
        expiration, domain, next);
    }

    // Mark that we've finished processing records
    function finishProcessing(err) {
      if (err) return cb(err);
      db.eval(hmz,2,'processing_domains','querying_domains', domain, next);
    }
  }

  // The interface interval function we return
  function iface(end) {
    if (end) {
      return db.quit(next);
    } else {
      // Get all the domains whose records expired some time before now
      db.eval(scoreRange,2,'expiring_domains','querying_domains',
        '-inf', Date.now(), function (err, res) {
          if (err) return cb(err);
          // Query each of these domains
          for (var i = 1; i < res.length; i += 2) {
            queryDomain(res[i], finishQuerying.bind(null, res[i]));
          }
        });
      return iface;
    }
  }
  return iface;
};
<commit_msg>Fix off-by-one error in getting domains<commit_after>var redis = require('redis');
var scoreRange = require('./lib/redis-scripts/score-range-to-hash.js')();
var zahd = require('./lib/redis-scripts/zadd-hdel.js')();
var hshd = require('./lib/redis-scripts/hset-hdel.js')();
var hmz = require('./lib/redis-scripts/hmovez.js')();
var queryDomain = require('getaaaaarr');
var equal = require('./lib/arrset.js').equal;

module.exports = function dnsmonctor(cfg, cb) {
  // The function to process newly-retrieved records with (if any).
  var process = cfg.process;
  // The function to process record retrival failures with (if any).
  var notfoundHandler = cfg.notfound;

  // TTL in seconds to set for records
  var ttl = cfg.ttl === 0 ? 0 : cfg.ttl || 300;

  var db = redis.createClient(cfg.redis.port, cfg.redis.hostname,
    {no_ready_check: true});
  if (cfg.redis.password) db.auth(cfg.redis.password);

  // Callback wrapper for final callbacks so as to not leak retvals
  function next(err){if (err) return cb(err); else cb();}

  // Handle the record response from a query
  function finishQuerying(domain, err, records) {
    // Set time until our next query
    var expiration = Date.now() + ttl * 1000;

    // If there was an error querying the domain
    if (err) {
      // If the domain was not found
      if (err.code == 'ENOTFOUND') {
        // If we have a function to handle missing domains
        if (notfoundHandler) {
          // Call it with a callback that lets it decide how to proceed
          return notfoundHandler(domain, function(remove) {
            // Remove the domain from circulation if requested
            if (remove) return db.hdel('querying_domains', domain, next);
            // Otherwise, keep it in circulation
            else completeQuery();
          });
        // If there's no function to handle missing domains
        } else {
          // Just return the domain to the query queue
          return completeQuery();
        }
      // If it was some other kind of error
      } else {
        // Spit it up
        return cb(err);
      }
    }

    // Set TTLs on the records
    records = records.map(function(record){record.ttl = ttl; return record});

    // If we process new records
    if (process) {

      // Set the new records and get the old ones
      db.getset('records:' + domain, JSON.stringify(records),
        function(err, oldrecords) { if (err) return cb(err);

        // If the old ones aren't the same as the new ones
        if (!equal(records,JSON.parse(oldrecords))) {

          // Mark this domain as processing
          db.eval(hshd,2,'processing_domains','querying_domains',
            domain, expiration, function(err, res) {
              if (err) return cb(err);

              // Process the new records
              process(domain,records,finishProcessing);
            });
        // If the old ones were the same,
        // just advance as if we weren't processing
        } else completeQuery();
      });
    } else {
      db.set('records:' + domain, JSON.stringify(records), completeQuery);
    }

    // Mark that we've set the records (if any) and finish
    function completeQuery(err) {
      if (err) return cb(err);
      db.eval(zahd,2,'expiring_domains','querying_domains',
        expiration, domain, next);
    }

    // Mark that we've finished processing records
    function finishProcessing(err) {
      if (err) return cb(err);
      db.eval(hmz,2,'processing_domains','querying_domains', domain, next);
    }
  }

  // The interface interval function we return
  function iface(end) {
    if (end) {
      return db.quit(next);
    } else {
      // Get all the domains whose records expired some time before now
      db.eval(scoreRange,2,'expiring_domains','querying_domains',
        '-inf', Date.now(), function (err, res) {
          if (err) return cb(err);
          // Query each of these domains
          for (var i = 0; i < res.length; i += 2) {
            queryDomain(res[i], finishQuerying.bind(null, res[i]));
          }
        });
      return iface;
    }
  }
  return iface;
};
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 **/
var _ = require('lodash'),
	async = require('async'),
	mongoose = require('mongoose'),
	chalk = require('chalk'),
	path = require('path');

function Seeder() {
	this.connected = false;
}

Seeder.prototype.connect = function(db, cb) {
	var _this = this;
	mongoose.connect(db, function(err) {
		// Log Error
		if (err) {
			console.error(chalk.red('Could not connect to MongoDB!'));
			console.log(err);
		} else {
			_this.connected = true;
			console.log('Successfully initialized mongoose-seed');
			cb();
		}
	});
};

Seeder.prototype.loadModels = function(modelPaths) {
	console.log(modelPaths);
	modelPaths.forEach(function(modelPath) {
		require(path.resolve(modelPath));
	});
};

Seeder.prototype.invalidModelCheck = function(models, cb) {
	var invalidModels = [];

	models.forEach(function(model) {
		if(_.indexOf(mongoose.modelNames(), model) === -1) {
			invalidModels.push(model);
		}
	});

	if (invalidModels.length) {
		cb(new Error('Models not registered in Mongoose: ' + invalidModels));
	} else {
		cb();
	}
};

Seeder.prototype.clearModels = function(models, cb) {
	if(!this.connected) {
		return new Error('Not connected to db, exiting function');
	}

	var modelNames = [];

	// Convert to array if not already
	if (Array.isArray(models)) {
		modelNames = models;
	} else if (typeof(models) === 'string') {
		modelNames.push(models);
	} else {
		console.error(chalk.red('Error: Invalid model type'));
		return;
	}

	// Confirm that all Models have been registered in Mongoose
	this.invalidModelCheck(modelNames, function(err) {
		if (err) {
			console.error(chalk.red('Error: ' + err.message));
			return;
		}

		// Clear each model
		async.each(modelNames, function(modelName, done) {
			var Model = mongoose.model(modelName);
			Model.remove({}, function(err) {
				if (err) {
					console.error(chalk.red('Error: ' + err.message));
					return;
				}
				console.log(modelName + 's collection cleared');
				done();
			});
		}, function(err) {
		// Final async callback
			if(err) { return; }
			cb();
		});
	});
};

Seeder.prototype.populateModels = function(seedData) {
	if(!this.connected) {
		return new Error('Not connected to db, exiting function');
	}

	var modelNames = _.unique(_.pluck(seedData,'model'));

	// Confirm that all Models have been registered in Mongoose
	var invalidModels = this.invalidModelCheck(modelNames, function(err) {
		if (err) {
			console.error(chalk.red('Error: ' + err.message));
			return;
		}

		// Populate each model
		seedData.forEach(function(entry) {
			var Model = mongoose.model(entry.model);
			entry.documents.forEach(function(document, j) {
				Model.create(document, function(err) {
					if (err) {
						console.error(chalk.red('Error creating document [' + j + '] of ' + entry.model + ' model'));
						console.error(chalk.red('Error: ' + err.message));
						return;
					}
					console.log('Successfully created document [' + j + '] of ' + entry.model + ' model');
				});
			});
		});

	});
};

module.exports = new Seeder();<commit_msg>Add callback to populateModels<commit_after>'use strict';

/**
 * Module dependencies.
 **/
var _ = require('lodash'),
	async = require('async'),
	mongoose = require('mongoose'),
	chalk = require('chalk'),
	path = require('path');

function Seeder() {
	this.connected = false;
}

Seeder.prototype.connect = function(db, cb) {
	var _this = this;
	mongoose.connect(db, function(err) {
		// Log Error
		if (err) {
			console.error(chalk.red('Could not connect to MongoDB!'));
			console.log(err);
		} else {
			_this.connected = true;
			console.log('Successfully initialized mongoose-seed');
			cb();
		}
	});
};

Seeder.prototype.loadModels = function(modelPaths) {
	console.log(modelPaths);
	modelPaths.forEach(function(modelPath) {
		require(path.resolve(modelPath));
	});
};

Seeder.prototype.invalidModelCheck = function(models, cb) {
	var invalidModels = [];

	models.forEach(function(model) {
		if(_.indexOf(mongoose.modelNames(), model) === -1) {
			invalidModels.push(model);
		}
	});

	if (invalidModels.length) {
		cb(new Error('Models not registered in Mongoose: ' + invalidModels));
	} else {
		cb();
	}
};

Seeder.prototype.clearModels = function(models, cb) {
	if(!this.connected) {
		return new Error('Not connected to db, exiting function');
	}

	var modelNames = [];

	// Convert to array if not already
	if (Array.isArray(models)) {
		modelNames = models;
	} else if (typeof(models) === 'string') {
		modelNames.push(models);
	} else {
		console.error(chalk.red('Error: Invalid model type'));
		return;
	}

	// Confirm that all Models have been registered in Mongoose
	this.invalidModelCheck(modelNames, function(err) {
		if (err) {
			console.error(chalk.red('Error: ' + err.message));
			return;
		}

		// Clear each model
		async.each(modelNames, function(modelName, done) {
			var Model = mongoose.model(modelName);
			Model.remove({}, function(err) {
				if (err) {
					console.error(chalk.red('Error: ' + err.message));
					return;
				}
				console.log(modelName + 's collection cleared');
				done();
			});
		}, function(err) {
		// Final async callback
			if(err) { return; }
			cb();
		});
	});
};

Seeder.prototype.populateModels = function(seedData, cb) {
	if(!this.connected) {
		return new Error('Not connected to db, exiting function');
	}

	var modelNames = _.unique(_.pluck(seedData,'model'));

	// Confirm that all Models have been registered in Mongoose
	var invalidModels = this.invalidModelCheck(modelNames, function(err) {
		if (err) {
			console.error(chalk.red('Error: ' + err.message));
			return;
		}

		// Populate each model
		seedData.forEach(function(entry) {
			var Model = mongoose.model(entry.model);
			entry.documents.forEach(function(document, j) {
				Model.create(document, function(err) {
					if (err) {
						console.error(chalk.red('Error creating document [' + j + '] of ' + entry.model + ' model'));
						console.error(chalk.red('Error: ' + err.message));
						return;
					}
					console.log('Successfully created document [' + j + '] of ' + entry.model + ' model');
				});
			});
		});
	});
	cb();
};

module.exports = new Seeder();
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var PluginBase = require('ember-cli-deploy-plugin');
var Promise = require('ember-cli/lib/ext/promise');
var readFileSync = require('fs').readFileSync;
var joinPath = require('path').join;

var API = require('./lib/api');
var uploadAsset = require('./lib/upload-asset');
var fetchCommit = require('./lib/fetch-commit');
var findFile = require('./lib/find-file');

var PAGEFRONTRC = '.pagefrontrc';
var INDEX = 'index.html';

module.exports = {
  name: 'ember-cli-deploy-pagefront',

  createDeployPlugin: function(options) {
    var Plugin = PluginBase.extend({
      name: options.name,
      requiredConfig: ['app', 'key'],
      defaultConfig: {
        key: function() {
          var rawPagefrontrc = readFileSync(findFile(PAGEFRONTRC));

          return JSON.parse(rawPagefrontrc).key
        }
      },

      configure: function(context) {
        this._super.configure.call(this, context);
        this.api = new API(this.readConfig('key'));
      },

      upload: function(context) {
        var app = this.readConfig('app');
        var manifestPath = joinPath(context.distDir, context.manifestPath);
        var manifest = readFileSync(manifestPath).toString().split("\n");
        var indexPath = joinPath(context.distDir, INDEX);
        var index = readFileSync(indexPath).toString();
        var uploadAssets = this._uploadAssets.bind(this, context.distDir);
        var didUploadAssets = this._didUploadAssets.bind(this);
        var uploadIndex = this._uploadIndex.bind(this, app, manifest, index);
        var didUploadIndex = this._didUploadIndex.bind(this);

        return this._createDifference(app, manifest)
          .then(uploadAssets)
          .then(didUploadAssets)
          .then(uploadIndex)
          .then(didUploadIndex);
      },

      _createDifference: function(app, manifest) {
        return this.api.createDifference(app, {
          manifest: manifest
        });
      },

      _uploadAssets: function(distDir, diff) {
        var uploads = diff.attributes.missing.map(function(asset) {
          return uploadAsset(distDir, asset);
        });

        return Promise.all(uploads);
      },

      _didUploadAssets: function(assets) {
        this.log('uploaded ' + assets.length + ' assets');
      },

      _uploadIndex: function(app, manifest, index) {
        var commit = fetchCommit();

        return this.api.createRelease(app, {
          index: index,
          commit_sha: commit.sha,
          commit_message: commit.message,
          manifest: manifest
        });
      },

      _didUploadIndex: function(release) {
        this.log('released v' + release.attributes.version);
      }
    });

    return new Plugin();
  }
};
<commit_msg>add fetchRevisions hook<commit_after>/* jshint node: true */
'use strict';

var PluginBase = require('ember-cli-deploy-plugin');
var Promise = require('ember-cli/lib/ext/promise');
var readFileSync = require('fs').readFileSync;
var joinPath = require('path').join;

var API = require('./lib/api');
var uploadAsset = require('./lib/upload-asset');
var fetchCommit = require('./lib/fetch-commit');
var findFile = require('./lib/find-file');

var PAGEFRONTRC = '.pagefrontrc';
var INDEX = 'index.html';

function mungeRelease(release) {
  return {
    revision: release.attributes.version,
    version: 'v' + release.attributes.version,
    timestamp: new Date(release.attributes.created_at).getTime(),
    active: false
  };
}

module.exports = {
  name: 'ember-cli-deploy-pagefront',

  createDeployPlugin: function(options) {
    var Plugin = PluginBase.extend({
      name: options.name,
      requiredConfig: ['app', 'key'],
      defaultConfig: {
        key: function() {
          var rawPagefrontrc = readFileSync(findFile(PAGEFRONTRC));

          return JSON.parse(rawPagefrontrc).key
        }
      },

      configure: function(context) {
        this._super.configure.call(this, context);
        this.api = new API(this.readConfig('key'));
      },

      fetchRevisions: function(context) {
        var app = this.readConfig('app');

        return this.api.listReleases(app).then(function(payload) {
          context.revisions = payload.map(mungeRelease);

          if (context.revisions.length) {
            context.revisions[0].active = true;
          }
        });
      },

      upload: function(context) {
        var app = this.readConfig('app');
        var manifestPath = joinPath(context.distDir, context.manifestPath);
        var manifest = readFileSync(manifestPath).toString().split("\n");
        var indexPath = joinPath(context.distDir, INDEX);
        var index = readFileSync(indexPath).toString();
        var uploadAssets = this._uploadAssets.bind(this, context.distDir);
        var didUploadAssets = this._didUploadAssets.bind(this);
        var uploadIndex = this._uploadIndex.bind(this, app, manifest, index);
        var didUploadIndex = this._didUploadIndex.bind(this);

        return this._createDifference(app, manifest)
          .then(uploadAssets)
          .then(didUploadAssets)
          .then(uploadIndex)
          .then(didUploadIndex);
      },

      _createDifference: function(app, manifest) {
        return this.api.createDifference(app, {
          manifest: manifest
        });
      },

      _uploadAssets: function(distDir, diff) {
        var uploads = diff.attributes.missing.map(function(asset) {
          return uploadAsset(distDir, asset);
        });

        return Promise.all(uploads);
      },

      _didUploadAssets: function(assets) {
        this.log('uploaded ' + assets.length + ' assets');
      },

      _uploadIndex: function(app, manifest, index) {
        var commit = fetchCommit();

        return this.api.createRelease(app, {
          index: index,
          commit_sha: commit.sha,
          commit_message: commit.message,
          manifest: manifest
        });
      },

      _didUploadIndex: function(release) {
        this.log('released v' + release.attributes.version);
      }
    });

    return new Plugin();
  }
};
<|endoftext|>


<commit_before>'use strict';

const util = require('util');

module.exports = {
    report: function report (results) {
        let lastFile = '';

        console.log('##teamcity[testSuiteStarted name=\'lesshint\']');

        results.forEach((result) => {
            const errFile = result.fullPath.replace(process.env.PWD + '/', '');

            if (lastFile !== errFile) {
                if (lastFile) {
                    console.log(util.format('##teamcity[testFinished name=\'%s\']', lastFile));
                }

                lastFile = errFile;
                console.log(util.format('##teamcity[testStarted name=\'%s\']', lastFile));
            }

            console.log(
                util.format(
                    '##teamcity[testFailed name=\'%s\' message=\'line %d, col %d, %s (%s) %s\']',
                    lastFile,
                    result.line,
                    result.column,
                    result.severity === 'error' ? 'Error' : 'Warning',
                    result.linter,
                    result.message.replace('\'', '|\'')
                )
            );
        });

        if (results.length) {
            console.log(util.format('##teamcity[testFinished name=\'%s\']', lastFile));
        } else {
            console.log('##teamcity[testStarted name=\'lesshint\']');
            console.log('##teamcity[testFinished name=\'lesshint\']');
        }

        console.log('##teamcity[testSuiteFinished name=\'lesshint\']');
    }
};
<commit_msg>process.cwd()<commit_after>'use strict';

const util = require('util');

module.exports = {
    report: function report (results) {
        let lastFile = '';

        console.log('##teamcity[testSuiteStarted name=\'lesshint\']');

        results.forEach((result) => {
            const errFile = result.fullPath.replace(process.cwd() + '/', '');

            if (lastFile !== errFile) {
                if (lastFile) {
                    console.log(util.format('##teamcity[testFinished name=\'%s\']', lastFile));
                }

                lastFile = errFile;
                console.log(util.format('##teamcity[testStarted name=\'%s\']', lastFile));
            }

            console.log(
                util.format(
                    '##teamcity[testFailed name=\'%s\' message=\'line %d, col %d, %s (%s) %s\']',
                    lastFile,
                    result.line,
                    result.column,
                    result.severity === 'error' ? 'Error' : 'Warning',
                    result.linter,
                    result.message.replace('\'', '|\'')
                )
            );
        });

        if (results.length) {
            console.log(util.format('##teamcity[testFinished name=\'%s\']', lastFile));
        } else {
            console.log('##teamcity[testStarted name=\'lesshint\']');
            console.log('##teamcity[testFinished name=\'lesshint\']');
        }

        console.log('##teamcity[testSuiteFinished name=\'lesshint\']');
    }
};
<|endoftext|>