<commit_before>/**
 * @author Vladimir Kozhin <affka@affka.ru>
 * @license MIT
 */

'use strict';

/**
 * @namespace Jii
 * @ignore
 */
var Jii = require('../Jii');

require('./Context');

/**
 * @class Jii.base.Module
 * @extends Jii.base.Context
 */
Jii.defineClass('Jii.base.Module', /** @lends Jii.base.Module.prototype */{

	__extends: Jii.base.Context,

	/**
	 * @type {string}
	 */
	id: null,

	/**
	 * The parent module of this module. Null if this module does not have a parent.
	 * @type {Jii.base.Module}
	 */
	module: null,

	/**
	 * Mapping from controller ID to controller configurations.
	 * Each name-value pair specifies the configuration of a single controller.
	 * A controller configuration can be either a string or an array.
	 * If the former, the string should be the fully qualified class name of the controller.
	 * If the latter, the array must contain a 'class' element which specifies
	 * the controller's fully qualified class name, and the rest of the name-value pairs
	 * in the array are used to initialize the corresponding controller properties. For example,
	 *
	 * ~~~
	 * {
     *   account: 'app.controllers.UserController',
     *   article: {
     *      className: 'app.controllers.PostController',
     *      pageTitle: 'something new'
     *   }
     * }
	 * ~~~
	 * @type {object}
	 */
	controllerMap: {},

	/**
	 * String the namespace that controller classes are in. If not set,
	 * it will use the "controllers" sub-namespace under the namespace of this module.
	 * For example, if the namespace of this module is "foo\bar", then the default
	 * controller namespace would be "foo\bar\controllers".
	 * @type {string}
	 */
	controllerNamespace: null,

	/**
	 * The default route of this module. Defaults to 'default'.
	 * The route may consist of child module ID, controller ID, and/or action ID.
	 * For example, `help`, `post/create`, `admin/post/create`.
	 * If action ID is not given, it will take the default value as specified in defaultAction.
	 * @type {string}
	 */
	defaultRoute: 'default',

	/**
	 * The layout that should be applied for views within this module. This refers to a view name
	 * relative to [[layoutPath]]. If this is not set, it means the layout value of the [[module|parent module]]
	 * will be taken. If this is false, layout will be disabled within this module.
	 * @type {string|boolean}
	 */
	layout: null,

	/**
	 * @type {object}
	 */
	_modules: null,

	/**
	 * @constructor
	 */
	constructor: function (id, moduleObject, config) {
		this.id = id;
		this.module = moduleObject;
		this._modules = {};

		this.__super(config);
	},

	init: function () {
		if (this.controllerNamespace === null) {
			var index = Jii._.lastIndexOf(this.className(), '.');
			this.controllerNamespace = this.className().substr(0, index);
		}
	},

	getUniqueId: function () {
		if (this.module) {
			var id = this.module.getUniqueId() + '/' + this.id;
			return Jii._s.ltrim(id, '/');
		}
		return this.id;
	},

	/**
	 * The root directory of the module.
	 * @type {string}
	 */
	_basePath: null,

	/**
	 * Returns the root directory of the module.
	 * It defaults to the directory containing the module class file.
	 * @return {string} the root directory of the module.
	 */
	getBasePath: function () {
		if (this._basePath === null) {
			this._basePath = Jii.getAlias('@' + this.className().replace(/\.[^.]+$/, ''))
		}

		return this._basePath;
	},

	/**
	 * Sets the root directory of the module.
	 * This method can only be invoked at the beginning of the constructor.
	 * @param  {string} path the root directory of the module. This can be either a directory name or a path alias.
	 */
	setBasePath: function (path) {
		this._basePath = Jii.getAlias(path);
	},

	/**
	 * Returns the directory that contains the controller classes according to [[controllerNamespace]].
	 * Note that in order for this method to return a value, you must define
	 * an alias for the root namespace of [[controllerNamespace]].
	 * @return {string} the directory that contains the controller classes.
	 */
	getControllerPath: function () {
		return Jii.getAlias('@' + this.controllerNamespace.replace('.', '/'));
	},

	/**
	 * The root directory that contains view files for this module
	 * @type {string}
	 */
	_viewPath: null,

	/**
	 * Returns the directory that contains the view files for this module.
	 * @return {string} the root directory of view files. Defaults to "[[basePath]]/view".
	 */
	getViewPath: function () {
		if (this._viewPath === null) {
			this._viewPath = this.getBasePath() + '/views';
		}
		return this._viewPath;
	},

	/**
	 * Sets the directory that contains the view files.
	 * @param {string} path the root directory of view files.
	 */
	setViewPath: function (path) {
		this._viewPath = Jii.getAlias(path);
	},

	/**
	 * The root directory that contains layout view files for this module.
	 * @type {string}
	 */
	_layoutPath: null,

	/**
	 * Returns the directory that contains layout view files for this module.
	 * @return {string} the root directory of layout files. Defaults to "[[viewPath]]/layouts".
	 */
	getLayoutPath: function () {
		if (this._layoutPath === null) {
			this._layoutPath = this.getViewPath() + '/layouts';
		}
		return this._layoutPath;
	},

	/**
	 * Sets the directory that contains the layout files.
	 * @param  {string} path the root directory of layout files.
	 */
	setLayoutPath: function (path) {
		this._layoutPath = Jii.getAlias(path);
	},

	/**
	 * Checks whether the child module of the specified ID exists.
	 * This method supports checking the existence of both child and grand child modules.
	 * @param {string} id module ID. For grand child modules, use ID path relative to this module (e.g. `admin/content`).
	 * @return {boolean} whether the named module exists. Both loaded and unloaded modules
	 * are considered.
	 */
	hasModule: function (id) {
		var index = Jii._.indexOf(id, '.');
		if (index !== -1) {
			var moduleId = id.substr(0, index);
			var childModuleId = id.substr(index + 1);

			// Check sub-module
			var moduleObject = this.getModule(moduleId);
			return moduleObject !== null ? moduleObject.hasModule(childModuleId) : false;
		}

		return Jii._.has(this._modules[id]);
	},

	/**
	 * Retrieves the child module of the specified ID.
	 * This method supports retrieving both child modules and grand child modules.
	 * @param {string} id module ID (case-sensitive). To retrieve grand child modules,
	 * use ID path relative to this module (e.g. `admin/content`).
	 * @return {Jii.base.Module} the module instance, null if the module does not exist.
	 */
	getModule: function (id) {
		// Get sub-module
		var index = Jii._.indexOf(id, '.');
		if (index !== -1) {
			var moduleId = id.substr(0, index);
			var childModuleId = id.substr(index + 1);

			var moduleObject = this.getModule(moduleId);
			return moduleObject !== null ? moduleObject.getModule(childModuleId) : null;
		}

		return this._modules[id] || null;
	},

	/**
	 * Adds a sub-module to this module.
	 * @param {string} id module ID
	 * @param {Jii.base.Module|array|null} moduleObject the sub-module to be added to this module. This can
	 * be one of the followings:
	 *
	 * - a [[Jii.base.Module]] object
	 * - a configuration array: when [[getModule()]] is called initially, the array
	 *   will be used to instantiate the sub-module
	 * - null: the named sub-module will be removed from this module
	 */
	setModule: function (id, moduleObject) {
		if (moduleObject === null) {
			delete this._modules[id];
		} else {
			// Create module instance
			moduleObject = Jii.createObject(moduleObject, id, this);

			// Add link
			this._modules[id] = moduleObject;
		}
	},

	/**
	 * Returns the sub-modules in this module.
	 * @return {Jii.base.Module[]} the modules (indexed by their IDs)
	 */
	getModules: function () {
		return this._modules;
	},

	/**
	 * Registers sub-modules in the current module.
	 *
	 * Each sub-module should be specified as a name-value pair, where
	 * name refers to the ID of the module and value the module or a configuration
	 * array that can be used to create the module. In the latter case, [[Jii.createObject()]]
	 * will be used to create the module.
	 *
	 * If a new sub-module has the same ID as an existing one, the existing one will be overwritten silently.
	 *
	 * The following is an example for registering two sub-modules:
	 *
	 * ~~~
	 * [
	 *     'comment' => [
	 *         'class' => 'app\modules\comment\CommentModule',
	 *         'db' => 'db',
	 *     ],
	 *     'booking' => ['class' => 'app\modules\booking\BookingModule'],
	 * ]
	 * ~~~
	 *
	 * @param {object} modules modules (id => module configuration or instances)
	 */
	setModules: function (modules) {
		Jii._.each(modules, Jii._.bind(function (moduleObject, id) {
			this._modules[id] = moduleObject;
		}, this));
	},

	/**
	 * Runs a controller action specified by a route.
	 * This method parses the specified route and creates the corresponding child module(s), controller and action
	 * instances. It then calls [[Jii.base.Controller::runAction()]] to run the action with the given parameters.
	 * If the route is empty, the method will use [[defaultRoute]].
	 * @param {string} route the route that specifies the action.
	 * @param {Jii.base.Context} context
	 * @return {Jii.when} the result of the action.
	 * @throws {Jii.exceptions.InvalidRouteException} if the requested route cannot be resolved into an action successfully
	 */
	runAction: function (route, context) {
		var parts = this.createController(route);
		if (parts !== null) {
			/** @type {Jii.base.Controller} */
			var controller = parts[0];
			var actionId = parts[1];

			return controller.runAction(actionId, context);
		}

		var id = this.getUniqueId();
		var requestName = id ? id + '/' + route : route;
		//throw new Jii.exceptions.InvalidRouteException('Unable to resolve the request `' + requestName + '`.');
		Jii.info('Unable to resolve the request `' + requestName + '`.');
	},

	/**
	 * Creates a controller instance based on the controller ID.
	 *
	 * The controller is created within this module. The method first attempts to
	 * create the controller based on the [[controllerMap]] of the module.
	 *
	 * @param {string} route the route consisting of module, controller and action IDs.
	 * @return {array|null} If the controller is created successfully, it will be returned together
	 * with the requested action ID. Otherwise false will be returned.
	 * @throws {Jii.exceptions.InvalidConfigException} if the controller class and its file do not match.
	 */
	createController: function (route) {
		if (route === '') {
			route = this.defaultRoute;
		}

		var id;
		var controller = null;
		var index = route.indexOf('/');

		if (index !== -1) {
			id = route.substr(0, index);
			route = route.substr(index + 1);
		} else {
			id = route;
			route = '';
		}

		var moduleObject = this.getModule(id);
		if (moduleObject !== null) {
			return moduleObject.createController(route);
		}

		if (Jii._.has(this.controllerMap, id)) {
			return Jii.createObject(this.controllerMap[id], id, this);
		} else if (/^[a-z0-9\\-_]+$/.test(id)) {

			var className = id.charAt(0).toUpperCase() + id.slice(1);
			className = className.replace('-', '') + 'Controller';
			className = this.controllerNamespace + '.' + className;

			var controllerClass = Jii.namespace(className);
			if (Jii._.isFunction(controllerClass)) {
				controller = new controllerClass(id, this);

				if (!(controller instanceof Jii.base.Controller)) {
					throw new Jii.exceptions.InvalidConfigException("Controller class must extend from Jii.base.Controller.");
				}
			}
		}

		return controller !== null ? [controller, route] : null;
	},

	/**
	 * This method is invoked right before an action of this module is to be executed (after all possible filters.)
	 * You may override this method to do last-minute preparation for the action.
	 * Make sure you call the parent implementation so that the relevant event is triggered.
	 * @param {Jii.base.Action} action the action to be executed.
	 * @return {boolean} whether the action should continue to be executed.
	 */
	beforeAction: function (action) {
		return true;
	},

	/**
	 * This method is invoked right after an action of this module has been executed.
	 * You may override this method to do some postprocessing for the action.
	 * Make sure you call the parent implementation so that the relevant event is triggered.
	 * @param {Jii.base.Action} action the action just executed.
	 */
	afterAction: function (action) {
	}

});
<commit_msg>Fix create controller from controllerMap in module<commit_after>/**
 * @author Vladimir Kozhin <affka@affka.ru>
 * @license MIT
 */

