<commit_before>(function(exports, window, node) {

//	console.log('---------')
//	console.log(node.window);

	var document = window.document;

	/*!
	*
	* Table: abstract representation of an HTML table
	*
	*/
	exports.Table = Table;
	exports.Table.Cell = Cell;

	// For simple testing
	// module.exports = Table;

	var JSUS = node.JSUS;
	var NDDB = node.NDDB;
	var HTMLRenderer = node.window.HTMLRenderer;
	var Entity = node.window.HTMLRenderer.Entity;

	Table.prototype = JSUS.clone(NDDB.prototype);
	//Table.prototype = new NDDB();
	Table.prototype.constructor = Table;

	Table.H = ['x','y','z'];
	Table.V = ['y','x', 'z'];

	Table.log = node.log;

	function Table (options, data) {
		options = options || {};

		Table.log = options.log || Table.log;
		this.defaultDim1 = options.defaultDim1 || 'x';
		this.defaultDim2 = options.defaultDim2 || 'y';
		this.defaultDim3 = options.defaultDim3 || 'z';

		this.table = options.table || document.createElement('table');
		this.id = options.id || 'table_' + Math.round(Math.random() * 1000);

		this.auto_update = ('undefined' !== typeof options.auto_update) ? options.auto_update : false;

		// Class for missing cells
		this.missing = options.missing || 'missing';
		this.pointers = {
						x: options.pointerX || 0,
						y: options.pointerY || 0,
						z: options.pointerZ || 0
		};

		this.header = [];
		this.footer = [];

		this.left = [];
		this.right = [];

		NDDB.call(this, options, data);

		// From NDDB
		this.options = this.__options;
	}

	// TODO: improve init
	Table.prototype.init = function (options) {
		NDDB.prototype.init.call(this, options);

		options = options || this.options;
		if ('undefined' !== typeof options.id) {

			this.table.id = options.id;
			this.id = options.id;
		}
		if (options.className) {
			this.table.className = options.className;
		}
		this.initRenderer(options.render);
	};

	Table.prototype.initRenderer = function(options) {
		this.htmlRenderer = new HTMLRenderer();
		this.htmlRenderer.addRenderer(function(el) {
			if ('object' === typeof el.content) {
				var tbl = new Table();
				for (var key in el.content) {
					if (el.content.hasOwnProperty(key)){
						tbl.addRow([key,el.content[key]]);
					}
				}
				return tbl.parse();
			}
		}, 2);
		if (options) {
			if (!(options instanceof Array)) {
				options = [options];
			}
			for (var i=0; i< options.length; i++) {
				this.htmlRenderer.addRenderer(options[i]);
			}
		}
	};

	// TODO: make it 3D
	Table.prototype.get = function (x, y) {
		var out = this;
		if ('undefined' !== typeof x) {
			out = this.select('x','=',x);
		}
		if ('undefined' !== typeof y) {
			out = out.select('y','=',y);
		}

		return out.fetch();
	};

	Table.prototype.addClass = function (c) {
		if (!c) return;
		if (c instanceof Array) c = c.join(' ');
		this.forEach(function (el) {
			node.window.addClass(el, c);
		});

		if (this.auto_update) {
			this.parse();
		}

		return this;
	};

	// Depends on node.window
	Table.prototype.removeClass = function (c) {
		if (!c) return;

		var func;
		if (c instanceof Array) {
			func = function(el, c) {
				for (var i=0; i< c.length; i++) {
					node.window.removeClass(el, c[i]);
				}
			};
		}
		else {
			func = node.window.removeClass;
		}

		this.forEach(function (el) {
			func.call(this,el,c);
		});

		if (this.auto_update) {
			this.parse();
		}

		return this;
	};

	Table.prototype._addSpecial = function (data, type) {
		if (!data) return;
		type = type || 'header';
		if ('object' !== typeof data) {
			return {content: data, type: type};
		}

		var out = [];
		for (var i=0; i < data.length; i++) {
			out.push({content: data[i], type: type});
		}
		return out;
	};

	Table.prototype.setHeader = function (header) {
		this.header = this._addSpecial(header);
	};

	Table.prototype.add2Header = function (header) {
		this.header = this.header.concat(this._addSpecial(header));
	};

	Table.prototype.setLeft = function (left) {
		this.left = this._addSpecial(left, 'left');
	};

	Table.prototype.add2Left = function (left) {
		this.left = this.left.concat(this._addSpecial(left, 'left'));
	};

	// TODO: setRight
	//Table.prototype.setRight = function (left) {
	//	this.right = this._addSpecial(left, 'right');
	//};

	Table.prototype.setFooter = function (footer) {
		this.footer = this._addSpecial(footer, 'footer');
	};

	Table._checkDim123 = function (dims) {
		var t = Table.H.slice(0);
		for (var i=0; i< dims.length; i++) {
			if (!JSUS.removeElement(dims[i],t)) return false;
		}
		return true;
	};

	/**
	* Updates the reference to the foremost element in the table.
	*
	* @param
	*/
	Table.prototype.updatePointer = function (pointer, value) {
		if (!pointer) return false;
		if (!JSUS.in_array(pointer, Table.H)) {
			Table.log('Cannot update invalid pointer: ' + pointer, 'ERR');
			return false;
		}

		if (value > this.pointers[pointer]) {
			this.pointers[pointer] = value;
			return true;
		}

	};

	Table.prototype._add = function (data, dims, x, y, z) {
		if (!data) return false;
		if (dims) {
			if (!Table._checkDim123(dims)) {
				Table.log('Invalid value for dimensions. Accepted only: x,y,z.');
				return false;
			}
		}
		else {
			dims = Table.H;
		}

		var insertCell = function (content){
			//Table.log('content');
			//Table.log(x + ' ' + y + ' ' + z);
			//Table.log(i + ' ' + j + ' ' + h);

			var cell = {};
			cell[dims[0]] = i; // i always defined
			cell[dims[1]] = (j) ? y+j : y;
			cell[dims[2]] = (h) ? z+h : z;
			cell.content = content;
			//Table.log(cell);
			this.insert(new Cell(cell));
			this.updatePointer(dims[0],cell[dims[0]]);
			this.updatePointer(dims[1],cell[dims[1]]);
			this.updatePointer(dims[2],cell[dims[2]]);
		};

		// By default, only the second dimension is incremented
		x = x || this.pointers[dims[0]];
		y = y || this.pointers[dims[1]] + 1;
		z = z || this.pointers[dims[2]];

		if ('object' !== typeof data) data = [data];

		var cell = null;
		// Loop Dim1
		for (var i = 0; i < data.length; i++) {
			//Table.log('data_i');
			//Table.log(data[i]);
			if (data[i] instanceof Array) {
				// Loop Dim2
				for (var j = 0; j < data[i].length; j++) {
				//Table.log(data[i]);
					if (data[i][j] instanceof Array) {
						//Table.log(data[i][j]);
						//Table.log(typeof data[i][j]);
						// Loop Dim3
						for (var h = 0; h < data[i][j].length; h++) {
							//Table.log('Here h');
							insertCell.call(this, data[i][j][h]);
						}
						h=0; // reset h
					}
					else {
						//Table.log('Here j');
						insertCell.call(this, data[i][j]);
					}
				}
				j=0; // reset j
			}
			else {
				//Table.log('Here i');
				insertCell.call(this, data[i]);
			}
		}

		//Table.log('After insert');
		//Table.log(this.db);

		// TODO: if coming from addRow or Column this should be done only at the end
		if (this.auto_update) {
			this.parse(true);
		}

	};

	Table.prototype.add = function (data, x, y) {
		if (!data) return;
		var cell = (data instanceof Cell) ? data : new Cell({
			x: x,
			y: y,
			content: data
		});
		var result = this.insert(cell);

		if (result) {
			this.updatePointer('x',x);
			this.updatePointer('y',y);
		}
		return result;
	};

	Table.prototype.addColumn = function (data, x, y) {
		if (!data) return false;
		return this._add(data, Table.V, x, y);
	};

	Table.prototype.addRow = function (data, x, y) {
		if (!data) return false;
		return this._add(data, Table.H, x, y);
	};

	//Table.prototype.bind = function (dim, property) {
		//this.binds[property] = dim;
	//};

	// TODO: Only 2D for now
	// TODO: improve algorithm, rewrite
	Table.prototype.parse = function () {

		// Create a cell element (td,th...)
		// and fill it with the return value of a
		// render value.
		var fromCell2TD = function (cell, el) {
			if (!cell) return;
			el = el || 'td';
			var TD = document.createElement(el);
			var content = this.htmlRenderer.render(cell);
			//var content = (!JSUS.isNode(c) || !JSUS.isElement(c)) ? document.createTextNode(c) : c;
			TD.appendChild(content);
			if (cell.className) TD.className = cell.className;
			return TD;
		};

		if (this.table) {
			while (this.table.hasChildNodes()) {
				this.table.removeChild(this.table.firstChild);
			}
		}

		var TABLE = this.table,
			TR,
			TD,
			i;

		// HEADER
		if (this.header && this.header.length > 0) {
			var THEAD = document.createElement('thead');
			TR = document.createElement('tr');
			// Add an empty cell to balance the left header column
			if (this.left && this.left.length > 0) {
				TR.appendChild(document.createElement('th'));
			}
			for (i=0; i < this.header.length; i++) {
				TR.appendChild(fromCell2TD.call(this, this.header[i],'th'));
			}
			THEAD.appendChild(TR);
			i=0;
			TABLE.appendChild(THEAD);
		}

		//console.log(this.table);
		//console.log(this.id);
		//console.log(this.db.length);

		// BODY
		if (this.length) {
			var TBODY = document.createElement('tbody');

			this.sort(['y','x']); // z to add first
			var trid = -1;
			// TODO: What happens if the are missing at the beginning ??
			var f = this.first();
			var old_x = f.x;
			var old_left = 0;

			for (i=0; i < this.db.length; i++) {
				//console.log('INSIDE TBODY LOOP');
				//console.log(this.id);
				if (trid !== this.db[i].y) {
					TR = document.createElement('tr');
					TBODY.appendChild(TR);
					trid = this.db[i].y;
					//Table.log(trid);
					old_x = f.x - 1; // must start exactly from the first

					// Insert left header, if any
					if (this.left && this.left.length) {
						TD = document.createElement('td');
						//TD.className = this.missing;
						TR.appendChild(fromCell2TD.call(this, this.left[old_left]));
						old_left++;
					}
				}

				// Insert missing cells
				if (this.db[i].x > old_x + 1) {
					var diff = this.db[i].x - (old_x + 1);
					for (var j=0; j < diff; j++ ) {
						TD = document.createElement('td');
						TD.className = this.missing;
						TR.appendChild(TD);
					}
				}
				// Normal Insert
				TR.appendChild(fromCell2TD.call(this, this.db[i]));

				// Update old refs
				old_x = this.db[i].x;
			}
			TABLE.appendChild(TBODY);
		}

		//FOOTER
		if (this.footer && this.footer.length > 0) {
			var TFOOT = document.createElement('tfoot');
			TR = document.createElement('tr');
			for (i=0; i < this.header.length; i++) {
				TR.appendChild(fromCell2TD.call(this, this.footer[i]));
			}
			TFOOT.appendChild(TR);
			TABLE.appendChild(TFOOT);
		}

		return TABLE;
	};

	Table.prototype.resetPointers = function (pointers) {
		pointers = pointers || {};
		this.pointers = {
				x: pointers.pointerX || 0,
				y: pointers.pointerY || 0,
				z: pointers.pointerZ || 0
		};
	};

	Table.prototype.clear = function (confirm) {
		if (NDDB.prototype.clear.call(this, confirm)) {
			this.resetPointers();
		}
	};

  // Cell Class
	Cell.prototype = new Entity();
	Cell.prototype.constructor = Cell;

	function Cell (cell){
		Entity.call(this, cell);
		this.x = ('undefined' !== typeof cell.x) ? cell.x : null;
		this.y = ('undefined' !== typeof cell.y) ? cell.y : null;
		this.z = ('undefined' !== typeof cell.z) ? cell.z : null;
	}

})(
	('undefined' !== typeof node) ? node.window || node : module.exports, // Exports
	('undefined' !== typeof window) ? window : module.parent.exports.window, // window
	('undefined' !== typeof node) ? node : module.parent.exports.node // node
);
<commit_msg>Table adapted to new NDDB (parent)<commit_after>(function(exports, window, node) {

//	console.log('---------')
//	console.log(node.window);

	var document = window.document;

	/*!
	*
	* Table: abstract representation of an HTML table
	*
	*/
	exports.Table = Table;
	exports.Table.Cell = Cell;

	// For simple testing
	// module.exports = Table;

	var JSUS = node.JSUS;
	var NDDB = node.NDDB;
	var HTMLRenderer = node.window.HTMLRenderer;
	var Entity = node.window.HTMLRenderer.Entity;

	Table.prototype = JSUS.clone(NDDB.prototype);
	//Table.prototype = new NDDB();
	Table.prototype.constructor = Table;

	Table.H = ['x','y','z'];
	Table.V = ['y','x', 'z'];

	Table.log = node.log;

	function Table (options, data, parent) {
		options = options || {};

		Table.log = options.log || Table.log;
		this.defaultDim1 = options.defaultDim1 || 'x';
		this.defaultDim2 = options.defaultDim2 || 'y';
		this.defaultDim3 = options.defaultDim3 || 'z';

		this.table = options.table || document.createElement('table');
		this.id = options.id || 'table_' + Math.round(Math.random() * 1000);

		this.auto_update = ('undefined' !== typeof options.auto_update) ? options.auto_update : false;

		// Class for missing cells
		this.missing = options.missing || 'missing';
		this.pointers = {
						x: options.pointerX || 0,
						y: options.pointerY || 0,
						z: options.pointerZ || 0
		};

		this.header = [];
		this.footer = [];

		this.left = [];
		this.right = [];

		NDDB.call(this, options, data, parent);

		// From NDDB
		this.options = this.__options;
	}

	// TODO: improve init
	Table.prototype.init = function (options) {
		NDDB.prototype.init.call(this, options);

		options = options || this.options;
		if ('undefined' !== typeof options.id) {

			this.table.id = options.id;
			this.id = options.id;
		}
		if (options.className) {
			this.table.className = options.className;
		}
		this.initRenderer(options.render);
	};

	Table.prototype.initRenderer = function(options) {
		this.htmlRenderer = new HTMLRenderer();
		this.htmlRenderer.addRenderer(function(el) {
			if ('object' === typeof el.content) {
				var tbl = new Table();
				for (var key in el.content) {
					if (el.content.hasOwnProperty(key)){
						tbl.addRow([key,el.content[key]]);
					}
				}
				return tbl.parse();
			}
		}, 2);
		if (options) {
			if (!(options instanceof Array)) {
				options = [options];
			}
			for (var i=0; i< options.length; i++) {
				this.htmlRenderer.addRenderer(options[i]);
			}
		}
	};

	// TODO: make it 3D
	Table.prototype.get = function (x, y) {
		var out = this;
		if ('undefined' !== typeof x) {
			out = this.select('x','=',x);
		}
		if ('undefined' !== typeof y) {
			out = out.select('y','=',y);
		}

		return out.fetch();
	};

	Table.prototype.addClass = function (c) {
		if (!c) return;
		if (c instanceof Array) c = c.join(' ');
		this.forEach(function (el) {
			node.window.addClass(el, c);
		});

		if (this.auto_update) {
			this.parse();
		}

		return this;
	};

	// Depends on node.window
	Table.prototype.removeClass = function (c) {
		if (!c) return;

		var func;
		if (c instanceof Array) {
			func = function(el, c) {
				for (var i=0; i< c.length; i++) {
					node.window.removeClass(el, c[i]);
				}
			};
		}
		else {
			func = node.window.removeClass;
		}

		this.forEach(function (el) {
			func.call(this,el,c);
		});

		if (this.auto_update) {
			this.parse();
		}

		return this;
	};

	Table.prototype._addSpecial = function (data, type) {
		if (!data) return;
		type = type || 'header';
		if ('object' !== typeof data) {
			return {content: data, type: type};
		}

		var out = [];
		for (var i=0; i < data.length; i++) {
			out.push({content: data[i], type: type});
		}
		return out;
	};

	Table.prototype.setHeader = function (header) {
		this.header = this._addSpecial(header);
	};

	Table.prototype.add2Header = function (header) {
		this.header = this.header.concat(this._addSpecial(header));
	};

	Table.prototype.setLeft = function (left) {
		this.left = this._addSpecial(left, 'left');
	};

	Table.prototype.add2Left = function (left) {
		this.left = this.left.concat(this._addSpecial(left, 'left'));
	};

	// TODO: setRight
	//Table.prototype.setRight = function (left) {
	//	this.right = this._addSpecial(left, 'right');
	//};

	Table.prototype.setFooter = function (footer) {
		this.footer = this._addSpecial(footer, 'footer');
	};

	Table._checkDim123 = function (dims) {
		var t = Table.H.slice(0);
		for (var i=0; i< dims.length; i++) {
			if (!JSUS.removeElement(dims[i],t)) return false;
		}
		return true;
	};

	/**
	* Updates the reference to the foremost element in the table.
	*
	* @param
	*/
	Table.prototype.updatePointer = function (pointer, value) {
		if (!pointer) return false;
		if (!JSUS.in_array(pointer, Table.H)) {
			Table.log('Cannot update invalid pointer: ' + pointer, 'ERR');
			return false;
		}

		if (value > this.pointers[pointer]) {
			this.pointers[pointer] = value;
			return true;
		}

	};

	Table.prototype._add = function (data, dims, x, y, z) {
		if (!data) return false;
		if (dims) {
			if (!Table._checkDim123(dims)) {
				Table.log('Invalid value for dimensions. Accepted only: x,y,z.');
				return false;
			}
		}
		else {
			dims = Table.H;
		}

		var insertCell = function (content){
			//Table.log('content');
			//Table.log(x + ' ' + y + ' ' + z);
			//Table.log(i + ' ' + j + ' ' + h);

			var cell = {};
			cell[dims[0]] = i; // i always defined
			cell[dims[1]] = (j) ? y+j : y;
			cell[dims[2]] = (h) ? z+h : z;
			cell.content = content;
			//Table.log(cell);
			this.insert(new Cell(cell));
			this.updatePointer(dims[0],cell[dims[0]]);
			this.updatePointer(dims[1],cell[dims[1]]);
			this.updatePointer(dims[2],cell[dims[2]]);
		};

		// By default, only the second dimension is incremented
		x = x || this.pointers[dims[0]];
		y = y || this.pointers[dims[1]] + 1;
		z = z || this.pointers[dims[2]];

		if ('object' !== typeof data) data = [data];

		var cell = null;
		// Loop Dim1
		for (var i = 0; i < data.length; i++) {
			//Table.log('data_i');
			//Table.log(data[i]);
			if (data[i] instanceof Array) {
				// Loop Dim2
				for (var j = 0; j < data[i].length; j++) {
				//Table.log(data[i]);
					if (data[i][j] instanceof Array) {
						//Table.log(data[i][j]);
						//Table.log(typeof data[i][j]);
						// Loop Dim3
						for (var h = 0; h < data[i][j].length; h++) {
							//Table.log('Here h');
							insertCell.call(this, data[i][j][h]);
						}
						h=0; // reset h
					}
					else {
						//Table.log('Here j');
						insertCell.call(this, data[i][j]);
					}
				}
				j=0; // reset j
			}
			else {
				//Table.log('Here i');
				insertCell.call(this, data[i]);
			}
		}

		//Table.log('After insert');
		//Table.log(this.db);

		// TODO: if coming from addRow or Column this should be done only at the end
		if (this.auto_update) {
			this.parse(true);
		}

	};

	Table.prototype.add = function (data, x, y) {
		if (!data) return;
		var cell = (data instanceof Cell) ? data : new Cell({
			x: x,
			y: y,
			content: data
		});
		var result = this.insert(cell);

		if (result) {
			this.updatePointer('x',x);
			this.updatePointer('y',y);
		}
		return result;
	};

	Table.prototype.addColumn = function (data, x, y) {
		if (!data) return false;
		return this._add(data, Table.V, x, y);
	};

	Table.prototype.addRow = function (data, x, y) {
		if (!data) return false;
		return this._add(data, Table.H, x, y);
	};

	//Table.prototype.bind = function (dim, property) {
		//this.binds[property] = dim;
	//};

	// TODO: Only 2D for now
	// TODO: improve algorithm, rewrite
	Table.prototype.parse = function () {

		// Create a cell element (td,th...)
		// and fill it with the return value of a
		// render value.
		var fromCell2TD = function (cell, el) {
			if (!cell) return;
			el = el || 'td';
			var TD = document.createElement(el);
			var content = this.htmlRenderer.render(cell);
			//var content = (!JSUS.isNode(c) || !JSUS.isElement(c)) ? document.createTextNode(c) : c;
			TD.appendChild(content);
			if (cell.className) TD.className = cell.className;
			return TD;
		};

		if (this.table) {
			while (this.table.hasChildNodes()) {
				this.table.removeChild(this.table.firstChild);
			}
		}

		var TABLE = this.table,
			TR,
			TD,
			i;

		// HEADER
		if (this.header && this.header.length > 0) {
			var THEAD = document.createElement('thead');
			TR = document.createElement('tr');
			// Add an empty cell to balance the left header column
			if (this.left && this.left.length > 0) {
				TR.appendChild(document.createElement('th'));
			}
			for (i=0; i < this.header.length; i++) {
				TR.appendChild(fromCell2TD.call(this, this.header[i],'th'));
			}
			THEAD.appendChild(TR);
			i=0;
			TABLE.appendChild(THEAD);
		}

		//console.log(this.table);
		//console.log(this.id);
		//console.log(this.db.length);

		// BODY
		if (this.length) {
			var TBODY = document.createElement('tbody');

			this.sort(['y','x']); // z to add first
			var trid = -1;
			// TODO: What happens if the are missing at the beginning ??
			var f = this.first();
			var old_x = f.x;
			var old_left = 0;

			for (i=0; i < this.db.length; i++) {
				//console.log('INSIDE TBODY LOOP');
				//console.log(this.id);
				if (trid !== this.db[i].y) {
					TR = document.createElement('tr');
					TBODY.appendChild(TR);
					trid = this.db[i].y;
					//Table.log(trid);
					old_x = f.x - 1; // must start exactly from the first

					// Insert left header, if any
					if (this.left && this.left.length) {
						TD = document.createElement('td');
						//TD.className = this.missing;
						TR.appendChild(fromCell2TD.call(this, this.left[old_left]));
						old_left++;
					}
				}

				// Insert missing cells
				if (this.db[i].x > old_x + 1) {
					var diff = this.db[i].x - (old_x + 1);
					for (var j=0; j < diff; j++ ) {
						TD = document.createElement('td');
						TD.className = this.missing;
						TR.appendChild(TD);
					}
				}
				// Normal Insert
				TR.appendChild(fromCell2TD.call(this, this.db[i]));

				// Update old refs
				old_x = this.db[i].x;
			}
			TABLE.appendChild(TBODY);
		}

		//FOOTER
		if (this.footer && this.footer.length > 0) {
			var TFOOT = document.createElement('tfoot');
			TR = document.createElement('tr');
			for (i=0; i < this.header.length; i++) {
				TR.appendChild(fromCell2TD.call(this, this.footer[i]));
			}
			TFOOT.appendChild(TR);
			TABLE.appendChild(TFOOT);
		}

		return TABLE;
	};

	Table.prototype.resetPointers = function (pointers) {
		pointers = pointers || {};
		this.pointers = {
				x: pointers.pointerX || 0,
				y: pointers.pointerY || 0,
				z: pointers.pointerZ || 0
		};
	};

	Table.prototype.clear = function (confirm) {
		if (NDDB.prototype.clear.call(this, confirm)) {
			this.resetPointers();
		}
	};

  // Cell Class
	Cell.prototype = new Entity();
	Cell.prototype.constructor = Cell;

	function Cell (cell){
		Entity.call(this, cell);
		this.x = ('undefined' !== typeof cell.x) ? cell.x : null;
		this.y = ('undefined' !== typeof cell.y) ? cell.y : null;
		this.z = ('undefined' !== typeof cell.z) ? cell.z : null;
	}

})(
	('undefined' !== typeof node) ? node.window || node : module.exports, // Exports
	('undefined' !== typeof window) ? window : module.parent.exports.window, // window
	('undefined' !== typeof node) ? node : module.parent.exports.node // node
);
<|endoftext|>


