<commit_before>/*
 * button.js
 * @author Freddy Garcia
 *
 * -- Part of the Core2D kit --
 * A representation of a button.
 */

"use strict";

// namespace
var Core2D = Core2D || {};

Core2D.BUTTON_STATE = {
	MAIN : 0,
	HOVER: 1,
	CLICK: 2
}; // Different states available to the button

Core2D.Button = (function()
{
	/*
	 * Creates a button based on the given properties
	 * TODO: pass in a label as part of the button
	 *
	 * @param	{Object} properties     the properties that will be given to the button
	 *
	 * @return  none
	 */
	var Button = function(properties)
	{
		// covering bases
		var properties       = properties           || {};
		properties.center    = properties.center    || {};
		properties.size      = properties.size      || {};
		properties.color     = properties.color     || {};
		properties.hover     = properties.hover     || {};
		properties.text      = properties.text      || {};
		properties.callbacks = properties.callbacks || {};

		// Settings -----------------------------------------------------
		this.center = {
			x : properties.center.x === undefined ? window.innerWidth / 2
			    : properties.center.x,
			y : properties.center.y === undefined ? window.innerHeight / 2
			    : properties.center.y
		};

		this.size	= {
			width  : properties.size.width  === undefined ? 30
			    : properties.size.width,
			height : properties.size.height === undefined ? 10
			    : properties.size.height,
			stroke : properties.size.stroke === undefined ? 2
			    : properties.size.stroke
		};

		this.color  = {
			fill   : properties.color.fill   === undefined ? "#4C6B88"
			    : properties.color.fill,
			stroke : properties.color.stroke === undefined ? "#4C6B88"
			    : properties.color.stroke
		};

		this.hover  = {
			fill   : properties.hover.fill   === undefined ? this.color.fill
			    : properties.hover.fill,
			stroke : properties.hover.stroke === undefined ? this.color.stroke
			    : properties.hover.stroke
		};

		this.text   = {
			string    : properties.text.string === undefined ? "Default"
			    : properties.text.string,
			color     : properties.text.color  === undefined ? "#EFECDE"
			    : properties.text.color,
			size      : properties.text.size   === undefined ? 12
			    : properties.text.size,
			font      : properties.text.font   === undefined ? "Helvetica"
			    : properties.text.font,
			alignment : properties.text.align  === undefined ? "center"
			    : properties.text.align
		};

		this.callbacks = {
			hover  : properties.callbacks.hover === undefined ? function(){console.log("default hover");}
			    : properties.callbacks.hover,
			click  : properties.callbacks.click === undefined ? function(){console.log("default click");}
			    : properties.callbacks.click,
			main   : properties.callbacks.main  === undefined ? function(){console.log("default main");}
			    : properties.callbacks.main
		};

		this.currentState = Core2D.BUTTON_STATE.MAIN;
	};

	/*
	 * Updates the button
	 *
	 * @return	none
	 */
	Button.prototype.update = function()
	{
		//if(this.clicked /*&& "function" == typeof func*/)
			//this.func();

		//this.clicked = false;*/
	};

	/*
	 * Draw the button in the given drawing context
	 *
	 * @param	ctx     the context that the button is being drawn to
	 */
	Button.prototype.render = function(ctx)
	{
		// restore point - pre rectangle
		ctx.save();
			ctx.lineWidth = this.size.stroke;

			// colors based on state
			switch(this.currentState)
			{
			case Core2D.BUTTON_STATE.MAIN:
				ctx.fillStyle   = this.color.fill;
				ctx.strokeStyle = this.color.stroke;

				break;

			case Core2D.BUTTON_STATE.HOVER:
				ctx.fillStyle   = this.color.fill;
				ctx.StrokeStyle = this.color.stroke;

				break;

			default:
				ctx.fillStyle   = this.color.fill;
				ctx.strokeStyle = this.color.stroke;

				break;
			}

			// draw
			ctx.fillRect(this.center.x - this.size.width/2, this.center.y - this.size.height/2, this.size.width, this.size.height);
			ctx.strokeRect(this.center.x - this.size.width/2, this.center.y - this.size.height/2, this.size.width, this.size.height);

		// revert changes - post rectangle
		ctx.restore();

		// restore point - pre text
		ctx.save();

			// text settings
			//ctx.font = "12px Arial";
			ctx.font      = this.text.size + "px " + this.text.font;
			ctx.fillStyle = this.text.color;
			ctx.textAlign = this.text.alignment;

			// draw text centered on the button
			// TODO: Base drawing on size of text relative to size of button!
			ctx.fillText(this.text.string, this.center.x, this.center.y + this.size.height/8);

		// revert changes - post text
		ctx.restore();
	};

	return Button;
})();<commit_msg>FoodFriends' button update - Fixed errors where certain button settings could not be set to default - added image support<commit_after>/*
 * button.js
 * @author Freddy Garcia
 *
 * -- Part of the Core2D kit --
 * A representation of a button.
 */

"use strict";

// namespace
var Core2D = Core2D || {};

Core2D.BUTTON_STATE = {
	MAIN : 0,
	HOVER: 1,
	CLICK: 2
}; // Different states available to the button

Core2D.Button = (function()
{
	/*
	 * Creates a button based on the given properties
	 * TODO: pass in a label as part of the button
	 *
	 * @param   {Object} properties     the properties that will be given to the button
	 *
	 * @return  none
	 */
	var Button = function(properties)
	{
		this.modify(properties);

		this.currentState  = Core2D.BUTTON_STATE.MAIN;
		this.previousState = Core2D.BUTTON_STATE.MAIN;
	};

	/*
	 * Changes the state of the button
	 *
	 * @param   the state to change into
	 *
	 * @return  none
	 */
	Button.prototype.changeState = function(newState)
	{
	    this.previousState = this.currentState;
		this.currentState = newState;

	    // transition action to new state
	    switch(this.currentState)
	    {
	    case Core2D.BUTTON_STATE.CLICK:
		    this.callbacks.onClick();
			break;

		case Core2D.BUTTON_STATE.HOVER:
		    this.callbacks.onHover();
			break;

		default:
		    this.callbacks.onMain();
			break;
	    };
	};

	Button.prototype.getState = function()
	{
		return this.currentState;
	};

	/*
	 * Updates the button
	 *
	 * @return	none
	 */
	Button.prototype.update = function()
	{
	};

	/*
	 * Modifies the button based on properties passed in
	 *
	 * @return  none
	 */
	Button.prototype.modify = function(properties)
	{
		// covering bases
		var properties       = properties           || {};
		properties.center    = properties.center    || {};
		properties.size      = properties.size      || {};
		properties.color     = properties.color     || {};
		properties.hover     = properties.hover     || {};
		properties.text      = properties.text      || {};
		properties.callbacks = properties.callbacks || {};

		this.center = {
		    x : properties.center.x === undefined ? window.innerWidth / 2
		        : properties.center.x,
		    y : properties.center.y === undefined ? window.innerHeight / 2
		        : properties.center.y
		};

		this.size	= {
		    width  : properties.size.width  === undefined ? 30
			    : properties.size.width,
			height : properties.size.height === undefined ? 10
			    : properties.size.height,
			stroke : properties.size.stroke === undefined ? 2
			    : properties.size.stroke
		};

		// image or color
		if(properties.image)
			this.image = properties.image; // requires image to already be loaded!

		else
		{
			this.color  = {
				fill   : properties.color.fill   === undefined ? "#4C6B88"
					: properties.color.fill,
				stroke : properties.color.stroke === undefined ? "#4C6B88"
					: properties.color.stroke
			};

			this.hover  = {
				fill   : properties.hover.fill   === undefined ? this.color.fill
					: properties.hover.fill,
				stroke : properties.hover.stroke === undefined ? this.color.stroke
					: properties.hover.stroke
			};
		}

		this.text   = {
			string    : properties.text.string === undefined ? ""
			    : properties.text.string,
			color     : properties.text.color  === undefined ? "#EFECDE"
			    : properties.text.color,
			size      : properties.text.size   === undefined ? 12
			    : properties.text.size,
			font      : properties.text.font   === undefined ? "Helvetica"
			    : properties.text.font,
			alignment : properties.text.align  === undefined ? "center"
			    : properties.text.align
		};

		this.callbacks = {
			onHover  : properties.callbacks.hover === undefined ? function(){console.log("default hover");}
			    : properties.callbacks.hover,
			onClick  : properties.callbacks.click === undefined ? function(){console.log("default click");}
			    : properties.callbacks.click,
			onMain   : properties.callbacks.main  === undefined ? function(){console.log("default main");}
			    : properties.callbacks.main
		};
	};

	/*
	 * Draw the button in the given drawing context
	 *
	 * @param	ctx     the context that the button is being drawn to
	 */
	Button.prototype.render = function(ctx)
	{
		// restore point - pre rectangle
		ctx.save();
			ctx.lineWidth = this.size.stroke;

			// colors based on state
			switch(this.currentState)
			{
			case Core2D.BUTTON_STATE.MAIN:
				if(this.image)
				{
				    // no need to set styles
				}

				else
				{
				    ctx.fillStyle   = this.color.fill;
				    ctx.strokeStyle = this.color.stroke;
				}

				break;

			case Core2D.BUTTON_STATE.HOVER:
				if(this.image)
				{
				    // no need to set styles
				}

				else
				{
				    ctx.fillStyle   = this.color.fill;
				    ctx.StrokeStyle = this.color.stroke;
				}

				break;

			default:
				if(this.image)
				{
				    // no need to set styles
				}

				else
				{
				    ctx.fillStyle   = this.color.fill;
				    ctx.strokeStyle = this.color.stroke;
				}

				break;
			}

			// image drawing
			if(this.image)
			{
			    ctx.drawImage(this.image, this.center.x - this.size.width/2,
				    this.center.y - this.size.height/2, this.size.width, this.size.height);
			}

			// standard color / text drawing
			else
			{
				// background
			    ctx.fillRect(this.center.x - this.size.width/2,
			        this.center.y - this.size.height/2, this.size.width, this.size.height);
			    ctx.strokeRect(this.center.x - this.size.width/2,
			        this.center.y - this.size.height/2, this.size.width, this.size.height);

				// text settings
			    ctx.font      = this.text.size + "px " + this.text.font;
			    ctx.fillStyle = this.text.color;
			    ctx.textAlign = this.text.alignment;

			    // draw text centered on the button
			    // TODO: Base drawing on size of text relative to size of button!
			    ctx.fillText(this.text.string, this.center.x, this.center.y + this.size.height/8);
			}

		// revert changes - post text
		ctx.restore();
	};

	return Button;
})();<|endoftext|>