'use strict';

/**
 * @namespace Jii
 * @ignore
 */
var Jii = require('../Jii');

require('./Context');

/**
 * @class Jii.base.Module
 * @extends Jii.base.Context
 */
Jii.defineClass('Jii.base.Module', /** @lends Jii.base.Module.prototype */{

	__extends: Jii.base.Context,

	/**
	 * @type {string}
	 */
	id: null,

	/**
	 * The parent module of this module. Null if this module does not have a parent.
	 * @type {Jii.base.Module}
	 */
	module: null,

	/**
	 * Mapping from controller ID to controller configurations.
	 * Each name-value pair specifies the configuration of a single controller.
	 * A controller configuration can be either a string or an array.
	 * If the former, the string should be the fully qualified class name of the controller.
	 * If the latter, the array must contain a 'class' element which specifies
	 * the controller's fully qualified class name, and the rest of the name-value pairs
	 * in the array are used to initialize the corresponding controller properties. For example,
	 *
	 * ~~~
	 * {
     *   account: 'app.controllers.UserController',
     *   article: {
     *      className: 'app.controllers.PostController',
     *      pageTitle: 'something new'
     *   }
     * }
	 * ~~~
	 * @type {object}
	 */
	controllerMap: {},

	/**
	 * String the namespace that controller classes are in. If not set,
	 * it will use the "controllers" sub-namespace under the namespace of this module.
	 * For example, if the namespace of this module is "foo\bar", then the default
	 * controller namespace would be "foo\bar\controllers".
	 * @type {string}
	 */
	controllerNamespace: null,

	/**
	 * The default route of this module. Defaults to 'default'.
	 * The route may consist of child module ID, controller ID, and/or action ID.
	 * For example, `help`, `post/create`, `admin/post/create`.
	 * If action ID is not given, it will take the default value as specified in defaultAction.
	 * @type {string}
	 */
	defaultRoute: 'default',

	/**
	 * The layout that should be applied for views within this module. This refers to a view name
	 * relative to [[layoutPath]]. If this is not set, it means the layout value of the [[module|parent module]]
	 * will be taken. If this is false, layout will be disabled within this module.
	 * @type {string|boolean}
	 */
	layout: null,

	/**
	 * @type {object}
	 */
	_modules: null,

	/**
	 * @constructor
	 */
	constructor: function (id, moduleObject, config) {
		this.id = id;
		this.module = moduleObject;
		this._modules = {};

		this.__super(config);
	},

	init: function () {
		if (this.controllerNamespace === null) {
			var index = Jii._.lastIndexOf(this.className(), '.');
			this.controllerNamespace = this.className().substr(0, index);
		}
	},

	getUniqueId: function () {
		if (this.module) {
			var id = this.module.getUniqueId() + '/' + this.id;
			return Jii._s.ltrim(id, '/');
		}
		return this.id;
	},

	/**
	 * The root directory of the module.
	 * @type {string}
	 */
	_basePath: null,

	/**
	 * Returns the root directory of the module.
	 * It defaults to the directory containing the module class file.
	 * @return {string} the root directory of the module.
	 */
	getBasePath: function () {
		if (this._basePath === null) {
			this._basePath = Jii.getAlias('@' + this.className().replace(/\.[^.]+$/, ''))
		}

		return this._basePath;
	},

	/**
	 * Sets the root directory of the module.
	 * This method can only be invoked at the beginning of the constructor.
	 * @param  {string} path the root directory of the module. This can be either a directory name or a path alias.
	 */
	setBasePath: function (path) {
		this._basePath = Jii.getAlias(path);
	},

	/**
	 * Returns the directory that contains the controller classes according to [[controllerNamespace]].
	 * Note that in order for this method to return a value, you must define
	 * an alias for the root namespace of [[controllerNamespace]].
	 * @return {string} the directory that contains the controller classes.
	 */
	getControllerPath: function () {
		return Jii.getAlias('@' + this.controllerNamespace.replace('.', '/'));
	},

	/**
	 * The root directory that contains view files for this module
	 * @type {string}
	 */
	_viewPath: null,

	/**
	 * Returns the directory that contains the view files for this module.
	 * @return {string} the root directory of view files. Defaults to "[[basePath]]/view".
	 */
	getViewPath: function () {
		if (this._viewPath === null) {
			this._viewPath = this.getBasePath() + '/views';
		}
		return this._viewPath;
	},

	/**
	 * Sets the directory that contains the view files.
	 * @param {string} path the root directory of view files.
	 */
	setViewPath: function (path) {
		this._viewPath = Jii.getAlias(path);
	},

	/**
	 * The root directory that contains layout view files for this module.
	 * @type {string}
	 */
	_layoutPath: null,

	/**
	 * Returns the directory that contains layout view files for this module.
	 * @return {string} the root directory of layout files. Defaults to "[[viewPath]]/layouts".
	 */
	getLayoutPath: function () {
		if (this._layoutPath === null) {
			this._layoutPath = this.getViewPath() + '/layouts';
		}
		return this._layoutPath;
	},

	/**
	 * Sets the directory that contains the layout files.
	 * @param  {string} path the root directory of layout files.
	 */
	setLayoutPath: function (path) {
		this._layoutPath = Jii.getAlias(path);
	},

	/**
	 * Checks whether the child module of the specified ID exists.
	 * This method supports checking the existence of both child and grand child modules.
	 * @param {string} id module ID. For grand child modules, use ID path relative to this module (e.g. `admin/content`).
	 * @return {boolean} whether the named module exists. Both loaded and unloaded modules
	 * are considered.
	 */
	hasModule: function (id) {
		var index = Jii._.indexOf(id, '.');
		if (index !== -1) {
			var moduleId = id.substr(0, index);
			var childModuleId = id.substr(index + 1);

			// Check sub-module
			var moduleObject = this.getModule(moduleId);
			return moduleObject !== null ? moduleObject.hasModule(childModuleId) : false;
		}

		return Jii._.has(this._modules[id]);
	},

	/**
	 * Retrieves the child module of the specified ID.
	 * This method supports retrieving both child modules and grand child modules.
	 * @param {string} id module ID (case-sensitive). To retrieve grand child modules,
	 * use ID path relative to this module (e.g. `admin/content`).
	 * @return {Jii.base.Module} the module instance, null if the module does not exist.
	 */
	getModule: function (id) {
		// Get sub-module
		var index = Jii._.indexOf(id, '.');
		if (index !== -1) {
			var moduleId = id.substr(0, index);
			var childModuleId = id.substr(index + 1);

			var moduleObject = this.getModule(moduleId);
			return moduleObject !== null ? moduleObject.getModule(childModuleId) : null;
		}

		return this._modules[id] || null;
	},

	/**
	 * Adds a sub-module to this module.
	 * @param {string} id module ID
	 * @param {Jii.base.Module|array|null} moduleObject the sub-module to be added to this module. This can
	 * be one of the followings:
	 *
	 * - a [[Jii.base.Module]] object
	 * - a configuration array: when [[getModule()]] is called initially, the array
	 *   will be used to instantiate the sub-module
	 * - null: the named sub-module will be removed from this module
	 */
	setModule: function (id, moduleObject) {
		if (moduleObject === null) {
			delete this._modules[id];
		} else {
			// Create module instance
			moduleObject = Jii.createObject(moduleObject, id, this);

			// Add link
			this._modules[id] = moduleObject;
		}
	},

	/**
	 * Returns the sub-modules in this module.
	 * @return {Jii.base.Module[]} the modules (indexed by their IDs)
	 */
	getModules: function () {
		return this._modules;
	},

	/**
	 * Registers sub-modules in the current module.
	 *
	 * Each sub-module should be specified as a name-value pair, where
	 * name refers to the ID of the module and value the module or a configuration
	 * array that can be used to create the module. In the latter case, [[Jii.createObject()]]
	 * will be used to create the module.
	 *
	 * If a new sub-module has the same ID as an existing one, the existing one will be overwritten silently.
	 *
	 * The following is an example for registering two sub-modules:
	 *
	 * ~~~
	 * [
	 *     'comment' => [
	 *         'class' => 'app\modules\comment\CommentModule',
	 *         'db' => 'db',
	 *     ],
	 *     'booking' => ['class' => 'app\modules\booking\BookingModule'],
	 * ]
	 * ~~~
	 *
	 * @param {object} modules modules (id => module configuration or instances)
	 */
	setModules: function (modules) {
		Jii._.each(modules, Jii._.bind(function (moduleObject, id) {
			this._modules[id] = moduleObject;
		}, this));
	},

	/**
	 * Runs a controller action specified by a route.
	 * This method parses the specified route and creates the corresponding child module(s), controller and action
	 * instances. It then calls [[Jii.base.Controller::runAction()]] to run the action with the given parameters.
	 * If the route is empty, the method will use [[defaultRoute]].
	 * @param {string} route the route that specifies the action.
	 * @param {Jii.base.Context} context
	 * @return {Jii.when} the result of the action.
	 * @throws {Jii.exceptions.InvalidRouteException} if the requested route cannot be resolved into an action successfully
	 */
	runAction: function (route, context) {
		var parts = this.createController(route);
		if (parts !== null) {
			/** @type {Jii.base.Controller} */
			var controller = parts[0];
			var actionId = parts[1];

			return controller.runAction(actionId, context);
		}

		var id = this.getUniqueId();
		var requestName = id ? id + '/' + route : route;
		//throw new Jii.exceptions.InvalidRouteException('Unable to resolve the request `' + requestName + '`.');
		Jii.info('Unable to resolve the request `' + requestName + '`.');
	},

	/**
	 * Creates a controller instance based on the controller ID.
	 *
	 * The controller is created within this module. The method first attempts to
	 * create the controller based on the [[controllerMap]] of the module.
	 *
	 * @param {string} route the route consisting of module, controller and action IDs.
	 * @return {[]|null} If the controller is created successfully, it will be returned together
	 * with the requested action ID. Otherwise false will be returned.
	 * @throws {Jii.exceptions.InvalidConfigException} if the controller class and its file do not match.
	 */
	createController: function (route) {
		if (route === '') {
			route = this.defaultRoute;
		}

		var id;
		var controller = null;
		var index = route.indexOf('/');

		if (index !== -1) {
			id = route.substr(0, index);
			route = route.substr(index + 1);
		} else {
			id = route;
			route = '';
		}

		if (Jii._.has(this.controllerMap, id)) {
			controller = Jii.createObject(this.controllerMap[id], id, this);
			return controller !== null ? [controller, route] : null;
		}

		var moduleObject = this.getModule(id);
		if (moduleObject !== null) {
			return moduleObject.createController(route);
		}

		if (/^[a-z0-9\\-_]+$/.test(id)) {

			var className = id.charAt(0).toUpperCase() + id.slice(1);
			className = className.replace('-', '') + 'Controller';
			className = this.controllerNamespace + '.' + className;

			var controllerClass = Jii.namespace(className);
			if (Jii._.isFunction(controllerClass)) {
				controller = new controllerClass(id, this);

				if (!(controller instanceof Jii.base.Controller)) {
					throw new Jii.exceptions.InvalidConfigException("Controller class must extend from Jii.base.Controller.");
				}
			}
		}

		return controller !== null ? [controller, route] : null;
	},

	/**
	 * This method is invoked right before an action of this module is to be executed (after all possible filters.)
	 * You may override this method to do last-minute preparation for the action.
	 * Make sure you call the parent implementation so that the relevant event is triggered.
	 * @param {Jii.base.Action} action the action to be executed.
	 * @return {boolean} whether the action should continue to be executed.
	 */
	beforeAction: function (action) {
		return true;
	},

	/**
	 * This method is invoked right after an action of this module has been executed.
	 * You may override this method to do some postprocessing for the action.
	 * Make sure you call the parent implementation so that the relevant event is triggered.
	 * @param {Jii.base.Action} action the action just executed.
	 */
	afterAction: function (action) {
	}

});
<|endoftext|>


