<commit_before>// Meyda Javascript DSP library

var Meyda = function(audioContext,source,bufferSize){

	//utilities
	var µ = function(i, amplitudeSpect){
		var numerator = 0;
		var denominator = 0;
		for(var k = 0; k < amplitudeSpect.length-1; k++){
			numerator += Math.pow(k,i)*amplitudeSpect[k];
			denominator += amplitudeSpect[k];
		}
		return numerator/denominator;
	}

	var isPowerOfTwo = function(num) {
		while (((num % 2) == 0) && num > 1) {
			num /= 2;
		}
		return (num == 1);
	}

	var hanning = function(sig){
		var hann = Float32Array(sig.length);
		var hanned = Float32Array(sig.length);
		for (var i = 0; i < sig.length+1; i++) {
			//According to the R documentation http://rgm.ogalab.net/RGM/R_rdfile?f=GENEAread/man/hanning.window.Rd&d=R_CC
			hann[i] = 0.5 - 0.5*Math.cos(2*Math.PI*i/(sig.length-1));
			hanned[i] = sig[i]*hann[i];
		};
		return hanned;
	}

	var self = this;

	if (isPowerOfTwo(bufferSize)) {
			self.featureExtractors = {
				"buffer" : function(bufferSize,m){
					return m.signal;
				},
				"rms": function(bufferSize, m){

					var rms = 0;
					for(var i = 0 ; i < m.signal.length ; i++){
						rms += Math.pow(m.signal[i],2);
					}
					rms = rms / m.signal.length;
					rms = Math.sqrt(rms);
					return rms;
				},
				"energy": function(bufferSize, m) {
					var energy = 0;
					for(var i = 0 ; i < m.signal.length ; i++){
						energy += Math.pow(Math.abs(m.signal[i]),2);
					}
					return energy;
				},
				"complexSpectrum": function(bufferSize, m) {
					return m.complexSpectrum;
				},
				"spectralSlope": function(bufferSize, m) {
					//linear regression
					var x = 0.0, y = 0.0, xy = 0.0, x2 = 0.0;
					for (var i = 0; i < m.ampSpectrum.length; i++) {
						y += m.ampSpectrum[i];
						xy += m.ampSpectrum[i] * i;
						x2 += i*i;
					};

					x = m.ampSpectrum.length/2;
					y /= m.ampSpectrum.length;
					xy /= m.ampSpectrum.length;
					x2 /= m.ampSpectrum.length;

					return (x*y - xy)/(x*x - x2);
				},
				"spectralCentroid": function(bufferSize, m){
					return µ(1,m.ampSpectrum);
				},
				"spectralRolloff": function(bufferSize, m){
					var magspec = m.ampSpectrum;
					var ec = 0;
					for(var i = 0; i < magspec.length; i++){
						ec += magspec[i];
					}
					var threshold = 0.85 * ec;
					var n = magspec.length - 1;
					while(ec > threshold && n >= 0){
						ec -= magspec[n];
		            	n--;
					}
					return ec;
				},
				"spectralFlatness": function(bufferSize, m){
					var powspec = m.featureExtractors.powerSpectrum(bufferSize, m);
					var numerator = 0;
					var denominator = 0;
					for(var i = 0; i < powspec.length-1;i++){
						numerator += Math.log(powspec[i]);
						denominator += powspec[i];
					}
					return Math.exp((1/powspec.length)*numerator)/((1/powspec.length)*denominator);
				},
				"spectralSpread": function(bufferSize, m){
					var magspec = m.ampSpectrum;
					return Math.sqrt(µ(2,magspec)-Math.pow(µ(1,magspec),2));
				},
				"spectralSkewness": function(bufferSize, m, spectrum){
					var magspec = m.ampSpectrum;
					var µ1 = µ(1,magspec);
					var µ2 = µ(2,magspec);
					var µ3 = µ(3,magspec);
					var numerator = 2*Math.pow(µ1,3)-3*µ1*µ2+µ3;
					var denominator = Math.pow(Math.sqrt(µ2-Math.pow(µ1,2)),3);
					return numerator/denominator;
				},
				"spectralKurtosis": function(bufferSize, m){
					var magspec = m.ampSpectrum;
					var µ1 = µ(1,magspec);
					var µ2 = µ(2,magspec);
					var µ3 = µ(3,magspec);
					var µ4 = µ(4,magspec);
					var numerator = -3*Math.pow(µ1,4)+6*µ1*µ2-4*µ1*µ3+µ4;
					var denominator = Math.pow(Math.sqrt(µ2-Math.pow(µ1,2)),4);
					return numerator/denominator;
				},
				"amplitudeSpectrum": function(bufferSize, m){
					return m.ampSpectrum;
				},
				"zcr": function(bufferSize, ml){
					var zcr = 0;
					for(var i = 0; i < m.signal.length; i++){
						if((m.signal[i] >= 0 && m.signal[i+1] < 0) || (m.signal[i] < 0 && m.signal[i+1] >= 0)){
							zcr++;
						}
					}
					return zcr;
				},
				"powerSpectrum": function(bufferSize, m){
					var powerSpectrum = new Float32Array(m.ampSpectrum.length);
					for (var i = 0; i < powerSpectrum.length; i++) {
						powerSpectrum[i] =  Math.pow(m.ampSpectrum[i],2);
					}
					return powerSpectrum;
				},
				"loudness": function(bufferSize, m){
					var barkScale = Float32Array(bufferSize);
					var NUM_BARK_BANDS = 24;
					var spec = Float32Array(NUM_BARK_BANDS);
					var tot = 0;
					var normalisedSpectrum = m.ampSpectrum;

					for(var i = 0; i < barkScale.length; i++){
						barkScale[i] = i*m.audioContext.sampleRate/(bufferSize);
						barkScale[i] = 13*Math.atan(barkScale[i]/1315.8) + 3.5* Math.atan(Math.pow(barkScale[i]/7518,2));
					}

					var bbLimits = [0];
					var currentBandEnd = barkScale[bufferSize-1]/NUM_BARK_BANDS;
					var currentBand = 1;
					for(var i = 0; i<bufferSize; i++){
						while(barkScale[i] > currentBandEnd){
							bbLimits[currentBand] = i;
							currentBand++;
							currentBandEnd = (currentBand*barkScale[bufferSize-1])/NUM_BARK_BANDS;
						}
					}

					bbLimits[NUM_BARK_BANDS] = bufferSize-1;

					for (var i = 1; i <= NUM_BARK_BANDS; i++){
						var sum = 0;
						for (var j = bbLimits[i-1] ; j < bbLimits[i] ; j++) {

							sum += normalisedSpectrum[j];
						}
						spec[i] = Math.pow(sum,0.23);
					}

					for (var i = 0; i < spec.length; i++){
						tot += spec[i];
					}

					return {
						specific: spec,
						total: tot
					};
				},
				"perceptualSpread": function(bufferSize, m) {
					var loudness = m.featureExtractors["loudness"](bufferSize, m);

					var max = 0;
					for (var i=0; i<loudness.specific.length; i++) {
						if (loudness.specific[i] > max) {
							max = loudness.specific[i];
						}
					}

					var spread = Math.pow((loudness.total - max)/loudness.total, 2);

					return spread;
				},
				"perceptualSharpness": function(bufferSize,m) {
					var loudness = m.featureExtractors["loudness"](bufferSize, m);
					var spec = loudness.specific;
					var output = 0;

					for (var i = 0; i < spec.length; i++) {
						if (i < 15) {
							output += (i+1) * spec[i+1];
						}
						else {
							output += 0.066 * Math.exp(0.171 * (i+1));
						}
					};
					output *= 0.11/loudness.total;

					return output;
				},
				"mfcc": function(bufferSize, m){
					//used tutorial from http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/
					var powSpec = m.ampSpectrum; //TBD: change to power spectrum!
					var freqToMel = function(freqValue){
						var melValue = 1125*Math.log(1+(freqValue/700));
						return melValue
					};
					var melToFreq = function(melValue){
						var freqValue = 700*(Math.exp(melValue/1125)-1);
						return freqValue;
					};
					var numFilters = 26; //26 filters is standard
					var melValues = Float32Array(numFilters);
					var melValuesInFreq = Float32Array(numFilters);
					var lowerLimitFreq = 0;
					var upperLimitFreq = audioContext.sampleRate/2;
					var lowerLimitMel = freqToMel(lowerLimitFreq);
					var upperLimitMel = freqToMel(upperLimitFreq);

					var range = upperLimitMel-lowerLimitMel;
					var valueToAdd = range/(numFilters-1);

					var fftBinsOfFreq = Array(numFilters);
					for (var i = 0; i < melValues.length; i++) {
						melValues[i] = i*valueToAdd;
						melValuesInFreq[i] = melToFreq(melValues[i]);
						fftBinsOfFreq[i] = Math.floor((bufferSize+1)*melValuesInFreq[i]/audioContext.sampleRate);
					};

					var filterBank = Array(numFilters);
					for (var j = 0; j < filterBank.length; j++) {
						//creating a two dimensional array of size numFiltes * (buffersize/2)+1 and pre-populating the arrays with 0s.
						filterBank[j] = Array.apply(null, new Array((bufferSize/2)+1)).map(Number.prototype.valueOf,0);
						for (var i = fftBinsOfFreq[j]; i < fftBinsOfFreq[j+1]; i++) {
							filterBank[j][i] = (i - fftBinsOfFreq[j])/(fftBinsOfFreq[j+1]-fftBinsOfFreq[j]);
						}
						for (var i = fftBinsOfFreq[j+1]; i < fftBinsOfFreq[j+2]; i++) {
							filterBank[j][i] = (fftBinsOfFreq[j+2]-i)/(fftBinsOfFreq[j+2]-fftBinsOfFreq[j+1])
						}
					}

					var mfcc = Array.apply(null, new Array(numFilters)).map(Number.prototype.valueOf,0);
					for (var i = 0; i < mfcc.length; i++) {
						for (var j = 0; j < ((bufferSize/2)+1); j++) {
							filterBank[i][j] = filterBank[i][j]*powSpec[i];
							mfcc[i] += filterBank[i][j];
						}
						mfcc[i] = Math.log(mfcc[i]);
					}

					for (var k = 0; k < mfcc.length; k++) {
						var v = 0;
						for (var n = 0; n < mfcc.length-1; n++) {
							v += mfcc[n]*Math.cos(Math.PI*k*(2*n+1)/(2*mfcc.length));
						}
						mfcc[k] = v;
					}
					return mfcc;
				}
			}
			//create nodes
			self.spn = audioContext.createScriptProcessor(bufferSize,1,0);

			self.spn.onaudioprocess = function(e) {
				//this is to obtain the current amplitude spectrum
				var inputData = e.inputBuffer.getChannelData(0);
				self.signal = inputData;
				var hannedSignal = hanning(self.signal);

				//create complexarray to hold the spectrum
				var data = new complex_array.ComplexArray(bufferSize);
				//map time domain
				data.map(function(value, i, n) {
					value.real = hannedSignal[i];
				});
				//transform
				var spec = data.FFT();
				//assign to meyda
				self.complexSpectrum = spec;
				self.ampSpectrum = new Float32Array(bufferSize/2);
				//calculate amplitude
				for (var i = 0; i < bufferSize/2; i++) {
					self.ampSpectrum[i] = Math.sqrt(Math.pow(spec.real[i],2) + Math.pow(spec.imag[i],2));

				}

			}

			self.audioContext = audioContext;

			self.get = function(feature) {
				if(typeof feature === "object"){
					var results = {};
					for (var x = 0; x < feature.length; x++){
						try{
							results[feature[x]] = (self.featureExtractors[feature[x]](bufferSize, self));
						} catch (e){
							console.error(e);
						}
					}
					return results;
				}
				else if (typeof feature === "string"){
					return self.featureExtractors[feature](bufferSize, self);
				}
				else{
					throw "Invalid Feature Format";
				}
			}
			source.connect(self.spn, 0, 0);
			return self;
	}
	else {
		throw "Buffer size is not a power of two: Meyda will not run."
	}

}