<commit_before>var gulp = require('gulp');
var karma = require('karma').server;

/**
 * Run test once and exit
 */
gulp.task('test', function (done) {
    karma.start({
        configFile: __dirname + '/../../karma.conf.js',
        singleRun: true
    }, function(e) {
        done();
    });
});

/**
 * Watch for file changes and re-run tests on each change
 */
gulp.task('tdd', function (done) {
    karma.start({
        configFile: __dirname + '/../../karma.conf.js'
    }, function(e) {
        done();
    });
});

/**
 * Run test once with code coverage and exit
 */
gulp.task('cover', function (done) {
  karma.start({
    configFile: __dirname + '/../../karma.conf.js',
    singleRun: true,
    reporters: ['coverage'],
    preprocessors: {
      'test/**/*.js': ['babel'],
      'src/**/*.js': ['babel', 'coverage']
    },
    coverageReporter: {
      type: 'html',
      dir: 'build/reports/coverage'
    }
  }, function (e) {
    done();
  });
});
<commit_msg>refactor(test): Improve test command<commit_after>var gulp        = require('gulp');
var KarmaServer = require('karma').Server;
var server      = require('./server');

/**
 * Run test once and exit
 */
gulp.task('test', ['lint'], function(done) {
  server.start(function() {
    var karmaServer = new KarmaServer({
      configFile: __dirname + '/../../karma.conf.js',
      singleRun: true
    }, function() {
      server.stop(function () {
        done();

        process.exit();
      });
    });

    karmaServer.start();
  });
});

/**
 * Watch for file changes and re-run tests on each change
 */
gulp.task('tdd', function(done) {
  var karmaServer = new KarmaServer({
    configFile: __dirname + '/../../karma.conf.js'
  }, function() {
    done();
  });

  karmaServer.start();
});

/**
 * Run test once with code coverage and exit
 */
gulp.task('cover', function(done) {
  var karmaServer = new KarmaServer({
    configFile: __dirname + '/../../karma.conf.js',
    singleRun: true,
    reporters: ['coverage'],
    preprocessors: {
      'test/**/*.js': ['babel'],
      'src/**/*.js': ['babel', 'coverage']
    },
    coverageReporter: {
      type: 'html',
      dir: 'build/reports/coverage'
    }
  }, function() {
    done();
  });

  karmaServer.start();
});
<|endoftext|>


<commit_before>(function (module) {
    module.controller('ProjectHomeController', ProjectHomeController);
    ProjectHomeController.$inject = ["project", "mcmodal", "templates", "$state"];

    function ProjectHomeController(project, mcmodal, templates, $state) {
        var ctrl = this;

        ctrl.project = project;
        ctrl.chooseTemplate = chooseTemplate;
        ctrl.chooseExistingProcess = chooseExistingProcess;
        ctrl.createSample = createSample;
        ctrl.useTemplate = useTemplate;
        ctrl.templates = templates;

        /////////////////////////

        function chooseTemplate() {
            mcmodal.chooseTemplate(ctrl.project, templates).then(function (processTemplateName) {
                $state.go('projects.project.processes.create', {process: processTemplateName});
            });
        }

        function useTemplate(templateName) {
            $state.go('projects.project.processes.create', {process: templateName});
        }

        function createSample() {
            $state.go('projects.project.processes.create', {process: 'As Received'});
        }

        function chooseExistingProcess() {
            mcmodal.chooseExistingProcess(ctrl.project).then(function (existingProcess) {
                $state.go('projects.project.processes.create', {process:  existingProcess.process_name, process_id: existingProcess.id});
            });
        }
    }
}(angular.module('materialscommons')));
<commit_msg>Add process_id into the $state.go statements. Have chooseExistingProcess make a REST call to get the list of processes.<commit_after>(function (module) {
    module.controller('ProjectHomeController', ProjectHomeController);
    ProjectHomeController.$inject = ["project", "mcmodal", "templates", "$state", "Restangular"];

    function ProjectHomeController(project, mcmodal, templates, $state, Restangular) {
        var ctrl = this;

        ctrl.project = project;
        ctrl.chooseTemplate = chooseTemplate;
        ctrl.chooseExistingProcess = chooseExistingProcess;
        ctrl.createSample = createSample;
        ctrl.useTemplate = useTemplate;
        ctrl.templates = templates;

        /////////////////////////

        function chooseTemplate() {
            mcmodal.chooseTemplate(ctrl.project, templates).then(function (processTemplateName) {
                $state.go('projects.project.processes.create', {process: processTemplateName, process_id: ''});
            });
        }

        function useTemplate(templateName) {
            $state.go('projects.project.processes.create', {process: templateName, process_id: ''});
        }

        function createSample() {
            $state.go('projects.project.processes.create', {process: 'As Received', process_id: ''});
        }

        function chooseExistingProcess() {
            Restangular.one('v2').one("projects", project.id).one("processes").getList().then(function(processes) {
                mcmodal.chooseExistingProcess(processes).then(function (existingProcess) {
                    var processName = existingProcess.process_name ? existingProcess.process_name : 'TEM';
                    $state.go('projects.project.processes.create', {process: processName, process_id: existingProcess.id});
                });
            });
        }
    }
}(angular.module('materialscommons')));
<|endoftext|>


<commit_before>var socketClusterServer = require('socketcluster-server');
var EventEmitter = require('events').EventEmitter;
var crypto = require('crypto');
var uuid = require('uuid');
var http = require('http');
var https = require('https');
var fs = require('fs');
var base64id = require('base64id');
var async = require('async');
var AuthEngine = require('sc-auth').AuthEngine;

var scErrors = require('sc-errors');
var InvalidActionError = scErrors.InvalidActionError;
var ResourceLimitError = scErrors.ResourceLimitError;
var BrokerError = scErrors.BrokerError;
var HTTPServerError = scErrors.HTTPServerError;
var TimeoutError = scErrors.TimeoutError;

var processTermTimeout = 10000;
var workerInitOptions = JSON.parse(process.env.workerInitOptions);

var handleError = function (isFatal, err) {
  var error = scErrors.dehydrateError(err, true);
  process.send({
    type: 'error',
    data: {
      error: error,
      workerPid: process.pid
    }
  }, null, function () {
    if (isFatal) {
      process.exit(1);
    }
  });
};

var handleWarning = function (warning) {
  var warning = scErrors.dehydrateError(warning, true);
  process.send({
    type: 'warning',
    data: {
      error: warning,
      workerPid: process.pid
    }
  });
};

var handleReady = function () {
  process.send({type: 'ready'});
};

var handleExit = function () {
  process.exit();
};

var scWorker;

function SCWorker(options) {
  if (scWorker) {
    // SCWorker is a singleton; it can only be instantiated once per process.
    throw new InvalidActionError('Attempted to instantiate a worker which has already been instantiated');
  }
  options = options || {};
  scWorker = this;

  this.EVENT_ERROR = 'error';
  this.EVENT_WARNING = 'warning';
  this.EVENT_EXIT = 'exit';
  this.EVENT_READY = 'ready';
  this.EVENT_CONNECTION = 'connection';

  this.MIDDLEWARE_START = 'start';

  this.type = 'worker';
  this._pendingResponseHandlers = {};

  if (options.run != null) {
    this.run = options.run;
  }
  if (options.createHTTPServer != null) {
    this.createHTTPServer = options.createHTTPServer;
  }

  this._init(workerInitOptions);
}

SCWorker.create = function (options) {
  return new SCWorker(options);
};