<commit_before>var path = require('path');

var browserify = require('browserify');
var clean = require("gulp-clean");
var concat = require('gulp-concat');
var express = require('express');
var gulp = require('gulp');
var livereload = require('gulp-livereload');
var livereloadInjector = require('connect-livereload');
var minifyHTML = require('gulp-minify-html');
var runSequence = require('run-sequence');
var sourceStream = require('vinyl-source-stream');
var templateCache = require('gulp-angular-templatecache');
var ts = require('gulp-typescript');
var util = require('gulp-util');
var watchify = require('watchify');
var stylus = require('gulp-stylus');
var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');
var minifyCSS = require('gulp-minify-css');
var replace = require('gulp-replace');
var transform = require('vinyl-transform');
var rename = require('gulp-rename');
var fs = require('fs');

var appIndexHtmlFilename = 'index.html';
var appProjectName = 'stencil';
var compiledAngularTemplateCacheFilename = 'templates.js';
var compiledCssFilename =  appProjectName + '.compiled.css';
var compiledJsFilename = appProjectName + '.compiled.js';
var appJsFilename = appProjectName + '.js';
var compiledShimVendorsJsFilename = 'vendors.js';
var fakeShimFilename = 'noop.js';

var expressServerPort = 3000;
var isWatchAndRun = false;
var isPackageRun = false;
var isPackageRelease = false;
var shimList = getConfigByKey('browserify-shim');