<commit_msg>small change<commit_after>// Meyda Javascript DSP library

var Meyda = function(audioContext,source,bufferSize){

	//utilities
	var µ = function(i, amplitudeSpect){
		var numerator = 0;
		var denominator = 0;
		for(var k = 0; k < amplitudeSpect.length-1; k++){
			numerator += Math.pow(k,i)*amplitudeSpect[k];
			denominator += amplitudeSpect[k];
		}
		return numerator/denominator;
	}

	var isPowerOfTwo = function(num) {
		while (((num % 2) == 0) && num > 1) {
			num /= 2;
		}
		return (num == 1);
	}

	var hanning = function(sig){
		var hann = Float32Array(sig.length);
		var hanned = Float32Array(sig.length);
		for (var i = 0; i < sig.length; i++) {
			//According to the R documentation http://rgm.ogalab.net/RGM/R_rdfile?f=GENEAread/man/hanning.window.Rd&d=R_CC
			hann[i] = 0.5 - 0.5*Math.cos(2*Math.PI*i/(sig.length-1));
			hanned[i] = sig[i]*hann[i];
		};
		return hanned;
	}

	var self = this;

	if (isPowerOfTwo(bufferSize)) {
			self.featureExtractors = {
				"buffer" : function(bufferSize,m){
					return m.signal;
				},
				"rms": function(bufferSize, m){

					var rms = 0;
					for(var i = 0 ; i < m.signal.length ; i++){
						rms += Math.pow(m.signal[i],2);
					}
					rms = rms / m.signal.length;
					rms = Math.sqrt(rms);
					return rms;
				},
				"energy": function(bufferSize, m) {
					var energy = 0;
					for(var i = 0 ; i < m.signal.length ; i++){
						energy += Math.pow(Math.abs(m.signal[i]),2);
					}
					return energy;
				},
				"complexSpectrum": function(bufferSize, m) {
					return m.complexSpectrum;
				},
				"spectralSlope": function(bufferSize, m) {
					//linear regression
					var x = 0.0, y = 0.0, xy = 0.0, x2 = 0.0;
					for (var i = 0; i < m.ampSpectrum.length; i++) {
						y += m.ampSpectrum[i];
						xy += m.ampSpectrum[i] * i;
						x2 += i*i;
					};

					x = m.ampSpectrum.length/2;
					y /= m.ampSpectrum.length;
					xy /= m.ampSpectrum.length;
					x2 /= m.ampSpectrum.length;

					return (x*y - xy)/(x*x - x2);
				},
				"spectralCentroid": function(bufferSize, m){
					return µ(1,m.ampSpectrum);
				},
				"spectralRolloff": function(bufferSize, m){
					var magspec = m.ampSpectrum;
					var ec = 0;
					for(var i = 0; i < magspec.length; i++){
						ec += magspec[i];
					}
					var threshold = 0.85 * ec;
					var n = magspec.length - 1;
					while(ec > threshold && n >= 0){
						ec -= magspec[n];
		            	n--;
					}
					return ec;
				},
				"spectralFlatness": function(bufferSize, m){
					var powspec = m.featureExtractors.powerSpectrum(bufferSize, m);
					var numerator = 0;
					var denominator = 0;
					for(var i = 0; i < powspec.length-1;i++){
						numerator += Math.log(powspec[i]);
						denominator += powspec[i];
					}
					return Math.exp((1/powspec.length)*numerator)/((1/powspec.length)*denominator);
				},
				"spectralSpread": function(bufferSize, m){
					var magspec = m.ampSpectrum;
					return Math.sqrt(µ(2,magspec)-Math.pow(µ(1,magspec),2));
				},
				"spectralSkewness": function(bufferSize, m, spectrum){
					var magspec = m.ampSpectrum;
					var µ1 = µ(1,magspec);
					var µ2 = µ(2,magspec);
					var µ3 = µ(3,magspec);
					var numerator = 2*Math.pow(µ1,3)-3*µ1*µ2+µ3;
					var denominator = Math.pow(Math.sqrt(µ2-Math.pow(µ1,2)),3);
					return numerator/denominator;
				},
				"spectralKurtosis": function(bufferSize, m){
					var magspec = m.ampSpectrum;
					var µ1 = µ(1,magspec);
					var µ2 = µ(2,magspec);
					var µ3 = µ(3,magspec);
					var µ4 = µ(4,magspec);
					var numerator = -3*Math.pow(µ1,4)+6*µ1*µ2-4*µ1*µ3+µ4;
					var denominator = Math.pow(Math.sqrt(µ2-Math.pow(µ1,2)),4);
					return numerator/denominator;
				},
				"amplitudeSpectrum": function(bufferSize, m){
					return m.ampSpectrum;
				},
				"zcr": function(bufferSize, ml){
					var zcr = 0;
					for(var i = 0; i < m.signal.length; i++){
						if((m.signal[i] >= 0 && m.signal[i+1] < 0) || (m.signal[i] < 0 && m.signal[i+1] >= 0)){
							zcr++;
						}
					}
					return zcr;
				},
				"powerSpectrum": function(bufferSize, m){
					var powerSpectrum = new Float32Array(m.ampSpectrum.length);
					for (var i = 0; i < powerSpectrum.length; i++) {
						powerSpectrum[i] =  Math.pow(m.ampSpectrum[i],2);
					}
					return powerSpectrum;
				},
				"loudness": function(bufferSize, m){
					var barkScale = Float32Array(bufferSize);
					var NUM_BARK_BANDS = 24;
					var spec = Float32Array(NUM_BARK_BANDS);
					var tot = 0;
					var normalisedSpectrum = m.ampSpectrum;

					for(var i = 0; i < barkScale.length; i++){
						barkScale[i] = i*m.audioContext.sampleRate/(bufferSize);
						barkScale[i] = 13*Math.atan(barkScale[i]/1315.8) + 3.5* Math.atan(Math.pow(barkScale[i]/7518,2));
					}

					var bbLimits = [0];
					var currentBandEnd = barkScale[bufferSize-1]/NUM_BARK_BANDS;
					var currentBand = 1;
					for(var i = 0; i<bufferSize; i++){
						while(barkScale[i] > currentBandEnd){
							bbLimits[currentBand] = i;
							currentBand++;
							currentBandEnd = (currentBand*barkScale[bufferSize-1])/NUM_BARK_BANDS;
						}
					}

					bbLimits[NUM_BARK_BANDS] = bufferSize-1;

					for (var i = 1; i <= NUM_BARK_BANDS; i++){
						var sum = 0;
						for (var j = bbLimits[i-1] ; j < bbLimits[i] ; j++) {

							sum += normalisedSpectrum[j];
						}
						spec[i] = Math.pow(sum,0.23);
					}

					for (var i = 0; i < spec.length; i++){
						tot += spec[i];
					}

					return {
						specific: spec,
						total: tot
					};
				},
				"perceptualSpread": function(bufferSize, m) {
					var loudness = m.featureExtractors["loudness"](bufferSize, m);

					var max = 0;
					for (var i=0; i<loudness.specific.length; i++) {
						if (loudness.specific[i] > max) {
							max = loudness.specific[i];
						}
					}

					var spread = Math.pow((loudness.total - max)/loudness.total, 2);

					return spread;
				},
				"perceptualSharpness": function(bufferSize,m) {
					var loudness = m.featureExtractors["loudness"](bufferSize, m);
					var spec = loudness.specific;
					var output = 0;

					for (var i = 0; i < spec.length; i++) {
						if (i < 15) {
							output += (i+1) * spec[i+1];
						}
						else {
							output += 0.066 * Math.exp(0.171 * (i+1));
						}
					};
					output *= 0.11/loudness.total;

					return output;
				},
				"mfcc": function(bufferSize, m){
					//used tutorial from http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/
					var powSpec = m.ampSpectrum; //TBD: change to power spectrum!
					var freqToMel = function(freqValue){
						var melValue = 1125*Math.log(1+(freqValue/700));
						return melValue
					};
					var melToFreq = function(melValue){
						var freqValue = 700*(Math.exp(melValue/1125)-1);
						return freqValue;
					};
					var numFilters = 26; //26 filters is standard
					var melValues = Float32Array(numFilters);
					var melValuesInFreq = Float32Array(numFilters);
					var lowerLimitFreq = 0;
					var upperLimitFreq = audioContext.sampleRate/2;
					var lowerLimitMel = freqToMel(lowerLimitFreq);
					var upperLimitMel = freqToMel(upperLimitFreq);

					var range = upperLimitMel-lowerLimitMel;
					var valueToAdd = range/(numFilters-1);

					var fftBinsOfFreq = Array(numFilters);
					for (var i = 0; i < melValues.length; i++) {
						melValues[i] = i*valueToAdd;
						melValuesInFreq[i] = melToFreq(melValues[i]);
						fftBinsOfFreq[i] = Math.floor((bufferSize+1)*melValuesInFreq[i]/audioContext.sampleRate);
					};

					var filterBank = Array(numFilters);
					for (var j = 0; j < filterBank.length; j++) {
						//creating a two dimensional array of size numFiltes * (buffersize/2)+1 and pre-populating the arrays with 0s.
						filterBank[j] = Array.apply(null, new Array((bufferSize/2)+1)).map(Number.prototype.valueOf,0);
						for (var i = fftBinsOfFreq[j]; i < fftBinsOfFreq[j+1]; i++) {
							filterBank[j][i] = (i - fftBinsOfFreq[j])/(fftBinsOfFreq[j+1]-fftBinsOfFreq[j]);
						}
						for (var i = fftBinsOfFreq[j+1]; i < fftBinsOfFreq[j+2]; i++) {
							filterBank[j][i] = (fftBinsOfFreq[j+2]-i)/(fftBinsOfFreq[j+2]-fftBinsOfFreq[j+1])
						}
					}

					var mfcc = Array.apply(null, new Array(numFilters)).map(Number.prototype.valueOf,0);
					for (var i = 0; i < mfcc.length; i++) {
						for (var j = 0; j < ((bufferSize/2)+1); j++) {
							filterBank[i][j] = filterBank[i][j]*powSpec[i];
							mfcc[i] += filterBank[i][j];
						}
						mfcc[i] = Math.log(mfcc[i]);
					}

					for (var k = 0; k < mfcc.length; k++) {
						var v = 0;
						for (var n = 0; n < mfcc.length-1; n++) {
							v += mfcc[n]*Math.cos(Math.PI*k*(2*n+1)/(2*mfcc.length));
						}
						mfcc[k] = v;
					}
					return mfcc;
				}
			}
			//create nodes
			self.spn = audioContext.createScriptProcessor(bufferSize,1,0);

			self.spn.onaudioprocess = function(e) {
				//this is to obtain the current amplitude spectrum
				var inputData = e.inputBuffer.getChannelData(0);
				self.signal = inputData;
				var hannedSignal = hanning(self.signal);

				//create complexarray to hold the spectrum
				var data = new complex_array.ComplexArray(bufferSize);
				//map time domain
				data.map(function(value, i, n) {
					value.real = hannedSignal[i];
				});
				//transform
				var spec = data.FFT();
				//assign to meyda
				self.complexSpectrum = spec;
				self.ampSpectrum = new Float32Array(bufferSize/2);
				//calculate amplitude
				for (var i = 0; i < bufferSize/2; i++) {
					self.ampSpectrum[i] = Math.sqrt(Math.pow(spec.real[i],2) + Math.pow(spec.imag[i],2));

				}

			}

			self.audioContext = audioContext;

			self.get = function(feature) {
				if(typeof feature === "object"){
					var results = {};
					for (var x = 0; x < feature.length; x++){
						try{
							results[feature[x]] = (self.featureExtractors[feature[x]](bufferSize, self));
						} catch (e){
							console.error(e);
						}
					}
					return results;
				}
				else if (typeof feature === "string"){
					return self.featureExtractors[feature](bufferSize, self);
				}
				else{
					throw "Invalid Feature Format";
				}
			}
			source.connect(self.spn, 0, 0);
			return self;
	}
	else {
		throw "Buffer size is not a power of two: Meyda will not run."
	}

}

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 */