SCWorker.prototype = Object.create(EventEmitter.prototype);

SCWorker.prototype.setAuthEngine = function (authEngine) {
  this.auth = authEngine;

  this.httpServer.auth = this.auth;
  this.scServer.setAuthEngine(this.auth);
};

SCWorker.prototype.setCodecEngine = function (codecEngine) {
  this.codec = codecEngine;
  this.scServer.setCodecEngine(this.codec);
};

SCWorker.prototype._init = function (options) {
  var self = this;

  this.options = {};

  for (var i in options) {
    if (options.hasOwnProperty(i)) {
      this.options[i] = options[i];
    }
  }

  if (this.options.processTermTimeout) {
    processTermTimeout = this.options.processTermTimeout;
  }

  if (this.options && this.options.protocolOptions && this.options.protocolOptions.pfx) {
    this.options.protocolOptions.pfx = new Buffer(this.options.protocolOptions.pfx, 'base64');
  }

  if (typeof this.options.authKey === 'object' && this.options.authKey !== null && this.options.authKey.type === 'Buffer') {
    this.options.authKey = new Buffer(this.options.authKey.data, 'base64');
  }

  if (this.options.propagateErrors) {
    this.on('error', handleError.bind(null, this.options.crashWorkerOnError));
    if (this.options.propagateWarnings) {
      this.on('warning', handleWarning);
    }
    this.on('exit', handleExit);
  }

  this.on(this.EVENT_READY, function () {
    self.start();
    handleReady();
  });

  this.id = this.options.id;
  this.isLeader = this.id == 0;

  this._middleware = {};
  this._middleware[this.MIDDLEWARE_START] = [];

  if (this.options.downgradeToUser && process.setuid) {
    try {
      process.setuid(this.options.downgradeToUser);
    } catch (err) {
      throw new InvalidActionError('Could not downgrade to user "' + this.options.downgradeToUser +
        '" - Either this user does not exist or the current process does not have the permission' +
        ' to switch to it');
    }
  }

  this.brokerEngine = require(this.options.brokerEngine);

  this._paths = options.paths;

  this._httpRequestCount = 0;
  this._wsRequestCount = 0;
  this._httpRPM = 0;
  this._wsRPM = 0;

  this.brokerEngineClient = new this.brokerEngine.Client({
    brokers: this.options.brokers,
    secretKey: this.options.secretKey,
    pubSubBatchDuration: this.options.pubSubBatchDuration,
    connectRetryErrorThreshold: this.options.brokerConnectRetryErrorThreshold
  });

  this.brokerEngineClient.on('error', function (err) {
    var error;
    if (typeof err == 'string') {
      error = new BrokerError(err);
    } else {
      error = err;
    }
    self.emitError(error);
  });
  this.brokerEngineClient.on('warning', function (warning) {
    self.emitWarning(warning);
  });
  this.exchange = this.global = this.brokerEngineClient.exchange();

  this.httpServer = this.createHTTPServer();

  this.httpServer.on('request', this._httpRequestHandler.bind(this));
  this.httpServer.on('upgrade', this._httpRequestHandler.bind(this));

  this.httpServer.exchange = this.httpServer.global = this.exchange;

  this.httpServer.on('error', function (err) {
    var error;
    if (typeof err == 'string') {
      error = new HTTPServerError(err);
    } else {
      error = err;
    }
    self.emitError(error);
  });

  var secure = this.options.protocol == 'https' ? 1 : 0;

  this.scServer = socketClusterServer.attach(this.httpServer, {
    brokerEngine: this.brokerEngineClient,
    wsEngine: this._paths.wsEnginePath,
    allowClientPublish: this.options.allowClientPublish,
    handshakeTimeout: this.options.handshakeTimeout,
    ackTimeout: this.options.ackTimeout,
    pingTimeout: this.options.pingTimeout,
    pingInterval: this.options.pingInterval,
    origins: this.options.origins,
    appName: this.options.appName,
    path: this.options.path,
    authKey: this.options.authKey,
    authPrivateKey: this.options.authPrivateKey,
    authPublicKey: this.options.authPublicKey,
    authAlgorithm: this.options.authAlgorithm,
    authSignAsync: this.options.authSignAsync,
    authVerifyAsync: this.options.authVerifyAsync,
    authDefaultExpiry: this.options.authDefaultExpiry,
    middlewareEmitWarnings: this.options.middlewareEmitWarnings,
    socketChannelLimit: this.options.socketChannelLimit,
    pubSubBatchDuration: this.options.pubSubBatchDuration,
    perMessageDeflate: this.options.perMessageDeflate,
    maxPayload: this.options.maxPayload,
    wsEngineServerOptions: this.options.wsEngineServerOptions
  });

  if (this.brokerEngineClient.setSCServer) {
    this.brokerEngineClient.setSCServer(this.scServer);
  }

  // Default authentication engine
  this.setAuthEngine(new AuthEngine());
  this.codec = this.scServer.codec;

  this._socketPath = this.scServer.getPath();
  this._socketPathRegex = new RegExp('^' + this._socketPath);

  this.scServer.on('_connection', function (socket) {
    // The connection event counts as a WS request
    self._wsRequestCount++;
    socket.on('message', function () {
      self._wsRequestCount++;
    });
    self.emit(self.EVENT_CONNECTION, socket);
  });

  this.scServer.on('warning', function (warning) {
    self.emitWarning(warning);
  });
  this.scServer.on('error', function (error) {
    self.emitError(error);
  });
  this.scServer.once('ready', function () {
    self.emit(self.EVENT_READY);
  });
};

SCWorker.prototype.createHTTPServer = function () {
  var httpServer;
  if (this.options.protocol == 'https') {
    httpServer = https.createServer(this.options.protocolOptions);
  } else {
    httpServer = http.createServer();
  }
  return httpServer;
};

// To be overriden.
SCWorker.prototype.run = function () {};

SCWorker.prototype.open = function () {
  this.startHTTPServer();
};

SCWorker.prototype.close = function (callback) {
  this.scServer.close();
  this.httpServer.close(callback);
};

// getSocketURL is deprecated
SCWorker.prototype.getSocketPath = SCWorker.prototype.getSocketURL = function () {
  return this._socketPath;
};

SCWorker.prototype.addMiddleware = function (type, middleware) {
  this._middleware[type].push(middleware);
};

SCWorker.prototype.removeMiddleware = function (type, middleware) {
  var middlewareFunctions = this._middleware[type];

  this._middleware[type] = middlewareFunctions.filter(function (fn) {
    return fn != middleware;
  });
};

SCWorker.prototype.startHTTPServer = function () {
  var self = this;

  var options = this.options;

  var start = function () {
    if (options.tcpSynBacklog != null) {
      self.httpServer.listen(options.sourcePort, options.host, options.tcpSynBacklog);
    } else if (options.host != null) {
      self.httpServer.listen(options.sourcePort, options.host);
    } else {
      self.httpServer.listen(options.sourcePort);
    }
  };

  var startMiddleware = this._middleware[this.MIDDLEWARE_START];
  if (startMiddleware.length) {
    var callbackInvoked = false;

    async.applyEachSeries(startMiddleware, options, function (err) {
      if (callbackInvoked) {
        self.emit('warning', new InvalidActionError('Callback for ' + self.MIDDLEWARE_START + ' middleware was already invoked'));
      } else {
        callbackInvoked = true;
        if (err) {
          throw err;
        } else {
          start();
        }
      }
    });
  } else {
    start();
  }
};

SCWorker.prototype.start = function () {
  var self = this;

  this._httpRequestCount = 0;
  this._wsRequestCount = 0;
  this._httpRPM = 0;
  this._wsRPM = 0;

  if (this._statusInterval != null) {
    clearInterval(this._statusInterval);
  }
  this._statusInterval = setInterval(this._calculateStatus.bind(this), this.options.workerStatusInterval);

  this.run();
  this.startHTTPServer();
};

SCWorker.prototype._httpRequestHandler = function (req, res) {
  var self = this;

  this._httpRequestCount++;

  req.exchange = req.global = this.exchange;

  var forwardedFor = req.headers['x-forwarded-for'];

  if (forwardedFor) {
    var forwardedClientIP;
    if (forwardedFor.indexOf(',') > -1) {
      forwardedClientIP = forwardedFor.split(',')[0];
    } else {
      forwardedClientIP = forwardedFor;
    }
    req.forwardedForAddress = forwardedClientIP;
  }
  if (req.connection) {
    req.remoteAddress = req.connection.remoteAddress;
    req.remoteFamily = req.connection.remoteFamily;
    req.remotePort = req.connection.remotePort;
  } else if (req.socket) {
    req.remoteAddress = req.socket.remoteAddress;
    req.remoteFamily = req.socket.remoteFamily;
    req.remotePort = req.socket.remotePort;
  }
};

SCWorker.prototype.getSCServer = function () {
  return this.scServer;
};

SCWorker.prototype.getHTTPServer = function () {
  return this.httpServer;
};