<commit_before>/*!
 * coins.js - coins object for bcoin
 * Copyright (c) 2014-2015, Fedor Indutny (MIT License)
 * Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
 * https://github.com/bcoin-org/bcoin
 */

var bcoin = require('./env');
var utils = bcoin.utils;
var assert = utils.assert;
var BufferReader = require('./reader');
var BufferWriter = require('./writer');

/**
 * Represents the outputs for a single transaction.
 * @exports Coins
 * @constructor
 * @param {TX|Object} tx/options - TX or options object.
 * @property {Hash} hash - Transaction hash.
 * @property {Number} version - Transaction version.
 * @property {Number} height - Transaction height (-1 if unconfirmed).
 * @property {Boolean} coinbase - Whether the containing
 * transaction is a coinbase.
 * @property {Coin[]} outputs - Coins.
 */

function Coins(options) {
  if (!(this instanceof Coins))
    return new Coins(options);

  if (!options)
    options = {};

  this.version = options.version != null ? options.version : -1;
  this.hash = options.hash || null;
  this.height = options.height != null ? options.height : -1;
  this.coinbase = options.coinbase || false;
  this.outputs = options.outputs || [];
}

/**
 * Add a single coin to the collection.
 * @param {Coin} coin
 */

Coins.prototype.add = function add(coin) {
  if (this.version === -1) {
    this.version = coin.version;
    this.hash = coin.hash;
    this.height = coin.height;
    this.coinbase = coin.coinbase;
  }

  if (coin.script.isUnspendable()) {
    this.outputs[coin.index] = null;
    return;
  }

  this.outputs[coin.index] = coin;
};

/**
 * Test whether the collection has a coin.
 * @param {Number} index
 * @returns {Boolean}
 */

Coins.prototype.has = function has(index) {
  return this.outputs[index] != null;
};

/**
 * Get a coin.
 * @param {Number} index
 * @returns {Coin}
 */

Coins.prototype.get = function get(index) {
  var coin = this.outputs[index];
  if (!coin)
    return;

  if (coin instanceof DeferredCoin)
    coin = coin.toCoin(this, index);

  return coin;
};

/**
 * Count unspent coins.
 * @returns {Number}
 */

Coins.prototype.count = function count(index) {
  var total = 0;
  var i;

  for (i = 0; i < this.outputs.length; i++) {
    if (this.outputs[i])
      total++;
  }

  return total;
};

/**
 * Remove a coin and return it.
 * @param {Number} index
 * @returns {Coin}
 */

Coins.prototype.spend = function spend(index) {
  var coin = this.get(index);
  this.outputs[index] = null;
  return coin;
};

/**
 * Serialize the coins object.
 * @param {TX|Coins} tx
 * @returns {Buffer}
 */

Coins.prototype.toRaw = function toRaw(writer) {
  var p = new BufferWriter(writer);
  var height = this.height;
  var i, output, prefix, hash, coinbase, mask;

  if (height === -1)
    height = 0x7fffffff;

  coinbase = this.coinbase;

  mask = (height << 1) | (coinbase ? 1 : 0);

  p.writeVarint(this.version);
  p.writeU32(mask >>> 0);

  for (i = 0; i < this.outputs.length; i++) {
    output = this.outputs[i];

    if (!output) {
      p.writeU8(0xff);
      continue;
    }

    if (output instanceof DeferredCoin) {
      p.writeBytes(output.toRaw());
      continue;
    }

    prefix = 0;

    // Saves up to 7 bytes.
    if (isPubkeyhash(output.script)) {
      prefix = 1;
      hash = output.script.code[2];
    } else if (isScripthash(output.script)) {
      prefix = 2;
      hash = output.script.code[1];
    }

    p.writeU8(prefix);

    if (prefix)
      p.writeBytes(hash);
    else
      bcoin.protocol.framer.script(output.script, p);

    p.writeVarint(output.value);
  }

  if (!writer)
    p = p.render();

  return p;
};

/**
 * Parse serialized coins.
 * @param {Buffer} data
 * @param {Hash} hash
 * @returns {Object} A "naked" coins object.
 */

Coins.parseRaw = function parseRaw(data, hash, index) {
  var p = new BufferReader(data);
  var i = 0;
  var version, height, coin, coins, mask, prefix, offset, size;

  version = p.readVarint();
  height = p.readU32();

  coins = {
    version: version,
    height: height >>> 1,
    hash: hash,
    coinbase: (height & 1) !== 0,
    outputs: []
  };

  if (coins.height === 0x7fffffff)
    coins.height = -1;

  while (p.left()) {
    offset = p.start();
    mask = p.readU8();

    if (mask === 0xff) {
      if (index != null) {
        if (i === index)
          return;
        i++;
        continue;
      }
      coins.outputs.push(null);
      i++;
      continue;
    }

    prefix = mask & 3;

    if (prefix === 0)
      p.seek(p.readVarint());
    else if (prefix <= 2)
      p.seek(20);
    else
      assert(false, 'Bad prefix.');

    p.readVarint();

    size = p.end();

    if (index != null && i !== index) {
      i++;
      continue;
    }

    coin = new DeferredCoin(offset, size, data);

    if (index != null)
      return coin.toCoin(coins, i);

    coins.outputs.push(coin);

    i++;
  }

  assert(index == null, 'Bad coin index.');

  return coins;
};

/**
 * Parse a single serialized coin.
 * @param {Buffer} data
 * @param {Hash} hash
 * @param {Number} index
 * @returns {Coin}
 */

Coins.parseCoin = function parseCoin(data, hash, index) {
  assert(index != null, 'Bad coin index.');
  return Coins.parseRaw(data, hash, index);
};

/**
 * Instantiate coins from a serialized Buffer.
 * @param {Buffer} data
 * @param {Hash} hash - Transaction hash.
 * @returns {Coins}
 */

Coins.fromRaw = function fromRaw(data, hash) {
  return new Coins(Coins.parseRaw(data, hash));
};

/**
 * Instantiate a coins object from a transaction.
 * @param {TX} tx
 * @returns {Coins}
 */

Coins.fromTX = function fromTX(tx) {
  var outputs = [];
  var i;

  for (i = 0; i < tx.outputs.length; i++) {
    if (tx.outputs[i].script.isUnspendable()) {
      outputs.push(null);
      continue;
    }
    outputs.push(bcoin.coin.fromTX(tx, i));
  }

  return new Coins({
    version: tx.version,
    hash: tx.hash('hex'),
    height: tx.height,
    coinbase: tx.isCoinbase(),
    outputs: outputs
  });
};

/**
 * A "deferred" coin is an object which defers
 * parsing of a compressed coin. Say there is
 * a transaction with 100 outputs. When block
 * comes in, there may only be _one_ input in
 * that entire block which redeems an output
 * from that transaction. When parsing the
 * Coins, there is no sense to get _all_ of
 * them into their abstract form. A "deferred"
 * coin is just a pointer to that coin in the
 * Coins buffer, as well as a size. Parsing
 * is done only if that coin is being redeemed.
 * @exposes DeferredCoin
 * @constructor
 * @private
 * @param {Number} offset
 * @param {Number} size
 * @param {Buffer} raw
 */

function DeferredCoin(offset, size, raw) {
  if (!(this instanceof DeferredCoin))
    return new DeferredCoin(offset, size, raw);

  this.offset = offset;
  this.size = size;
  this.raw = raw;
}

/**
 * Parse the deferred data and return a Coin.
 * @param {Coins} coins
 * @param {Number} index
 * @returns {Coin}
 */

DeferredCoin.prototype.toCoin = function toCoin(coins, index) {
  var p = new BufferReader(this.raw);
  var prefix, script, value;

  p.seek(this.offset);

  prefix = p.readU8() & 3;

  if (prefix === 0)
    script = new bcoin.script(bcoin.protocol.parser.parseScript(p));
  else if (prefix === 1)
    script = bcoin.script.createPubkeyhash(p.readBytes(20));
  else if (prefix === 2)
    script = bcoin.script.createScripthash(p.readBytes(20));
  else
    assert(false, 'Bad prefix.');

  value = p.readVarint();

  return new bcoin.coin({
    version: coins.version,
    coinbase: coins.coinbase,
    height: coins.height,
    hash: coins.hash,
    index: index,
    script: script,
    value: value
  });
};

/**
 * Slice off the part of the buffer
 * relevant to this particular coin.
 * @returns {Buffer}
 */

DeferredCoin.prototype.toRaw = function toRaw() {
  return this.raw.slice(this.offset, this.offset + this.size);
};

/*
 * Helpers
 */

function isPubkeyhash(script) {
  return script.isPubkeyhash() && bcoin.script.checkMinimal(script.code[2]);
}

function isScripthash(script) {
  return script.isScripthash() && bcoin.script.checkMinimal(script.code[1]);
}

/*
 * Expose
 */

module.exports = Coins;
<commit_msg>typos.<commit_after>/*!
 * coins.js - coins object for bcoin
 * Copyright (c) 2014-2015, Fedor Indutny (MIT License)
 * Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
 * https://github.com/bcoin-org/bcoin
 */

var bcoin = require('./env');
var utils = bcoin.utils;
var assert = utils.assert;
var BufferReader = require('./reader');
var BufferWriter = require('./writer');

/**
 * Represents the outputs for a single transaction.
 * @exports Coins
 * @constructor
 * @param {TX|Object} tx/options - TX or options object.
 * @property {Hash} hash - Transaction hash.
 * @property {Number} version - Transaction version.
 * @property {Number} height - Transaction height (-1 if unconfirmed).
 * @property {Boolean} coinbase - Whether the containing
 * transaction is a coinbase.
 * @property {Coin[]} outputs - Coins.
 */