'use strict';

const TransformCache = require('../lib/TransformCache');

const crypto = require('crypto');
const docblock = require('./DependencyGraph/docblock');
const fs = require('fs');
const invariant = require('fbjs/lib/invariant');
const isAbsolutePath = require('absolute-path');
const jsonStableStringify = require('json-stable-stringify');

const {join: joinPath, relative: relativePath, extname} = require('path');

import type {TransformedCode, Options as TransformOptions} from '../JSTransformer/worker/worker';
import type GlobalTransformCache from '../lib/GlobalTransformCache';
import type {SourceMap} from '../lib/SourceMap';
import type {GetTransformCacheKey} from '../lib/TransformCache';
import type {ReadTransformProps} from '../lib/TransformCache';
import type {Reporter} from '../lib/reporting';
import type Cache from './Cache';
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
import type ModuleCache from './ModuleCache';

export type ReadResult = {
  code: string,
  dependencies?: ?Array<string>,
  dependencyOffsets?: ?Array<number>,
  map?: ?SourceMap,
  source: string,
};

export type TransformCode = (
  module: Module,
  sourceCode: string,
  transformOptions: TransformOptions,
) => Promise<TransformedCode>;

export type HasteImpl = {
  getHasteName(filePath: string): (string | void),
  // This exists temporarily to enforce consistency while we deprecate
  // @providesModule.
  enforceHasteNameMatches?: (
    filePath: string,
    expectedName: (string | void),
  ) => void,
};

export type Options = {
  cacheTransformResults?: boolean,
  hasteImpl?: HasteImpl,
  resetCache?: boolean,
};

export type ConstructorArgs = {
  cache: Cache,
  depGraphHelpers: DependencyGraphHelpers,
  globalTransformCache: ?GlobalTransformCache,
  file: string,
  moduleCache: ModuleCache,
  options: Options,
  reporter: Reporter,
  getTransformCacheKey: GetTransformCacheKey,
  transformCode: ?TransformCode,
};

type DocBlock = {+[key: string]: string};

class Module {

  path: string;
  type: string;

  _moduleCache: ModuleCache;
  _cache: Cache;
  _transformCode: ?TransformCode;
  _getTransformCacheKey: GetTransformCacheKey;
  _depGraphHelpers: DependencyGraphHelpers;
  _options: Options;
  _reporter: Reporter;
  _globalCache: ?GlobalTransformCache;

  _docBlock: ?DocBlock;
  _hasteNameCache: ?{+hasteName: ?string};
  _sourceCode: ?string;
  _readPromises: Map<string, Promise<ReadResult>>;

  constructor({
    cache,
    depGraphHelpers,
    file,
    getTransformCacheKey,
    globalTransformCache,
    moduleCache,
    options,
    reporter,
    transformCode,
  }: ConstructorArgs) {
    if (!isAbsolutePath(file)) {
      throw new Error('Expected file to be absolute path but got ' + file);
    }

    this.path = file;
    this.type = 'Module';

    this._moduleCache = moduleCache;
    this._cache = cache;
    this._transformCode = transformCode;
    this._getTransformCacheKey = getTransformCacheKey;
    this._depGraphHelpers = depGraphHelpers;
    this._options = options || {};
    this._reporter = reporter;
    this._globalCache = globalTransformCache;

    this._readPromises = new Map();
  }

  isHaste(): Promise<boolean> {
    return this._cache.get(
      this.path,
      'isHaste',
      () => Promise.resolve(this._getHasteName() != null),
    );
  }

  getCode(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({code}) => code);
  }

  getMap(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({map}) => map);
  }

  getName(): Promise<string> {
    return this._cache.get(
      this.path,
      'name',
      () => Promise.resolve().then(() => {
        const name = this._getHasteName();
        if (name != null) {
          return name;
        }

        const p = this.getPackage();

        if (!p) {
          // Name is full path
          return this.path;
        }

        return p.getName()
          .then(packageName => {
            if (!packageName) {
              return this.path;
            }

            return joinPath(packageName, relativePath(p.root, this.path)).replace(/\\/g, '/');
          });
      })
    );
  }

  getPackage() {
    return this._moduleCache.getPackageForModule(this);
  }

  getDependencies(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({dependencies}) => dependencies);
  }

  /**
   * We don't need to invalidate the TranformCache itself because it guarantees
   * itself that if a source code changed we won't return the cached transformed
   * code.
   */
  invalidate() {
    this._cache.invalidate(this.path);
    this._readPromises.clear();
    this._sourceCode = null;
    this._docBlock = null;
    this._hasteNameCache = null;
  }

  _readSourceCode(): string {
    if (this._sourceCode == null) {
      this._sourceCode = fs.readFileSync(this.path, 'utf8');
    }
    return this._sourceCode;
  }

  _readDocBlock(): DocBlock {
    if (this._docBlock == null) {
      this._docBlock = docblock.parseAsObject(this._readSourceCode());
    }
    return this._docBlock;
  }

  _getHasteName(): ?string {
    if (this._hasteNameCache != null) {
      return this._hasteNameCache.hasteName;
    }
    const hasteImpl = this._options.hasteImpl;
    if (hasteImpl === undefined || hasteImpl.enforceHasteNameMatches) {
      const moduleDocBlock = this._readDocBlock();
      const {providesModule} = moduleDocBlock;
      this._hasteNameCache = {
        hasteName: providesModule && !this._depGraphHelpers.isNodeModulesDir(this.path)
          ? /^\S+/.exec(providesModule)[0]
          : undefined,
      };
    }
    if (hasteImpl !== undefined) {
      const {enforceHasteNameMatches} = hasteImpl;
      if (enforceHasteNameMatches) {
        /* $FlowFixMe: this rely on the above if being executed, that is fragile. Rework the algo. */
        enforceHasteNameMatches(this.path, this._hasteNameCache.hasteName);
      }
      this._hasteNameCache = {hasteName: hasteImpl.getHasteName(this.path)};
    } else {
      // Extract an id for the module if it's using @providesModule syntax
      // and if it's NOT in node_modules (and not a whitelisted node_module).
      // This handles the case where a project may have a dep that has @providesModule
      // docblock comments, but doesn't want it to conflict with whitelisted @providesModule
      // modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
      // project-specific code that is using @providesModule.
      const moduleDocBlock = this._readDocBlock();
      const {providesModule} = moduleDocBlock;
      this._hasteNameCache = {
        hasteName:
          providesModule && !this._depGraphHelpers.isNodeModulesDir(this.path)
            ? /^\S+/.exec(providesModule)[0]
            : undefined,
      };
    }
    return this._hasteNameCache.hasteName;
  }

  /**
   * To what we read from the cache or worker, we need to add id and source.
   */
  _finalizeReadResult(
    source: string,
    id: ?string,
    extern: boolean,
    result: TransformedCode,
  ): ReadResult {
    if (this._options.cacheTransformResults === false) {
      const {dependencies} = result;
      /* $FlowFixMe: this code path is dead, remove. */
      return {dependencies};
    }
    return {...result, id, source};
  }

  _transformCodeForCallback(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    const {_transformCode} = this;
    invariant(_transformCode != null, 'missing code transform funtion');
    const {sourceCode, transformOptions} = cacheProps;
    return _transformCode(this, sourceCode, transformOptions).then(
      freshResult => process.nextTick(callback, undefined, freshResult),
      error => process.nextTick(callback, error),
    );
  }

  _transformAndStoreCodeGlobally(
    cacheProps: ReadTransformProps,
    globalCache: GlobalTransformCache,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    this._transformCodeForCallback(
      cacheProps,
      (transformError, transformResult) => {
        if (transformError != null) {
          callback(transformError);
          return;
        }
        invariant(
          transformResult != null,
          'Inconsistent state: there is no error, but no results either.',
        );
        globalCache.store(cacheProps, transformResult);
        callback(undefined, transformResult);
      },
    );
  }

  _getTransformedCode(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    const {_globalCache} = this;
    if (_globalCache == null || !_globalCache.shouldFetch(cacheProps)) {
      this._transformCodeForCallback(cacheProps, callback);
      return;
    }
    _globalCache.fetch(cacheProps).then(
      globalCachedResult => process.nextTick(() => {
        if (globalCachedResult == null) {
          this._transformAndStoreCodeGlobally(cacheProps, _globalCache, callback);
          return;
        }
        callback(undefined, globalCachedResult);
      }),
      globalCacheError => process.nextTick(() => callback(globalCacheError)),
    );
  }

  _getAndCacheTransformedCode(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    this._getTransformedCode(cacheProps, (error, result) => {
      if (error) {
        callback(error);
        return;
      }
      invariant(result != null, 'missing result');
      TransformCache.writeSync({...cacheProps, result});
      callback(undefined, result);
    });
  }

  /**
   * Read everything about a module: source code, transformed code,
   * dependencies, etc. The overall process is to read the cache first, and if
   * it's a miss, we let the worker write to the cache and read it again.
   */
  read(transformOptions: TransformOptions): Promise<ReadResult> {
    const key = stableObjectHash(transformOptions || {});
    const promise = this._readPromises.get(key);
    if (promise != null) {
      return promise;
    }
    const freshPromise = Promise.resolve().then(() => {
      const sourceCode = this._readSourceCode();
      const moduleDocBlock = this._readDocBlock();
      const id = this._getHasteName();
      // Ignore requires in JSON files or generated code. An example of this
      // is prebuilt files like the SourceMap library.
      const extern = this.isJSON() || 'extern' in moduleDocBlock;
      if (extern) {
        transformOptions = {...transformOptions, extern};
      }
      const getTransformCacheKey = this._getTransformCacheKey;
      const cacheProps = {
        filePath: this.path,
        sourceCode,
        getTransformCacheKey,
        transformOptions,
        cacheOptions: {
          resetCache: this._options.resetCache,
          reporter: this._reporter,
        },
      };
      const cachedResult = TransformCache.readSync(cacheProps);
      if (cachedResult) {
        return Promise.resolve(this._finalizeReadResult(sourceCode, id, extern, cachedResult));
      }
      return new Promise((resolve, reject) => {
        this._getAndCacheTransformedCode(
          cacheProps,
          (transformError, freshResult) => {
            if (transformError) {
              reject(transformError);
              return;
            }
            invariant(freshResult != null, 'inconsistent state');
            resolve(this._finalizeReadResult(sourceCode, id, extern, freshResult));
          },
        );
      });
    });
    this._readPromises.set(key, freshPromise);
    return freshPromise;
  }

  hash() {
    return `Module : ${this.path}`;
  }

  isJSON() {
    return extname(this.path) === '.json';
  }

  isAsset() {
    return false;
  }

  isPolyfill() {
    return false;
  }
}