SCWorker.prototype._calculateStatus = function () {
  var perMinuteFactor = 60000 / this.options.workerStatusInterval;
  this._httpRPM = this._httpRequestCount * perMinuteFactor;
  this._wsRPM = this._wsRequestCount * perMinuteFactor;
  this._httpRequestCount = 0;
  this._wsRequestCount = 0;

  var memThreshold = this.options.killWorkerMemoryThreshold;

  if (memThreshold != null) {
    var memoryUsage = process.memoryUsage();
    if (memoryUsage.heapUsed > memThreshold) {
      var message = 'Worker killed itself because its memory ';
      message += 'usage of ' + memoryUsage.heapUsed + ' exceeded ';
      message += 'the killWorkerMemoryThreshold of ' + memThreshold;
      var warning = new ResourceLimitError(message);
      this.emitWarning(warning);
      process.exit();
    }
  }
};

SCWorker.prototype.getStatus = function () {
  return {
    clientCount: this.scServer.clientsCount,
    httpRPM: this._httpRPM,
    wsRPM: this._wsRPM
  };
};

SCWorker.prototype._createIPCResponseHandler = function (callback) {
  var self = this;
  var cid = uuid.v4();

  var responseTimeout = setTimeout(function () {
    var responseHandler = self._pendingResponseHandlers[cid];
    delete self._pendingResponseHandlers[cid];
    var timeoutError = new TimeoutError('IPC response timed out');
    responseHandler.callback(timeoutError);
  }, this.options.ipcAckTimeout);

  this._pendingResponseHandlers[cid] = {
    callback: callback,
    timeout: responseTimeout
  };

  return cid;
};

SCWorker.prototype.handleMasterResponse = function (message) {
  var responseHandler = this._pendingResponseHandlers[message.rid];
  if (responseHandler) {
    clearTimeout(responseHandler.timeout);
    delete this._pendingResponseHandlers[message.rid];
    var properError = scErrors.hydrateError(message.error, true);
    responseHandler.callback(properError, message.data);
  }
};

SCWorker.prototype.sendToMaster = function (data, callback) {
  var messagePacket = {
    type: 'workerMessage',
    data: data,
    workerId: this.id
  };

  if (callback) {
    messagePacket.cid = this._createIPCResponseHandler(callback);
  }
  process.send(messagePacket);
};

SCWorker.prototype.respondToMaster = function (err, data, rid) {
  process.send({
    type: 'workerResponse',
    error: scErrors.dehydrateError(err, true),
    data: data,
    workerId: this.id,
    rid: rid
  });
};

SCWorker.prototype.handleMasterEvent = function () {
  this.emit.apply(this, arguments);
};

SCWorker.prototype.handleMasterMessage = function (message) {
  var self = this

  self.emit('masterMessage', message.data, function (err, data) {
    if (message.cid) {
      self.respondToMaster(err, data, message.cid);
    }
  });
};

SCWorker.prototype.emitError = function (err) {
  this.emit(this.EVENT_ERROR, err);
};

SCWorker.prototype.emitWarning = function (warning) {
  this.emit(this.EVENT_WARNING, warning);
};

var handleWorkerClusterMessage = function (wcMessage) {
  if (wcMessage.type == 'terminate') {
    if (scWorker && !wcMessage.data.immediate) {
      scWorker.close(function () {
        process.exit();
      });
      setTimeout(function () {
        process.exit();
      }, processTermTimeout);
    } else {
      process.exit();
    }
  } else {
    if (!scWorker) {
      throw new InvalidActionError(`Attempted to send '${wcMessage.type}' to worker ${workerInitOptions.id} before it was instantiated`);
    }
    if (wcMessage.type == 'emit') {
      if (wcMessage.data) {
        scWorker.handleMasterEvent(wcMessage.event, wcMessage.data);
      } else {
        scWorker.handleMasterEvent(wcMessage.event);
      }
    } else if (wcMessage.type == 'masterMessage') {
      scWorker.handleMasterMessage(wcMessage);
    } else if (wcMessage.type == 'masterResponse') {
      scWorker.handleMasterResponse(wcMessage);
    }
  }
};

process.on('message', handleWorkerClusterMessage);

process.on('uncaughtException', function (err) {
  handleError(workerInitOptions.crashWorkerOnError, err);
});

module.exports = SCWorker;
<commit_msg>Drop support for global property - Always use exchange property instead<commit_after>var socketClusterServer = require('socketcluster-server');
var EventEmitter = require('events').EventEmitter;
var crypto = require('crypto');
var uuid = require('uuid');
var http = require('http');
var https = require('https');
var fs = require('fs');
var base64id = require('base64id');
var async = require('async');
var AuthEngine = require('sc-auth').AuthEngine;

var scErrors = require('sc-errors');
var InvalidActionError = scErrors.InvalidActionError;
var ResourceLimitError = scErrors.ResourceLimitError;
var BrokerError = scErrors.BrokerError;
var HTTPServerError = scErrors.HTTPServerError;
var TimeoutError = scErrors.TimeoutError;

var processTermTimeout = 10000;
var workerInitOptions = JSON.parse(process.env.workerInitOptions);

var handleError = function (isFatal, err) {
  var error = scErrors.dehydrateError(err, true);
  process.send({
    type: 'error',
    data: {
      error: error,
      workerPid: process.pid
    }
  }, null, function () {
    if (isFatal) {
      process.exit(1);
    }
  });
};

var handleWarning = function (warning) {
  var warning = scErrors.dehydrateError(warning, true);
  process.send({
    type: 'warning',
    data: {
      error: warning,
      workerPid: process.pid
    }
  });
};

var handleReady = function () {
  process.send({type: 'ready'});
};

var handleExit = function () {
  process.exit();
};

var scWorker;

function SCWorker(options) {
  if (scWorker) {
    // SCWorker is a singleton; it can only be instantiated once per process.
    throw new InvalidActionError('Attempted to instantiate a worker which has already been instantiated');
  }
  options = options || {};
  scWorker = this;

  this.EVENT_ERROR = 'error';
  this.EVENT_WARNING = 'warning';
  this.EVENT_EXIT = 'exit';
  this.EVENT_READY = 'ready';
  this.EVENT_CONNECTION = 'connection';

  this.MIDDLEWARE_START = 'start';

  this.type = 'worker';
  this._pendingResponseHandlers = {};

  if (options.run != null) {
    this.run = options.run;
  }
  if (options.createHTTPServer != null) {
    this.createHTTPServer = options.createHTTPServer;
  }

  this._init(workerInitOptions);
}

SCWorker.create = function (options) {
  return new SCWorker(options);
};

SCWorker.prototype = Object.create(EventEmitter.prototype);

SCWorker.prototype.setAuthEngine = function (authEngine) {
  this.auth = authEngine;

  this.httpServer.auth = this.auth;
  this.scServer.setAuthEngine(this.auth);
};

SCWorker.prototype.setCodecEngine = function (codecEngine) {
  this.codec = codecEngine;
  this.scServer.setCodecEngine(this.codec);
};