function Coins(options) {
  if (!(this instanceof Coins))
    return new Coins(options);

  if (!options)
    options = {};

  this.version = options.version != null ? options.version : -1;
  this.hash = options.hash || null;
  this.height = options.height != null ? options.height : -1;
  this.coinbase = options.coinbase || false;
  this.outputs = options.outputs || [];
}

/**
 * Add a single coin to the collection.
 * @param {Coin} coin
 */

Coins.prototype.add = function add(coin) {
  if (this.version === -1) {
    this.version = coin.version;
    this.hash = coin.hash;
    this.height = coin.height;
    this.coinbase = coin.coinbase;
  }

  if (coin.script.isUnspendable()) {
    this.outputs[coin.index] = null;
    return;
  }

  this.outputs[coin.index] = coin;
};

/**
 * Test whether the collection has a coin.
 * @param {Number} index
 * @returns {Boolean}
 */

Coins.prototype.has = function has(index) {
  return this.outputs[index] != null;
};

/**
 * Get a coin.
 * @param {Number} index
 * @returns {Coin}
 */

Coins.prototype.get = function get(index) {
  var coin = this.outputs[index];
  if (!coin)
    return;

  if (coin instanceof DeferredCoin)
    coin = coin.toCoin(this, index);

  return coin;
};

/**
 * Count unspent coins.
 * @returns {Number}
 */

Coins.prototype.count = function count(index) {
  var total = 0;
  var i;

  for (i = 0; i < this.outputs.length; i++) {
    if (this.outputs[i])
      total++;
  }

  return total;
};

/**
 * Remove a coin and return it.
 * @param {Number} index
 * @returns {Coin}
 */

Coins.prototype.spend = function spend(index) {
  var coin = this.get(index);
  this.outputs[index] = null;
  return coin;
};

/**
 * Serialize the coins object.
 * @param {TX|Coins} tx
 * @returns {Buffer}
 */

Coins.prototype.toRaw = function toRaw(writer) {
  var p = new BufferWriter(writer);
  var height = this.height;
  var i, output, prefix, hash, coinbase, mask;

  if (height === -1)
    height = 0x7fffffff;

  coinbase = this.coinbase;

  mask = (height << 1) | (coinbase ? 1 : 0);

  p.writeVarint(this.version);
  p.writeU32(mask >>> 0);

  for (i = 0; i < this.outputs.length; i++) {
    output = this.outputs[i];

    if (!output) {
      p.writeU8(0xff);
      continue;
    }

    if (output instanceof DeferredCoin) {
      p.writeBytes(output.toRaw());
      continue;
    }

    prefix = 0;

    // Saves up to 7 bytes.
    if (isPubkeyhash(output.script)) {
      prefix = 1;
      hash = output.script.code[2];
    } else if (isScripthash(output.script)) {
      prefix = 2;
      hash = output.script.code[1];
    }

    p.writeU8(prefix);

    if (prefix)
      p.writeBytes(hash);
    else
      bcoin.protocol.framer.script(output.script, p);

    p.writeVarint(output.value);
  }

  if (!writer)
    p = p.render();

  return p;
};

/**
 * Parse serialized coins.
 * @param {Buffer} data
 * @param {Hash} hash
 * @returns {Object} A "naked" coins object.
 */

Coins.parseRaw = function parseRaw(data, hash, index) {
  var p = new BufferReader(data);
  var i = 0;
  var version, height, coin, coins, mask, prefix, offset, size;

  version = p.readVarint();
  height = p.readU32();

  coins = {
    version: version,
    height: height >>> 1,
    hash: hash,
    coinbase: (height & 1) !== 0,
    outputs: []
  };

  if (coins.height === 0x7fffffff)
    coins.height = -1;

  while (p.left()) {
    offset = p.start();
    mask = p.readU8();

    if (mask === 0xff) {
      if (index != null) {
        if (i === index)
          return;
        i++;
        continue;
      }
      coins.outputs.push(null);
      i++;
      continue;
    }

    prefix = mask & 3;

    if (prefix === 0)
      p.seek(p.readVarint());
    else if (prefix <= 2)
      p.seek(20);
    else
      assert(false, 'Bad prefix.');

    p.readVarint();

    size = p.end();

    if (index != null && i !== index) {
      i++;
      continue;
    }

    coin = new DeferredCoin(offset, size, data);

    if (index != null)
      return coin.toCoin(coins, i);

    coins.outputs.push(coin);

    i++;
  }

  assert(index == null, 'Bad coin index.');

  return coins;
};

/**
 * Parse a single serialized coin.
 * @param {Buffer} data
 * @param {Hash} hash
 * @param {Number} index
 * @returns {Coin}
 */

Coins.parseCoin = function parseCoin(data, hash, index) {
  assert(index != null, 'Bad coin index.');
  return Coins.parseRaw(data, hash, index);
};

/**
 * Instantiate coins from a serialized Buffer.
 * @param {Buffer} data
 * @param {Hash} hash - Transaction hash.
 * @returns {Coins}
 */

Coins.fromRaw = function fromRaw(data, hash) {
  return new Coins(Coins.parseRaw(data, hash));
};

/**
 * Instantiate a coins object from a transaction.
 * @param {TX} tx
 * @returns {Coins}
 */

Coins.fromTX = function fromTX(tx) {
  var outputs = [];
  var i;

  for (i = 0; i < tx.outputs.length; i++) {
    if (tx.outputs[i].script.isUnspendable()) {
      outputs.push(null);
      continue;
    }
    outputs.push(bcoin.coin.fromTX(tx, i));
  }

  return new Coins({
    version: tx.version,
    hash: tx.hash('hex'),
    height: tx.height,
    coinbase: tx.isCoinbase(),
    outputs: outputs
  });
};

/**
 * A "deferred" coin is an object which defers
 * parsing of a compressed coin. Say there is
 * a transaction with 100 outputs. When a block
 * comes in, there may only be _one_ input in
 * that entire block which redeems an output
 * from that transaction. When parsing the
 * Coins, there is no sense to get _all_ of
 * them into their abstract form. A deferred
 * coin is just a pointer to that coin in the
 * Coins buffer, as well as a size. Parsing
 * is done only if that coin is being redeemed.
 * @exports DeferredCoin
 * @constructor
 * @private
 * @param {Number} offset
 * @param {Number} size
 * @param {Buffer} raw
 */

function DeferredCoin(offset, size, raw) {
  if (!(this instanceof DeferredCoin))
    return new DeferredCoin(offset, size, raw);

  this.offset = offset;
  this.size = size;
  this.raw = raw;
}

/**
 * Parse the deferred data and return a Coin.
 * @param {Coins} coins
 * @param {Number} index
 * @returns {Coin}
 */

DeferredCoin.prototype.toCoin = function toCoin(coins, index) {
  var p = new BufferReader(this.raw);
  var prefix, script, value;

  p.seek(this.offset);

  prefix = p.readU8() & 3;

  if (prefix === 0)
    script = new bcoin.script(bcoin.protocol.parser.parseScript(p));
  else if (prefix === 1)
    script = bcoin.script.createPubkeyhash(p.readBytes(20));
  else if (prefix === 2)
    script = bcoin.script.createScripthash(p.readBytes(20));
  else
    assert(false, 'Bad prefix.');

  value = p.readVarint();

  return new bcoin.coin({
    version: coins.version,
    coinbase: coins.coinbase,
    height: coins.height,
    hash: coins.hash,
    index: index,
    script: script,
    value: value
  });
};

/**
 * Slice off the part of the buffer
 * relevant to this particular coin.
 * @returns {Buffer}
 */

DeferredCoin.prototype.toRaw = function toRaw() {
  return this.raw.slice(this.offset, this.offset + this.size);
};

/*
 * Helpers
 */

function isPubkeyhash(script) {
  return script.isPubkeyhash() && bcoin.script.checkMinimal(script.code[2]);
}

function isScripthash(script) {
  return script.isScripthash() && bcoin.script.checkMinimal(script.code[1]);
}

/*
 * Expose
 */

module.exports = Coins;
<|endoftext|>


<commit_before>'use strict';

/**
* the well-known version vector that characterizes causality between
* updates
* @param {string} id the entry chosen by the local site (1 entry <-> 1 site)
*/
function VV (id) {
  this._e = id;
  this._v = {};
  this._v[this._e] = 0;
}

/**
* Return the clock representing this id
* @return {object} {_e:id, _c:[0;N] } The clock
*/
VV.prototype.ec = function () {
  return {_e:this._e, _c:this._v[this._e]};
};

/**
* Return a new VV from the object structure provided
* @param {object} o The new structure
* @return {VV} The new structure provided
*/
VV.prototype.from = function (o) {
  if(o._e && o._v) {
    let res = new VV(o._e);
    res._v = o._v;
    return res;
  } else {
    throw new Error('The new structure need to be conformed to: {_e: \'your-id\', _v: {} }');
  }
};

/**
* Clone the current structure
* @return {VV} The new structure provided
*/
VV.prototype.clone = function () {
  return this.from(this);
};

/**
* Increment the entry of the vector on local update
* @return {object} {_e: entry, _c: counter} uniquely identifying the operation
*/
VV.prototype.increment = function () {
  if (!(this._e in this._v)) {
    this._v[this._e] = 0;
  }
  this._v[this._e] += 1;
  return {_e: this._e, _c: this._v[this._e]};
};
/**
* Increment the version vector with the incoming pair representing the
* operation
* @param {object} ec the entry clock of the received operation supposedly ready
*/
VV.prototype.incrementFrom = function (ec) {
  this._v[ec._e] = ec._c; // if ready, it means + 1 on the entry
};

/**
* Check if the target ec is strictly lower than the local one. Probably
* meaning that the information linked to it has already been delivered
* @param {object} ec the entry and counter which identifies an operation
*/
VV.prototype.isLower = function (ec) {
  init(this._v, ec._e);
  return ((ec._e in this._v) && (ec._c <= this._v[ec._e]));
};

function init (a, k) {
  if(k && a && !a[k]) a[k] = 0;
}

/**
* Check if the target VV is causally ready
* @param {VV} vv the version vector to check
*/
VV.prototype.isReady = function (vv) {
  let ready = true;
  // #1 verify that all entry of this._v exists in vv
  let keys = Object.keys(this._v);
  let i = 0;
  while (ready && i<keys.length) {
    if (!(keys[i] in vv._v) || (this._v[keys[i]] > vv._v[keys[i]])) {
      ready = false;
    }
    ++i;
  }

  // #2 verify that all entry of vv._v exists in this._v
  keys = Object.keys(vv._v);
  i = 0;
  while (ready && i<keys.length) {
    if ((keys[i] !== vv._e) && (!(keys[i] in this._v) || (this._v[keys[i]] > vv._v[keys[i]]))) {
      ready = false;
    }
    ++i;
  }

  return (ready && ((vv._v[vv._e]===1) || ((vv._e in this._v) && (vv._v[vv._e] === (this._v[vv._e] +1) ))));
};