// use weak map to speed up hash creation of known objects
const knownHashes = new WeakMap();
function stableObjectHash(object) {
  let digest = knownHashes.get(object);
  if (!digest) {
    digest = crypto.createHash('md5')
      .update(jsonStableStringify(object))
      .digest('base64');
    knownHashes.set(object, digest);
  }

  return digest;
}

module.exports = Module;
<commit_msg>packager: Module.js: cover the error cases<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 */

'use strict';

const TransformCache = require('../lib/TransformCache');

const crypto = require('crypto');
const docblock = require('./DependencyGraph/docblock');
const fs = require('fs');
const invariant = require('fbjs/lib/invariant');
const isAbsolutePath = require('absolute-path');
const jsonStableStringify = require('json-stable-stringify');

const {join: joinPath, relative: relativePath, extname} = require('path');

import type {TransformedCode, Options as TransformOptions} from '../JSTransformer/worker/worker';
import type GlobalTransformCache from '../lib/GlobalTransformCache';
import type {SourceMap} from '../lib/SourceMap';
import type {GetTransformCacheKey} from '../lib/TransformCache';
import type {ReadTransformProps} from '../lib/TransformCache';
import type {Reporter} from '../lib/reporting';
import type Cache from './Cache';
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
import type ModuleCache from './ModuleCache';

export type ReadResult = {
  code: string,
  dependencies?: ?Array<string>,
  dependencyOffsets?: ?Array<number>,
  map?: ?SourceMap,
  source: string,
};

export type TransformCode = (
  module: Module,
  sourceCode: string,
  transformOptions: TransformOptions,
) => Promise<TransformedCode>;

export type HasteImpl = {
  getHasteName(filePath: string): (string | void),
  // This exists temporarily to enforce consistency while we deprecate
  // @providesModule.
  enforceHasteNameMatches?: (
    filePath: string,
    expectedName: (string | void),
  ) => void,
};

export type Options = {
  cacheTransformResults?: boolean,
  hasteImpl?: HasteImpl,
  resetCache?: boolean,
};

export type ConstructorArgs = {
  cache: Cache,
  depGraphHelpers: DependencyGraphHelpers,
  globalTransformCache: ?GlobalTransformCache,
  file: string,
  moduleCache: ModuleCache,
  options: Options,
  reporter: Reporter,
  getTransformCacheKey: GetTransformCacheKey,
  transformCode: ?TransformCode,
};

type DocBlock = {+[key: string]: string};

class Module {

  path: string;
  type: string;

  _moduleCache: ModuleCache;
  _cache: Cache;
  _transformCode: ?TransformCode;
  _getTransformCacheKey: GetTransformCacheKey;
  _depGraphHelpers: DependencyGraphHelpers;
  _options: Options;
  _reporter: Reporter;
  _globalCache: ?GlobalTransformCache;

  _docBlock: ?DocBlock;
  _hasteNameCache: ?{+hasteName: ?string};
  _sourceCode: ?string;
  _readPromises: Map<string, Promise<ReadResult>>;

  constructor({
    cache,
    depGraphHelpers,
    file,
    getTransformCacheKey,
    globalTransformCache,
    moduleCache,
    options,
    reporter,
    transformCode,
  }: ConstructorArgs) {
    if (!isAbsolutePath(file)) {
      throw new Error('Expected file to be absolute path but got ' + file);
    }

    this.path = file;
    this.type = 'Module';

    this._moduleCache = moduleCache;
    this._cache = cache;
    this._transformCode = transformCode;
    this._getTransformCacheKey = getTransformCacheKey;
    this._depGraphHelpers = depGraphHelpers;
    this._options = options || {};
    this._reporter = reporter;
    this._globalCache = globalTransformCache;

    this._readPromises = new Map();
  }

  isHaste(): Promise<boolean> {
    return this._cache.get(
      this.path,
      'isHaste',
      () => Promise.resolve().then(() => this._getHasteName() != null),
    );
  }

  getCode(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({code}) => code);
  }

  getMap(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({map}) => map);
  }

  getName(): Promise<string> {
    return this._cache.get(
      this.path,
      'name',
      () => Promise.resolve().then(() => {
        const name = this._getHasteName();
        if (name != null) {
          return name;
        }

        const p = this.getPackage();

        if (!p) {
          // Name is full path
          return this.path;
        }

        return p.getName()
          .then(packageName => {
            if (!packageName) {
              return this.path;
            }

            return joinPath(packageName, relativePath(p.root, this.path)).replace(/\\/g, '/');
          });
      })
    );
  }

  getPackage() {
    return this._moduleCache.getPackageForModule(this);
  }

  getDependencies(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({dependencies}) => dependencies);
  }

  /**
   * We don't need to invalidate the TranformCache itself because it guarantees
   * itself that if a source code changed we won't return the cached transformed
   * code.
   */
  invalidate() {
    this._cache.invalidate(this.path);
    this._readPromises.clear();
    this._sourceCode = null;
    this._docBlock = null;
    this._hasteNameCache = null;
  }

  _readSourceCode(): string {
    if (this._sourceCode == null) {
      this._sourceCode = fs.readFileSync(this.path, 'utf8');
    }
    return this._sourceCode;
  }

  _readDocBlock(): DocBlock {
    if (this._docBlock == null) {
      this._docBlock = docblock.parseAsObject(this._readSourceCode());
    }
    return this._docBlock;
  }

  _getHasteName(): ?string {
    if (this._hasteNameCache != null) {
      return this._hasteNameCache.hasteName;
    }
    const hasteImpl = this._options.hasteImpl;
    if (hasteImpl === undefined || hasteImpl.enforceHasteNameMatches) {
      const moduleDocBlock = this._readDocBlock();
      const {providesModule} = moduleDocBlock;
      this._hasteNameCache = {
        hasteName: providesModule && !this._depGraphHelpers.isNodeModulesDir(this.path)
          ? /^\S+/.exec(providesModule)[0]
          : undefined,
      };
    }
    if (hasteImpl !== undefined) {
      const {enforceHasteNameMatches} = hasteImpl;
      if (enforceHasteNameMatches) {
        /* $FlowFixMe: this rely on the above if being executed, that is fragile. Rework the algo. */
        enforceHasteNameMatches(this.path, this._hasteNameCache.hasteName);
      }
      this._hasteNameCache = {hasteName: hasteImpl.getHasteName(this.path)};
    } else {
      // Extract an id for the module if it's using @providesModule syntax
      // and if it's NOT in node_modules (and not a whitelisted node_module).
      // This handles the case where a project may have a dep that has @providesModule
      // docblock comments, but doesn't want it to conflict with whitelisted @providesModule
      // modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
      // project-specific code that is using @providesModule.
      const moduleDocBlock = this._readDocBlock();
      const {providesModule} = moduleDocBlock;
      this._hasteNameCache = {
        hasteName:
          providesModule && !this._depGraphHelpers.isNodeModulesDir(this.path)
            ? /^\S+/.exec(providesModule)[0]
            : undefined,
      };
    }
    return this._hasteNameCache.hasteName;
  }

  /**
   * To what we read from the cache or worker, we need to add id and source.
   */
  _finalizeReadResult(
    source: string,
    id: ?string,
    extern: boolean,
    result: TransformedCode,
  ): ReadResult {
    if (this._options.cacheTransformResults === false) {
      const {dependencies} = result;
      /* $FlowFixMe: this code path is dead, remove. */
      return {dependencies};
    }
    return {...result, id, source};
  }

  _transformCodeForCallback(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    const {_transformCode} = this;
    invariant(_transformCode != null, 'missing code transform funtion');
    const {sourceCode, transformOptions} = cacheProps;
    return _transformCode(this, sourceCode, transformOptions).then(
      freshResult => process.nextTick(callback, undefined, freshResult),
      error => process.nextTick(callback, error),
    );
  }

  _transformAndStoreCodeGlobally(
    cacheProps: ReadTransformProps,
    globalCache: GlobalTransformCache,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    this._transformCodeForCallback(
      cacheProps,
      (transformError, transformResult) => {
        if (transformError != null) {
          callback(transformError);
          return;
        }
        invariant(
          transformResult != null,
          'Inconsistent state: there is no error, but no results either.',
        );
        globalCache.store(cacheProps, transformResult);
        callback(undefined, transformResult);
      },
    );
  }

  _getTransformedCode(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    const {_globalCache} = this;
    if (_globalCache == null || !_globalCache.shouldFetch(cacheProps)) {
      this._transformCodeForCallback(cacheProps, callback);
      return;
    }
    _globalCache.fetch(cacheProps).then(
      globalCachedResult => process.nextTick(() => {
        if (globalCachedResult == null) {
          this._transformAndStoreCodeGlobally(cacheProps, _globalCache, callback);
          return;
        }
        callback(undefined, globalCachedResult);
      }),
      globalCacheError => process.nextTick(() => callback(globalCacheError)),
    );
  }

  _getAndCacheTransformedCode(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    this._getTransformedCode(cacheProps, (error, result) => {
      if (error) {
        callback(error);
        return;
      }
      invariant(result != null, 'missing result');
      TransformCache.writeSync({...cacheProps, result});
      callback(undefined, result);
    });
  }

  /**
   * Read everything about a module: source code, transformed code,
   * dependencies, etc. The overall process is to read the cache first, and if
   * it's a miss, we let the worker write to the cache and read it again.
   */
  read(transformOptions: TransformOptions): Promise<ReadResult> {
    const key = stableObjectHash(transformOptions || {});
    const promise = this._readPromises.get(key);
    if (promise != null) {
      return promise;
    }
    const freshPromise = Promise.resolve().then(() => {
      const sourceCode = this._readSourceCode();
      const moduleDocBlock = this._readDocBlock();
      const id = this._getHasteName();
      // Ignore requires in JSON files or generated code. An example of this
      // is prebuilt files like the SourceMap library.
      const extern = this.isJSON() || 'extern' in moduleDocBlock;
      if (extern) {
        transformOptions = {...transformOptions, extern};
      }
      const getTransformCacheKey = this._getTransformCacheKey;
      const cacheProps = {
        filePath: this.path,
        sourceCode,
        getTransformCacheKey,
        transformOptions,
        cacheOptions: {
          resetCache: this._options.resetCache,
          reporter: this._reporter,
        },
      };
      const cachedResult = TransformCache.readSync(cacheProps);
      if (cachedResult) {
        return Promise.resolve(this._finalizeReadResult(sourceCode, id, extern, cachedResult));
      }
      return new Promise((resolve, reject) => {
        this._getAndCacheTransformedCode(
          cacheProps,
          (transformError, freshResult) => {
            if (transformError) {
              reject(transformError);
              return;
            }
            invariant(freshResult != null, 'inconsistent state');
            resolve(this._finalizeReadResult(sourceCode, id, extern, freshResult));
          },
        );
      });
    });
    this._readPromises.set(key, freshPromise);
    return freshPromise;
  }

  hash() {
    return `Module : ${this.path}`;
  }

  isJSON() {
    return extname(this.path) === '.json';
  }

  isAsset() {
    return false;
  }

  isPolyfill() {
    return false;
  }
}