SCWorker.prototype._init = function (options) {
  var self = this;

  this.options = {};

  for (var i in options) {
    if (options.hasOwnProperty(i)) {
      this.options[i] = options[i];
    }
  }

  if (this.options.processTermTimeout) {
    processTermTimeout = this.options.processTermTimeout;
  }

  if (this.options && this.options.protocolOptions && this.options.protocolOptions.pfx) {
    this.options.protocolOptions.pfx = new Buffer(this.options.protocolOptions.pfx, 'base64');
  }

  if (typeof this.options.authKey === 'object' && this.options.authKey !== null && this.options.authKey.type === 'Buffer') {
    this.options.authKey = new Buffer(this.options.authKey.data, 'base64');
  }

  if (this.options.propagateErrors) {
    this.on('error', handleError.bind(null, this.options.crashWorkerOnError));
    if (this.options.propagateWarnings) {
      this.on('warning', handleWarning);
    }
    this.on('exit', handleExit);
  }

  this.on(this.EVENT_READY, function () {
    self.start();
    handleReady();
  });

  this.id = this.options.id;
  this.isLeader = this.id == 0;

  this._middleware = {};
  this._middleware[this.MIDDLEWARE_START] = [];

  if (this.options.downgradeToUser && process.setuid) {
    try {
      process.setuid(this.options.downgradeToUser);
    } catch (err) {
      throw new InvalidActionError('Could not downgrade to user "' + this.options.downgradeToUser +
        '" - Either this user does not exist or the current process does not have the permission' +
        ' to switch to it');
    }
  }

  this.brokerEngine = require(this.options.brokerEngine);

  this._paths = options.paths;

  this._httpRequestCount = 0;
  this._wsRequestCount = 0;
  this._httpRPM = 0;
  this._wsRPM = 0;

  this.brokerEngineClient = new this.brokerEngine.Client({
    brokers: this.options.brokers,
    secretKey: this.options.secretKey,
    pubSubBatchDuration: this.options.pubSubBatchDuration,
    connectRetryErrorThreshold: this.options.brokerConnectRetryErrorThreshold
  });

  this.brokerEngineClient.on('error', function (err) {
    var error;
    if (typeof err == 'string') {
      error = new BrokerError(err);
    } else {
      error = err;
    }
    self.emitError(error);
  });
  this.brokerEngineClient.on('warning', function (warning) {
    self.emitWarning(warning);
  });
  this.exchange = this.brokerEngineClient.exchange();

  this.httpServer = this.createHTTPServer();

  this.httpServer.on('request', this._httpRequestHandler.bind(this));
  this.httpServer.on('upgrade', this._httpRequestHandler.bind(this));

  this.httpServer.exchange = this.exchange;

  this.httpServer.on('error', function (err) {
    var error;
    if (typeof err == 'string') {
      error = new HTTPServerError(err);
    } else {
      error = err;
    }
    self.emitError(error);
  });

  var secure = this.options.protocol == 'https' ? 1 : 0;

  this.scServer = socketClusterServer.attach(this.httpServer, {
    brokerEngine: this.brokerEngineClient,
    wsEngine: this._paths.wsEnginePath,
    allowClientPublish: this.options.allowClientPublish,
    handshakeTimeout: this.options.handshakeTimeout,
    ackTimeout: this.options.ackTimeout,
    pingTimeout: this.options.pingTimeout,
    pingInterval: this.options.pingInterval,
    origins: this.options.origins,
    appName: this.options.appName,
    path: this.options.path,
    authKey: this.options.authKey,
    authPrivateKey: this.options.authPrivateKey,
    authPublicKey: this.options.authPublicKey,
    authAlgorithm: this.options.authAlgorithm,
    authSignAsync: this.options.authSignAsync,
    authVerifyAsync: this.options.authVerifyAsync,
    authDefaultExpiry: this.options.authDefaultExpiry,
    middlewareEmitWarnings: this.options.middlewareEmitWarnings,
    socketChannelLimit: this.options.socketChannelLimit,
    pubSubBatchDuration: this.options.pubSubBatchDuration,
    perMessageDeflate: this.options.perMessageDeflate,
    maxPayload: this.options.maxPayload,
    wsEngineServerOptions: this.options.wsEngineServerOptions
  });

  if (this.brokerEngineClient.setSCServer) {
    this.brokerEngineClient.setSCServer(this.scServer);
  }

  // Default authentication engine
  this.setAuthEngine(new AuthEngine());
  this.codec = this.scServer.codec;

  this._socketPath = this.scServer.getPath();
  this._socketPathRegex = new RegExp('^' + this._socketPath);

  this.scServer.on('_connection', function (socket) {
    // The connection event counts as a WS request
    self._wsRequestCount++;
    socket.on('message', function () {
      self._wsRequestCount++;
    });
    self.emit(self.EVENT_CONNECTION, socket);
  });

  this.scServer.on('warning', function (warning) {
    self.emitWarning(warning);
  });
  this.scServer.on('error', function (error) {
    self.emitError(error);
  });
  this.scServer.once('ready', function () {
    self.emit(self.EVENT_READY);
  });
};

SCWorker.prototype.createHTTPServer = function () {
  var httpServer;
  if (this.options.protocol == 'https') {
    httpServer = https.createServer(this.options.protocolOptions);
  } else {
    httpServer = http.createServer();
  }
  return httpServer;
};

// To be overriden.
SCWorker.prototype.run = function () {};

SCWorker.prototype.open = function () {
  this.startHTTPServer();
};

SCWorker.prototype.close = function (callback) {
  this.scServer.close();
  this.httpServer.close(callback);
};

// getSocketURL is deprecated
SCWorker.prototype.getSocketPath = SCWorker.prototype.getSocketURL = function () {
  return this._socketPath;
};

SCWorker.prototype.addMiddleware = function (type, middleware) {
  this._middleware[type].push(middleware);
};

SCWorker.prototype.removeMiddleware = function (type, middleware) {
  var middlewareFunctions = this._middleware[type];

  this._middleware[type] = middlewareFunctions.filter(function (fn) {
    return fn != middleware;
  });
};

SCWorker.prototype.startHTTPServer = function () {
  var self = this;

  var options = this.options;

  var start = function () {
    if (options.tcpSynBacklog != null) {
      self.httpServer.listen(options.sourcePort, options.host, options.tcpSynBacklog);
    } else if (options.host != null) {
      self.httpServer.listen(options.sourcePort, options.host);
    } else {
      self.httpServer.listen(options.sourcePort);
    }
  };

  var startMiddleware = this._middleware[this.MIDDLEWARE_START];
  if (startMiddleware.length) {
    var callbackInvoked = false;

    async.applyEachSeries(startMiddleware, options, function (err) {
      if (callbackInvoked) {
        self.emit('warning', new InvalidActionError('Callback for ' + self.MIDDLEWARE_START + ' middleware was already invoked'));
      } else {
        callbackInvoked = true;
        if (err) {
          throw err;
        } else {
          start();
        }
      }
    });
  } else {
    start();
  }
};

SCWorker.prototype.start = function () {
  var self = this;

  this._httpRequestCount = 0;
  this._wsRequestCount = 0;
  this._httpRPM = 0;
  this._wsRPM = 0;

  if (this._statusInterval != null) {
    clearInterval(this._statusInterval);
  }
  this._statusInterval = setInterval(this._calculateStatus.bind(this), this.options.workerStatusInterval);

  this.run();
  this.startHTTPServer();
};

SCWorker.prototype._httpRequestHandler = function (req, res) {
  var self = this;

  this._httpRequestCount++;

  req.exchange = this.exchange;

  var forwardedFor = req.headers['x-forwarded-for'];

  if (forwardedFor) {
    var forwardedClientIP;
    if (forwardedFor.indexOf(',') > -1) {
      forwardedClientIP = forwardedFor.split(',')[0];
    } else {
      forwardedClientIP = forwardedFor;
    }
    req.forwardedForAddress = forwardedClientIP;
  }
  if (req.connection) {
    req.remoteAddress = req.connection.remoteAddress;
    req.remoteFamily = req.connection.remoteFamily;
    req.remotePort = req.connection.remotePort;
  } else if (req.socket) {
    req.remoteAddress = req.socket.remoteAddress;
    req.remoteFamily = req.socket.remoteFamily;
    req.remotePort = req.socket.remotePort;
  }
};

SCWorker.prototype.getSCServer = function () {
  return this.scServer;
};

SCWorker.prototype.getHTTPServer = function () {
  return this.httpServer;
};

SCWorker.prototype._calculateStatus = function () {
  var perMinuteFactor = 60000 / this.options.workerStatusInterval;
  this._httpRPM = this._httpRequestCount * perMinuteFactor;
  this._wsRPM = this._wsRequestCount * perMinuteFactor;
  this._httpRequestCount = 0;
  this._wsRequestCount = 0;

  var memThreshold = this.options.killWorkerMemoryThreshold;

  if (memThreshold != null) {
    var memoryUsage = process.memoryUsage();
    if (memoryUsage.heapUsed > memThreshold) {
      var message = 'Worker killed itself because its memory ';
      message += 'usage of ' + memoryUsage.heapUsed + ' exceeded ';
      message += 'the killWorkerMemoryThreshold of ' + memThreshold;
      var warning = new ResourceLimitError(message);
      this.emitWarning(warning);
      process.exit();
    }
  }
};

SCWorker.prototype.getStatus = function () {
  return {
    clientCount: this.scServer.clientsCount,
    httpRPM: this._httpRPM,
    wsRPM: this._wsRPM
  };
};

SCWorker.prototype._createIPCResponseHandler = function (callback) {
  var self = this;
  var cid = uuid.v4();

  var responseTimeout = setTimeout(function () {
    var responseHandler = self._pendingResponseHandlers[cid];
    delete self._pendingResponseHandlers[cid];
    var timeoutError = new TimeoutError('IPC response timed out');
    responseHandler.callback(timeoutError);
  }, this.options.ipcAckTimeout);

  this._pendingResponseHandlers[cid] = {
    callback: callback,
    timeout: responseTimeout
  };

  return cid;
};

SCWorker.prototype.handleMasterResponse = function (message) {
  var responseHandler = this._pendingResponseHandlers[message.rid];
  if (responseHandler) {
    clearTimeout(responseHandler.timeout);
    delete this._pendingResponseHandlers[message.rid];
    var properError = scErrors.hydrateError(message.error, true);
    responseHandler.callback(properError, message.data);
  }
};

SCWorker.prototype.sendToMaster = function (data, callback) {
  var messagePacket = {
    type: 'workerMessage',
    data: data,
    workerId: this.id
  };

  if (callback) {
    messagePacket.cid = this._createIPCResponseHandler(callback);
  }
  process.send(messagePacket);
};

SCWorker.prototype.respondToMaster = function (err, data, rid) {
  process.send({
    type: 'workerResponse',
    error: scErrors.dehydrateError(err, true),
    data: data,
    workerId: this.id,
    rid: rid
  });
};

SCWorker.prototype.handleMasterEvent = function () {
  this.emit.apply(this, arguments);
};