/**
* Merge the VV provided with our VV
* @return {VV} Return the new merge structure
*/
VV.prototype.merge = function (other) {
  let res = new VV(this._e);
  res._v = this._v;
  if(this._v && this._v && other._e && other._e) {
    Object.keys(other._v).forEach(k => {
      res._v[k] = Math.max(this._v[k]||0, other._v[k]||0);
    });
    return res;
  } else {
    throw new Error('It is not the right structure.');
  }
};

/**
* Merge the VV provided with our VV
* IMPORTANT: Supposed typeof _e === string
* @return {VV|object} Return the new merge structure
*/
VV.prototype.equals = function (vv) {
  if(typeof vv === typeof VV || vv._e && vv._v) {
    let ourKeys = Object.keys(this._v);
    let vvKeys = Object.keys(vv._v);
    // If the length is different or ids are different
    if (ourKeys.length !== vvKeys.length || this._e === vv._e) {
      return false;
    }

    ourKeys.forEach(k => {
      if(!(k in vvKeys) || this._v[k] !== vvKeys[k]) return false;
    });
    vvKeys.forEach(k => {
      if(!(k in ourKeys) || this._v[k] !== vvKeys[k]) return false;
    });

    return true;
  } else {
    throw new Error('Not a VV or an object with the same values');
  }
};

module.exports = VV;
<commit_msg>move vv to es6 class yntax<commit_after>'use strict';

function init (a, k) {
  if(k && a && !a[k]) a[k] = 0;
}

/**
* The well-known Version Vector (VV) that characterizes causality between
* updates
*/
class VersionVector {
  /**
   * Constructor
   * @param {string} id the entry chosen by the local site (1 entry <-> 1 site)
   */
  constructor (id) {
    this._e = id;
    this._v = {};
    this._v[this._e] = 0;
  }

  /**
  * Return the clock representing this id
  * @return {object} {_e:id, _c:[0;N] } The clock
  */
  ec () {
    return {_e:this._e, _c:this._v[this._e]};
  }

  /**
  * Return a new VV from the object structure provided
  * @param {object} o The new structure
  * @return {VV} The new structure provided
  */
  from (o) {
    if(o._e && o._v) {
      let res = new VersionVector(o._e);
      res._v = o._v;
      return res;
    } else {
      throw new Error('The new structure need to be conformed to: {_e: \'your-id\', _v: {} }');
    }
  }

  /**
  * Clone the current structure
  * @return {VV} The new structure provided
  */
  clone () {
    return this.from(this);
  }

  /**
  * Increment the entry of the vector on local update
  * @return {object} {_e: entry, _c: counter} uniquely identifying the operation
  */
  increment () {
    if (!(this._e in this._v)) {
      this._v[this._e] = 0;
    }
    this._v[this._e] += 1;
    return {_e: this._e, _c: this._v[this._e]};
  }

  /**
  * Increment the version vector with the incoming pair representing the
  * operation
  * @param {object} ec the entry clock of the received operation supposedly ready
  */
  incrementFrom (ec) {
    this._v[ec._e] = ec._c; // if ready, it means + 1 on the entry
  }

  /**
  * Check if the target ec is strictly lower than the local one. Probably
  * meaning that the information linked to it has already been delivered
  * @param {object} ec the entry and counter which identifies an operation
  */
  isLower (ec) {
    init(this._v, ec._e);
    return ((ec._e in this._v) && (ec._c <= this._v[ec._e]));
  }

  /**
  * Check if the target VV is causally ready
  * @param {VV} vv the version vector to check
  */
  isReady (vv) {
    let ready = true;
    // #1 verify that all entry of this._v exists in vv
    let keys = Object.keys(this._v);
    let i = 0;
    while (ready && i<keys.length) {
      if (!(keys[i] in vv._v) || (this._v[keys[i]] > vv._v[keys[i]])) {
        ready = false;
      }
      ++i;
    }

    // #2 verify that all entry of vv._v exists in this._v
    keys = Object.keys(vv._v);
    i = 0;
    while (ready && i<keys.length) {
      if ((keys[i] !== vv._e) && (!(keys[i] in this._v) || (this._v[keys[i]] > vv._v[keys[i]]))) {
        ready = false;
      }
      ++i;
    }

    return (ready && ((vv._v[vv._e]===1) || ((vv._e in this._v) && (vv._v[vv._e] === (this._v[vv._e] +1) ))));
  }

  /**
  * Merge the VV provided with our VV
  * @return {VV} Return the new merge structure
  */
  merge (other) {
    let res = new VersionVector(this._e);
    res._v = this._v;
    if(this._v && this._v && other._e && other._e) {
      Object.keys(other._v).forEach(k => {
        res._v[k] = Math.max(this._v[k]||0, other._v[k]||0);
      });
      return res;
    } else {
      throw new Error('It is not the right structure.');
    }
  }

  /**
  * Merge the VV provided with our VV
  * **IMPORTANT:** Supposed typeof _e === string
  * @return {VV|object} Return the new merge structure
  */
  equals (vv) {
    if(typeof vv === typeof VersionVector || vv._e && vv._v) {
      let ourKeys = Object.keys(this._v);
      let vvKeys = Object.keys(vv._v);
      // If the length is different or ids are different
      if (ourKeys.length !== vvKeys.length || this._e === vv._e) {
        return false;
      }

      ourKeys.forEach(k => {
        if(!(k in vvKeys) || this._v[k] !== vvKeys[k]) return false;
      });
      vvKeys.forEach(k => {
        if(!(k in ourKeys) || this._v[k] !== vvKeys[k]) return false;
      });

      return true;
    } else {
      throw new Error('Not a VV or an object with the same values');
    }
  }
}

module.exports = VersionVector;
<|endoftext|>


<commit_before>/**
 * Projects List
 */

Router.route('/projects', {
    name: 'projects',
    template: 'projects',
    subscriptions: function() {
        this.subscribe('projects');
        this.subscribe('settings');
    }
});

/**
 * Project
 */

Router.route('/project/:_id', {
    name: 'project.show',
    path: '/project/:_id',
    template: 'projectPage',

    // a place to put your subscriptions
    subscriptions: function() {
       this.subscribe('memberships');

        // add the subscription to the waitlist
       //this.subscribe('project', this.params._id).wait();
    },
    data: function() {
        return Projects.findOne(this.params._id);
    }
});<commit_msg>projectMembers route<commit_after>/**
 * Projects List
 */

Router.route('/projects', {
    name: 'projects',
    template: 'projects',
    subscriptions: function() {
        this.subscribe('projects');
        this.subscribe('settings');
    }
});

/**
 * Project
 */

Router.route('/projects/:_id', {
    name: 'project.show',
    path: '/projects/:_id',
    template: 'projectPage',

    // a place to put your subscriptions
    subscriptions: function() {
       this.subscribe('memberships');

        // add the subscription to the waitlist
       //this.subscribe('project', this.params._id).wait();
    },
    data: function() {
        return Projects.findOne(this.params._id);
    }
});

/**
 * Projectmembers
 */

Router.route('/projects/:_id/members', {
    name: 'project.members',
    path: '/projects/:_id/members',
    template: 'projectMembers',

    // a place to put your subscriptions
    subscriptions: function() {
        this.subscribe('memberships');

        // add the subscription to the waitlist
        //this.subscribe('project', this.params._id).wait();
    },
    data: function() {
        return {
            project: Projects.findOne(this.params._id),
            _id: this.params._id
        }
    }
});<|endoftext|>


<commit_before>const sListenersMap = Symbol("listenersMap");
const sInsertOn = Symbol("insertOn");

export default
class EventEmitter {
  constructor() {
    this[sListenersMap] = {};
  }

  on(event, action) {
    return this[sInsertOn](0, event, action);
  }

  prependOn(event, action) {
    return this[sInsertOn](0, event, action);
  }

  listeners(event) {
    return this[sListenersMap][event];
  }

  emit(event, ...args) {
    this[sListenersMap][event].forEach(l => l(...args));
  }

  [sInsertOn](index, event, action) {
    const map = this[sListenersMap];
    const listeners = (map[event] = map[event] || []);
    listeners.splice(index, 0, action);

    const dispose = () => {
      const i = listeners.indexOf(action);
      if (i >= 0) {
        listeners.splice(i, 1);
      }
    };
    return {dispose};
  }
}
<commit_msg>Fix EventEmitter<commit_after>const sListenersMap = Symbol("listenersMap");
const sInsertOn = Symbol("insertOn");

export default
class EventEmitter {
  constructor() {
    this[sListenersMap] = {};
  }

  on(event, action) {
    const map = this[sListenersMap];
    const listeners = (map[event] = map[event] || []);
    listeners.push(action);

    const dispose = () => {
      const i = listeners.indexOf(action);
      if (i >= 0) {
        listeners.splice(i, 1);
      }
    };
    return {dispose};
  }

  prependOn(event, action) {
    const map = this[sListenersMap];
    const listeners = (map[event] = map[event] || []);
    listeners.shift(action);

    const dispose = () => {
      const i = listeners.indexOf(action);
      if (i >= 0) {
        listeners.splice(i, 1);
      }
    };
    return {dispose};
  }

  listeners(event) {
    return this[sListenersMap][event] || [];
  }