// use weak map to speed up hash creation of known objects
const knownHashes = new WeakMap();
function stableObjectHash(object) {
  let digest = knownHashes.get(object);
  if (!digest) {
    digest = crypto.createHash('md5')
      .update(jsonStableStringify(object))
      .digest('base64');
    knownHashes.set(object, digest);
  }

  return digest;
}

module.exports = Module;
<|endoftext|>


<commit_before>var router = (function() {
    'use strict';

    var router = {};
    var httpMethods = {
        get: 'GET',
        post: 'POST',
        put: 'PUT',
        delete: 'DELETE'
    }
    var requests = {};

    ///////////////////////////////////
    // Generic Router Exception Def  //
    ///////////////////////////////////

    function RouterException (message, innerType, internalMessage) {
        this.type = 'RouterException';
        this.innerType = innerType || 'innerServerException';
        this.message = message;
        this.internalMessage = internalMessage || null;
    }

    ////////////////////////
    // Internal Functions //
    ////////////////////////

    /**
     * Adds a HTTP Method with the corresponding, url the handler for it.
     * There can be one HTTP Method with many urls.
     * @param {GET/POST/PUT/DELETE}   method   HTTP Method
     * @param {URL String}   url      URL String gotten from the request object
     * @param {Function} callback Handler that makes a call to the "hard-core" logic of the server
     * @param {Bool} async Defines where to store the callback function
     */
    function addMethod (method, url, callback, async) {
        if(!requests[method]) {
            requests[method] = {
                callbacks: {},
                asyncCallbacks: {}
            }
        }
        if(!async) {
            requests[method].callbacks[url] = callback;
        }
        else {
            requests[method].asyncCallbacks[url] = callback;
        }
    }

    //////////////////////////
    // Router API functions //
    //////////////////////////

    // SYNC

    router.get = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.get, url, callback);
    }

    router.post = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.post, url, callback);
    }

    router.put = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.put, url, callback);
    }

    router.delete = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.delete, url, callback);
    }

    // ASYNC

    router.getAsync = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.get, url, callback, true);
    }

    router.postAsync = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.post, url, callback, true);
    }

    router.putAsync = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.put, url, callback, true);
    }

    router.deleteAsync = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.delete, url, callback, true);
    }

        /**
     * Executes one of the predefined actions depending on the given parameters object in the process function.
     * @param  {[type]} method       'GET/POST/PUT/DELETE'
     * @param  {[type]} url          '/example/url'. Url that we get from the http request object.
     */
    router.executeCallback = function (request, response, async) {
        var method = request.method,
            url = request.url;
        if(!requests[method]) {
            throw new RouterException('HTTP Method not found.');
        }
        else {
            var callBackToBeExecuted = (!async)? requests[method].callbacks[url] : requests[method].asyncCallbacks[url];

            if(!callBackToBeExecuted) {
                throw new RouterException('HTTP Method with url "' + url + '" was not found.', 'pageNotFoundException');
            }
            callBackToBeExecuted(request, response);
        }
    }

    return router;

}());

module.exports = router;
<commit_msg>Changing behaviour of executeCallback function in router No more throws an error if callbackToBeExecuted is undefined. Executes callback only if it's defined.<commit_after>var router = (function() {
    'use strict';

    var router = {};
    var httpMethods = {
        get: 'GET',
        post: 'POST',
        put: 'PUT',
        delete: 'DELETE'
    }
    var requests = {};

    ///////////////////////////////////
    // Generic Router Exception Def  //
    ///////////////////////////////////

    function RouterException (message, innerType, internalMessage) {
        this.type = 'RouterException';
        this.innerType = innerType || 'innerServerException';
        this.message = message;
        this.internalMessage = internalMessage || null;
    }

    ////////////////////////
    // Internal Functions //
    ////////////////////////

    /**
     * Adds a HTTP Method with the corresponding, url the handler for it.
     * There can be one HTTP Method with many urls.
     * @param {GET/POST/PUT/DELETE}   method   HTTP Method
     * @param {URL String}   url      URL String gotten from the request object
     * @param {Function} callback Handler that makes a call to the "hard-core" logic of the server
     * @param {Bool} async Defines where to store the callback function
     */
    function addMethod (method, url, callback, async) {
        if(!requests[method]) {
            requests[method] = {
                callbacks: {},
                asyncCallbacks: {}
            }
        }
        if(!async) {
            requests[method].callbacks[url] = callback;
        }
        else {
            requests[method].asyncCallbacks[url] = callback;
        }
    }

    //////////////////////////
    // Router API functions //
    //////////////////////////

    // SYNC

    router.get = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.get, url, callback);
    }

    router.post = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.post, url, callback);
    }

    router.put = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.put, url, callback);
    }

    router.delete = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.delete, url, callback);
    }

    // ASYNC

    router.getAsync = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.get, url, callback, true);
    }

    router.postAsync = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.post, url, callback, true);
    }

    router.putAsync = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.put, url, callback, true);
    }

    router.deleteAsync = function (url, callback) {
        if(!url && !callback) {
            throw new RouterException('Url, or callback is undefined or null.');
        }
        addMethod(httpMethods.delete, url, callback, true);
    }

    /**
     * Executes one of the predefined actions depending on the given parameters object in the process function.
     * @param  {[type]} method       'GET/POST/PUT/DELETE'
     * @param  {[type]} url          '/example/url'. Url that we get from the http request object.
     */
    router.executeCallback = function (request, response, async) {
        var method = request.method,
            url = request.url;
        if(!requests[method]) {
            throw new RouterException('HTTP Method not found.');
        }
        else {
            var callBackToBeExecuted = (!async)? requests[method].callbacks[url] : requests[method].asyncCallbacks[url];
            if(!!callBackToBeExecuted) {
                callBackToBeExecuted(request, response);
            }
        }
    }

    return router;

}());

module.exports = router;
<|endoftext|>


<commit_before>#!/usr/bin/node

var fs = require('fs');
var file_config = process.env.CONFIG || '/etc/dhcp/dhcpd.conf';
var file_leases = process.env.LEASES || '/var/lib/dhcp/dhcpd.leases';
var moment = require('moment');
var debug = require('debug')('dhcpleases');
var _ = require('underscore');
var express = require('express');
var app = express();

/*
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-4.1.1-P1

lease 172.30.3.189 {
  starts 6 2012/12/01 15:07:57;
  ends 6 2012/12/01 15:08:50;
  tstp 6 2012/12/01 15:08:50;
  cltt 6 2012/12/01 15:07:57;
  binding state free;
  hardware ethernet 64:20:0c:69:75:60;
  uid "\001d \014iu`";
}
*/

var leases = {};
var subnet = {};
var old = {};
var i;

var explodeRange = function (start, finish) {
    var ip1 = start.split(".");
    var ip2 = finish.split(".");

    var range = [];

    var i = ip1;
    while ((parseInt(i[3]) !== parseInt(ip2[3])) ||
           (parseInt(i[2]) !== parseInt(ip2[2])) ||
           (parseInt(i[1]) !== parseInt(ip2[1])) ||
           (parseInt(i[0]) !== parseInt(ip2[0]))) {
        range.push(i.join("."));
        if (i[3] < 255) {
            i[3]++;
        } else if (i[3] === 255 && i[2] < 255) {
            i[3] = 0;
            i[2]++;
        } else if (i[2] === 255 && i[1] < 255) {
            i[3] = 0;
            i[2] = 0;
            i[1]++;
        } else if (i[1] === 255 && i[0] < 255) {
            i[3] = 0;
            i[2] = 0;
            i[1] = 0;
            i[0]++;
        } else {
            throw new Error("Range error: IP out of range");
        }
    }
    range.push(finish);
    return range;
};