SCWorker.prototype.handleMasterMessage = function (message) {
  var self = this

  self.emit('masterMessage', message.data, function (err, data) {
    if (message.cid) {
      self.respondToMaster(err, data, message.cid);
    }
  });
};

SCWorker.prototype.emitError = function (err) {
  this.emit(this.EVENT_ERROR, err);
};

SCWorker.prototype.emitWarning = function (warning) {
  this.emit(this.EVENT_WARNING, warning);
};

var handleWorkerClusterMessage = function (wcMessage) {
  if (wcMessage.type == 'terminate') {
    if (scWorker && !wcMessage.data.immediate) {
      scWorker.close(function () {
        process.exit();
      });
      setTimeout(function () {
        process.exit();
      }, processTermTimeout);
    } else {
      process.exit();
    }
  } else {
    if (!scWorker) {
      throw new InvalidActionError(`Attempted to send '${wcMessage.type}' to worker ${workerInitOptions.id} before it was instantiated`);
    }
    if (wcMessage.type == 'emit') {
      if (wcMessage.data) {
        scWorker.handleMasterEvent(wcMessage.event, wcMessage.data);
      } else {
        scWorker.handleMasterEvent(wcMessage.event);
      }
    } else if (wcMessage.type == 'masterMessage') {
      scWorker.handleMasterMessage(wcMessage);
    } else if (wcMessage.type == 'masterResponse') {
      scWorker.handleMasterResponse(wcMessage);
    }
  }
};

process.on('message', handleWorkerClusterMessage);

process.on('uncaughtException', function (err) {
  handleError(workerInitOptions.crashWorkerOnError, err);
});

module.exports = SCWorker;
<|endoftext|>


<commit_before>'use strict'

const fs = require('fs')
const glob = require('glob-all')
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin')
const loadMinified = require('./load-minified')

const env = config.build.env

const webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  devtool: config.build.productionSourceMap ? '#source-map' : false,
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    }),
    // extract css into its own file
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    new PurgeCSSPlugin({
      paths: glob.sync([
        path.join(__dirname, '../src/**/*.vue'),
        path.join(__dirname, '../src/**/*.vue'),
        path.join(__dirname, '../*.html')
      ]),
      styleExtensions: ['.css'],
      whitelistPatterns: [/^fade.*/],
      extractors: [
        {
          extractor: class {static extract (content) { return content.match(/[A-z0-9-:\/]+/g) }},
          extensions: ['html', 'vue']
        }
      ]
    }),

    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    new OptimizeCSSPlugin({
      cssProcessorOptions: {
        safe: true
      }
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency',
      serviceWorkerLoader: `<script>${loadMinified(path.join(__dirname, './service-worker-prod.js'))}</script>`
    }),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource && /\.js$/.test(module.resource) &&
          module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ]),
    // copy public content
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../public'),
        to: config.build.assetsRoot,
        ignore: ['.*']
      }
    ]),
    // service worker caching
    new SWPrecacheWebpackPlugin({
      cacheId: 'albionstatus',
      filename: 'service-worker.js',
      staticFileGlobs: ['dist/**/*.{js,html,css,eot,woff,woff2,ttf,svg}'],
      minify: true,
      stripPrefix: 'dist/',
      runtimeCaching: [
        {
          urlPattern: /^https:\/\/api\.albionstatus\.com\//,
          handler: 'cacheFirst'
        }
      ]
    })
  ]
})

if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig
<commit_msg>Change strategy for api call caching<commit_after>'use strict'

const fs = require('fs')
const glob = require('glob-all')
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin')
const loadMinified = require('./load-minified')

const env = config.build.env

const webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  devtool: config.build.productionSourceMap ? '#source-map' : false,
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    }),
    // extract css into its own file
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    new PurgeCSSPlugin({
      paths: glob.sync([
        path.join(__dirname, '../src/**/*.vue'),
        path.join(__dirname, '../src/**/*.vue'),
        path.join(__dirname, '../*.html')
      ]),
      styleExtensions: ['.css'],
      whitelistPatterns: [/^fade.*/],
      extractors: [
        {
          extractor: class {static extract (content) { return content.match(/[A-z0-9-:\/]+/g) }},
          extensions: ['html', 'vue']
        }
      ]
    }),

    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    new OptimizeCSSPlugin({
      cssProcessorOptions: {
        safe: true
      }
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency',
      serviceWorkerLoader: `<script>${loadMinified(path.join(__dirname, './service-worker-prod.js'))}</script>`
    }),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource && /\.js$/.test(module.resource) &&
          module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ]),
    // copy public content
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../public'),
        to: config.build.assetsRoot,
        ignore: ['.*']
      }
    ]),
    // service worker caching
    new SWPrecacheWebpackPlugin({
      cacheId: 'albionstatus',
      filename: 'service-worker.js',
      staticFileGlobs: ['dist/**/*.{js,html,css,eot,woff,woff2,ttf,svg}'],
      minify: true,
      stripPrefix: 'dist/',
      runtimeCaching: [
        {
          urlPattern: /^https:\/\/api\.albionstatus\.com\//,
          handler: 'networkFirst'
        }
      ]
    })
  ]
})

if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig
<|endoftext|>


<commit_before>var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');

const ENV = process.env.NODE_ENV = process.env.ENV = 'production';

module.exports = webpackMerge(commonConfig, {
  devtool: 'source-map',

  output: {
    path: helpers.root('dist'),
    publicPath: '/',
    filename: '[name].[hash].js',
    chunkFilename: '[id].[hash].chunk.js'
  },

  htmlLoader: {
    minimize: false // workaround for ng2
  },

  plugins: [
    new webpack.NoErrorsPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618
      mangle: {
        keep_fnames: true
      }
    }),
    new ExtractTextPlugin('[name].[hash].css'),
    new webpack.DefinePlugin({
      'process.env': {
        'ENV': JSON.stringify(ENV)
      }
    })
  ]
});
<commit_msg>optimized config<commit_after>var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');

const ENV = process.env.NODE_ENV = process.env.ENV = 'production';

module.exports = webpackMerge(commonConfig, {
    devtool: 'source-map',

    output: {
        path: helpers.root('dist'),
        publicPath: '/',
        filename: '[name].[hash].js',
        chunkFilename: '[id].[hash].chunk.js'
    },

    htmlLoader: {
        minimize: false // workaround for ng2
    },

    plugins: [
        new webpack.NoErrorsPlugin(),
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618
            mangle: {
                keep_fnames: true,
                screw_ie8: true
            },
            compress: {
                screw_ie8: true,
                warnings: false
            },
            output: {
                comments: false,
                screw_ie8: true
            }
        }),
        new ExtractTextPlugin('[name].[hash].css'),
        new webpack.DefinePlugin({
            'process.env': {
                'ENV': JSON.stringify(ENV)
            }
        })
    ]
});
<|endoftext|>


<commit_before>'use strict';

function canvas_draw(){
    canvas_buffer.clearRect(
      0,
      0,
      canvas_width,
      canvas_height
    );

    draw_logic();

    if(canvas_menu){
        canvas_buffer.save();

        canvas_buffer.fillStyle = '#111';
        canvas_buffer.fillRect(
          canvas_x - 125,
          canvas_y - 50,
          250,
          100
        );

        canvas_buffer.fillStyle = '#fff';
        canvas_buffer.font = canvas_fonts['medium'];
        canvas_buffer.textAlign = 'center';
        canvas_buffer.textBaseline = 'middle';
        canvas_buffer.fillText(
          canvas_resume,
          canvas_x,
          canvas_y - 25
        );
        canvas_buffer.fillText(
          canvas_quit,
          canvas_x,
          canvas_y + 25
        );

        canvas_buffer.restore();
    }

    canvas_canvas.clearRect(
      0,
      0,
      canvas_width,
      canvas_height
    );
    canvas_canvas.drawImage(
      document.getElementById('buffer'),
      0,
      0
    );
}

function canvas_drawloop(){
    canvas_draw();
    canvas_animationFrame = window.requestAnimationFrame(canvas_drawloop);
}

// Required args: vertices
// Optional args: properties, style
function canvas_draw_path(args){
    args['properties'] = args['properties'] || {};
    args['style'] = args['style'] || canvas_style;

    canvas_buffer.beginPath();
    for(var vertex in args['vertices']){
        canvas_buffer[args['vertices'][vertex]['type'] || 'lineTo'](
          args['vertices'][vertex]['x'],
          args['vertices'][vertex]['y'],
          args['vertices'][vertex]['radius'],
          args['vertices'][vertex]['startAngle'],
          args['vertices'][vertex]['endAngle'],
          args['vertices'][vertex]['antiClockwise']
        );
    }
    canvas_buffer.closePath();

    for(var property in args['properties']){
        canvas_buffer[property] = args['properties'][property];
    }

    canvas_buffer[args['style']]();
}

function canvas_init(){
    canvas_resize();
    canvas_setmode({
      'mode': 0,
    });
}

function canvas_menu_quit(){
    if(canvas_menu){
        canvas_setmode({
          'mode': 0,
        });
    }
}