var sources = {
    ts: 'app/**/*.ts',
    build: './build/app',
    dist: './dist/app',
    zip: './dist',
    html: 'app/' + appIndexHtmlFilename,
    app: 'app/',
    templates: [
        'app/**/*.html',
        '!app/assets/**/*.html',
        '!app/' + appIndexHtmlFilename
    ],
    assets: [
        'app/assets/**/*.*'
    ],
    stylus: [
        'app/**/*.styl',
        'app/**/*.css'
    ]
};

/***********************************************************************************************************************
 * Local functions / Utilities
 **********************************************************************************************************************/

function browserifier() {
    var shim;
    var b = browserify(sources.build + '/' + appJsFilename, {
        fullsources: false,
        cache: {},
        packageCache: {},
        debug: true
    });

    // NOTE
    // Exclude shim-ified libraries from the main app.
    // So we mark and tell browserify that these are external resources
    for(shim in shimList) {
        b.external(shim);
    }

    return b;
}

function reload(event) {
    setTimeout(function() {
        livereload.changed();
        util.log('[reloaded] ' + path.basename(event.path));
    }, 2000);
}

function getConfigByKey(key) {
    var config = require('./package.json');
    return config[key];
}

gulp.task('clean', function() {
    return gulp.src([sources.build, sources.dist], {read: false})
    .pipe(clean());
});

gulp.task('start-livereload', function(){
    livereload.listen();
});

gulp.task('start-server', function() {
    var server = express();

    if (!isPackageRun) {
        server.use(livereloadInjector());
        server.use(express.static(sources.build));
    } else {
        server.use(express.static(sources.dist));
    }

    server.listen(expressServerPort);

    util.log(util.colors.green(appProjectName + ' is listening on port ' + expressServerPort));
});

gulp.task('browserify', function(){
    return browserifier()
    .bundle()
    .pipe(sourceStream(compiledJsFilename))
    .pipe(gulp.dest(sources.build));
});

gulp.task('watchify', function() {

    var browseritor = watchify(
        browserifier()
    );

    browseritor.on('update', rebundle);

    function rebundle() {
        return browseritor
        .bundle()
        .on('error', util.log.bind(util, 'Browserify Error'))
        .pipe(sourceStream(compiledJsFilename))
        .pipe(gulp.dest(sources.build));
    }

    return rebundle();
});

gulp.task('minify-js', function() {
    return gulp.src(path.join(sources.build, compiledJsFilename))
    .pipe(uglify({
        mangle: true
    }))
    .pipe(gulp.dest(path.join(sources.dist, '/')));
});

gulp.task('minify-css', function() {
    return gulp.src(path.join(sources.build, compiledCssFilename))
    .pipe(minifyCSS())
    .pipe(gulp.dest(path.join(sources.dist, '/')));
});

gulp.task('browserify-vendors', function() {
    var shim;
    var noopJS = path.join(sources.app, fakeShimFilename);

    // HACK ALERT
    // create a fake entry point so that browserify will give us
    // a stream where we can require the shim-ified libraries
    fs.writeFile(noopJS, '');

    var browserified = transform(function(filename){
        var b = browserify(filename);

        for(shim in shimList) {
            b.require(shim);
        }

        return b.bundle();
    });

    return gulp.src(path.join(sources.app, fakeShimFilename))
    .pipe(browserified)
    .pipe(rename(compiledShimVendorsJsFilename))
    .pipe(gulp.dest(path.join(sources.build, '/')))
    .on('end', function() {
        // we named the shim file @ checck `compiledShimVendorsJsFilename`, thus it's safe to
        // delete the fake file after writing the contents to its destination folder
        fs.unlink(noopJS);
    });
});

/***********************************************************************************************************************
 * Copy-ish Tasks
 **********************************************************************************************************************/

gulp.task('copy-index-html', function() {
    return gulp.src(sources.html)
    .pipe(replace(/{%compiledCssFilename%}/, compiledCssFilename))
    .pipe(replace(/{%compiledJsFilename%}/, compiledJsFilename))
    .pipe(replace(/{%compiledShimVendorsJsFilename%}/, compiledShimVendorsJsFilename))
    .pipe(gulp.dest(isPackageRelease ? sources.dist : sources.build));
});

gulp.task('copy-assets', function() {
    return gulp.src(sources.assets, {
        base: 'assets'
    })
    .pipe(gulp.dest(path.join(isPackageRelease ? sources.dist : sources.build)));
});

/***********************************************************************************************************************
 * Transpiler Tasks
 **********************************************************************************************************************/

gulp.task('compile-templates', function() {
    return gulp.src(sources.templates)
    .pipe(minifyHTML())
    .pipe(templateCache(
        compiledAngularTemplateCacheFilename, {
            module: 'Templates',
            moduleSystem: 'Browserify',
            standalone: true
        }))
    .pipe(gulp.dest(sources.build));
});

gulp.task('compile-typescript', function() {
    return gulp.src(sources.ts)
    .pipe(ts({
        module: 'commonjs'
    }))
    .pipe(gulp.dest(sources.build));
});

gulp.task('compile-stylus', function() {
    return gulp.src(sources.stylus)
    .pipe(stylus())
    .pipe(concat(compiledCssFilename))
    .pipe(gulp.dest(isPackageRelease ? sources.dist : sources.build))
    .pipe(gulpif(isWatchAndRun, livereload()));
});

/***********************************************************************************************************************
 * Bulk Tasks
 **********************************************************************************************************************/

gulp.task('watches', function() {

    gulp.watch(sources.html, ['copy-index-html']);
    gulp.watch(sources.stylus, ['compile-stylus']);
    gulp.watch(sources.ts, ['compile-typescript']);
    gulp.watch(sources.templates, ['compile-templates']);
    gulp.watch(sources.assets, ['copy-assets']);

    // post-build watcher(s)
    gulp.watch([
        path.join(sources.build, compiledJsFilename),
        path.join(sources.build, appIndexHtmlFilename)
    ], {
        debounceDelay: 1000
    })
    .on('change', function(event) {
        if (isWatchAndRun) {
            reload(event);
        }
    });
});

/***********************************************************************************************************************
 * Common Tasks
 **********************************************************************************************************************/

gulp.task('build', function() {
    runSequence(
        'clean',
        [
            'copy-assets',
            'copy-index-html',
            'compile-typescript',
            'compile-templates'
        ],
        'compile-stylus',
        'browserify'
    );
});

gulp.task('run', function() {
    runSequence(
        'start-server'
    );
});

gulp.task('watch', function() {
    runSequence(
        'watchify',
        'watches'
    );
});