var updateFile = function() {
    old.leases = subnet.leases.slice(0); // clone the array
    subnet.leases = [];
    debug("Updated at " + moment().format('MMMM Do YYYY, h:mm:ss a'));
    var i = 0;
    var _active = {},
        _leases = [];

    fs.readFileSync(file_leases).toString().split(/\r?\n/).forEach(function(line){
        if (line.match(/^lease/)) {
            var match = (/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/).exec(line);
            _leases[i] = new Object();
            _leases[i].ip = match[0];
        }
        if (line.match(/^  starts/)) {
            var match = (/\d{4}\/\d{2}\/\d{2} \d{2}\:\d{2}\:\d{2}/).exec(line);
            _leases[i].starts = match[0];
        }
        if (line.match(/^  ends/)) {
            if (line.match(/never/)) {
                _leases[i].ends = "never";
            } else {
                var match = (/\d{4}\/\d{2}\/\d{2} \d{2}\:\d{2}\:\d{2}/).exec(line);
                _leases[i].ends = match[0];
            }
        }
        if (line.match(/^  binding state/)) {
            var match = (/active|free/).exec(line);
            _leases[i].state = match[0];
        }
        if (line.match(/^  uid/)) {
            var match = (/".*"/).exec(line);
            _leases[i].uid = match[0].replace(/"/g, '');
        }
        if (line.match(/^  client-hostname/)) {
            var match = (/".*"/).exec(line);
            _leases[i].hostname = match[0].replace(/"/g, '');
        }
        if (line.match(/^  hardware ethernet/)) {
            var match = (/[a-f0-9\:]{17}/).exec(line);
            _leases[i].ethernet = match[0];
        }
        if (line.match(/^}/)) {
            i++;
        }
    });

    for (var i = 0; i < _leases.length; i++) {
        if (_leases[i].state == 'active') {
            _active[_leases[i].ip] = _leases[i];
        }
    }

    // Only count 'active' leases.
    for (var key in _active) {
        subnet.leases.push(_active[key]);
    }
    subnet.meta.used = subnet.leases.length;

    io.sockets.emit("update", subnet.meta);

    if (old.leases !== undefined) {
        // Use .slice(0) to send a COPY of the array, not the reference to the actuall array
        io.sockets.emit("changed", difference(old.leases.slice(0),subnet.leases.slice(0)));
    }
};

var difference = function(original, updated) {
    for (var i = original.length - 1; i >= 0; i--) {
        var delFromOriginal = null;
        for (var j = updated.length - 1; j >= 0; j--) {
            var delFromUpdated = null;
            if (JSON.stringify(original[i]) == JSON.stringify(updated[j])) {
                // JSON.stringify() is not the best, if the lease is out of order
                // (shouldn't be), the JSON will not be equal.
                // In JSON, { a: 1, b:2 } DOES NOT EQUAL { b: 2, a: 1}
                delFromOriginal = i;
                delFromUpdated = j;
            }
            if (delFromUpdated !== null) updated.splice(delFromUpdated,1);
        }
        // We delete from both arrays to make the loop exponentially faster.
        if (delFromOriginal !== null) original.splice(delFromOriginal,1);
    };
    // Return only the updated array's information.
    return updated;
};

fs.readFileSync(file_config).toString().split(/\r?\n/).forEach(function(line){
    if (line.match(/^#/)) return;
    if (line.match(/^\s*subnet/)) {
        i = line.match(/(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/g);
        subnet = { meta: { subnet: i[0], netmask: i[1] }, leases: [] };
    }
    if (line.match(/^\s+range/)) {
        range = line.match(/(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/g);
        subnet.meta.start = range[0];
        subnet.meta.finish = range[1];
        range = explodeRange(range[0], range[1]);
        subnet.meta.total = range.length;
    }
});

var server = app.listen(process.env.PORT || 3412);

var io = require('socket.io').listen(server, { log: false });

updateFile();

fs.watch(file_leases, function(event, filename) {
    updateFile();
});

app.get('/', function(req, res) {
    res.json(subnet);
});

io.on('connection', function(socket){
    socket.emit("init", subnet);
});<commit_msg>fix force UTC<commit_after>#!/usr/bin/node

var fs = require('fs');
var file_config = process.env.CONFIG || '/etc/dhcp/dhcpd.conf';
var file_leases = process.env.LEASES || '/var/lib/dhcp/dhcpd.leases';
var moment = require('moment');
var debug = require('debug')('dhcpleases');
var _ = require('underscore');
var express = require('express');
var app = express();

/*
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-4.1.1-P1

lease 172.30.3.189 {
  starts 6 2012/12/01 15:07:57;
  ends 6 2012/12/01 15:08:50;
  tstp 6 2012/12/01 15:08:50;
  cltt 6 2012/12/01 15:07:57;
  binding state free;
  hardware ethernet 64:20:0c:69:75:60;
  uid "\001d \014iu`";
}
*/

var leases = {};
var subnet = {};
var old = {};
var i;

var explodeRange = function (start, finish) {
    var ip1 = start.split(".");
    var ip2 = finish.split(".");

    var range = [];

    var i = ip1;
    while ((parseInt(i[3]) !== parseInt(ip2[3])) ||
           (parseInt(i[2]) !== parseInt(ip2[2])) ||
           (parseInt(i[1]) !== parseInt(ip2[1])) ||
           (parseInt(i[0]) !== parseInt(ip2[0]))) {
        range.push(i.join("."));
        if (i[3] < 255) {
            i[3]++;
        } else if (i[3] === 255 && i[2] < 255) {
            i[3] = 0;
            i[2]++;
        } else if (i[2] === 255 && i[1] < 255) {
            i[3] = 0;
            i[2] = 0;
            i[1]++;
        } else if (i[1] === 255 && i[0] < 255) {
            i[3] = 0;
            i[2] = 0;
            i[1] = 0;
            i[0]++;
        } else {
            throw new Error("Range error: IP out of range");
        }
    }
    range.push(finish);
    return range;
};

var updateFile = function() {
    old.leases = subnet.leases.slice(0); // clone the array
    subnet.leases = [];
    debug("Updated at " + moment().format('MMMM Do YYYY, h:mm:ss a'));
    var i = 0;
    var _active = {},
        _leases = [];

    fs.readFileSync(file_leases).toString().split(/\r?\n/).forEach(function(line){
        if (line.match(/^lease/)) {
            var match = (/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/).exec(line);
            _leases[i] = new Object();
            _leases[i].ip = match[0];
        }
        if (line.match(/^  starts/)) {
            var match = (/\d{4}\/\d{2}\/\d{2} \d{2}\:\d{2}\:\d{2}/).exec(line);
            _leases[i].starts = moment(match[0] + " Z").format("X");
        }
        if (line.match(/^  ends/)) {
            if (line.match(/never/)) {
                _leases[i].ends = "never";
            } else {
                var match = (/\d{4}\/\d{2}\/\d{2} \d{2}\:\d{2}\:\d{2}/).exec(line);
                _leases[i].ends = moment(match[0] + " Z").format("X");
            }
        }
        if (line.match(/^  binding state/)) {
            var match = (/active|free/).exec(line);
            _leases[i].state = match[0];
        }
        if (line.match(/^  uid/)) {
            var match = (/".*"/).exec(line);
            _leases[i].uid = match[0].replace(/"/g, '');
        }
        if (line.match(/^  client-hostname/)) {
            var match = (/".*"/).exec(line);
            _leases[i].hostname = match[0].replace(/"/g, '');
        }
        if (line.match(/^  hardware ethernet/)) {
            var match = (/[a-f0-9\:]{17}/).exec(line);
            _leases[i].ethernet = match[0];
        }
        if (line.match(/^}/)) {
            i++;
        }
    });

    for (var i = 0; i < _leases.length; i++) {
        if (_leases[i].state == 'active') {
            _active[_leases[i].ip] = _leases[i];
        }
    }

    // Only count 'active' leases.
    for (var key in _active) {
        subnet.leases.push(_active[key]);
    }
    subnet.meta.used = subnet.leases.length;

    io.sockets.emit("update", subnet.meta);

    if (old.leases !== undefined) {
        // Use .slice(0) to send a COPY of the array, not the reference to the actuall array
        io.sockets.emit("changed", difference(old.leases.slice(0),subnet.leases.slice(0)));
    }
};

var difference = function(original, updated) {
    for (var i = original.length - 1; i >= 0; i--) {
        var delFromOriginal = null;
        for (var j = updated.length - 1; j >= 0; j--) {
            var delFromUpdated = null;
            if (JSON.stringify(original[i]) == JSON.stringify(updated[j])) {
                // JSON.stringify() is not the best, if the lease is out of order
                // (shouldn't be), the JSON will not be equal.
                // In JSON, { a: 1, b:2 } DOES NOT EQUAL { b: 2, a: 1}
                delFromOriginal = i;
                delFromUpdated = j;
            }
            if (delFromUpdated !== null) updated.splice(delFromUpdated,1);
        }
        // We delete from both arrays to make the loop exponentially faster.
        if (delFromOriginal !== null) original.splice(delFromOriginal,1);
    };
    // Return only the updated array's information.
    return updated;
};

fs.readFileSync(file_config).toString().split(/\r?\n/).forEach(function(line){
    if (line.match(/^#/)) return;
    if (line.match(/^\s*subnet/)) {
        i = line.match(/(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/g);
        subnet = { meta: { subnet: i[0], netmask: i[1] }, leases: [] };
    }
    if (line.match(/^\s+range/)) {
        range = line.match(/(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/g);
        subnet.meta.start = range[0];
        subnet.meta.finish = range[1];
        range = explodeRange(range[0], range[1]);
        subnet.meta.total = range.length;
    }
});

var server = app.listen(process.env.PORT || 3412);

var io = require('socket.io').listen(server, { log: false });

updateFile();

fs.watch(file_leases, function(event, filename) {
    updateFile();
});

app.get('/', function(req, res) {
    res.json(subnet);
});

io.on('connection', function(socket){
    socket.emit("init", subnet);
});<|endoftext|>


<commit_before>
  /**
   *  Tables block view, it encompasses...:
   *
   *  - Tables list
   *  - Tables aside (create new vis)
   *
   *  It needs:
   *
   *  - Tables collection
   *  - User model
   *  - App config object
   *  - Background importer
   *
   *  An example:
   *
   *  var tablesView = new cdb.admin.dashboard.Tables({
   *    el:         $('article.tables'),
   *    collection: tables,
   *    user:       user,
   *    config:     config,
   *    importer:   importer
   *  });
   */

  /*
    TODO list:

      - When delete a table show the red block.
      - Specs.
  */

  cdb.admin.dashboard.Tables = cdb.core.View.extend({

    events: {
      'click a.create_new': '_showCreationDialog',
      'click .remove':      '_removeTag'
    },

    initialize: function() {
      // User can create tables
      this.active = true;

      this.tables = this.options.tables;

      this.template = cdb.templates.getTemplate('dashboard/views/tables');
      this.render();

      this.user = this.options.user;

      this._initViews();
      this._bindEvents();
    },

    render: function() {
      this.$el.append(this.template());
      return this;
    },

    _initViews: function() {

      var self = this;

      _.bindAll(this, "_changeTitle");

      // Tables list
      this.tableList = new cdb.admin.dashboard.TableList({
        el:         this.$('#tablelist'),
        collection: this.tables,
        config:     this.options.config,
        user:       this.options.user
      });

      this.model = new Backbone.Model({
        show_default_title: true,
        default_title: "Recent tables"
      });

      this.tableList.bind("remove", this._onRemove, this);
      this.tableList.bind("showLoader", this.showLoader, this);

      this.add_related_model(this.model);
      this.addView(this.tableList);
    },

    _bindEvents: function() {
      this.tables.bind('add reset', this._setupTablesView, this);

      this.model.on("change:show_default_title", this._changeTitle, this);
      this.model.on("change:padding",            this._changePadding, this);
    },

    _onRemove: function() {
      this.tables.options.set({ type: "table" });
      this.showLoader();
      this.trigger("fetch", this);
    },

    /**
     *  Setup tables view
     */
    _setupTablesView: function() {
      this._changeTitle();
      this._decideActiveBlock();
      this._setupLimits();
      this.hideLoader();
    },

    showDefaultTitle: function(show) {
      this.model.set("show_default_title", show);
    },

    showLoader: function() {
      this.$el.find(".loader").show();
    },

    hideLoader: function() {
      this.$el.find(".loader").hide();
    },

    /**
    *  Change element padding
    */
    _changePadding: function() {

      if (this.model.get("padding")) this.$el.removeClass("no_padding");
      else this.$el.addClass("no_padding");

    },

    _changeTitle: function() {

      var title = "";

      var preview_items_count = this.tables._PREVIEW_ITEMS_PER_PAGE;

      if (this.tables.options.get("type") == 'table') preview_items_count = this.tables._PREVIEW_TABLES_PER_PAGE;

      if (this.tables.options.get("per_page") == preview_items_count) {
        title = this.model.get("default_title");
      }  else {

        var q     = this.tables.options.get("q");
        var tag   = this.tables.options.get("tags");
        var count = this.tables.total_entries;

        if (tag) {
          title = count + " table" + ( count != 1 ? "s" : "") + " with the tag " + tag + "";
        } else if (q) {
          title = count + " table" + ( count != 1 ? "s" : "") + " with " + q + " found";
        } else {
          title = count + " table" + ( count != 1 ? "s" : "") + " created";
        }

      }

      this.$("h2 span").html(title);

    },

    /**
     *  Set limit parameter checking user limitations
     */
    _decideActiveBlock: function() {

      var active  = this.tables.size() > 0;
      var preview = this.tables.options.get("per_page") == this.tables._PREVIEW_ITEMS_PER_PAGE;

      this.$el[ preview ? 'addClass' : 'removeClass' ]('view_all');
      this.$el[ active  ? 'addClass' : 'removeClass' ]('active');
    },

    _removeTag: function(e) {
      e.preventDefault();
      e.stopPropagation();

      this.trigger("removeTag", this);
    },

    hide: function() {
      this.$el.removeClass("active");
    },

    /**
     *  Set limit parameter checking user limitations
     */
    _setupLimits: function() {
      var user = this.options.user.toJSON()
        , custom_cartodb = this.options.config.custom_com_hosted
        , overcome_bytes_quota = ((((user.byte_quota - user.remaining_byte_quota) / user.byte_quota) * 100) >= 100)
        , overcome_tables_quota = (((user.table_count / user.table_quota) * 100) >= 100);

      if (!custom_cartodb &&
          (overcome_bytes_quota || overcome_tables_quota) &&
          user.byte_quota != null &&
          user.byte_quota != 0 &&
          user.table_quota != null &&
          user.table_quota != 0
        ) {
        this.active = false;
      } else {
        this.active = true;
      }

      this._setCreateButton();
    },

    /**
     *  Setup creation button, activate or disable it
     */
    _setCreateButton: function() {
      this.$(".create_new")[this.active ? 'removeClass' : 'addClass' ]("grey disabled");
    },

    /**
     *  Start background import
     */
    _importStarted: function(item_queue_id) {

      // Start importer before first polling arrives
      this.options.importer.changeState({state: "preprocessing"});

      var self = this
        , imp = new cdb.admin.Import({ item_queue_id: item_queue_id });

      imp.bind("importComplete", function(e){
        setTimeout(self.options.importer.hide, 3000);
        imp.unbind();
      },this).bind("importError", function(e){
        cdb.log.info(e);
      },this).bind('change:state', function(i) {
        self.options.importer.changeState(i.toJSON());
      },this).bind('change:success', function(i) {
        self.options.importer.changeState(i.toJSON());
      }, this);

      imp.pollCheck();
    },

    /**
     * Show import/create dialog or upgrade dialog if user reachs limits
     */
    _showCreationDialog: function(e) {
      this.killEvent(e);

      // If view is not active, don't show the dialog
      if (!this.active) return false;

      cdb.god.trigger('mixpanel', "Open create table");
      this.trigger('openCreateTableDialog');
    },

    /**
     *  Show upgrade window
     */
    _showUpgradeDialog: function() {
      var dlg = new cdb.admin.UpgradeDialog({
            model: this.options.user,
            config: this.options.config
          });

      this.$el.append(dlg.render().el);

      dlg.open();
    }
  })
<commit_msg>Bind changes in the user model to the recalc of the table view limits<commit_after>
  /**
   *  Tables block view, it encompasses...:
   *
   *  - Tables list
   *  - Tables aside (create new vis)
   *
   *  It needs:
   *
   *  - Tables collection
   *  - User model
   *  - App config object
   *  - Background importer
   *
   *  An example:
   *
   *  var tablesView = new cdb.admin.dashboard.Tables({
   *    el:         $('article.tables'),
   *    collection: tables,
   *    user:       user,
   *    config:     config,
   *    importer:   importer
   *  });
   */

  /*
    TODO list:

      - When delete a table show the red block.
      - Specs.
  */

  cdb.admin.dashboard.Tables = cdb.core.View.extend({

    events: {
      'click a.create_new': '_showCreationDialog',
      'click .remove':      '_removeTag'
    },

    initialize: function() {
      // User can create tables
      this.active = true;

      this.tables = this.options.tables;

      this.template = cdb.templates.getTemplate('dashboard/views/tables');
      this.render();

      this.user = this.options.user;

      this._initViews();
      this._bindEvents();
    },

    render: function() {
      this.$el.append(this.template());
      return this;
    },

    _initViews: function() {

      var self = this;

      _.bindAll(this, "_changeTitle");

      // Tables list
      this.tableList = new cdb.admin.dashboard.TableList({
        el:         this.$('#tablelist'),
        collection: this.tables,
        config:     this.options.config,
        user:       this.options.user
      });

      this.model = new Backbone.Model({
        show_default_title: true,
        default_title: "Recent tables"
      });

      this.tableList.bind("remove", this._onRemove, this);
      this.tableList.bind("showLoader", this.showLoader, this);

      this.add_related_model(this.model);
      this.addView(this.tableList);
    },

    _bindEvents: function() {
      this.tables.bind('add reset', this._setupTablesView, this);

      this.model.on("change:show_default_title", this._changeTitle, this);
      this.model.on("change:padding",            this._changePadding, this);

      this.user.on("change:byte_quota change:table_count", this._setupLimits, this);
    },

    _onRemove: function() {

      this.tables.options.set({ type: "table" });
      this.trigger("fetch", this);
    },

    /**
     *  Setup tables view
     */
    _setupTablesView: function() {
      this._changeTitle();
      this._decideActiveBlock();
      this._setupLimits();
      this.hideLoader();
    },

    showDefaultTitle: function(show) {
      this.model.set("show_default_title", show);
    },

    showLoader: function() {
      this.$el.find(".loader").show();
    },

    hideLoader: function() {
      this.$el.find(".loader").hide();
    },

    /**
    *  Change element padding
    */
    _changePadding: function() {

      if (this.model.get("padding")) this.$el.removeClass("no_padding");
      else this.$el.addClass("no_padding");

    },

    _changeTitle: function() {

      var title = "";

      var preview_items_count = this.tables._PREVIEW_ITEMS_PER_PAGE;

      if (this.tables.options.get("type") == 'table') preview_items_count = this.tables._PREVIEW_TABLES_PER_PAGE;

      if (this.tables.options.get("per_page") == preview_items_count) {
        title = this.model.get("default_title");
      }  else {

        var q     = this.tables.options.get("q");
        var tag   = this.tables.options.get("tags");
        var count = this.tables.total_entries;

        if (tag) {
          title = count + " table" + ( count != 1 ? "s" : "") + " with the tag " + tag + "";
        } else if (q) {
          title = count + " table" + ( count != 1 ? "s" : "") + " with " + q + " found";
        } else {
          title = count + " table" + ( count != 1 ? "s" : "") + " created";
        }

      }

      this.$("h2 span").html(title);

    },

    /**
     *  Set limit parameter checking user limitations
     */
    _decideActiveBlock: function() {

      var active  = this.tables.size() > 0;
      var preview = this.tables.options.get("per_page") == this.tables._PREVIEW_ITEMS_PER_PAGE;

      this.$el[ preview ? 'addClass' : 'removeClass' ]('view_all');
      this.$el[ active  ? 'addClass' : 'removeClass' ]('active');
    },

    _removeTag: function(e) {
      e.preventDefault();
      e.stopPropagation();

      this.trigger("removeTag", this);
    },

    hide: function() {
      this.$el.removeClass("active");
    },

    /**
     *  Set limit parameter checking user limitations
     */
    _setupLimits: function() {
      var user = this.options.user.toJSON()
        , custom_cartodb = this.options.config.custom_com_hosted
        , overcome_bytes_quota = ((((user.byte_quota - user.remaining_byte_quota) / user.byte_quota) * 100) >= 100)
        , overcome_tables_quota = (((user.table_count / user.table_quota) * 100) >= 100);

      if (!custom_cartodb &&
          (overcome_bytes_quota || overcome_tables_quota) &&
          user.byte_quota != null &&
          user.byte_quota != 0 &&
          user.table_quota != null &&
          user.table_quota != 0
        ) {
        this.active = false;
      } else {
        this.active = true;
      }

      this._setCreateButton();
    },

    /**
     *  Setup creation button, activate or disable it
     */
    _setCreateButton: function() {
      this.$(".create_new")[this.active ? 'removeClass' : 'addClass' ]("grey disabled");
    },

    /**
     *  Start background import
     */
    _importStarted: function(item_queue_id) {

      // Start importer before first polling arrives
      this.options.importer.changeState({state: "preprocessing"});

      var self = this
        , imp = new cdb.admin.Import({ item_queue_id: item_queue_id });

      imp.bind("importComplete", function(e){
        setTimeout(self.options.importer.hide, 3000);
        imp.unbind();
      },this).bind("importError", function(e){
        cdb.log.info(e);
      },this).bind('change:state', function(i) {
        self.options.importer.changeState(i.toJSON());
      },this).bind('change:success', function(i) {
        self.options.importer.changeState(i.toJSON());
      }, this);

      imp.pollCheck();
    },

    /**
     * Show import/create dialog or upgrade dialog if user reachs limits
     */
    _showCreationDialog: function(e) {
      this.killEvent(e);

      // If view is not active, don't show the dialog
      if (!this.active) return false;

      cdb.god.trigger('mixpanel', "Open create table");
      this.trigger('openCreateTableDialog');
    },

    /**
     *  Show upgrade window
     */
    _showUpgradeDialog: function() {
      var dlg = new cdb.admin.UpgradeDialog({
            model: this.options.user,
            config: this.options.config
          });

      this.$el.append(dlg.render().el);

      dlg.open();
    }
  })
<|endoftext|>


<commit_before>"use strict";

apingApp.config(['$provide', function ($provide) {

    $provide.constant("apingApiKeys", {
        youtube : "<YOUR_YOUTUBE_API_KEY>",
        instagram: "<YOUR_INSTAGRAM_API_KEY>",
        instagramClientId: "<YOUR_INSTAGRAM_CLIENT_ID>",
    });

    $provide.constant("apingDefaultSettings", {
        templateUrl : "../src/aping_design_sample.html",
        items : 20, //items per request
        maxItems: 100, //max items per aping
        orderBy : "timestamp",
        orderReverse : "true",
        type: "social",
    });

}]);<commit_msg>impr: new apiKey mechanism<commit_after>"use strict";

apingApp.config(['$provide', function ($provide) {

    "use strict";
    apingApp.config(['$provide', function ($provide) {

        $provide.constant("apingApiKeys", {
            youtube : [
                {'apiKey':'<YOUR_YOUTUBE_API_KEY>'}
            ],
            instagram: [
                {'access_token':'<YOUR_INSTAGRAM_TOKEN>'}
            ],
            facebook: [
                {'access_token':'<YOUR_FACEBOOK_TOKEN>'}
            ],
            twitter: [
                {'bearer_token':'<YOUR_TWITTER_BEARER_TOKEN>'}
            ],
            vimeo: [
                {'access_token':'<YOUR_VIMEO_TOKEN>'}
            ],
        });

        $provide.constant("apingDefaultSettings", {
            templateUrl : "<PATH_TO_YOUR_DEFAULT_DESIGN>",
            items : 20, //items per request
            maxItems: 100, //max items per aping
            orderBy : "timestamp",
            orderReverse : "true",
            model: "social",
        });

    }]);

    $provide.constant("apingDefaultSettings", {
        templateUrl : "../src/aping_design_sample.html",
        items : 20, //items per request
        maxItems: 100, //max items per aping
        orderBy : "timestamp",
        orderReverse : "true",
        type: "social",
    });

}]);<|endoftext|>


<commit_before>var    _ = require('underscore'),
     mbc = require('mbc-common'),
    conf = mbc.config.Caspa,
    search_options = mbc.config.Search,
    collections = mbc.config.Common.Collections,
    uuid = require('node-uuid'),
    logger = mbc.logger().addLogger('caspa_backends'),
    backboneio = require('backbone.io');

// Override mongoStore read method with custom
var searchWrapper = require('./searchWrapper.js');

var iobackends = module.exports = exports = function (db, publisher) {
    var self = this;
    this.middleware = {
        debug: function (req, res, next) {
            logger.debug('Backend:', req.backend);
            logger.debug('Method: ', req.method);
            logger.debug('Channel:', req.channel);
            logger.debug('Options:', JSON.stringify(req.options));
            logger.debug('Model:  ', JSON.stringify(req.model));
            next();
        },

        uuid: function (req, res, next) {
            if( req.method == 'create' && req.model._id === undefined) {
                req.model._id = uuid.v1();
            }
            next();
        },

        publishJSON: function (req, res, next) {
            publisher.publishJSON([req.backend, req.method].join('.'), { model: req.model });
            next();
        }
    };

    this.backends = {
        app: {
            use: [backboneio.middleware.configStore()]
        },
        transform: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Transforms,
                opts: { search: search_options.Transforms },
            }},
        media: {
            mongo: {
                db: db,
                collection: collections.Medias,
                opts: { search: search_options.Medias },
            }},
        piece: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Pieces,
                opts: { search: search_options.Pieces },
            }},
        list: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Lists,
                opts: { search: search_options.Lists },
            }},
        sched: {
            use: [this.middleware.uuid, this.middleware.publishJSON],
            mongo: {
                db: db,
                collection: collections.Scheds,
                opts: { search: search_options.Scheds },
            }},
        status: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Status,
                opts: { search: search_options.Status },
            }},
        frame: {
            use: [backboneio.middleware.memoryStore(db, 'progress', {})],
        },
        mostomessages: {
            mongo: {
                db: db,
                collection: collections.Mostomessages,
                opts: { search: search_options.Mostomessages },
            }},
        sketch: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Sketchs,
                opts: { search: search_options.Sketchs },
            }},
    };

    /* process the backends object to streamline code */
    var binded = [];
    _(this.backends).each (function (backend) {
        backend.io = backboneio.createBackend();
        if (backend.use) {
            _(backend.use).each (function (usefn) {
                backend.io.use(usefn);
            });
        }
        if (backend.mongo) {
            var mongo = _.extend ({db: db, opts: {}}, backend.mongo);
            var fn = _.identity;
            binded.push (backend.mongo.collection);

            if (_.has(mongo.opts, 'search'))
                fn = searchWrapper;
            backend.io.use(
                fn(backboneio.middleware.mongoStore(mongo.db,
                                                    mongo.collection,
                                                    mongo.opts)));
        }
        backend.io.use (self.middleware.debug);
    });

    logger.info ('binding to mongo collections:', binded.join(', ') + '.');
};