function canvas_menu_toggle(){
    canvas_menu = !canvas_menu;
}

function canvas_resize(){
    if(canvas_mode <= 0){
        return;
    }

    canvas_height = window.innerHeight;
    document.getElementById('buffer').height = canvas_height;
    document.getElementById('canvas').height = canvas_height;
    canvas_y = canvas_height / 2;

    canvas_width = window.innerWidth;
    document.getElementById('buffer').width = canvas_width;
    document.getElementById('canvas').width = canvas_width;
    canvas_x = canvas_width / 2;

    canvas_buffer.font = canvas_fonts['medium'];

    core_call({
      'todo': 'resize_logic',
    });
}

// Required args: mode
// Optional args: newgame
function canvas_setmode(args){
    args = core_args({
      'args': args,
      'defaults': {
        'newgame': false,
      },
    });

    window.cancelAnimationFrame(canvas_animationFrame);
    window.clearInterval(canvas_interval);

    canvas_menu = false;
    canvas_mode = args['mode'];

    if(core_isfunction({
      'todo': 'setmode_logic',
    })){
        setmode_logic(args['newgame']);

    }else{
        canvas_mode = 1;
        args['newgame'] = true;
    }

    // Main menu mode.
    if(canvas_mode === 0){
        canvas_buffer = 0;
        canvas_canvas = 0;
        return;
    }

    // Simulation modes.
    if(args['newgame']){
        var properties = '';

        if(!canvas_oncontextmenu){
            properties = ' oncontextmenu="return false" ';
        }

        document.body.innerHTML =
          '<canvas id=canvas' + properties + '></canvas><canvas id=buffer></canvas>';

        canvas_buffer = document.getElementById('buffer').getContext('2d');
        canvas_canvas = document.getElementById('canvas').getContext('2d');

        canvas_resize();
    }

    core_call({
      'args': canvas_mode,
      'todo': 'load_level',
    });

    canvas_animationFrame = window.requestAnimationFrame(canvas_drawloop);

    if(core_isfunction({
      'todo': 'logic',
    })){
        canvas_interval = window.setInterval(
          logic,
          canvas_interval_ms
        );
    }
}

var canvas_animationFrame = 0;
var canvas_buffer = 0;
var canvas_canvas = 0;
var canvas_fonts = {
  'big': '300% monospace',
  'medium': '200% monospace',
  'small': '100% monospace',
};
var canvas_height = 0;
var canvas_interval = 0;
var canvas_interval_ms = 25;
var canvas_menu = false;
var canvas_mode = 0;
var canvas_oncontextmenu = true;
var canvas_quit = 'Q = Main Menu';
var canvas_resume = 'ESC = Resume';
var canvas_style = 'fill';
var canvas_width = 0;
var canvas_x = 0;
var canvas_y = 0;

window.onresize = canvas_resize;
<commit_msg>added another core_args() usage<commit_after>'use strict';

function canvas_draw(){
    canvas_buffer.clearRect(
      0,
      0,
      canvas_width,
      canvas_height
    );

    draw_logic();

    if(canvas_menu){
        canvas_buffer.save();

        canvas_buffer.fillStyle = '#111';
        canvas_buffer.fillRect(
          canvas_x - 125,
          canvas_y - 50,
          250,
          100
        );

        canvas_buffer.fillStyle = '#fff';
        canvas_buffer.font = canvas_fonts['medium'];
        canvas_buffer.textAlign = 'center';
        canvas_buffer.textBaseline = 'middle';
        canvas_buffer.fillText(
          canvas_resume,
          canvas_x,
          canvas_y - 25
        );
        canvas_buffer.fillText(
          canvas_quit,
          canvas_x,
          canvas_y + 25
        );

        canvas_buffer.restore();
    }

    canvas_canvas.clearRect(
      0,
      0,
      canvas_width,
      canvas_height
    );
    canvas_canvas.drawImage(
      document.getElementById('buffer'),
      0,
      0
    );
}

function canvas_drawloop(){
    canvas_draw();
    canvas_animationFrame = window.requestAnimationFrame(canvas_drawloop);
}

// Required args: vertices
// Optional args: properties, style
function canvas_draw_path(args){
    args = core_args({
      'args': args,
      'defaults': {
        'properties': {},
        'style': canvas_style,
      },
    });

    canvas_buffer.beginPath();
    for(var vertex in args['vertices']){
        canvas_buffer[args['vertices'][vertex]['type'] || 'lineTo'](
          args['vertices'][vertex]['x'],
          args['vertices'][vertex]['y'],
          args['vertices'][vertex]['radius'],
          args['vertices'][vertex]['startAngle'],
          args['vertices'][vertex]['endAngle'],
          args['vertices'][vertex]['antiClockwise']
        );
    }
    canvas_buffer.closePath();

    for(var property in args['properties']){
        canvas_buffer[property] = args['properties'][property];
    }

    canvas_buffer[args['style']]();
}

function canvas_init(){
    canvas_resize();
    canvas_setmode({
      'mode': 0,
    });
}

function canvas_menu_quit(){
    if(canvas_menu){
        canvas_setmode({
          'mode': 0,
        });
    }
}

function canvas_menu_toggle(){
    canvas_menu = !canvas_menu;
}

function canvas_resize(){
    if(canvas_mode <= 0){
        return;
    }

    canvas_height = window.innerHeight;
    document.getElementById('buffer').height = canvas_height;
    document.getElementById('canvas').height = canvas_height;
    canvas_y = canvas_height / 2;

    canvas_width = window.innerWidth;
    document.getElementById('buffer').width = canvas_width;
    document.getElementById('canvas').width = canvas_width;
    canvas_x = canvas_width / 2;

    canvas_buffer.font = canvas_fonts['medium'];

    core_call({
      'todo': 'resize_logic',
    });
}

// Required args: mode
// Optional args: newgame
function canvas_setmode(args){
    args = core_args({
      'args': args,
      'defaults': {
        'newgame': false,
      },
    });

    window.cancelAnimationFrame(canvas_animationFrame);
    window.clearInterval(canvas_interval);

    canvas_menu = false;
    canvas_mode = args['mode'];

    if(core_isfunction({
      'todo': 'setmode_logic',
    })){
        setmode_logic(args['newgame']);

    }else{
        canvas_mode = 1;
        args['newgame'] = true;
    }

    // Main menu mode.
    if(canvas_mode === 0){
        canvas_buffer = 0;
        canvas_canvas = 0;
        return;
    }

    // Simulation modes.
    if(args['newgame']){
        var properties = '';

        if(!canvas_oncontextmenu){
            properties = ' oncontextmenu="return false" ';
        }

        document.body.innerHTML =
          '<canvas id=canvas' + properties + '></canvas><canvas id=buffer></canvas>';

        canvas_buffer = document.getElementById('buffer').getContext('2d');
        canvas_canvas = document.getElementById('canvas').getContext('2d');

        canvas_resize();
    }

    core_call({
      'args': canvas_mode,
      'todo': 'load_level',
    });

    canvas_animationFrame = window.requestAnimationFrame(canvas_drawloop);

    if(core_isfunction({
      'todo': 'logic',
    })){
        canvas_interval = window.setInterval(
          logic,
          canvas_interval_ms
        );
    }
}

var canvas_animationFrame = 0;
var canvas_buffer = 0;
var canvas_canvas = 0;
var canvas_fonts = {
  'big': '300% monospace',
  'medium': '200% monospace',
  'small': '100% monospace',
};
var canvas_height = 0;
var canvas_interval = 0;
var canvas_interval_ms = 25;
var canvas_menu = false;
var canvas_mode = 0;
var canvas_oncontextmenu = true;
var canvas_quit = 'Q = Main Menu';
var canvas_resume = 'ESC = Resume';
var canvas_style = 'fill';
var canvas_width = 0;
var canvas_x = 0;
var canvas_y = 0;

window.onresize = canvas_resize;
<|endoftext|>


<commit_before>var gulp = require('gulp');
var karma = require('karma').server;

/**
 * Run test once and exit
 */
gulp.task('test', function (done) {
    karma.start({
        configFile: __dirname + '/../../karma.conf.js',
        singleRun: true
    }, function(e) {
        done();
    });
});

/**
 * Watch for file changes and re-run tests on each change
 */
gulp.task('tdd', function (done) {
    karma.start({
        configFile: __dirname + '/../../karma.conf.js'
    }, function(e) {
        done();
    });
});
<commit_msg>fix(karma): exit when test fails<commit_after>var gulp = require('gulp');
var karma = require('karma');

/**
 * Run test once and exit
 */
gulp.task('test', function (done) {
    new karma.Server({
        configFile: __dirname + '/../../karma.conf.js',
        singleRun: true
    }, function(e) {
        done(e === 0 ? null : 'karma exited with status ' + e);
    }).start();
});

/**
 * Watch for file changes and re-run tests on each change
 */
gulp.task('tdd', function (done) {
    new karma.Server({
        configFile: __dirname + '/../../karma.conf.js'
    }, function(e) {
        done();
    }).start();
});
<|endoftext|>