gulp.task('watchrun', function() {
    isWatchAndRun = true;

    runSequence(
        'clean',
        [
            'copy-assets',
            'copy-index-html',
            'compile-typescript',
            'compile-templates'
        ],
        'compile-stylus',
        'browserify-vendors',
        'browserify',
        'watches',
        'watchify',
        'start-livereload',
        'run'
    );
});

gulp.task('release', function() {
    isPackageRelease = true;
    runSequence(
        'clean',
        [
            'copy-assets',
            'copy-index-html',
            'compile-typescript',
            'compile-templates'
        ],
        'compile-stylus',
        'browserify',
        'minify-js',
        'minify-css'
    );
});

gulp.task('releaserun', function() {
    isPackageRun = true;
    isPackageRelease = true;
    runSequence(
        'release',
        'run'
    );
});

gulp.task('default', ['watchrun']);<commit_msg>fix - missed minifying vendors js fix - browserify vendors on production release<commit_after>var path = require('path');

var browserify = require('browserify');
var clean = require("gulp-clean");
var concat = require('gulp-concat');
var express = require('express');
var gulp = require('gulp');
var livereload = require('gulp-livereload');
var livereloadInjector = require('connect-livereload');
var minifyHTML = require('gulp-minify-html');
var runSequence = require('run-sequence');
var sourceStream = require('vinyl-source-stream');
var templateCache = require('gulp-angular-templatecache');
var ts = require('gulp-typescript');
var util = require('gulp-util');
var watchify = require('watchify');
var stylus = require('gulp-stylus');
var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');
var minifyCSS = require('gulp-minify-css');
var replace = require('gulp-replace');
var transform = require('vinyl-transform');
var rename = require('gulp-rename');
var fs = require('fs');

var appIndexHtmlFilename = 'index.html';
var appProjectName = 'stencil';
var compiledAngularTemplateCacheFilename = 'templates.js';
var compiledCssFilename =  appProjectName + '.compiled.css';
var compiledJsFilename = appProjectName + '.compiled.js';
var appJsFilename = appProjectName + '.js';
var compiledShimVendorsJsFilename = 'vendors.js';
var fakeShimFilename = 'noop.js';

var expressServerPort = 3000;
var isWatchAndRun = false;
var isPackageRun = false;
var isPackageRelease = false;
var shimList = getConfigByKey('browserify-shim');

var sources = {
    ts: 'app/**/*.ts',
    build: './build/app',
    dist: './dist/app',
    zip: './dist',
    html: 'app/' + appIndexHtmlFilename,
    app: 'app/',
    templates: [
        'app/**/*.html',
        '!app/assets/**/*.html',
        '!app/' + appIndexHtmlFilename
    ],
    assets: [
        'app/assets/**/*.*'
    ],
    stylus: [
        'app/**/*.styl',
        'app/**/*.css'
    ]
};

/***********************************************************************************************************************
 * Local functions / Utilities
 **********************************************************************************************************************/

function browserifier() {
    var shim;
    var b = browserify(sources.build + '/' + appJsFilename, {
        fullsources: false,
        cache: {},
        packageCache: {},
        debug: true
    });

    // NOTE
    // Exclude shim-ified libraries from the main app.
    // So we mark and tell browserify that these are external resources
    for(shim in shimList) {
        b.external(shim);
    }

    return b;
}

function reload(event) {
    setTimeout(function() {
        livereload.changed();
        util.log('[reloaded] ' + path.basename(event.path));
    }, 2000);
}

function getConfigByKey(key) {
    var config = require('./package.json');
    return config[key];
}

gulp.task('clean', function() {
    return gulp.src([sources.build, sources.dist], {read: false})
    .pipe(clean());
});

gulp.task('start-livereload', function(){
    livereload.listen();
});

gulp.task('start-server', function() {
    var server = express();

    if (!isPackageRun) {
        server.use(livereloadInjector());
        server.use(express.static(sources.build));
    } else {
        server.use(express.static(sources.dist));
    }

    server.listen(expressServerPort);

    util.log(util.colors.green(appProjectName + ' is listening on port ' + expressServerPort));
});

gulp.task('browserify', function(){
    return browserifier()
    .bundle()
    .pipe(sourceStream(compiledJsFilename))
    .pipe(gulp.dest(sources.build));
});

gulp.task('watchify', function() {

    var browseritor = watchify(
        browserifier()
    );

    browseritor.on('update', rebundle);

    function rebundle() {
        return browseritor
        .bundle()
        .on('error', util.log.bind(util, 'Browserify Error'))
        .pipe(sourceStream(compiledJsFilename))
        .pipe(gulp.dest(sources.build));
    }

    return rebundle();
});

gulp.task('minify-js', function() {
    return gulp.src([
        path.join(sources.build, compiledJsFilename),
        path.join(sources.build, compiledShimVendorsJsFilename)
    ])
    .pipe(uglify({
        mangle: true
    }))
    .pipe(gulp.dest(path.join(sources.dist, '/')));
});

gulp.task('minify-css', function() {
    return gulp.src(path.join(sources.build, compiledCssFilename))
    .pipe(minifyCSS())
    .pipe(gulp.dest(path.join(sources.dist, '/')));
});

gulp.task('browserify-vendors', function() {
    var shim;
    var noopJS = path.join(sources.app, fakeShimFilename);

    // HACK ALERT
    // create a fake entry point so that browserify will give us
    // a stream where we can require the shim-ified libraries
    fs.writeFile(noopJS, '');

    var browserified = transform(function(filename){
        var b = browserify(filename);

        for(shim in shimList) {
            b.require(shim);
        }

        return b.bundle();
    });

    return gulp.src(path.join(sources.app, fakeShimFilename))
    .pipe(browserified)
    .pipe(rename(compiledShimVendorsJsFilename))
    .pipe(gulp.dest(path.join(sources.build, '/')))
    .on('end', function() {
        // we named the shim file @ checck `compiledShimVendorsJsFilename`, thus it's safe to
        // delete the fake file after writing the contents to its destination folder
        fs.unlink(noopJS);
    });
});

/***********************************************************************************************************************
 * Copy-ish Tasks
 **********************************************************************************************************************/

gulp.task('copy-index-html', function() {
    return gulp.src(sources.html)
    .pipe(replace(/{%compiledCssFilename%}/, compiledCssFilename))
    .pipe(replace(/{%compiledJsFilename%}/, compiledJsFilename))
    .pipe(replace(/{%compiledShimVendorsJsFilename%}/, compiledShimVendorsJsFilename))
    .pipe(gulp.dest(isPackageRelease ? sources.dist : sources.build));
});

gulp.task('copy-assets', function() {
    return gulp.src(sources.assets, {
        base: 'assets'
    })
    .pipe(gulp.dest(path.join(isPackageRelease ? sources.dist : sources.build)));
});

/***********************************************************************************************************************
 * Transpiler Tasks
 **********************************************************************************************************************/

gulp.task('compile-templates', function() {
    return gulp.src(sources.templates)
    .pipe(minifyHTML())
    .pipe(templateCache(
        compiledAngularTemplateCacheFilename, {
            module: 'Templates',
            moduleSystem: 'Browserify',
            standalone: true
        }))
    .pipe(gulp.dest(sources.build));
});

gulp.task('compile-typescript', function() {
    return gulp.src(sources.ts)
    .pipe(ts({
        module: 'commonjs'
    }))
    .pipe(gulp.dest(sources.build));
});

gulp.task('compile-stylus', function() {
    return gulp.src(sources.stylus)
    .pipe(stylus())
    .pipe(concat(compiledCssFilename))
    .pipe(gulp.dest(isPackageRelease ? sources.dist : sources.build))
    .pipe(gulpif(isWatchAndRun, livereload()));
});

/***********************************************************************************************************************
 * Bulk Tasks
 **********************************************************************************************************************/

gulp.task('watches', function() {

    gulp.watch(sources.html, ['copy-index-html']);
    gulp.watch(sources.stylus, ['compile-stylus']);
    gulp.watch(sources.ts, ['compile-typescript']);
    gulp.watch(sources.templates, ['compile-templates']);
    gulp.watch(sources.assets, ['copy-assets']);

    // post-build watcher(s)
    gulp.watch([
        path.join(sources.build, compiledJsFilename),
        path.join(sources.build, appIndexHtmlFilename)
    ], {
        debounceDelay: 1000
    })
    .on('change', function(event) {
        if (isWatchAndRun) {
            reload(event);
        }
    });
});

/***********************************************************************************************************************
 * Common Tasks
 **********************************************************************************************************************/

gulp.task('build', function() {
    runSequence(
        'clean',
        [
            'copy-assets',
            'copy-index-html',
            'compile-typescript',
            'compile-templates'
        ],
        'compile-stylus',
        'browserify'
    );
});

gulp.task('run', function() {
    runSequence(
        'start-server'
    );
});

gulp.task('watch', function() {
    runSequence(
        'watchify',
        'watches'
    );
});

gulp.task('watchrun', function() {
    isWatchAndRun = true;

    runSequence(
        'clean',
        [
            'copy-assets',
            'copy-index-html',
            'compile-typescript',
            'compile-templates'
        ],
        'compile-stylus',
        'browserify-vendors',
        'browserify',
        'watches',
        'watchify',
        'start-livereload',
        'run'
    );
});

gulp.task('release', function() {
    isPackageRelease = true;
    runSequence(
        'clean',
        [
            'copy-assets',
            'copy-index-html',
            'compile-typescript',
            'compile-templates'
        ],
        'compile-stylus',
        'browserify-vendors',
        'browserify',
        'minify-js',
        'minify-css'
    );
});

gulp.task('releaserun', function() {
    isPackageRun = true;
    isPackageRelease = true;
    runSequence(
        'release',
        'run'
    );
});

gulp.task('default', ['watchrun']);<|endoftext|>


<commit_before>export {
  default
} from 'https://www.lactame.com//lib/molecular-formula/0.42.0/molecular-formula.js';
// } from 'http://localhost:9898/cheminfo-js/molecular-formula/dist/molecular-formula.js';
<commit_msg>chore: update molecular-formula to 0.42.1<commit_after>export {
  default
} from 'https://www.lactame.com//lib/molecular-formula/0.42.1/molecular-formula.js';
// } from 'http://localhost:9898/cheminfo-js/molecular-formula/dist/molecular-formula.js';
<|endoftext|>


<commit_before>import * as d3 from 'd3';
import _ from 'lodash';
import { d3keybinding } from '../lib/d3.keybinding.js';
import { t } from '../util/locale';
import { modeBrowse, modeSelect } from './index';
import { actionNoop, actionRotateWay } from '../actions/index';
import { behaviorEdit } from '../behavior/index';