iobackends.prototype.register_sync = function (collection, name) {
    var backend = this.get_io (name);
    function sync (method, model, options) {
        var event = {create: 'created', read: 'updated', update: 'updated', delete: 'removed'};

        logger.warn ('in sync for backend', name, method, event[method]);

        backend.emit (event[method], model.toJSON());
    };

    collection.osync = sync;
};

iobackends.prototype.emit = function (name, args) {
    _.apply(this.backends[name].emit, args);
};

iobackends.prototype.get_ios = function () {
    var ret = {};
    var self = this;
    _(_.keys(this.backends)).each (function (backend) {
        ret[backend + 'backend'] = self.backends[backend].io;
    });
    return ret;
};

iobackends.prototype.get = function (name) {
    return this.backends[name];
};

iobackends.prototype.get_io = function (name) {
    return this.get(name).io;
};
<commit_msg>kill get_io<commit_after>var    _ = require('underscore'),
     mbc = require('mbc-common'),
    conf = mbc.config.Caspa,
    search_options = mbc.config.Search,
    collections = mbc.config.Common.Collections,
    uuid = require('node-uuid'),
    logger = mbc.logger().addLogger('caspa_backends'),
    backboneio = require('backbone.io');

// Override mongoStore read method with custom
var searchWrapper = require('./searchWrapper.js');