  emit(event, ...args) {
    this[sListenersMap][event].forEach(l => l(...args));
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
var liveServer = require("./index");

var port = process.env.PORT;

process.argv.forEach(function(v,idx) {
	if (v.indexOf("--port=") >- 1) {
		var portString = v.substring(7);
        var portNumber = parseInt(portString, 10);
		if (portNumber == portString) {
			port = portNumber;
    		process.argv.splice(idx,1);
    	}
	}
});

if (process.argv[2])
	process.chdir(process.argv[2]);

liveServer.start(port);
<commit_msg>Fix whitespace.<commit_after>#!/usr/bin/env node
var liveServer = require("./index");

var port = process.env.PORT;

process.argv.forEach(function(v, idx) {
	if (v.indexOf("--port=") >- 1) {
		var portString = v.substring(7);
		var portNumber = parseInt(portString, 10);
		if (portNumber == portString) {
			port = portNumber;
			process.argv.splice(idx, 1);
		}
	}
});

if (process.argv[2])
	process.chdir(process.argv[2]);

liveServer.start(port);
<|endoftext|>


<commit_before>'use strict';

var util = require('util');
var utils = require('./utils.js');

/**
 * Polyfill a method
 * @param obj object e.g. `document`
 * @param name method name present on object e.g. `addEventListener`
 * @param replacement replacement function
 * @param track {optional} record instrumentation to an array
 */
function fill(obj, name, replacement, track) {
  var orig = obj[name];
  obj[name] = replacement(orig);
  if (track) {
    track.push([obj, name, orig]);
  }
}

var originals = [];

var wrappers = {
  console: function (Raven) {
    var wrapConsoleMethod = function (level) {
      if (!(level in console)) {
        return;
      }

      fill(console, level, function (originalConsoleLevel) {
        var sentryLevel = level === 'warn'
            ? 'warning'
            : level;

        return function () {
          var args = [].slice.call(arguments);

          var msg = '' + args.join(' ');
          var data = {
            level: sentryLevel,
            logger: 'console',
            extra: {
              'arguments': args
            }
          };

          Raven.captureBreadcrumb({
            message: msg,
            level: data.level,
            category: 'console'
          });

          originalConsoleLevel.apply(console, args);
        };
      }, originals);
    };

    ['debug', 'info', 'warn', 'error', 'log'].forEach(wrapConsoleMethod);
  },

  http: function (Raven) {
    var http = require('http');
    var OrigClientRequest = http.ClientRequest;
    var ClientRequest = function (options, cb) {
      // Note: this won't capture a breadcrumb if a response never comes
      // It would be useful to know if that was the case, though, so
      // todo: revisit to see if we can capture sth indicating response never came
      // possibility: capture one breadcrumb for "req sent" and one for "res recvd"
      // seems excessive but solves the problem and *is* strictly more information
      // could be useful for weird response sequencing bug scenarios
      var self = this;
      OrigClientRequest.call(self, options, cb);

      // We could just always grab these from self.agent, self.method, self._headers, self.path, etc
      // but certain other http-instrumenting libraries (like nock, which we use for tests) fail to
      // maintain the guarantee that after calling OrigClientRequest, those fields will be populated
      var url, method;
      if (typeof options === 'string') {
        url = options;
        method = 'GET';
      } else {
        url = (options.protocol || '') + '//' +
              (options.hostname || options.host || '') +
              (options.path || '/');
        method = options.method || 'GET';
      }

      // Don't capture breadcrumb for our own requests
      if (!Raven.dsn || url.indexOf(Raven.dsn.host) === -1) {
        self.once('response', function (response) {
          Raven.captureBreadcrumb({
            type: 'http',
            category: 'http',
            data: {
              method: method,
              url: url,
              status_code: response.statusCode
            }
          });

          // No-op to consume response data since we added a response handler
          // see https://nodejs.org/api/http.html#http_class_http_clientrequest
          response.on('data', function () {});
        });
      }
    };
    util.inherits(ClientRequest, OrigClientRequest);
    fill(http, 'ClientRequest', function () {
      return ClientRequest;
    }, originals);

    // http.request orig refs module-internal ClientRequest, not exported one, so
    // it still points at orig ClientRequest after our monkeypatch; these reimpls
    // just get that reference updated to use our new ClientRequest
    fill(http, 'request', function () {
      return function (options, cb) {
        return new http.ClientRequest(options, cb);
      };
    }, originals);

    fill(http, 'get', function () {
      return function (options, cb) {
        var req = http.request(options, cb);
        req.end();
        return req;
      };
    }, originals);
  },

  pg: function (Raven) {
    // Using fill helper here is hard because of `this` binding
    var pg = require('pg');
    var origQuery = pg.Connection.prototype.query;
    pg.Connection.prototype.query = function (text) {
      Raven.captureBreadcrumb({
        category: 'postgres',
        message: text
      });
      origQuery.call(this, text);
    };
    originals.push([pg.Connection.prototype, 'query', origQuery]);
  }
};

function instrument(key, Raven) {
  try {
    wrappers[key](Raven);
    utils.consoleAlert('Enabled automatic breadcrumbs for ' + key);
  } catch (e) {
    // associated module not available
  }
}

function restoreOriginals() {
  var original;
  // eslint-disable-next-line no-cond-assign
  while (original = originals.shift()) {
    var obj = original[0];
    var name = original[1];
    var orig = original[2];
    obj[name] = orig;
  }
}

module.exports = {
  instrument: instrument,
  restoreOriginals: restoreOriginals
};
<commit_msg>Change http breadcrumb instrumentation to use emit monkeypatch instead of response listener<commit_after>'use strict';

var util = require('util');
var utils = require('./utils.js');

/**
 * Polyfill a method
 * @param obj object e.g. `document`
 * @param name method name present on object e.g. `addEventListener`
 * @param replacement replacement function
 * @param track {optional} record instrumentation to an array
 */
function fill(obj, name, replacement, track) {
  var orig = obj[name];
  obj[name] = replacement(orig);
  if (track) {
    track.push([obj, name, orig]);
  }
}

var originals = [];

var wrappers = {
  console: function (Raven) {
    var wrapConsoleMethod = function (level) {
      if (!(level in console)) {
        return;
      }

      fill(console, level, function (originalConsoleLevel) {
        var sentryLevel = level === 'warn'
            ? 'warning'
            : level;

        return function () {
          var args = [].slice.call(arguments);

          var msg = '' + args.join(' ');
          var data = {
            level: sentryLevel,
            logger: 'console',
            extra: {
              'arguments': args
            }
          };

          Raven.captureBreadcrumb({
            message: msg,
            level: data.level,
            category: 'console'
          });

          originalConsoleLevel.apply(console, args);
        };
      }, originals);
    };

    ['debug', 'info', 'warn', 'error', 'log'].forEach(wrapConsoleMethod);
  },

  http: function (Raven) {
    var http = require('http');
    var OrigClientRequest = http.ClientRequest;
    var ClientRequest = function (options, cb) {
      // Note: this won't capture a breadcrumb if a response never comes
      // It would be useful to know if that was the case, though, so
      // todo: revisit to see if we can capture sth indicating response never came
      // possibility: capture one breadcrumb for "req sent" and one for "res recvd"
      // seems excessive but solves the problem and *is* strictly more information
      // could be useful for weird response sequencing bug scenarios
      var self = this;
      OrigClientRequest.call(self, options, cb);

      // We could just always grab these from self.agent, self.method, self._headers, self.path, etc
      // but certain other http-instrumenting libraries (like nock, which we use for tests) fail to
      // maintain the guarantee that after calling OrigClientRequest, those fields will be populated
      var url, method;
      if (typeof options === 'string') {
        url = options;
        method = 'GET';
      } else {
        url = (options.protocol || '') + '//' +
              (options.hostname || options.host || '') +
              (options.path || '/');
        method = options.method || 'GET';
      }

      // Don't capture breadcrumb for our own requests
      if (!Raven.dsn || url.indexOf(Raven.dsn.host) === -1) {
        fill(self, 'emit', function (origEmit) {
          return function (evt, maybeResp) {
            if (evt === 'response') {
              Raven.captureBreadcrumb({
                type: 'http',
                category: 'http',
                data: {
                  method: method,
                  url: url,
                  status_code: maybeResp.statusCode
                }
              });
            }
            return origEmit.apply(this, arguments);
          };
        }, originals);
      }
    };
    util.inherits(ClientRequest, OrigClientRequest);
    fill(http, 'ClientRequest', function () {
      return ClientRequest;
    }, originals);

    // http.request orig refs module-internal ClientRequest, not exported one, so
    // it still points at orig ClientRequest after our monkeypatch; these reimpls
    // just get that reference updated to use our new ClientRequest
    fill(http, 'request', function () {
      return function (options, cb) {
        return new http.ClientRequest(options, cb);
      };
    }, originals);

    fill(http, 'get', function () {
      return function (options, cb) {
        var req = http.request(options, cb);
        req.end();
        return req;
      };
    }, originals);
  },

  pg: function (Raven) {
    // Using fill helper here is hard because of `this` binding
    var pg = require('pg');
    var origQuery = pg.Connection.prototype.query;
    pg.Connection.prototype.query = function (text) {
      Raven.captureBreadcrumb({
        category: 'postgres',
        message: text
      });
      origQuery.call(this, text);
    };
    originals.push([pg.Connection.prototype, 'query', origQuery]);
  }
};

function instrument(key, Raven) {
  try {
    wrappers[key](Raven);
    utils.consoleAlert('Enabled automatic breadcrumbs for ' + key);
  } catch (e) {
    // associated module not available
  }
}

function restoreOriginals() {
  var original;
  // eslint-disable-next-line no-cond-assign
  while (original = originals.shift()) {
    var obj = original[0];
    var name = original[1];
    var orig = original[2];
    obj[name] = orig;
  }
}

module.exports = {
  instrument: instrument,
  restoreOriginals: restoreOriginals
};
<|endoftext|>


<commit_before>
var fs = require('fs');
var path = require('path');
var Flow = require('./misc/flow');

var moduleOptions = require('./options');
var command = moduleOptions.command;

require('./misc/utils'); // TODO: make it explicit

//
// export
//

exports.build = build;
exports.options = moduleOptions;
exports.command = function(args, config){
  return command(args, config, build);
};

//
// if launched directly, run builder
//
if (process.mainModule === module)
  command(null, null, build);

//
// main function
//

function build(options){

  //
  // init
  //

  options = moduleOptions.norm(options);

  var flow = new Flow(options);
  var fconsole = flow.console;

  flow.outputResourceDir = 'res/';

  // temporary here
  flow.tmpl = {
    themes: {},
    themeResources: {}
  };
  flow.l10n = {
    cultureList: [],  // TODO: fetch culture list from basis.l10n
    defList: [],
    getTokenList: [],
    pathes: {}
  };

  fconsole.start('Build settings');
  fconsole.log('Base:', options.base);
  fconsole.log('Input file:', options.file);
  fconsole.log('Output path:', options.output);
  fconsole.endl();

  //
  // preprocessing
  //

  fconsole.start('Preprocessors');
  for (var type in options.preprocess)
  {
    var list = options.preprocess[type];
    var newList = flow.files.preprocess[type] = [];
    var hasPrerocessor = false;

    for (var i = 0; i < list.length; i++)
    {
      var preprocessorPath = list[i];

      fconsole.log('[' + type + '] ' + preprocessorPath);

      try {
        var processor = require(preprocessorPath);

        if (typeof processor.process == 'function')
        {
          newList.push(processor.process);
          hasPrerocessor = true;
        }
        else
          fconsole.log('[ERROR] Preprocessor has no process function. Skipped.');
      } catch(e) {
        fconsole.log('[ERROR] Error on preprocessor load: ' + e);
      }

      fconsole.end();
    }
  }
  if (!hasPrerocessor)
    fconsole.log('  not defined');
  fconsole.endl();

  //
  // process input
  //
  var inputFilename = options.file;

  // check input file exists
  if (!fs.existsSync(inputFilename) || !fs.statSync(inputFilename).isFile())
  {
    console.warn('Input file ' + inputFilename + ' not found');
    process.exit();
  }

  fconsole.start('\nInit\n====\n');

  // add input file in queue
  flow.files.add({
    filename: inputFilename
  });

  //
  // Main part
  //

  var handlers = [
    // extract files
    require('./html/extract'),
    require('./js/extract'),
    require('./tmpl/extract'),
    require('./css/extract'),
    require('./res/extract'),
    require('./l10n/extract'),

    // input file graph
    options.target == 'file-map' ? require('./misc/makeFileMap') : false,
    options.target == 'input-graph' ? require('./misc/makeInputGraph') : false,

    // process css
    require('./css/optimizeNames'),
    require('./css/makePackages'),
    require('./css/linear'),
    require('./css/merge'),
    require('./css/pack'),
    require('./css/translate'),

    // process l10n
    require('./l10n/buildIndex'),
    require('./l10n/makePackages'),
    require('./l10n/pack'),
    require('./l10n/modifyCall'),

    // process tmpl
    require('./tmpl/translate'),
    require('./tmpl/pregenerate'),

    // css/html resources
    require('./res/translate'),
    require('./res/buildMap'),

    // process js
    require('./js/relink'),
    require('./js/merge'),
    require('./js/makePackages'),
    require('./js/resolvePathes'),
    require('./js/translate'),
    require('./js/json'),
    require('./js/buildPackages'),
    require('./js/pack'),
    require('./js/realignHtml'),

    // process html
    require('./html/translate'),

    // output file graph
    options.target == 'output-graph' ? require('./misc/makeOutputGraph') : false,

    // make a zip
    options.target == 'zip' ? require('./misc/makeZip') : false,

    // flush output
    require('./misc/writeFiles'),

    finalHandler
  ].filter(Boolean);

  var taskCount = 0;
  var timing = [];
  var time;

  function asyncTaskStart(){
    taskCount++;
  }
  function asyncTaskDone(){
    taskCount--;
    nextHandler();
  }

  function nextHandler(){
    if (!taskCount && handlers.length)
    {
      time.time = new Date - time.time;
      timing.push(time);

      fconsole.resetDeep();

      process.nextTick(runHandler);
    }
  }

  function runHandler(){
    var handler = handlers.shift();
    var title = handler.handlerName;

    if (title)
      fconsole.log('\n' + title + '\n' + ('='.repeat(title.length)) + '\n');

    fconsole.incDeep();

    time = {
      name: title,
      time: +new Date
    };
    handler(flow, asyncTaskStart, asyncTaskDone);

    nextHandler();
  }

  runHandler();

  //
  // show totals
  //
  function finalHandler(){
    // file types
    (function(){
      var fileTypeMap = {};
      var outputFileCount = 0;
      var outputSize = 0;
      flow.files.queue.forEach(function(file){
        var stat = fileTypeMap[file.type];

        if (!stat)
        {
          stat = fileTypeMap[file.type] = {
            queueFiles: [],
            outputFiles: [],
            outputSize: 0
          };
        }

        stat.queueFiles.push(file.filename);

        if (file.outputFilename && 'outputContent' in file)
        {
          outputFileCount++;
          outputSize += file.outputContent.length;
          stat.outputSize += file.outputContent.length;
          stat.outputFiles.push(file.outputFilename + ' ' + file.outputContent.length + ' bytes');
        }
      }, fileTypeMap);

      fconsole.start('File queue:');
      for (var key in fileTypeMap)
        fconsole.log(key + ': ' + fileTypeMap[key].queueFiles.length);
      fconsole.endl();

      fconsole.start('Output ' + outputFileCount + ' files in ' + outputSize + ' bytes:')
      for (var key in fileTypeMap)
      {
        var files = fileTypeMap[key].outputFiles;

        if (!files.length)
          continue;

        var header = key + ': ' + files.length + ', ' + fileTypeMap[key].outputSize + ' bytes';
        if (key == 'script' || key == 'style')
        {
          fconsole.start(header);
          fconsole.list(files);
          fconsole.end();
        }
        else
          fconsole.log(header);
      }
      fconsole.endl();

    })();

    // timing
    fconsole.start('Timing:');
    timing.forEach(function(t){
      var time = String(t.time || 0);
      fconsole.log(' '.repeat(6 - time.length) + time + '  ' + (t.name || '[No title step]'));
    });
    fconsole.endl();

    // total time
    fconsole.log('Build done in ' + (flow.time() / 1000).toFixed(3) + 's');
  }

  finalHandler.handlerName = 'Build stat';
}

<commit_msg>fix final file stat output<commit_after>
var fs = require('fs');
var path = require('path');
var Flow = require('./misc/flow');

var moduleOptions = require('./options');
var command = moduleOptions.command;

require('./misc/utils'); // TODO: make it explicit

//
// export
//

exports.build = build;
exports.options = moduleOptions;
exports.command = function(args, config){
  return command(args, config, build);
};

//
// if launched directly, run builder
//
if (process.mainModule === module)
  command(null, null, build);

//
// main function
//

function build(options){

  //
  // init
  //

  options = moduleOptions.norm(options);

  var flow = new Flow(options);
  var fconsole = flow.console;

  flow.outputResourceDir = 'res/';

  // temporary here
  flow.tmpl = {
    themes: {},
    themeResources: {}
  };
  flow.l10n = {
    cultureList: [],  // TODO: fetch culture list from basis.l10n
    defList: [],
    getTokenList: [],
    pathes: {}
  };

  fconsole.start('Build settings');
  fconsole.log('Base:', options.base);
  fconsole.log('Input file:', options.file);
  fconsole.log('Output path:', options.output);
  fconsole.endl();

  //
  // preprocessing
  //

  fconsole.start('Preprocessors');
  for (var type in options.preprocess)
  {
    var list = options.preprocess[type];
    var newList = flow.files.preprocess[type] = [];
    var hasPrerocessor = false;

    for (var i = 0; i < list.length; i++)
    {
      var preprocessorPath = list[i];

      fconsole.log('[' + type + '] ' + preprocessorPath);

      try {
        var processor = require(preprocessorPath);

        if (typeof processor.process == 'function')
        {
          newList.push(processor.process);
          hasPrerocessor = true;
        }
        else
          fconsole.log('[ERROR] Preprocessor has no process function. Skipped.');
      } catch(e) {
        fconsole.log('[ERROR] Error on preprocessor load: ' + e);
      }

      fconsole.end();
    }
  }
  if (!hasPrerocessor)
    fconsole.log('  not defined');
  fconsole.endl();

  //
  // process input
  //
  var inputFilename = options.file;

  // check input file exists
  if (!fs.existsSync(inputFilename) || !fs.statSync(inputFilename).isFile())
  {
    console.warn('Input file ' + inputFilename + ' not found');
    process.exit();
  }

  fconsole.start('\nInit\n====\n');

  // add input file in queue
  flow.files.add({
    filename: inputFilename
  });

  //
  // Main part
  //

  var handlers = [
    // extract files
    require('./html/extract'),
    require('./js/extract'),
    require('./tmpl/extract'),
    require('./css/extract'),
    require('./res/extract'),
    require('./l10n/extract'),

    // input file graph
    options.target == 'file-map' ? require('./misc/makeFileMap') : false,
    options.target == 'input-graph' ? require('./misc/makeInputGraph') : false,

    // process css
    require('./css/optimizeNames'),
    require('./css/makePackages'),
    require('./css/linear'),
    require('./css/merge'),
    require('./css/pack'),
    require('./css/translate'),

    // process l10n
    require('./l10n/buildIndex'),
    require('./l10n/makePackages'),
    require('./l10n/pack'),
    require('./l10n/modifyCall'),

    // process tmpl
    require('./tmpl/translate'),
    require('./tmpl/pregenerate'),

    // css/html resources
    require('./res/translate'),
    require('./res/buildMap'),

    // process js
    require('./js/relink'),
    require('./js/merge'),
    require('./js/makePackages'),
    require('./js/resolvePathes'),
    require('./js/translate'),
    require('./js/json'),
    require('./js/buildPackages'),
    require('./js/pack'),
    require('./js/realignHtml'),

    // process html
    require('./html/translate'),

    // output file graph
    options.target == 'output-graph' ? require('./misc/makeOutputGraph') : false,

    // make a zip
    options.target == 'zip' ? require('./misc/makeZip') : false,

    // flush output
    require('./misc/writeFiles'),

    finalHandler
  ].filter(Boolean);

  var taskCount = 0;
  var timing = [];
  var time;

  function asyncTaskStart(){
    taskCount++;
  }
  function asyncTaskDone(){
    taskCount--;
    nextHandler();
  }

  function nextHandler(){
    if (!taskCount && handlers.length)
    {
      time.time = new Date - time.time;
      timing.push(time);

      fconsole.resetDeep();

      process.nextTick(runHandler);
    }
  }

  function runHandler(){
    var handler = handlers.shift();
    var title = handler.handlerName;

    if (title)
      fconsole.log('\n' + title + '\n' + ('='.repeat(title.length)) + '\n');

    fconsole.incDeep();

    time = {
      name: title,
      time: +new Date
    };
    handler(flow, asyncTaskStart, asyncTaskDone);

    nextHandler();
  }

  runHandler();

  //
  // show totals
  //
  function finalHandler(){
    // file types
    (function(){
      var fileTypeMap = {};
      var fileMap = {};
      var outputFileCount = 0;
      var outputSize = 0;

      flow.files.queue.forEach(function(file){
        var stat = fileTypeMap[file.type];

        if (!stat)
        {
          stat = fileTypeMap[file.type] = {
            queueFiles: [],
            outputFiles: [],
            outputSize: 0
          };
        }

        stat.queueFiles.push(file.filename);

        if (file.outputFilename && 'outputContent' in file)
        {
          if (!fileMap[file.outputFilename]) // prevent duplicates
          {
            fileMap[file.outputFilename] = true;
            outputFileCount++;

            var fileSize = Buffer.byteLength(file.outputContent, file.encoding);
            outputSize += fileSize;
            stat.outputSize += fileSize;
            stat.outputFiles.push(file.outputFilename + ' ' + fileSize + ' bytes');
          }
        }
      }, fileTypeMap);

      fconsole.start('File queue:');
      for (var key in fileTypeMap)
        fconsole.log(key + ': ' + fileTypeMap[key].queueFiles.length);
      fconsole.endl();

      fconsole.start('Output ' + outputFileCount + ' files in ' + outputSize + ' bytes:')
      for (var key in fileTypeMap)
      {
        var files = fileTypeMap[key].outputFiles;

        if (!files.length)
          continue;

        var header = key + ': ' + files.length + ', ' + fileTypeMap[key].outputSize + ' bytes';
        if (key == 'script' || key == 'style')
        {
          fconsole.start(header);
          fconsole.list(files);
          fconsole.end();
        }
        else
          fconsole.log(header);
      }
      fconsole.endl();

    })();

    // timing
    fconsole.start('Timing:');
    timing.forEach(function(t){
      var time = String(t.time || 0);
      fconsole.log(' '.repeat(6 - time.length) + time + '  ' + (t.name || '[No title step]'));
    });
    fconsole.endl();

    // total time
    fconsole.log('Build done in ' + (flow.time() / 1000).toFixed(3) + 's');
  }

  finalHandler.handlerName = 'Build stat';
}

<|endoftext|>


<commit_before>var Inflector = require('inflected');
var Cape = require('./utilities');

// Cape.Router
//
// public properties:
//   routes: array of hashes that contains routing information.
//   params: the parameters that are extracted from URL hash fragment.
//   namespace: the namespace part of URL hash fragment
//   resource: the resource part of URL hash fragment
//   action: the action name of current route
//   container: the name of container of component
//   component: the name of component
// private properties:
//   _: the object that holds internal methods and properties of this class.
var Router = function Router(rootContainer) {
  this._ = new _Internal(this);
  this.rootContainer = rootContainer || window;
  this.routes = [];
  this.params = {};
  this.namespace = null;
  this.resource = null;
  this.action = null;
  this.container = null;
  this.component = null;
  this.waiting = false;
  this.flash = {};
};

Cape.extend(Router.prototype, {
  draw: function(callback) {
    var mapper;

    if (typeof callback !== 'function')
      throw new Error("The last argument must be a function.");
    if (callback.length === 0)
      throw new Error("Callback requires an argument.");

    mapper = new global.Cape.RoutingMapper(this);
    callback(mapper);
  },
  mount: function(elementId) {
    this._.targetElementId = elementId;
  },
  start: function() {
    var self = this, callback;

    if (window.addEventListener)
      window.addEventListener('hashchange', self._.eventListener, false);
    else if (window.attachEvent)
      window.attachEvent('onhashchange', self._.eventListener);

    this.currentHash = window.location.href.split('#')[1] || '';
    this.navigate(this.currentHash);
  },
  stop: function() {
    var self = this;

    if (window.removeEventListener)
      window.removeEventListener('hashchange', self._.eventListener, false);
    else if (window.detachEvent)
      window.detachEvent('onhashchange', self._.eventListener);
  },
  routeFor: function(hash) {
    var i, len, route;

    for (i = 0, len = this.routes.length; i < len; i++) {
      route = this.routes[i];
      if (hash.match(route.regexp)) return route;
    }
    throw new Error("No route match. [" + hash + "]");
  },
  navigate: function(hash, options) {
    var self = this, promises, promise, i, len;

    this._.currentHash = hash;
    this._.setHash(hash);

    options = options || {};
    this.flash.notice = options.notice;
    this.flash.alert = options.alert;

    if (this._.beforeNavigationCallbacks.length) {
      promises = [];
      promise = new Promise(function(resolve, reject) { resolve(hash) });
      promises.push(promise);
      for (i = 0, len = this._.beforeNavigationCallbacks.length; i < len; i++) {
        promise = promise.then(this._.beforeNavigationCallbacks[i]);
        promises.push(promise)
      }
      Promise.all(promises).then(function(results) {
        self._.mountComponent(results.pop())
      }, self._.errorHandler);
    }
    else {
      self._.mountComponent(hash);
    }
  },
  show: function(klass) {
    var component = new klass();
    component.mount(this._.targetElementId);
    this._.mountedComponentClass = klass;
    this._.mountedComponent = component;
  },
  attach: function(component) {
    var target = component;
    for (var i = 0, len = this._.attachedComponents.length; i < len; i++) {
      if (this._.attachedComponents[i] === component) return;
    }
    this._.attachedComponents.push(component);
  },
  detach: function(component) {
    for (var i = 0, len = this._.attachedComponents.length; i < len; i++) {
      if (this._.attachedComponents[i] === component) {
        this._.attachedComponents.splice(i, 1);
        break;
      }
    }
  },
  beforeNavigation: function(callback) {
    this._.beforeNavigationCallbacks.push(callback);
  },
  errorHandler: function(callback) {
    this._.errorHandler = callback;
  },
  notify: function() {
    var i;

    for (i = this._.attachedComponents.length; i--;) {
      this._.attachedComponents[i].refresh();
    }
  }
});

// Internal properties of Cape.Router
var _Internal = function _Internal(main) {
  var self = this;
  this.main = main;
  this.eventListener = function() {
    var hash = window.location.href.split('#')[1] || '';
    if (hash != self.currentHash) self.main.navigate(hash);
  };
  this.beforeNavigationCallbacks = [];
  this.attachedComponents = [];
  this.currentHash = null;
  this.mountedComponent = null;
  this.targetElementId = null;
}

// Internal methods of Cape.Router
Cape.extend(_Internal.prototype, {
  mountComponent: function(hash) {
    var route, componentClass;

    if (typeof hash !== 'string')
      throw new Error("The first argument must be a string.");

    route = this.main.routeFor(hash);
    this.main.namespace = route.namespace;
    this.main.resource = route.resource;
    this.main.action = route.action;
    this.main.container = route.container;
    this.main.component = route.component;
    this.setParams(route);
    componentClass = this.getComponentClassFor(route);

    if (componentClass === this.mountedComponentClass) {
      this.main.notify();
    }
    else {
      if (this.mountedComponent) this.mountedComponent.unmount();
      this.main.notify();
      component = new componentClass;
      component.mount(this.targetElementId);
      this.mountedComponentClass = componentClass;
      this.mountedComponent = component;
    }

    this.main.flash = {};
  },
  setHash: function(hash) {
    window.location.hash = hash;
  },
  setParams: function(route) {
    var md = this.currentHash.match(route.regexp);
    this.main.params = {};
    route.keys.forEach(function(key, i) {
      this.main.params[key] = md[i + 1];
    }.bind(this));
  },
  getComponentClassFor: function(route) {
    var fragments, obj, i, componentName;

    fragments = [];
    if (route.container) {
      route.container.split('.').forEach(function(part) {
        fragments.push(Inflector.camelize(part));
      })
    }

    obj = this.main.rootContainer;
    for (i = 0; obj && i < fragments.length; i++) {
      if (obj[fragments[i]]) obj = obj[fragments[i]];
      else obj = null;
    }

    componentName = Inflector.camelize(route.component);
    if (obj && obj[componentName]) return obj[componentName];

    throw new Error(
      "Component class "
        + fragments.concat([componentName]).join('.')
        + " is not defined."
    );
  }
});

module.exports = Router;
<commit_msg>Remove unused waiting property from Router<commit_after>var Inflector = require('inflected');
var Cape = require('./utilities');

// Cape.Router
//
// public properties:
//   routes: array of hashes that contains routing information.
//   params: the parameters that are extracted from URL hash fragment.
//   namespace: the namespace part of URL hash fragment
//   resource: the resource part of URL hash fragment
//   action: the action name of current route
//   container: the name of container of component
//   component: the name of component
// private properties:
//   _: the object that holds internal methods and properties of this class.
var Router = function Router(rootContainer) {
  this._ = new _Internal(this);
  this.rootContainer = rootContainer || window;
  this.routes = [];
  this.params = {};
  this.namespace = null;
  this.resource = null;
  this.action = null;
  this.container = null;
  this.component = null;
  this.flash = {};
};

Cape.extend(Router.prototype, {
  draw: function(callback) {
    var mapper;

    if (typeof callback !== 'function')
      throw new Error("The last argument must be a function.");
    if (callback.length === 0)
      throw new Error("Callback requires an argument.");

    mapper = new global.Cape.RoutingMapper(this);
    callback(mapper);
  },
  mount: function(elementId) {
    this._.targetElementId = elementId;
  },
  start: function() {
    var self = this, callback;

    if (window.addEventListener)
      window.addEventListener('hashchange', self._.eventListener, false);
    else if (window.attachEvent)
      window.attachEvent('onhashchange', self._.eventListener);

    this.currentHash = window.location.href.split('#')[1] || '';
    this.navigate(this.currentHash);
  },
  stop: function() {
    var self = this;

    if (window.removeEventListener)
      window.removeEventListener('hashchange', self._.eventListener, false);
    else if (window.detachEvent)
      window.detachEvent('onhashchange', self._.eventListener);
  },
  routeFor: function(hash) {
    var i, len, route;

    for (i = 0, len = this.routes.length; i < len; i++) {
      route = this.routes[i];
      if (hash.match(route.regexp)) return route;
    }
    throw new Error("No route match. [" + hash + "]");
  },
  navigate: function(hash, options) {
    var self = this, promises, promise, i, len;

    this._.currentHash = hash;
    this._.setHash(hash);

    options = options || {};
    this.flash.notice = options.notice;
    this.flash.alert = options.alert;

    if (this._.beforeNavigationCallbacks.length) {
      promises = [];
      promise = new Promise(function(resolve, reject) { resolve(hash) });
      promises.push(promise);
      for (i = 0, len = this._.beforeNavigationCallbacks.length; i < len; i++) {
        promise = promise.then(this._.beforeNavigationCallbacks[i]);
        promises.push(promise)
      }
      Promise.all(promises).then(function(results) {
        self._.mountComponent(results.pop())
      }, self._.errorHandler);
    }
    else {
      self._.mountComponent(hash);
    }
  },
  show: function(klass) {
    var component = new klass();
    component.mount(this._.targetElementId);
    this._.mountedComponentClass = klass;
    this._.mountedComponent = component;
  },
  attach: function(component) {
    var target = component;
    for (var i = 0, len = this._.attachedComponents.length; i < len; i++) {
      if (this._.attachedComponents[i] === component) return;
    }
    this._.attachedComponents.push(component);
  },
  detach: function(component) {
    for (var i = 0, len = this._.attachedComponents.length; i < len; i++) {
      if (this._.attachedComponents[i] === component) {
        this._.attachedComponents.splice(i, 1);
        break;
      }
    }
  },
  beforeNavigation: function(callback) {
    this._.beforeNavigationCallbacks.push(callback);
  },
  errorHandler: function(callback) {
    this._.errorHandler = callback;
  },
  notify: function() {
    var i;

    for (i = this._.attachedComponents.length; i--;) {
      this._.attachedComponents[i].refresh();
    }
  }
});

// Internal properties of Cape.Router
var _Internal = function _Internal(main) {
  var self = this;
  this.main = main;
  this.eventListener = function() {
    var hash = window.location.href.split('#')[1] || '';
    if (hash != self.currentHash) self.main.navigate(hash);
  };
  this.beforeNavigationCallbacks = [];
  this.attachedComponents = [];
  this.currentHash = null;
  this.mountedComponent = null;
  this.targetElementId = null;
}

// Internal methods of Cape.Router
Cape.extend(_Internal.prototype, {
  mountComponent: function(hash) {
    var route, componentClass;

    if (typeof hash !== 'string')
      throw new Error("The first argument must be a string.");

    route = this.main.routeFor(hash);
    this.main.namespace = route.namespace;
    this.main.resource = route.resource;
    this.main.action = route.action;
    this.main.container = route.container;
    this.main.component = route.component;
    this.setParams(route);
    componentClass = this.getComponentClassFor(route);

    if (componentClass === this.mountedComponentClass) {
      this.main.notify();
    }
    else {
      if (this.mountedComponent) this.mountedComponent.unmount();
      this.main.notify();
      component = new componentClass;
      component.mount(this.targetElementId);
      this.mountedComponentClass = componentClass;
      this.mountedComponent = component;
    }

    this.main.flash = {};
  },
  setHash: function(hash) {
    window.location.hash = hash;
  },
  setParams: function(route) {
    var md = this.currentHash.match(route.regexp);
    this.main.params = {};
    route.keys.forEach(function(key, i) {
      this.main.params[key] = md[i + 1];
    }.bind(this));
  },
  getComponentClassFor: function(route) {
    var fragments, obj, i, componentName;

    fragments = [];
    if (route.container) {
      route.container.split('.').forEach(function(part) {
        fragments.push(Inflector.camelize(part));
      })
    }

    obj = this.main.rootContainer;
    for (i = 0; obj && i < fragments.length; i++) {
      if (obj[fragments[i]]) obj = obj[fragments[i]];
      else obj = null;
    }

    componentName = Inflector.camelize(route.component);
    if (obj && obj[componentName]) return obj[componentName];

    throw new Error(
      "Component class "
        + fragments.concat([componentName]).join('.')
        + " is not defined."
    );
  }
});

module.exports = Router;
<|endoftext|>