export function modeRotate(context, wayId) {
    var mode = {
        id: 'rotate',
        button: 'browse'
    };

    var keybinding = d3keybinding('rotate'),
        edit = behaviorEdit(context);

    mode.enter = function() {
        context.install(edit);

        var annotation = t('operations.rotate.annotation.' + context.geometry(wayId)),
            way = context.graph().entity(wayId),
            nodes = _.uniq(context.graph().childNodes(way)),
            points = nodes.map(function(n) { return context.projection(n.loc); }),
            pivot = d3.polygonCentroid(points),
            angle;

        context.perform(
            actionNoop(),
            annotation
        );

        context.surface()
            .on('mousemove.rotate', rotate)
            .on('click.rotate', finish);

        context.history()
            .on('undone.rotate', undone);

        keybinding
            .on('⎋', cancel)
            .on('↩', finish);

        d3.select(document)
            .call(keybinding);

        function rotate() {
            var mousePoint = context.mouse(),
                newAngle = Math.atan2(mousePoint[1] - pivot[1], mousePoint[0] - pivot[0]);

            if (typeof angle === 'undefined') angle = newAngle;

            context.replace(
                actionRotateWay(wayId, pivot, newAngle - angle, context.projection),
                annotation
            );

            angle = newAngle;
        }

        function finish() {
            d3.event.stopPropagation();
            context.enter(modeSelect(context, [wayId]).suppressMenu(true));
        }

        function cancel() {
            context.pop();
            context.enter(modeSelect(context, [wayId]).suppressMenu(true));
        }

        function undone() {
            context.enter(modeBrowse(context));
        }
    };

    mode.exit = function() {
        context.uninstall(edit);

        context.surface()
            .on('mousemove.rotate', null)
            .on('click.rotate', null);

        context.history()
            .on('undone.rotate', null);

        keybinding.off();
    };

    return mode;
}
<commit_msg>Support behaviors in Rotate mode<commit_after>import * as d3 from 'd3';
import _ from 'lodash';
import { d3keybinding } from '../lib/d3.keybinding.js';
import { t } from '../util/locale';

import {
    actionNoop,
    actionRotateWay
} from '../actions/index';

import { behaviorEdit } from '../behavior/index';

import {
    modeBrowse,
    modeSelect
} from './index';

import {
    operationCircularize,
    operationDelete,
    operationMove,
    operationOrthogonalize,
    operationReflectLong,
    operationReflectShort
} from '../operations/index';

export function modeRotate(context, wayId) {
    var mode = {
        id: 'rotate',
        button: 'browse'
    };

    var keybinding = d3keybinding('rotate'),
        behaviors = [
            behaviorEdit(context),
            operationCircularize([wayId], context).behavior,
            operationDelete([wayId], context).behavior,
            operationMove([wayId], context).behavior,
            operationOrthogonalize([wayId], context).behavior,
            operationReflectLong([wayId], context).behavior,
            operationReflectShort([wayId], context).behavior
        ],
        prevGraph,
        prevAngle,
        pivot;

    mode.enter = function() {
        var way = context.graph().entity(wayId),
            nodes = _.uniq(context.graph().childNodes(way)),
            points = nodes.map(function(n) { return context.projection(n.loc); });

        pivot = d3.polygonCentroid(points);

        behaviors.forEach(function(behavior) {
            context.install(behavior);
        });

        var annotation = t('operations.rotate.annotation.' + context.geometry(wayId));

        context.perform(actionNoop(), annotation);

        context.surface()
            .on('mousemove.rotate', doRotate)
            .on('click.rotate', finish);

        context.history()
            .on('undone.rotate', undone);

        keybinding
            .on('⎋', cancel)
            .on('↩', finish);

        d3.select(document)
            .call(keybinding);

        function doRotate() {
            var fn;
            if (prevGraph !== context.graph()) {
                fn = context.perform;
            } else {
                fn = context.replace;
            }

            var currMouse = context.mouse(),
                currAngle = Math.atan2(currMouse[1] - pivot[1], currMouse[0] - pivot[0]);

            if (typeof prevAngle === 'undefined') prevAngle = currAngle;
            var delta = currAngle - prevAngle;

            fn(actionRotateWay(wayId, pivot, delta, context.projection), annotation);
            prevAngle = currAngle;
            prevGraph = context.graph();
        }

        function finish() {
            d3.event.stopPropagation();
            context.enter(modeSelect(context, [wayId]).suppressMenu(true));
        }

        function cancel() {
            context.pop();
            context.enter(modeSelect(context, [wayId]).suppressMenu(true));
        }

        function undone() {
            context.enter(modeBrowse(context));
        }
    };

    mode.exit = function() {
        behaviors.forEach(function(behavior) {
            context.uninstall(behavior);
        });

        context.surface()
            .on('mousemove.rotate', null)
            .on('click.rotate', null);

        context.history()
            .on('undone.rotate', null);

        keybinding.off();
    };

    return mode;
}
<|endoftext|>


<commit_before>'use strict';
var path = require('path');
var assert = require('yeoman-assert');
var helpers = require('yeoman-generator').test;

describe('generator-ngpack:app', function () {
  before(function (done) {
    helpers.run(path.join(__dirname, '../generators/app'))
      .withOptions({someOption: true})
      .withPrompts({someAnswer: true})
      .on('end', done);
  });

  it('creates files', function () {
    assert.file([
      'dummyfile.txt'
    ]);
  });
});
<commit_msg>Unit tests for app generator<commit_after>'use strict';
var path = require('path');
var assert = require('yeoman-assert');
var helpers = require('yeoman-generator').test;

describe('generator-ng-bat:app', function () {
  var prompts = {
    name: 'tumblr',
    repository: 'https://github.com/batman/tumblr',
    license: 'MIT'
  };
  before(function (done) {
    helpers.run(path.join(__dirname, '../generators/app'))
      .withOptions({/*No options functionality so far*/})
      .withPrompts(prompts)
      .on('end', done);
  });

  it('creates files', function () {
    assert.file([
      '.editorconfig',
      '.eslintrc',
      '.gitignore',
      'package.json',
      'README.md',
      'robots.txt',
      'webpack.config.js',
      'app/index.html',
      'app/images/angular.png',
      'app/images/webpack.png',
      'app/src/app.module.js',
      'app/src/common/common.module.js',
      'app/src/common/common.scss',
      'app/src/core/core.module.js',
      'app/src/core/core.scss',
      'app/src/core/restangular.config.js',
      'app/src/core/router.config.js',
      'app/src/core/router.run.js',
      'app/src/welcome/welcome.controller.js',
      'app/src/welcome/welcome.html',
      'app/src/welcome/welcome.module.js',
      'app/src/welcome/welcome.scss'
    ]);
  });

  it('populates package.json', function () {
    assert.JSONFileContent('package.json', prompts);
  });

});
<|endoftext|>


<commit_before>/**
 * @fileoverview A binary heap container.
 * Based on the `heapq` module in Python's standard library.
 */

/**
 * Binary heap container.
 * @constructor
 * @param {Function(a, b)->boolean} [cmpFunc] A comparison function which
 *     returns whether it's first argument is less than the second argument.
 *     If this argument is not provided, then the `<` operator will be used.
 */
PF.Heap = function(cmpFunc) {
    /**
     * Comparison function.
     * @type Function(a, b)->boolean
     * @private
     */
    this._cmp = cmpFunc || function(a, b) {return a < b;};

    /**
     * An array as a heap.
     * @type Array
     * @private
     */
    this._heap = [];
};

/**
 * Get the top(smallest) item from the heap.
 */
PF.Heap.prototype.top = function() {
    return this._heap[0];
};

/**
 * Get the size of the heap.
 * @return {integer} The number of items in the heap.
 */
PF.Heap.prototype.size = function() {
    return this._heap.length;
};

/**
 * Determine whether the heap is empty.
 * @return {boolean}
 */
PF.Heap.prototype.isEmpty = function() {
    return !this.size();
};

/**
 * Push an item onto the heap.
 */
PF.Heap.prototype.push = function(item) {
    var heap = this._heap;

    heap.push(item);
    this._siftDown(0, heap.length - 1);
};

/**
 * Pop the smallest item off the heap.
 */
PF.Heap.prototype.pop = function() {
    var heap, lastItem, returnItem;

    heap= this._heap;
    lastItem = heap.pop();

    if (heap.length) {
        returnItem = heap[0];
        heap[0] = lastItem;
        this._siftUp(0);
    } else {
        returnItem = lastItem;
    }
    return returnItem;
};

/**
 * Pop and return the current smallest value, and add the new item.
 *
 * This is more efficient than `pop()` followed by `push()`, and can be
 * more appropriate when using a fixed-size heap. Note that the value
 * returned may be larger than the pushed item! That constrains reasonable
 * uses of this routine unless written as part of a conditional replacement.
 *
 * {@code
 *     if (item > heap.top()) {
 *         item = heap.replace(item);
 *     }
 * }
 */
PF.Heap.prototype.replace = function(item) {
    var returnItem = this._heap[0];
    this._heap[0] = item;
    this._siftUp(0);
    return returnItem;
};

/**
 * Sift down the possibly out-of-order value.
 * @param {integer} startPos Start index of the array as a heap.
 * @param {integer} pos Index of the leaf with possiblly out-of-order value.
 * @private
 */
PF.Heap.prototype._siftDown = function(startPos, pos) {
    var heap, cmp, newItem, parentPos, parent;

    heap = this._heap;
    cmp = this._cmp;
    newItem = heap[pos];

    // Follow the path to the root, moving parents down until finding a place
    // newItem fits.
    while (pos > startPos) {
        parentPos = (pos - 1) >> 1;
        parent = heap[parentPos];
        if (cmp(newItem, parent)) {
            heap[pos] = parent;
            pos = parentPos;
            continue;
        }
        break;
    }
    heap[pos] = newItem;
};

/**
 * Sift up the possibly out-of-order value.
 * @param {integer} pos Index of leaf with possibly out-of-order value.
 * @private
 */
PF.Heap.prototype._siftUp = function(pos) {
    var heap, cmp, endPos, startPos, newItem, childPos, rightPos;

    cmp = this._cmp;
    heap = this._heap;
    endPos = heap.length;
    startPos = pos;
    newItem = heap[pos];

    // Bubble up the smaller child until hitting a leaf.
    childPos = 2 * pos + 1; // leftmost child position
    while (childPos < endPos) {
        // Set childPos to index of smaller child.
        rightPos = childPos + 1;
        if (rightPos < endPos && !cmp(heap[childPos], heap[rightPos])) {
            childPos = rightPos;
        }
        // Move the smaller child up.
        heap[pos] = heap[childPos];
        pos = childPos;
        childPos = 2 * pos + 1;
    }
    // The leaf at pos is empty now. Put newItem here, and bubble it up
    // to its final resting place (by sifting its parent down).
    heap[pos] = newItem;
    this._siftDown(startPos, pos);
};
<commit_msg>add: `pushpop` method to modules/Heap.js<commit_after>/**
 * @fileoverview A binary heap container.
 * Based on the `heapq` module in Python's standard library.
 */

/**
 * Binary heap container.
 * @constructor
 * @param {Function(a, b)->boolean} [cmpFunc] A comparison function which
 *     returns whether it's first argument is less than the second argument.
 *     If this argument is not provided, then the `<` operator will be used.
 */