<commit_before>var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

var env = config.build.env

var webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  devtool: config.build.productionSourceMap ? '#source-map' : false,
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    }),
    // extract css into its own file
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    new OptimizeCSSPlugin({
      cssProcessorOptions: {
        safe: true
      }
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})

if (config.build.productionGzip) {
  var CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig
<commit_msg>change build params<commit_after>var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

var env = config.build.env

var webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  devtool: config.build.productionSourceMap ? '#source-map' : false,
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    }),
    // extract css into its own file
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].css') // no-hash-name
      //filename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    new OptimizeCSSPlugin({
      cssProcessorOptions: {
        safe: true
      }
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})

if (config.build.productionGzip) {
  var CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig
<|endoftext|>


<commit_before>'use babel'
import { Point, Range } from 'atom'
import pathUtils from 'path'
import fs from 'fs'
import common from './common'

function findImportAtPosition(line, column){
  const cells = common.splitCells(line);
  if(cells.length>=2 && cells[0].toLowerCase()==='resource'){
    const path = cells[1]
    const startCol = line.indexOf(path);
    const endCol = startCol+path.length;
    const extension = pathUtils.extname(path)
    const name = pathUtils.basename(path, extension)
    if ((column>startCol) && (column<endCol)) {
      return {
        startCol,
        endCol,
        path,
        name,
        extension
      };
    }
  }
  return undefined
}

export default {
  getKeywordSuggestions(textEditor, point, autocompleteRobotProvider){
    const line = textEditor.lineTextForBufferRow(point.row);
    const importInfo = findImportAtPosition(line, point.column)
    if(importInfo===undefined){
      return undefined
    }

    const matchingImportedResources = new Set()

    // accurate import
    const activeResource = common.getCurrentResource(textEditor.getPath(), autocompleteRobotProvider)
    if(activeResource){
      for(const importedResource of activeResource.imports.resources){
        if(importedResource.path===importInfo.path){
          if(importedResource.resourceKey){
            const resource = autocompleteRobotProvider.getResourceByKey(importedResource.resourceKey)
            if(resource){
              matchingImportedResources.add(resource)
            }
          }
          break
        }
      }
    }

    if(matchingImportedResources.size===0){
      // approximate import
      const resourceKeys = autocompleteRobotProvider.getResourceKeys()
      for(const resourceKey of resourceKeys){
        const resource = autocompleteRobotProvider.getResourceByKey(resourceKey)
        if(resource && resource.name === importInfo.name && resource.extension === importInfo.extension){
          matchingImportedResources.add(resource)
        }
      }
    }

    if (matchingImportedResources.size===0) {
      return undefined;
    }

    // build hyperclick callback
    let callback = undefined;
    if(matchingImportedResources.size===1) {
      const resource = Array.from(matchingImportedResources)[0]
      callback = () => {
        atom.workspace.open(resource.path, {initialLine: 0, initialColumn: 0})
        .then(editor => editor.scrollToCursorPosition())
        .catch(error => console.log(`Error opening editor: ${error}`))
      }
    } else {
      callback = [];
      for (const resource of Array.from(matchingImportedResources)) {
        callback.push({
          title: resource.path,
          callback() {
            atom.workspace.open(resource.path, {initialLine: 0, initialColumn: 0})
            .then(editor => editor.scrollToCursorPosition())
            .catch(error => console.log(`Error opening editor: ${error}`))
          }
        })
      }
    }

    return {
      range: new Range(new Point(point.row, importInfo.startCol), new Point(point.row, importInfo.endCol)),
      callback
    };
  }
}
<commit_msg>Fix error that prevented opening imported resources<commit_after>'use babel'
import { Point, Range } from 'atom'
import pathUtils from 'path'
import fs from 'fs'
import common from './common'

function findImportAtPosition(line, column){
  const cells = common.splitCells(line);
  if(cells.length>=2 && cells[0].toLowerCase()==='resource'){
    const path = cells[1]
    const startCol = line.indexOf(path);
    const endCol = startCol+path.length;
    const extension = pathUtils.extname(path)
    const name = pathUtils.basename(path, extension)
    if ((column>startCol) && (column<endCol)) {
      return {
        startCol,
        endCol,
        path,
        name,
        extension
      };
    }
  }
  return undefined
}

export default {
  getKeywordSuggestions(textEditor, point, autocompleteRobotProvider){
    const line = textEditor.lineTextForBufferRow(point.row);
    const importInfo = findImportAtPosition(line, point.column)
    if(importInfo===undefined){
      return undefined
    }

    const matchingImportedResources = new Set()

    // accurate import
    const activeResource = common.getCurrentResource(textEditor.getPath(), autocompleteRobotProvider)
    if(activeResource){
      for(let importedResource of activeResource.imports.resources){
        const importAbsolutePath = pathUtils.join(
          pathUtils.dirname(activeResource.path), importInfo.path)
        importedResource = autocompleteRobotProvider.getResourceByKey(importedResource.resourceKey)
        if(importedResource && importedResource.path===pathUtils.normalize(importAbsolutePath)){
          matchingImportedResources.add(importedResource)
          break
        }
      }
    }

    if(matchingImportedResources.size===0){
      // approximate import
      const resourceKeys = autocompleteRobotProvider.getResourceKeys()
      for(const resourceKey of resourceKeys){
        const resource = autocompleteRobotProvider.getResourceByKey(resourceKey)
        if(resource && resource.name === importInfo.name && resource.extension === importInfo.extension){
          matchingImportedResources.add(resource)
        }
      }
    }

    if (matchingImportedResources.size===0) {
      return undefined;
    }

    // build hyperclick callback
    let callback = undefined;
    if(matchingImportedResources.size===1) {
      const resource = Array.from(matchingImportedResources)[0]
      callback = () => {
        atom.workspace.open(resource.path, {initialLine: 0, initialColumn: 0})
        .then(editor => editor.scrollToCursorPosition())
        .catch(error => console.log(`Error opening editor: ${error}`))
      }
    } else {
      callback = [];
      for (const resource of Array.from(matchingImportedResources)) {
        callback.push({
          title: resource.path,
          callback() {
            atom.workspace.open(resource.path, {initialLine: 0, initialColumn: 0})
            .then(editor => editor.scrollToCursorPosition())
            .catch(error => console.log(`Error opening editor: ${error}`))
          }
        })
      }
    }

    return {
      range: new Range(new Point(point.row, importInfo.startCol), new Point(point.row, importInfo.endCol)),
      callback
    };
  }
}
<|endoftext|>


<commit_before>"use strict";

/**
 * Development configuration for the application server
 * @type {
 *      libraries: {},     // Libraries installed per NPM as "alias: name"
 *      npm: string,       // Path to "node_modules" directory for libraries and modules installed per NPM
 *      directory: string, // Path to directory with the modules of this project
 *      modules: {
 *          npm: {},       // Modules installed per NPM with configurations as "name: moduleconfig"
 *          directory: {}  // Modules of this project with configurations as "name: moduleconfig"
 *      }
 * }
 */
module.exports = {
    directory: __dirname + '/../modules/',
    modules: {
        directory: {
            example: {
                // Configuration of the module
            }
        }
    }
};
<commit_msg>Better documentation<commit_after>"use strict";

/**
 * Development configuration for the application server
 * @type {
 *      libraries: {},     // Libraries installed per NPM as "alias: name"
 *      npm: string,       // Absolute path to "node_modules" directory for libraries and modules installed per NPM
 *      directory: string, // Absolute path to directory with the modules of this project
 *      modules: {
 *          npm: {},       // Modules installed per NPM with configurations as "name: moduleconfig"
 *          directory: {}  // Modules of this project with configurations as "name: moduleconfig"
 *      }
 * }
 */
module.exports = {
    directory: __dirname + '/../modules/',
    modules: {
        directory: {
            example: {
                // Configuration of the module
            }
        }
    }
};
<|endoftext|>


<commit_before>var gulp = require('gulp');
var karma = require('karma');

/**
 * Run test once and exit
 */
gulp.task('test', function (done) {
    new karma.Server({
        configFile: __dirname + '/../../karma.conf.js',
        singleRun: true
    }, function(e) {
        done(e === 0 ? null : 'karma exited with status ' + e);
    }).start();
});

/**
 * Watch for file changes and re-run tests on each change
 */
gulp.task('tdd', function (done) {
    new karma.Server({
        configFile: __dirname + '/../../karma.conf.js'
    }, function(e) {
        done();
    }).start();
});
<commit_msg>chore(karma): fix karma test runner<commit_after>var gulp = require('gulp');
var karma = require('karma');

/**
 * Run test once and exit
 */
gulp.task('test', function (done) {
    new karma.Server({
        configFile: __dirname + '/../../karma.conf.js',
        singleRun: true
    }, function(e) {
        done();
    }).start();
});

/**
 * Watch for file changes and re-run tests on each change
 */
gulp.task('tdd', function (done) {
    new karma.Server({
        configFile: __dirname + '/../../karma.conf.js'
    }, function(e) {
        done();
    }).start();
});
<|endoftext|>