var iobackends = module.exports = exports = function (db, publisher) {
    var self = this;
    this.middleware = {
        debug: function (req, res, next) {
            logger.debug('Backend:', req.backend);
            logger.debug('Method: ', req.method);
            logger.debug('Channel:', req.channel);
            logger.debug('Options:', JSON.stringify(req.options));
            logger.debug('Model:  ', JSON.stringify(req.model));
            next();
        },

        uuid: function (req, res, next) {
            if( req.method == 'create' && req.model._id === undefined) {
                req.model._id = uuid.v1();
            }
            next();
        },

        publishJSON: function (req, res, next) {
            publisher.publishJSON([req.backend, req.method].join('.'), { model: req.model });
            next();
        }
    };

    this.backends = {
        app: {
            use: [backboneio.middleware.configStore()]
        },
        transform: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Transforms,
                opts: { search: search_options.Transforms },
            }},
        media: {
            mongo: {
                db: db,
                collection: collections.Medias,
                opts: { search: search_options.Medias },
            }},
        piece: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Pieces,
                opts: { search: search_options.Pieces },
            }},
        list: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Lists,
                opts: { search: search_options.Lists },
            }},
        sched: {
            use: [this.middleware.uuid, this.middleware.publishJSON],
            mongo: {
                db: db,
                collection: collections.Scheds,
                opts: { search: search_options.Scheds },
            }},
        status: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Status,
                opts: { search: search_options.Status },
            }},
        frame: {
            use: [backboneio.middleware.memoryStore(db, 'progress', {})],
        },
        mostomessages: {
            mongo: {
                db: db,
                collection: collections.Mostomessages,
                opts: { search: search_options.Mostomessages },
            }},
        sketch: {
            use: [this.middleware.uuid],
            mongo: {
                db: db,
                collection: collections.Sketchs,
                opts: { search: search_options.Sketchs },
            }},
    };

    /* process the backends object to streamline code */
    var binded = [];
    _(this.backends).each (function (backend) {
        backend.io = backboneio.createBackend();
        if (backend.use) {
            _(backend.use).each (function (usefn) {
                backend.io.use(usefn);
            });
        }
        if (backend.mongo) {
            var mongo = _.extend ({db: db, opts: {}}, backend.mongo);
            var fn = _.identity;
            binded.push (backend.mongo.collection);

            if (_.has(mongo.opts, 'search'))
                fn = searchWrapper;
            backend.io.use(
                fn(backboneio.middleware.mongoStore(mongo.db,
                                                    mongo.collection,
                                                    mongo.opts)));
        }
        backend.io.use (self.middleware.debug);
    });

    logger.info ('binding to mongo collections:', binded.join(', ') + '.');
};

iobackends.prototype.register_sync = function (collection, name) {
    var backend = this.get_io (name);
    function sync (method, model, options) {
        var event = {create: 'created', read: 'updated', update: 'updated', delete: 'removed'};

        logger.warn ('in sync for backend', name, method, event[method]);

        backend.emit (event[method], model.toJSON());
    };

    collection.osync = sync;
};

iobackends.prototype.emit = function (name, args) {
    _.apply(this.backends[name].emit, args);
};

iobackends.prototype.get_ios = function () {
    var ret = {};
    var self = this;
    _(_.keys(this.backends)).each (function (backend) {
        ret[backend + 'backend'] = self.backends[backend].io;
    });
    return ret;
};

iobackends.prototype.get = function (name) {
    return this.backends[name];
};

<|endoftext|>