PF.Heap = function(cmpFunc) {
    /**
     * Comparison function.
     * @type Function(a, b)->boolean
     * @private
     */
    this._cmp = cmpFunc || function(a, b) {return a < b;};

    /**
     * An array as a heap.
     * @type Array
     * @private
     */
    this._heap = [];
};

/**
 * Get the top(smallest) item from the heap.
 */
PF.Heap.prototype.top = function() {
    return this._heap[0];
};

/**
 * Get the size of the heap.
 * @return {integer} The number of items in the heap.
 */
PF.Heap.prototype.size = function() {
    return this._heap.length;
};

/**
 * Determine whether the heap is empty.
 * @return {boolean}
 */
PF.Heap.prototype.isEmpty = function() {
    return !this.size();
};

/**
 * Push an item onto the heap.
 */
PF.Heap.prototype.push = function(item) {
    var heap = this._heap;

    heap.push(item);
    this._siftDown(0, heap.length - 1);
};

/**
 * Pop the smallest item off the heap.
 */
PF.Heap.prototype.pop = function() {
    var heap, lastItem, returnItem;

    heap= this._heap;
    lastItem = heap.pop();

    if (heap.length) {
        returnItem = heap[0];
        heap[0] = lastItem;
        this._siftUp(0);
    } else {
        returnItem = lastItem;
    }
    return returnItem;
};

/**
 * Pop and return the current smallest value, and add the new item.
 *
 * This is more efficient than `pop()` followed by `push()`, and can be
 * more appropriate when using a fixed-size heap. Note that the value
 * returned may be larger than the pushed item! That constrains reasonable
 * uses of this routine unless written as part of a conditional replacement.
 *
 * {@code
 *     if (item > heap.top()) {
 *         item = heap.replace(item);
 *     }
 * }
 */
PF.Heap.prototype.replace = function(item) {
    var returnItem = this._heap[0];
    this._heap[0] = item;
    this._siftUp(0);
    return returnItem;
};

/**
 * Fast version of a push followed by a pop.
 */
PF.Heap.prototype.pushpop = function(item) {
    var heap = this._heap, t;

    if (heap.length && this._cmp(heap[0], item)) {
        t = heap[0];
        heap[0] = item;
        item = t;
        this._siftUp(0);
    }
    return item;
};

/**
 * Sift down the possibly out-of-order value.
 * @param {integer} startPos Start index of the array as a heap.
 * @param {integer} pos Index of the leaf with possiblly out-of-order value.
 * @private
 */
PF.Heap.prototype._siftDown = function(startPos, pos) {
    var heap, cmp, newItem, parentPos, parent;

    heap = this._heap;
    cmp = this._cmp;
    newItem = heap[pos];

    // Follow the path to the root, moving parents down until finding a place
    // newItem fits.
    while (pos > startPos) {
        parentPos = (pos - 1) >> 1;
        parent = heap[parentPos];
        if (cmp(newItem, parent)) {
            heap[pos] = parent;
            pos = parentPos;
            continue;
        }
        break;
    }
    heap[pos] = newItem;
};

/**
 * Sift up the possibly out-of-order value.
 * @param {integer} pos Index of leaf with possibly out-of-order value.
 * @private
 */
PF.Heap.prototype._siftUp = function(pos) {
    var heap, cmp, endPos, startPos, newItem, childPos, rightPos;

    cmp = this._cmp;
    heap = this._heap;
    endPos = heap.length;
    startPos = pos;
    newItem = heap[pos];

    // Bubble up the smaller child until hitting a leaf.
    childPos = 2 * pos + 1; // leftmost child position
    while (childPos < endPos) {
        // Set childPos to index of smaller child.
        rightPos = childPos + 1;
        if (rightPos < endPos && !cmp(heap[childPos], heap[rightPos])) {
            childPos = rightPos;
        }
        // Move the smaller child up.
        heap[pos] = heap[childPos];
        pos = childPos;
        childPos = 2 * pos + 1;
    }
    // The leaf at pos is empty now. Put newItem here, and bubble it up
    // to its final resting place (by sifting its parent down).
    heap[pos] = newItem;
    this._siftDown(startPos, pos);
};
<|endoftext|>


<commit_before>/**
 * @file reputation command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

let recentUsers = [];
const COOLDOWN = 12;

exports.exec = async (Bastion, message) => {
  try {
    if (!recentUsers.includes(message.author.id)) {
      let user = message.mentions.users.first();
      if (!user) return;
      if (user.id === message.author.id) {
        /**
        * Error condition is encountered.
        * @fires error
        */
        return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'forbidden'), 'You can\'t give reputation to yourself!', message.channel);
      }

      let profile = await Bastion.db.get(`SELECT reputation FROM profiles WHERE userID=${user.id}`);
      if (!profile) {
        await Bastion.db.run('INSERT INTO profiles (userID, reputation) VALUES (?, ?)', [ user.id, 1 ]);
      }
      else {
        await Bastion.db.run(`UPDATE profiles SET reputation=${parseInt(profile.reputation) + 1} WHERE userID=${user.id}`);
      }

      recentUsers.push(message.author.id);
      setTimeout(() => {
        recentUsers.splice(recentUsers.indexOf(message.author.id), 1);
      }, COOLDOWN * 60 * 60 * 1000);

      message.channel.send({
        embed: {
          color: Bastion.colors.GREEN,
          description: `You have given one reputation to ${user.tag}`
        }
      }).catch(e => {
        Bastion.log.error(e);
      });
    }
    else {
      /**
      * Error condition is encountered.
      * @fires error
      */
      return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'cooldown'), `You have recently given reputation to someone, please wait at least ${COOLDOWN} hours before giving reputation again.`, message.channel);
    }
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [ 'rep' ],
  enabled: true
};

exports.help = {
  name: 'reputation',
  botPermission: '',
  userTextPermission: '',
  userVoicePermission: '',
  usage: 'reputation <@USER_MENTION>',
  example: [ 'reputation @k3rn31p4nic#8383' ]
};
<commit_msg>Update reputation.js<commit_after>/**
 * @file reputation command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

let recentUsers = [];
const COOLDOWN = 12;

exports.exec = async (Bastion, message, args) => {
  try {
    if (/^tay(?:lor)?(?: alison)?(?: swift)?$/i.test(args && args.join(' '))) {
      let reputationLyrics = [
        'Big **reputation**, big **reputation**\nOoh, you and me, we got big **reputations**, ah\nAnd you heard about me, ooh',
        'Big **reputation**, big **reputation**\nOoh, you and me would be a big conversation, ah\nAnd I heard about you, ooh',
        'I got a **reputation**, girl, that don\'t precede me\nI\'m one call away whenever you need me',
        'I got issues and chips on both of my shoulders\n**Reputation** precedes me, in rumors, I\'m knee-deep'
      ]
      return message.channel.send({
        embed: {
          description: reputationLyrics[Math.floor(Math.random() * reputationLyrics.length)]
        }
      })
    }

    if (!recentUsers.includes(message.author.id)) {
      let user = message.mentions.users.first();
      if (!user) return;
      if (user.id === message.author.id) {
        /**
        * Error condition is encountered.
        * @fires error
        */
        return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'forbidden'), 'You can\'t give reputation to yourself!', message.channel);
      }

      let profile = await Bastion.db.get(`SELECT reputation FROM profiles WHERE userID=${user.id}`);
      if (!profile) {
        await Bastion.db.run('INSERT INTO profiles (userID, reputation) VALUES (?, ?)', [ user.id, 1 ]);
      }
      else {
        await Bastion.db.run(`UPDATE profiles SET reputation=${parseInt(profile.reputation) + 1} WHERE userID=${user.id}`);
      }

      recentUsers.push(message.author.id);
      setTimeout(() => {
        recentUsers.splice(recentUsers.indexOf(message.author.id), 1);
      }, COOLDOWN * 60 * 60 * 1000);

      message.channel.send({
        embed: {
          color: Bastion.colors.GREEN,
          description: `You have given one reputation to ${user.tag}`
        }
      }).catch(e => {
        Bastion.log.error(e);
      });
    }
    else {
      /**
      * Error condition is encountered.
      * @fires error
      */
      return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'cooldown'), `You have recently given reputation to someone, please wait at least ${COOLDOWN} hours before giving reputation again.`, message.channel);
    }
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [ 'rep' ],
  enabled: true
};

exports.help = {
  name: 'reputation',
  botPermission: '',
  userTextPermission: '',
  userVoicePermission: '',
  usage: 'reputation <@USER_MENTION>',
  example: [ 'reputation @k3rn31p4nic#8383' ]
};
<|endoftext|>


<commit_before>'use strict';

var Validator = require('validator')
  , Utils = require('./utils')
  , sequelizeError = require('./errors')
  , Promise = require('./promise')
  , DataTypes = require('./data-types')
  , _ = require('lodash');

function noop() {}

// Deprecate this.
Validator.notNull = function() {
  throw new Error('Warning "notNull" validation has been deprecated in favor of Schema based "allowNull"');
};

// https://github.com/chriso/validator.js/blob/1.5.0/lib/validators.js

Validator.extend('notEmpty', function(str) {
  return !str.match(/^[\s\t\r\n]*$/);
});

Validator.extend('len', function(str, min, max) {
  return this.isLength(str, min, max);
});

Validator.extend('isUrl', function(str) {
  return this.isURL(str);
});

Validator.extend('isIPv6', function(str) {
  return this.isIP(str, 6);
});

Validator.extend('isIPv4', function(str) {
  return this.isIP(str, 4);
});

Validator.extend('notIn', function(str, values) {
  return !this.isIn(str, values);
});

Validator.extend('regex', function(str, pattern, modifiers) {
  str += '';
  if (Object.prototype.toString.call(pattern).slice(8, -1) !== 'RegExp') {
    pattern = new RegExp(pattern, modifiers);
  }
  return str.match(pattern);
});

Validator.extend('notRegex', function(str, pattern, modifiers) {
  return !this.regex(str, pattern, modifiers);
});

Validator.extend('isDecimal', function(str) {
  return str !== '' && str.match(/^(?:-?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/);
});

Validator.extend('min', function(str, val) {
  var number = parseFloat(str);
  return isNaN(number) || number >= val;
});

Validator.extend('max', function(str, val) {
  var number = parseFloat(str);
  return isNaN(number) || number <= val;
});

Validator.extend('not', function(str, pattern, modifiers) {
  return this.notRegex(str, pattern, modifiers);
});

Validator.extend('contains', function(str, elem) {
  return str.indexOf(elem) >= 0 && !!elem;
});

Validator.extend('notContains', function(str, elem) {
  return !this.contains(str, elem);
});

Validator.extend('is', function(str, pattern, modifiers) {
  return this.regex(str, pattern, modifiers);
});

function extendModelValidations(modelInstance) {
  Validator.extend('isImmutable', function(str, param, field) {
    return (modelInstance.isNewRecord || modelInstance.dataValues[field] === modelInstance._previousDataValues[field]);
  });
}

/**
 * The Main DAO Validator.
 *
 * @param {DAO} modelInstance The model instance.
 * @param {Object} options A dict with options.
 * @constructor
 */
var InstanceValidator = module.exports = function(modelInstance, options) {
  options = options || {};

  if (options.fields && !options.skip) {
    options.skip = Utils._.difference(Object.keys(modelInstance.Model.attributes), options.fields);
  }

  // assign defined and default options
  this.options = Utils._.defaults(options, {
    skip: []
  });

  this.modelInstance = modelInstance;

  /**
   * Exposes a reference to validator.js. This allows you to add custom validations using `Validator.extend`
   * @name Validator
   */
  this.Validator = Validator;

  /**
   *  All errors will be stored here from the validations.
   *
   * @type {Array} Will contain keys that correspond to attributes which will
   *   be Arrays of Errors.
   */
  this.errors = [];

  /** @type {boolean} Indicates if validations are in progress */
  this.inProgress = false;

  extendModelValidations(modelInstance);
};

/** @define {string} The error key for arguments as passed by custom validators */
InstanceValidator.RAW_KEY_NAME = '__raw';

/**
 * The main entry point for the Validation module, invoke to start the dance.
 *
 * @return {Promise}
 */
InstanceValidator.prototype.validate = function() {
  if (this.inProgress) {
    throw new Error('Validations already in progress.');
  }
  this.inProgress = true;

  var self = this;
  return Promise.settle([
    self._builtinValidators(),
    self._customValidators()
  ]).then(function() {
    if (self.errors.length) {
      return new sequelizeError.ValidationError('Validation error', self.errors);
    }

    return new Promise(function(resolve) {
      resolve();
    });
  });
};

/**
 * Invoke the Validation sequence:
 *   - Before Validation Model Hooks
 *   - Validation
 *   - After Validation Model Hooks
 *
 * @return {Promise}
 */
InstanceValidator.prototype.hookValidate = function() {
  var self = this;
  return self.modelInstance.Model.runHooks('beforeValidate', self.modelInstance, self.options).then(function() {
    return self.validate().then(function(error) {
      if (error) {
        throw error;
      }
    });
  }).then(function() {
    return self.modelInstance.Model.runHooks('afterValidate', self.modelInstance, self.options);
  }).return(self.modelInstance);
};

/**
 * Will run all the built-in validators.
 *
 * @return {Promise(Array.<Promise.PromiseInspection>)} A promise from .settle().
 * @private
 */
InstanceValidator.prototype._builtinValidators = function() {
  var self = this;

  // promisify all attribute invocations
  var validators = [];
  Utils._.forIn(this.modelInstance.rawAttributes, function(rawAttribute, field) {
    if (self.options.skip.indexOf(field) >= 0) {
      return;
    }

    var value = self.modelInstance.dataValues[field];

    if (!rawAttribute._autoGenerated && !rawAttribute.autoIncrement) {
      // perform validations based on schema
      self._validateSchema(rawAttribute, field, value);
    }

    if (self.modelInstance.validators.hasOwnProperty(field)) {
      validators.push(self._builtinAttrValidate.call(self, value, field));
    }
  });

  return Promise.settle(validators);
};

/**
 * Will run all the custom validators.
 *
 * @return {Promise(Array.<Promise.PromiseInspection>)} A promise from .settle().
 * @private
 */
InstanceValidator.prototype._customValidators = function() {

  var validators = [];
  var self = this;
  Utils._.each(this.modelInstance.__options.validate, function(validator,
    validatorType) {

    var valprom = self._invokeCustomValidator(validator, validatorType)
      // errors are handled in settling, stub this
      .catch(noop);

    validators.push(valprom);
  });

  return Promise.settle(validators);
};

/**
 * Validate a single attribute with all the defined built-in validators.
 *
 * @param {*} value Anything.
 * @param {string} field The field name.
 * @return {Promise} A promise, will always resolve,
 *   auto populates error on this.error local object.
 * @private
 */
InstanceValidator.prototype._builtinAttrValidate = function(value, field) {
  var self = this;
  // check if value is null (if null not allowed the Schema pass will capture it)
  if (value === null || typeof value === 'undefined') {
    return Promise.resolve();
  }

  // Promisify each validator
  var validators = [];
  Utils._.forIn(this.modelInstance.validators[field], function(test,
    validatorType) {
    if (['isUrl', 'isURL'].indexOf(validatorType) !== -1 && test === true) {
      // Preserve backwards compat. Validator.js now expects the second param to isURL to be an object
      test = {};
    }

    // Check for custom validator.
    if (typeof test === 'function') {
      return validators.push(self._invokeCustomValidator(test, validatorType, true, value, field));
    }

    var validatorPromise = self._invokeBuiltinValidator(value, test, validatorType, field);
    // errors are handled in settling, stub this
    validatorPromise.catch(noop);
    validators.push(validatorPromise);
  });

  return Promise.settle(validators)
    .then(this._handleSettledResult.bind(this, field));
};

/**
 * Prepare and invoke a custom validator.
 *
 * @param {Function} validator The custom validator.
 * @param {string} validatorType the custom validator type (name).
 * @param {boolean=} optAttrDefined Set to true if custom validator was defined
 *   from the Attribute
 * @return {Promise} A promise.
 * @private
 */
InstanceValidator.prototype._invokeCustomValidator = Promise.method(function(validator, validatorType, optAttrDefined, optValue, optField) {
  var validatorFunction = null;  // the validation function to call
  var isAsync = false;

  var validatorArity = validator.length;
  // check if validator is async and requires a callback
  var asyncArity = 1;
  var errorKey = validatorType;
  var invokeArgs;
  if (optAttrDefined) {
    asyncArity = 2;
    invokeArgs = optValue;
    errorKey = optField;
  }
  if (validatorArity === asyncArity) {
    isAsync = true;
  }

  if (isAsync) {
    if (optAttrDefined) {
      validatorFunction = Promise.promisify(validator.bind(this.modelInstance, invokeArgs));
    } else {
      validatorFunction = Promise.promisify(validator.bind(this.modelInstance));
    }
    return validatorFunction()
      .catch(this._pushError.bind(this, false, errorKey));
  } else {
    return Promise.try(validator.bind(this.modelInstance, invokeArgs))
      .catch(this._pushError.bind(this, false, errorKey));
  }
});

/**
 * Prepare and invoke a build-in validator.
 *
 * @param {*} value Anything.
 * @param {*} test The test case.
 * @param {string} validatorType One of known to Sequelize validators.
 * @param {string} field The field that is being validated
 * @return {Object} An object with specific keys to invoke the validator.
 * @private
 */
InstanceValidator.prototype._invokeBuiltinValidator = Promise.method(function(value, test, validatorType, field) {

  // check if Validator knows that kind of validation test
  if (typeof Validator[validatorType] !== 'function') {
    throw new Error('Invalid validator function: ' + validatorType);
  }

  // extract extra arguments for the validator
  var validatorArgs = test.hasOwnProperty('args') || test.hasOwnProperty('msg') ? test.args : test;

  // extract the error msg
  var errorMessage = test.hasOwnProperty('msg') && test.msg ? test.msg :
    'Validation ' + validatorType + ' failed';

  if (!Array.isArray(validatorArgs)) {
    validatorArgs = [validatorArgs];
  } else {
    validatorArgs = validatorArgs.slice(0);
  }
  validatorArgs.push(field);
  if (!Validator[validatorType].apply(Validator, [value].concat(validatorArgs))) {
    throw errorMessage;
  }
});

/**
 * Will validate a single field against its schema definition (isnull).
 *
 * @param {Object} rawAttribute As defined in the Schema.
 * @param {string} field The field name.
 * @param {*} value anything.
 * @private
 */
InstanceValidator.prototype._validateSchema = function(rawAttribute, field, value) {
  var error;

  if (rawAttribute.allowNull === false && ((value === null) || (value === undefined))) {
    error = new sequelizeError.ValidationErrorItem(field + ' cannot be null', 'notNull Violation', field, value);
    this.errors.push(error);
  }

  if (rawAttribute.type === DataTypes.STRING || rawAttribute.type instanceof DataTypes.STRING || rawAttribute.type === DataTypes.TEXT || rawAttribute.type instanceof DataTypes.TEXT) {
    if (Array.isArray(value) || (_.isObject(value) && !value._isSequelizeMethod) && !Buffer.isBuffer(value)) {
      error = new sequelizeError.ValidationErrorItem(field + ' cannot be an array or an object', 'string violation', field, value);
      this.errors.push(error);
    }
  }
};

/**
 * Handles the returned result of a Promise.settle.
 *
 * If errors are found it populates this.error.
 *
 * @param {string} field The attribute name.
 * @param {Array.<Promise.PromiseInspection>} Promise inspection objects.
 * @private
 */
InstanceValidator.prototype._handleSettledResult = function(field, promiseInspections) {
  var self = this;
  promiseInspections.forEach(function(promiseInspection) {
    if (promiseInspection.isRejected()) {
      var rejection = promiseInspection.error();
      self._pushError(true, field, rejection);
    }
  });
};

/**
 * Signs all errors retaining the original.
 *
 * @param {boolean} isBuiltin Determines if error is from builtin validator.
 * @param {string} errorKey The error key to assign on this.errors object.
 * @param {Error|string} rawError The original error.
 * @private
 */
InstanceValidator.prototype._pushError = function(isBuiltin, errorKey, rawError) {
  var message = rawError.message || rawError || 'Validation error';
  var error = new sequelizeError.ValidationErrorItem(message, 'Validation error', errorKey, rawError);
  error[InstanceValidator.RAW_KEY_NAME] = rawError;

  this.errors.push(error);
};
<commit_msg>Fix for isEmail validator in iojs / node 0.12<commit_after>'use strict';

var Validator = require('validator')
  , Utils = require('./utils')
  , sequelizeError = require('./errors')
  , Promise = require('./promise')
  , DataTypes = require('./data-types')
  , _ = require('lodash');

function noop() {}

// Deprecate this.
Validator.notNull = function() {
  throw new Error('Warning "notNull" validation has been deprecated in favor of Schema based "allowNull"');
};

// https://github.com/chriso/validator.js/blob/1.5.0/lib/validators.js

Validator.extend('notEmpty', function(str) {
  return !str.match(/^[\s\t\r\n]*$/);
});

Validator.extend('len', function(str, min, max) {
  return this.isLength(str, min, max);
});

Validator.extend('isUrl', function(str) {
  return this.isURL(str);
});

Validator.extend('isIPv6', function(str) {
  return this.isIP(str, 6);
});

Validator.extend('isIPv4', function(str) {
  return this.isIP(str, 4);
});

Validator.extend('notIn', function(str, values) {
  return !this.isIn(str, values);
});

Validator.extend('regex', function(str, pattern, modifiers) {
  str += '';
  if (Object.prototype.toString.call(pattern).slice(8, -1) !== 'RegExp') {
    pattern = new RegExp(pattern, modifiers);
  }
  return str.match(pattern);
});

Validator.extend('notRegex', function(str, pattern, modifiers) {
  return !this.regex(str, pattern, modifiers);
});

Validator.extend('isDecimal', function(str) {
  return str !== '' && str.match(/^(?:-?(?:[0-9]+))?(?:\.[0-9]*)?(?:[eE][\+\-]?(?:[0-9]+))?$/);
});

Validator.extend('min', function(str, val) {
  var number = parseFloat(str);
  return isNaN(number) || number >= val;
});

Validator.extend('max', function(str, val) {
  var number = parseFloat(str);
  return isNaN(number) || number <= val;
});

Validator.extend('not', function(str, pattern, modifiers) {
  return this.notRegex(str, pattern, modifiers);
});

Validator.extend('contains', function(str, elem) {
  return str.indexOf(elem) >= 0 && !!elem;
});

Validator.extend('notContains', function(str, elem) {
  return !this.contains(str, elem);
});

Validator.extend('is', function(str, pattern, modifiers) {
  return this.regex(str, pattern, modifiers);
});

function extendModelValidations(modelInstance) {
  Validator.extend('isImmutable', function(str, param, field) {
    return (modelInstance.isNewRecord || modelInstance.dataValues[field] === modelInstance._previousDataValues[field]);
  });
}

/**
 * The Main DAO Validator.
 *
 * @param {DAO} modelInstance The model instance.
 * @param {Object} options A dict with options.
 * @constructor
 */
var InstanceValidator = module.exports = function(modelInstance, options) {
  options = options || {};

  if (options.fields && !options.skip) {
    options.skip = Utils._.difference(Object.keys(modelInstance.Model.attributes), options.fields);
  }

  // assign defined and default options
  this.options = Utils._.defaults(options, {
    skip: []
  });

  this.modelInstance = modelInstance;

  /**
   * Exposes a reference to validator.js. This allows you to add custom validations using `Validator.extend`
   * @name Validator
   */
  this.Validator = Validator;

  /**
   *  All errors will be stored here from the validations.
   *
   * @type {Array} Will contain keys that correspond to attributes which will
   *   be Arrays of Errors.
   */
  this.errors = [];

  /** @type {boolean} Indicates if validations are in progress */
  this.inProgress = false;

  extendModelValidations(modelInstance);
};

/** @define {string} The error key for arguments as passed by custom validators */
InstanceValidator.RAW_KEY_NAME = '__raw';

/**
 * The main entry point for the Validation module, invoke to start the dance.
 *
 * @return {Promise}
 */
InstanceValidator.prototype.validate = function() {
  if (this.inProgress) {
    throw new Error('Validations already in progress.');
  }
  this.inProgress = true;

  var self = this;
  return Promise.settle([
    self._builtinValidators(),
    self._customValidators()
  ]).then(function() {
    if (self.errors.length) {
      return new sequelizeError.ValidationError('Validation error', self.errors);
    }

    return new Promise(function(resolve) {
      resolve();
    });
  });
};

/**
 * Invoke the Validation sequence:
 *   - Before Validation Model Hooks
 *   - Validation
 *   - After Validation Model Hooks
 *
 * @return {Promise}
 */
InstanceValidator.prototype.hookValidate = function() {
  var self = this;
  return self.modelInstance.Model.runHooks('beforeValidate', self.modelInstance, self.options).then(function() {
    return self.validate().then(function(error) {
      if (error) {
        throw error;
      }
    });
  }).then(function() {
    return self.modelInstance.Model.runHooks('afterValidate', self.modelInstance, self.options);
  }).return(self.modelInstance);
};

/**
 * Will run all the built-in validators.
 *
 * @return {Promise(Array.<Promise.PromiseInspection>)} A promise from .settle().
 * @private
 */
InstanceValidator.prototype._builtinValidators = function() {
  var self = this;

  // promisify all attribute invocations
  var validators = [];
  Utils._.forIn(this.modelInstance.rawAttributes, function(rawAttribute, field) {
    if (self.options.skip.indexOf(field) >= 0) {
      return;
    }

    var value = self.modelInstance.dataValues[field];

    if (!rawAttribute._autoGenerated && !rawAttribute.autoIncrement) {
      // perform validations based on schema
      self._validateSchema(rawAttribute, field, value);
    }

    if (self.modelInstance.validators.hasOwnProperty(field)) {
      validators.push(self._builtinAttrValidate.call(self, value, field));
    }
  });

  return Promise.settle(validators);
};

/**
 * Will run all the custom validators.
 *
 * @return {Promise(Array.<Promise.PromiseInspection>)} A promise from .settle().
 * @private
 */
InstanceValidator.prototype._customValidators = function() {

  var validators = [];
  var self = this;
  Utils._.each(this.modelInstance.__options.validate, function(validator,
    validatorType) {

    var valprom = self._invokeCustomValidator(validator, validatorType)
      // errors are handled in settling, stub this
      .catch(noop);

    validators.push(valprom);
  });

  return Promise.settle(validators);
};

/**
 * Validate a single attribute with all the defined built-in validators.
 *
 * @param {*} value Anything.
 * @param {string} field The field name.
 * @return {Promise} A promise, will always resolve,
 *   auto populates error on this.error local object.
 * @private
 */
InstanceValidator.prototype._builtinAttrValidate = function(value, field) {
  var self = this;
  // check if value is null (if null not allowed the Schema pass will capture it)
  if (value === null || typeof value === 'undefined') {
    return Promise.resolve();
  }

  // Promisify each validator
  var validators = [];
  Utils._.forIn(this.modelInstance.validators[field], function(test,
    validatorType) {

    if (['isUrl', 'isURL', 'isEmail'].indexOf(validatorType) !== -1 && test === true) {
      // Preserve backwards compat. Validator.js now expects the second param to isURL and isEmail to be an object
      test = {};
    }

    // Check for custom validator.
    if (typeof test === 'function') {
      return validators.push(self._invokeCustomValidator(test, validatorType, true, value, field));
    }

    var validatorPromise = self._invokeBuiltinValidator(value, test, validatorType, field);
    // errors are handled in settling, stub this
    validatorPromise.catch(noop);
    validators.push(validatorPromise);
  });

  return Promise.settle(validators)
    .then(this._handleSettledResult.bind(this, field));
};

/**
 * Prepare and invoke a custom validator.
 *
 * @param {Function} validator The custom validator.
 * @param {string} validatorType the custom validator type (name).
 * @param {boolean=} optAttrDefined Set to true if custom validator was defined
 *   from the Attribute
 * @return {Promise} A promise.
 * @private
 */
InstanceValidator.prototype._invokeCustomValidator = Promise.method(function(validator, validatorType, optAttrDefined, optValue, optField) {
  var validatorFunction = null;  // the validation function to call
  var isAsync = false;

  var validatorArity = validator.length;
  // check if validator is async and requires a callback
  var asyncArity = 1;
  var errorKey = validatorType;
  var invokeArgs;
  if (optAttrDefined) {
    asyncArity = 2;
    invokeArgs = optValue;
    errorKey = optField;
  }
  if (validatorArity === asyncArity) {
    isAsync = true;
  }

  if (isAsync) {
    if (optAttrDefined) {
      validatorFunction = Promise.promisify(validator.bind(this.modelInstance, invokeArgs));
    } else {
      validatorFunction = Promise.promisify(validator.bind(this.modelInstance));
    }
    return validatorFunction()
      .catch(this._pushError.bind(this, false, errorKey));
  } else {
    return Promise.try(validator.bind(this.modelInstance, invokeArgs))
      .catch(this._pushError.bind(this, false, errorKey));
  }
});

/**
 * Prepare and invoke a build-in validator.
 *
 * @param {*} value Anything.
 * @param {*} test The test case.
 * @param {string} validatorType One of known to Sequelize validators.
 * @param {string} field The field that is being validated
 * @return {Object} An object with specific keys to invoke the validator.
 * @private
 */
InstanceValidator.prototype._invokeBuiltinValidator = Promise.method(function(value, test, validatorType, field) {
  // check if Validator knows that kind of validation test
  if (typeof Validator[validatorType] !== 'function') {
    throw new Error('Invalid validator function: ' + validatorType);
  }

  // extract extra arguments for the validator
  var validatorArgs = test.hasOwnProperty('args') || test.hasOwnProperty('msg') ? test.args : test;

  // extract the error msg
  var errorMessage = test.hasOwnProperty('msg') && test.msg ? test.msg :
    'Validation ' + validatorType + ' failed';

  if (!Array.isArray(validatorArgs)) {
    validatorArgs = [validatorArgs];
  } else {
    validatorArgs = validatorArgs.slice(0);
  }
  validatorArgs.push(field);

  if (!Validator[validatorType].apply(Validator, [value].concat(validatorArgs))) {
    throw errorMessage;
  }
});

/**
 * Will validate a single field against its schema definition (isnull).
 *
 * @param {Object} rawAttribute As defined in the Schema.
 * @param {string} field The field name.
 * @param {*} value anything.
 * @private
 */
InstanceValidator.prototype._validateSchema = function(rawAttribute, field, value) {
  var error;

  if (rawAttribute.allowNull === false && ((value === null) || (value === undefined))) {
    error = new sequelizeError.ValidationErrorItem(field + ' cannot be null', 'notNull Violation', field, value);
    this.errors.push(error);
  }

  if (rawAttribute.type === DataTypes.STRING || rawAttribute.type instanceof DataTypes.STRING || rawAttribute.type === DataTypes.TEXT || rawAttribute.type instanceof DataTypes.TEXT) {
    if (Array.isArray(value) || (_.isObject(value) && !value._isSequelizeMethod) && !Buffer.isBuffer(value)) {
      error = new sequelizeError.ValidationErrorItem(field + ' cannot be an array or an object', 'string violation', field, value);
      this.errors.push(error);
    }
  }
};

/**
 * Handles the returned result of a Promise.settle.
 *
 * If errors are found it populates this.error.
 *
 * @param {string} field The attribute name.
 * @param {Array.<Promise.PromiseInspection>} Promise inspection objects.
 * @private
 */
InstanceValidator.prototype._handleSettledResult = function(field, promiseInspections) {
  var self = this;
  promiseInspections.forEach(function(promiseInspection) {
    if (promiseInspection.isRejected()) {
      var rejection = promiseInspection.error();
      self._pushError(true, field, rejection);
    }
  });
};

/**
 * Signs all errors retaining the original.
 *
 * @param {boolean} isBuiltin Determines if error is from builtin validator.
 * @param {string} errorKey The error key to assign on this.errors object.
 * @param {Error|string} rawError The original error.
 * @private
 */
InstanceValidator.prototype._pushError = function(isBuiltin, errorKey, rawError) {
  var message = rawError.message || rawError || 'Validation error';
  var error = new sequelizeError.ValidationErrorItem(message, 'Validation error', errorKey, rawError);
  error[InstanceValidator.RAW_KEY_NAME] = rawError;

  this.errors.push(error);
};
<|endoftext|>