<commit_before>'use strict';

/**
* NOTE: the original C code, the long comment, copyright, license, and the constants are from [netlib]{http://www.netlib.org/fdlibm/s_log1p.c}.
*
* The implementation follows the original, but has been modified for JavaScript.
*/

/**
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/

/**
* double log1p(double x)
*
*  Method :
*    1. Argument Reduction: find k and f such that
*
*        1+x = 2^k * (1+f)
*
*      where  sqrt(2)/2 < 1+f < sqrt(2).
*
*      Note: if k=0, then f=x is exact. However, if k!=0, then f may not be representable exactly. In that case, a correction term is needed. Let u=1+x rounded. Let c = (1+x)-u, then
*
*        log(1+x) - log(u) ~ c/u
*
*      Thus, we proceed to compute log(u), and add back the correction term c/u.
*
*      Note: when x > 2**53, one can simply return log(x).
*
*   2. Approximation of log1p(f).
*     Let s = f/(2+f); based on
*
*        log(1+f) = log(1+s) - log(1-s)
*                 = 2s + 2/3 s**3 + 2/5 s**5 + ...
*                 = 2s + s*R
*
*     We use a special Reme algorithm on [0,0.1716] to generate a polynomial of degree 14 to approximate R The maximum error of this polynomial approximation is bounded by 2**-58.45. In other words,
*
*                 2      4      6      8      10      12      14
*        R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
*
*     (Note: the values of Lp1 to Lp7 are listed in the program.)
*
*     and
*
*        |      2          14          |     -58.45
*        | Lp1*s +...+Lp7*s    -  R(z) | <= 2
*        |                             |
*
*     Note that
*
*        2s = f - s*f
*           = f - hfsq + s*hfsq
*
*     where hfsq = f*f/2.
*
*     In order to guarantee error in log below 1 ulp, we compute log by
*
*        log1p(f) = f - (hfsq - s*(hfsq+R)).
*
*	3. Finally,
*
*        log1p(x) = k*ln2 + log1p(f).
*                 = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
*
*     Here ln2 is split into two floating point number:
*
*        ln2_hi + ln2_lo
*
*     where n*ln2_hi is always exact for |n| < 2000.
*
*   Special cases:
*     log1p(x) is NaN with signal if x < -1 (including -INF)
*     log1p(+INF) is +INF
*     log1p(-1) is -INF with signal
*     log1p(NaN) is NaN with no signal
*
*   Accuracy:
*     according to an error analysis, the error is always less than 1 ulp (unit in the last place).
*
*   Constants:
*     The hexadecimal values are the intended ones for the following constants. The decimal values may be used, provided that the compiler will convert from decimal to binary accurately enough to produce the hexadecimal values shown.
*
*   Note:
*     Assuming log() returns accurate answer, the following algorithm can be used to compute log1p(x) to within a few ULP:
*
*        u = 1+x;
*        if(u==1.0) return x;
*        else       return log(u)*(x/(u-1.0));
*
*     See HP-15C Advanced Functions Handbook, p.193.
*/

// MODULES //

var highWord = require( 'math-float64-get-high-word' );
var setHighWord = require( 'math-float64-set-high-word' );

// CONSTANTS //

var PINF = require( 'const-pinf-float64' );
var NINF = require( 'const-ninf-float64' );

var BIAS = 1023;

// High and low words of ln(2):
var LN2_HI = 6.93147180369123816490e-01; // 0x3fe62e42 0xfee00000
var LN2_LO = 1.90821492927058770002e-10; // 0x3dea39ef 0x35793c76

// sqrt(2)-1:
var SQRT2M1 = 4.142135623730950488017e-01;  // 0x3fda8279 0x99fcef34

// sqrt(2)/2-1:
var SQRT2HALFM1 = -2.928932188134524755992e-01; // 0xbfd2bec3 0x33018866

// 2**-29:
var SMALL = 1.862645149230957e-09; // 0x3e200000 0x00000000

// 2**-54:
var TINY = 5.551115123125783e-17;

// Max unsafe integer => 2**53:
var TWO53 = 9007199254740992;

// 2/3:
var TWO_THIRDS = 6.666666666666666666e-01;

// Polynomial coefficients:
var Lp1 = 6.666666666666735130e-01; // 0x3FE55555 0x55555593
var Lp2 = 3.999999999940941908e-01; // 0x3FD99999 0x9997FA04
var Lp3 = 2.857142874366239149e-01; // 0x3FD24924 0x94229359
var Lp4 = 2.222219843214978396e-01; // 0x3FCC71C5 0x1D8E78AF
var Lp5 = 1.818357216161805012e-01; // 0x3FC74664 0x96CB03DE
var Lp6 = 1.531383769920937332e-01; // 0x3FC39A09 0xD078C69F
var Lp7 = 1.479819860511658591e-01; // 0x3FC2F112 0xDF3E5244

// LOG1P //

/**
* FUNCTION: log1p( x )
*	Computes the natural logarithm of `1+x`.
*
* @param {Number} x - input value
* @returns {Number} function value
*/
function log1p( x ) {
	var hfsq;
	var hu;
	var y;
	var f;
	var c;
	var s;
	var z;
	var R;
	var u;
	var k;

	if ( x < -1 || x !== x ) {
		return NaN;
	}
	if ( x === -1 ) {
		return NINF;
	}
	if ( x === PINF ) {
		return PINF;
	}
	if ( x === 0 ) {
		return 0;
	}
	// Set y = |x|:
	if ( x < 0 ) {
		y = -x;
	} else {
		y = x;
	}
	// Argument reduction...
	k = 1;
	if ( y < SQRT2M1 ) { // if |x| < sqrt(2)-1 => ~0.41422
		if ( y < SMALL ) { // if |x| < 2**-29
			if( y < TINY ) { // if |x| < 2**-54
				return x;
			}
			// Use a simple two-term Taylor series...
			return x - x*x*0.5;
		}
		if ( x > SQRT2HALFM1 ) { // if x > sqrt(2)/2-1 => ~-0.2929
			// => -0.2929 < x < 0.41422
			k = 0;
			f = x; // exact
			hu = 1;
		}
	}
	// Address case where `f` cannot be represented exactly...
	if ( k !== 0 ) {
		if ( y < TWO53 ) {
			u = 1.0 + x;
			hu = highWord( u );

			// Bit shift to isolate the exponent and then subtract the bias:
			k = (hu>>20) - BIAS;

			// Correction term...
			if ( k > 0 ) { // positive unbiased exponent
				c = 1.0 - (u-x);
			} else { // nonpositive unbiased exponent
				c = x - (u-1.0);
			}
			c /= u;
		} else {
			u = x;
			hu = highWord( u );

			// Bit shift to isolate the exponent and then subtract the bias:
			k = (hu>>20) - BIAS;

			// Correction term is zero:
			c = 0;
		}
		// Apply a bit mask (0 00000000000 11111111111111111111) to remove the exponent:
		hu &= 0x000fffff; // max value => 1048575

		// Check if u significand is less than sqrt(2) significand => 0x6a09e => 01101010000010011110
		if ( hu < 434334 ) {
			// Normalize u by setting the exponent to 1023 (bias) => 0x3ff00000 => 0 01111111111 00000000000000000000
			u = setHighWord( u, hu|0x3ff00000 );
		} else {
			k += 1;

			// Normalize u/2 by setting the exponent to 1022 (bias-1 => 2**-1 = 1/2) => 0x3fe00000 => 0 01111111110 00000000000000000000
			u = setHighWord( u, hu|0x3fe00000 );

			// Subtract hu significand from next largest hu => 0 00000000001 00000000000000000000 => 0x00100000 => 1048576
			hu = (1048576-hu)>>2;
		}
		f = u - 1.0;
	}
	// Approximation of log1p(f)...
	hfsq = 0.5 * f * f;
	if( hu === 0 ) { // if |f| < 2**-20
		if ( f === 0 ) {
			if ( k === 0 ) {
				return 0;
			}
			c += k * LN2_LO;
			return k * LN2_HI + c;
		}
		R = hfsq * (1.0 - TWO_THIRDS*f); // avoid division
		if ( k === 0 ) {
			return f - R;
		}
		return k*LN2_HI - ( (R - (k*LN2_LO + c)) - f );
	}
	s = f / (2.0 + f);
	z = s * s;

	// TODO: use math-polyval
	R = z * (Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));

	if ( k === 0 ) {
		return f - ( hfsq - s*(hfsq+R) );
	}
	return k*LN2_HI - ( (hfsq - (s*(hfsq+R) + (k*LN2_LO + c))) - f );
} // end FUNCTION log1p()

// EXPORTS //

module.exports = log1p;
<commit_msg>Remove redundant code paths for handling small values<commit_after>'use strict';

/**
* NOTE: the original C code, the long comment, copyright, license, and the constants are from [netlib]{http://www.netlib.org/fdlibm/s_log1p.c}.
*
* The implementation follows the original, but has been modified for JavaScript.
*/

/**
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/

/**
* double log1p(double x)
*
*  Method :
*    1. Argument Reduction: find k and f such that
*
*        1+x = 2^k * (1+f)
*
*      where  sqrt(2)/2 < 1+f < sqrt(2).
*
*      Note: if k=0, then f=x is exact. However, if k!=0, then f may not be representable exactly. In that case, a correction term is needed. Let u=1+x rounded. Let c = (1+x)-u, then
*
*        log(1+x) - log(u) ~ c/u
*
*      Thus, we proceed to compute log(u), and add back the correction term c/u.
*
*      Note: when x > 2**53, one can simply return log(x).
*
*   2. Approximation of log1p(f).
*     Let s = f/(2+f); based on
*
*        log(1+f) = log(1+s) - log(1-s)
*                 = 2s + 2/3 s**3 + 2/5 s**5 + ...
*                 = 2s + s*R
*
*     We use a special Reme algorithm on [0,0.1716] to generate a polynomial of degree 14 to approximate R The maximum error of this polynomial approximation is bounded by 2**-58.45. In other words,
*
*                 2      4      6      8      10      12      14
*        R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
*
*     (Note: the values of Lp1 to Lp7 are listed in the program.)
*
*     and
*
*        |      2          14          |     -58.45
*        | Lp1*s +...+Lp7*s    -  R(z) | <= 2
*        |                             |
*
*     Note that
*
*        2s = f - s*f
*           = f - hfsq + s*hfsq
*
*     where hfsq = f*f/2.
*
*     In order to guarantee error in log below 1 ulp, we compute log by
*
*        log1p(f) = f - (hfsq - s*(hfsq+R)).
*
*	3. Finally,
*
*        log1p(x) = k*ln2 + log1p(f).
*                 = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
*
*     Here ln2 is split into two floating point number:
*
*        ln2_hi + ln2_lo
*
*     where n*ln2_hi is always exact for |n| < 2000.
*
*   Special cases:
*     log1p(x) is NaN with signal if x < -1 (including -INF)
*     log1p(+INF) is +INF
*     log1p(-1) is -INF with signal
*     log1p(NaN) is NaN with no signal
*
*   Accuracy:
*     according to an error analysis, the error is always less than 1 ulp (unit in the last place).
*
*   Constants:
*     The hexadecimal values are the intended ones for the following constants. The decimal values may be used, provided that the compiler will convert from decimal to binary accurately enough to produce the hexadecimal values shown.
*
*   Note:
*     Assuming log() returns accurate answer, the following algorithm can be used to compute log1p(x) to within a few ULP:
*
*        u = 1+x;
*        if(u==1.0) return x;
*        else       return log(u)*(x/(u-1.0));
*
*     See HP-15C Advanced Functions Handbook, p.193.
*/

// MODULES //

var highWord = require( 'math-float64-get-high-word' );
var setHighWord = require( 'math-float64-set-high-word' );

// CONSTANTS //

var PINF = require( 'const-pinf-float64' );
var NINF = require( 'const-ninf-float64' );

var BIAS = 1023;

// High and low words of ln(2):
var LN2_HI = 6.93147180369123816490e-01; // 0x3fe62e42 0xfee00000
var LN2_LO = 1.90821492927058770002e-10; // 0x3dea39ef 0x35793c76

// sqrt(2)-1:
var SQRT2M1 = 4.142135623730950488017e-01;  // 0x3fda8279 0x99fcef34

// sqrt(2)/2-1:
var SQRT2HALFM1 = -2.928932188134524755992e-01; // 0xbfd2bec3 0x33018866

// 2**-29:
var SMALL = 1.862645149230957e-09; // 0x3e200000 0x00000000

// 2**-54:
var TINY = 5.551115123125783e-17;

// Max unsafe integer => 2**53:
var TWO53 = 9007199254740992;

// 2/3:
var TWO_THIRDS = 6.666666666666666666e-01;

// Polynomial coefficients:
var Lp1 = 6.666666666666735130e-01; // 0x3FE55555 0x55555593
var Lp2 = 3.999999999940941908e-01; // 0x3FD99999 0x9997FA04
var Lp3 = 2.857142874366239149e-01; // 0x3FD24924 0x94229359
var Lp4 = 2.222219843214978396e-01; // 0x3FCC71C5 0x1D8E78AF
var Lp5 = 1.818357216161805012e-01; // 0x3FC74664 0x96CB03DE
var Lp6 = 1.531383769920937332e-01; // 0x3FC39A09 0xD078C69F
var Lp7 = 1.479819860511658591e-01; // 0x3FC2F112 0xDF3E5244

// LOG1P //

/**
* FUNCTION: log1p( x )
*	Computes the natural logarithm of `1+x`.
*
* @param {Number} x - input value
* @returns {Number} function value
*/
function log1p( x ) {
	var hfsq;
	var hu;
	var y;
	var f;
	var c;
	var s;
	var z;
	var R;
	var u;
	var k;

	if ( x < -1 || x !== x ) {
		return NaN;
	}
	if ( x === -1 ) {
		return NINF;
	}
	if ( x === PINF ) {
		return PINF;
	}
	if ( x === 0 ) {
		return 0;
	}
	// Set y = |x|:
	if ( x < 0 ) {
		y = -x;
	} else {
		y = x;
	}
	// Argument reduction...
	k = 1;

	// Check if argument reduction is needed and if we can just return a small value approximation requiring less computation but with equivalent accuracy...
	if ( y < SQRT2M1 ) { // if |x| < sqrt(2)-1 => ~0.41422
		if ( y < SMALL ) { // if |x| < 2**-29
			if( y < TINY ) { // if |x| < 2**-54
				return x;
			}
			// Use a simple two-term Taylor series...
			return x - x*x*0.5;
		}
		// Check if `f=x` can be represented exactly (no need for correction terms), allowing us to bypass argument reduction...
		if ( x > SQRT2HALFM1 ) { // if x > sqrt(2)/2-1 => ~-0.2929
			// => -0.2929 < x < 0.41422
			k = 0;
			f = x; // exact
			hu = 1;
		}
	}
	// Address case where `f` cannot be represented exactly...
	if ( k !== 0 ) {
		if ( y < TWO53 ) {
			u = 1.0 + x;
			hu = highWord( u );

			// Bit shift to isolate the exponent and then subtract the bias:
			k = (hu>>20) - BIAS;

			// Correction term...
			if ( k > 0 ) { // positive unbiased exponent
				c = 1.0 - (u-x);
			} else { // nonpositive unbiased exponent
				c = x - (u-1.0);
			}
			c /= u;
		} else {
			u = x;
			hu = highWord( u );

			// Bit shift to isolate the exponent and then subtract the bias:
			k = (hu>>20) - BIAS;

			// Correction term is zero:
			c = 0;
		}
		// Apply a bit mask (0 00000000000 11111111111111111111) to remove the exponent:
		hu &= 0x000fffff; // max value => 1048575

		// Check if u significand is less than sqrt(2) significand => 0x6a09e => 01101010000010011110
		if ( hu < 434334 ) {
			// Normalize u by setting the exponent to 1023 (bias) => 0x3ff00000 => 0 01111111111 00000000000000000000
			u = setHighWord( u, hu|0x3ff00000 );
		} else {
			k += 1;

			// Normalize u/2 by setting the exponent to 1022 (bias-1 => 2**-1 = 1/2) => 0x3fe00000 => 0 01111111110 00000000000000000000
			u = setHighWord( u, hu|0x3fe00000 );

			// Subtract hu significand from next largest hu => 0 00000000001 00000000000000000000 => 0x00100000 => 1048576
			hu = (1048576-hu)>>2;
		}
		f = u - 1.0;
	}
	// Approximation of log1p(f)...
	hfsq = 0.5 * f * f;
	if( hu === 0 ) { // if |f| < 2**-20
		if ( f === 0 ) {
			c += k * LN2_LO;
			return k * LN2_HI + c;
		}
		R = hfsq * (1.0 - TWO_THIRDS*f); // avoid division
		return k*LN2_HI - ( (R - (k*LN2_LO + c)) - f );
	}
	s = f / (2.0 + f);
	z = s * s;

	// TODO: use math-polyval
	R = z * (Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));

	if ( k === 0 ) {
		return f - ( hfsq - s*(hfsq+R) );
	}
	return k*LN2_HI - ( (hfsq - (s*(hfsq+R) + (k*LN2_LO + c))) - f );
} // end FUNCTION log1p()

// EXPORTS //

module.exports = log1p;
<|endoftext|>


<commit_before>'use strict()';

var fs = require('fs'),
  exec = require('child_process').exec,
  os = require('os'),
  username = require('username');

if(process.env.NODE_ENV === 'test') var test = true;

/**
 * Returns the path for the startup folder in Windows
 * @returns {String} path
 */

function getWinStartupPath() {
  var path;
  var majorRelease = os.release().substring(1, 0);
  if(majorRelease >= 6) {
    path = 'C:\\Users\\' + username.sync() + '\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup';
  }
  else {
    path = 'C:\\Documents and Settings\\' + username.sync() + '\\Start Menu\\Programs\\Startup';
  }

  return path;
}

/**
  * Enables autostart
  * @param {String} key
  * @param {String} command
  * @param {String} path
  * @param {Function} callback
  */

function enableAutostart(key, command, path, callback) {
  var err = '';

  if(!key || !command || !path || !callback) {
    if(!test) console.error('Not enough arguments passed to node-autostart, enableAutostart().');
    return 1;
  }

  if(typeof(key) !== 'string') {
    if(!test) console.error('node-autostart: Passed "key" to enableAutostart() is not a string.');
    return 1;
  }

  if(typeof(command) !== 'string') {
    if(!test) console.error('node-autostart: Passed "command" to enableAutostart() is not a string.');
    return 1;
  }

  if(typeof(path) !== 'string') {
    if(!test) console.error('node-autostart: Passed "path" to enableAutostart() is not a string.');
    return 1;
  }

  if(typeof(callback) !== 'function') {
    if(!test) console.error('node-autostart: Passed "callback" to enableAutostart() is not a function.');
    return 1;
  }

  isAutostartEnabled(key, function(isEnabled, error) {
    if (error !== null) {
      err = error;
      callback(err);
      return 1;
    }

    /* istanbul ignore next */
    if (isEnabled === true) {
      err = 'Autostart already is enabled';
      callback(err);
      return 1;
    }

    /* istanbul ignore if  */
    if (os.platform() === 'darwin') {
      //Adding a service with the given key to launchd, using launchctl
      /* istanbul ignore next */
      exec('launchctl submit -l ' + key + ' cd ' + path + ' && ' + command, function(error, stdout, stderr) {
        if (error !== null) {
          err = error;
        } else if (stderr !== '') {
          err = stderr;
        }

        if (err === '' || err === undefined) err = null;
        callback(err);
      });
    //} else if (os.platform() === 'linux') {
      //crontab stuff
    } else if (os.platform() === 'win32') {
      var batchFileContent; //File to be placed in the startup folder, will be generated here
      batchFileContent = 'cd ' + path + ' && ' + command;
      fs.writeFile(getWinStartupPath() + '/' + key + '.bat', batchFileContent, function (error) {
        err = error;

        if (err === '' || err === undefined) err = null;
        callback(err);
      });
    }
  });
}

/**
  * Disables autostart
  * @param {String} key
  * @param {Function} callback
  */

function disableAutostart(key, callback) {
  var err;

  if(!key || !callback) {
    if(!test) console.error('Not enough arguments passed to node-autostart, disableAutostart()');
    return 1;
  }

  if(typeof(key) !== 'string') {
    if(!test) console.error('node-autostart: Passed "key" to disableAutostart() is not a string.');
    return 1;
  }

  if(typeof(callback) !== 'function') {
    if(!test) console.error('node-autostart: Passed "callback" to disableAutostart() is not a function.');
    return 1;
  }

  isAutostartEnabled(key, function(isEnabled, error) {
    if (error !== null) {
      err = error;
      callback(err);
      return 1;
    }

    /* istanbul ignore next */
    if (!isEnabled) {
      err = 'Autostart is not enabled, so you cannot disable it ¯\\_(ツ)_/¯';
      callback(err);
      return 1;
    }

    /* istanbul ignore if  */
    if (os.platform() === "darwin") {
      //Removing the launchd service with the name of the passed key
      /* istanbul ignore next */
      exec('launchctl remove ' + key, function(error, stdout, stderr) {
        if (error !== '') {
          err = error;
        } else if (stderr !== '') {
          err = stderr;
        }

        if (err === '' || err === undefined) err = null;

        callback(err);
      });
    //} else if (os.platform() === 'linux') {
      //crontab stuff
    //} else if (os.platform() === 'win32') {

    }
  });
}

/**
  * Checks if autostart is enabled
  * @param {String} key
  * @param {Function} callback
  */

function isAutostartEnabled(key, callback) {
  var err;
  var isEnabled;

  if(!key || !callback) {
    if(!test) console.error('Not enough arguments passed to node-autostart, disableAutostart()');
    return 1;
  }

  if(typeof(key) !== 'string') {
    if(!test) console.error('node-autostart: Passed "key" to disableAutostart() is not a string.');
    return 1;
  }

  if(typeof(callback) !== 'function') {
    if(!test) console.error('node-autostart: Passed "callback" to disableAutostart() is not a function.');
    return 1;
  }

  /* istanbul ignore if  */
  if (os.platform() === "darwin") {
    /* istanbul ignore next */
    exec('launchctl list | grep -q "' + key + '"; printf $?', function(error, stdout, stderr) {
      if (error !== null) {
        err = error;
      } else if (stderr !== '') {
        err = stderr;
      }

      if (stdout === '0') {
        isEnabled = true;
      }
      else if (stdout === '1') {
        isEnabled = false;
      }
      else {
        err = 'An unexpected error happened trying to check the output of launchctl. Please report this.';
      }

      if(err === '' || err === undefined) err = null;

      callback(isEnabled, err);
    });
  //} else if (os.platform() === "linux") {
    //crontab stuff
  } else if (os.platform() === "win32") {
    if(err === '' || err === undefined) err = null;
    callback(isEnabled = false, err);
  }
  /* istanbul ignore else */
  else {
    err = 'Your platform currently is not supported';
    callback(isEnabled = false, err);
  }
}

module.exports = {
  enableAutostart: enableAutostart,
  disableAutostart: disableAutostart,
  isAutostartEnabled: isAutostartEnabled
};
<commit_msg>Updated testing<commit_after>'use strict()';

var fs = require('fs'),
  exec = require('child_process').exec,
  os = require('os'),
  username = require('username');

if(process.env.NODE_ENV === 'test') var test = true;

/**
 * Returns the path for the startup folder in Windows
 * @returns {String} path
 */
/* istanbul ignore next */
function getWinStartupPath() {
  var path;
  var majorRelease = os.release().substring(1, 0);
  if(majorRelease >= 6) {
    path = 'C:\\Users\\' + username.sync() + '\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup';
  }
  else {
    path = 'C:\\Documents and Settings\\' + username.sync() + '\\Start Menu\\Programs\\Startup';
  }

  return path;
}

/**
  * Enables autostart
  * @param {String} key
  * @param {String} command
  * @param {String} path
  * @param {Function} callback
  */

function enableAutostart(key, command, path, callback) {
  var err = '';

  if(!key || !command || !path || !callback) {
    if(!test) console.error('Not enough arguments passed to node-autostart, enableAutostart().');
    return 1;
  }

  if(typeof(key) !== 'string') {
    if(!test) console.error('node-autostart: Passed "key" to enableAutostart() is not a string.');
    return 1;
  }

  if(typeof(command) !== 'string') {
    if(!test) console.error('node-autostart: Passed "command" to enableAutostart() is not a string.');
    return 1;
  }

  if(typeof(path) !== 'string') {
    if(!test) console.error('node-autostart: Passed "path" to enableAutostart() is not a string.');
    return 1;
  }

  if(typeof(callback) !== 'function') {
    if(!test) console.error('node-autostart: Passed "callback" to enableAutostart() is not a function.');
    return 1;
  }

  isAutostartEnabled(key, function(isEnabled, error) {
    if (error !== null) {
      err = error;
      callback(err);
      return 1;
    }

    /* istanbul ignore next */
    if (isEnabled === true) {
      err = 'Autostart already is enabled';
      callback(err);
      return 1;
    }

    /* istanbul ignore if  */
    if (os.platform() === 'darwin') {
      //Adding a service with the given key to launchd, using launchctl
      /* istanbul ignore next */
      exec('launchctl submit -l ' + key + ' cd ' + path + ' && ' + command, function(error, stdout, stderr) {
        if (error !== null) {
          err = error;
        } else if (stderr !== '') {
          err = stderr;
        }

        if (err === '' || err === undefined) err = null;
        callback(err);
      });
    //} else if (os.platform() === 'linux') {
      //crontab stuff
    } /* istanbul ignore next */ else if (os.platform() === 'win32') {
      var batchFileContent; //File to be placed in the startup folder, will be generated here
      batchFileContent = 'cd ' + path + ' && ' + command;
      fs.writeFile(getWinStartupPath() + '/' + key + '.bat', batchFileContent, function (error) {
        err = error;

        if (err === '' || err === undefined) err = null;
        callback(err);
      });
    }
  });
}

/**
  * Disables autostart
  * @param {String} key
  * @param {Function} callback
  */

function disableAutostart(key, callback) {
  var err;

  if(!key || !callback) {
    if(!test) console.error('Not enough arguments passed to node-autostart, disableAutostart()');
    return 1;
  }

  if(typeof(key) !== 'string') {
    if(!test) console.error('node-autostart: Passed "key" to disableAutostart() is not a string.');
    return 1;
  }

  if(typeof(callback) !== 'function') {
    if(!test) console.error('node-autostart: Passed "callback" to disableAutostart() is not a function.');
    return 1;
  }

  isAutostartEnabled(key, function(isEnabled, error) {
    if (error !== null) {
      err = error;
      callback(err);
      return 1;
    }

    /* istanbul ignore next */
    if (!isEnabled) {
      err = 'Autostart is not enabled, so you cannot disable it ¯\\_(ツ)_/¯';
      callback(err);
      return 1;
    }

    /* istanbul ignore if  */
    if (os.platform() === "darwin") {
      //Removing the launchd service with the name of the passed key
      /* istanbul ignore next */
      exec('launchctl remove ' + key, function(error, stdout, stderr) {
        if (error !== '') {
          err = error;
        } else if (stderr !== '') {
          err = stderr;
        }

        if (err === '' || err === undefined) err = null;

        callback(err);
      });
    //} else if (os.platform() === 'linux') {
      //crontab stuff
    //} else if (os.platform() === 'win32') {

    }
  });
}

/**
  * Checks if autostart is enabled
  * @param {String} key
  * @param {Function} callback
  */

function isAutostartEnabled(key, callback) {
  var err;
  var isEnabled;

  if(!key || !callback) {
    if(!test) console.error('Not enough arguments passed to node-autostart, disableAutostart()');
    return 1;
  }

  if(typeof(key) !== 'string') {
    if(!test) console.error('node-autostart: Passed "key" to disableAutostart() is not a string.');
    return 1;
  }

  if(typeof(callback) !== 'function') {
    if(!test) console.error('node-autostart: Passed "callback" to disableAutostart() is not a function.');
    return 1;
  }

  /* istanbul ignore if  */
  if (os.platform() === "darwin") {
    /* istanbul ignore next */
    exec('launchctl list | grep -q "' + key + '"; printf $?', function(error, stdout, stderr) {
      if (error !== null) {
        err = error;
      } else if (stderr !== '') {
        err = stderr;
      }

      if (stdout === '0') {
        isEnabled = true;
      }
      else if (stdout === '1') {
        isEnabled = false;
      }
      else {
        err = 'An unexpected error happened trying to check the output of launchctl. Please report this.';
      }

      if(err === '' || err === undefined) err = null;

      callback(isEnabled, err);
    });
  //} else if (os.platform() === "linux") {
    //crontab stuff
  } /* istanbul ignore next */ else if (os.platform() === "win32") {
    if(err === '' || err === undefined) err = null;
    callback(isEnabled = false, err);
  }
  /* istanbul ignore else */
  else {
    err = 'Your platform currently is not supported';
    callback(isEnabled = false, err);
  }
}

module.exports = {
  enableAutostart: enableAutostart,
  disableAutostart: disableAutostart,
  isAutostartEnabled: isAutostartEnabled
};
<|endoftext|>


<commit_before>(function(module) {
	"use strict";

	var Theme = {};

	Theme.defineWidgetAreas = function(areas, callback) {
		areas = areas.concat([
			{
				'name': 'Homepage Sidebar',
				'template': 'home.tpl',
				'location': 'sidebar'
			},
			{
				'name': 'Category Sidebar',
				'template': 'category.tpl',
				'location': 'sidebar'
			}
		]);

		callback(null, areas);
	};

	module.exports = Theme;

}(module));<commit_msg>Added header<commit_after>(function(module) {
	"use strict";

	var Theme = {};

	Theme.defineWidgetAreas = function(areas, callback) {
		areas = areas.concat([
			{
				'name': 'Homepage Sidebar',
				'template': 'home.tpl',
				'location': 'sidebar'
			},
			{
				'name': 'Category Sidebar',
				'template': 'category.tpl',
				'location': 'sidebar'
			},
			{
				'name': 'Homepage Header',
				'template': 'home.tpl',
				'location': 'header'
			}
		]);

		callback(null, areas);
	};

	module.exports = Theme;

}(module));
<|endoftext|>


<commit_before>// karma.conf.js - the config file for karma, which runs our tests.

var path = require('path');
var webpack = require('webpack');
var webpack_config = require('./webpack.config');

/*
 * We use webpack to build our tests. It's a pain to have to wait for webpack
 * to build everything; however it's the easiest way to load our dependencies
 * from node_modules.
 *
 * If you run karma in multi-run mode (with `npm run test-multi`), it will watch
 * the tests for changes, and webpack will rebuild using a cache. This is much quicker
 * than a clean rebuild.
 */

// the name of the test file. By default, a special file which runs all tests.
var testFile = process.env.KARMA_TEST_FILE || 'test/all-tests.js';

process.env.PHANTOMJS_BIN = 'node_modules/.bin/phantomjs';
process.env.Q_DEBUG = 1;

/* the webpack config is based on the real one, to (a) try to simulate the
 * deployed environment as closely as possible, and (b) to avoid a shedload of
 * cut-and-paste.
 */

// find out if we're shipping olm, and where it is, if so.
const olm_entry = webpack_config.entry['olm'];

// remove the default entries - karma provides its own (via the 'files' and
// 'preprocessors' config below)
delete webpack_config['entry'];

// add ./test as a search path for js
webpack_config.module.rules.unshift({
    test: /\.js$/, use: "babel-loader",
    include: [path.resolve('./src'), path.resolve('./test')],
});

// disable parsing for sinon, because it
// tries to do voodoo with 'require' which upsets
// webpack (https://github.com/webpack/webpack/issues/304)
webpack_config.module.noParse.push(/sinon\/pkg\/sinon\.js$/);

// ?
webpack_config.resolve.alias['sinon'] = 'sinon/pkg/sinon.js';

webpack_config.resolve.modules = [
    path.resolve('./test'),
    "node_modules"
];

webpack_config.devtool = 'inline-source-map';

module.exports = function (config) {
    const myconfig = {
        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['mocha'],

        // list of files / patterns to load in the browser
        files: [
            'node_modules/babel-polyfill/browser.js',
            testFile,

            // make the images available via our httpd. They will be avaliable
            // below http://localhost:[PORT]/base/. See also `proxies` which
            // defines alternative URLs for them.
            //
            // This isn't required by any of the tests, but it stops karma
            // logging warnings when it serves a 404 for them.
            {
                pattern: 'node_modules/matrix-react-sdk/res/img/*',
                watched: false, included: false, served: true, nocache: false,
            },
            {
                pattern: 'res/themes/**',
                watched: false, included: false, served: true, nocache: false,
            },
        ],

        proxies: {
            // redirect img links to the karma server. See above.
            "/img/": "/base/node_modules/matrix-react-sdk/res/img/",
            "/themes/": "/base/res/themes/",
        },

        // preprocess matching files before serving them to the browser
        // available preprocessors:
        // https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
            '{src,test}/**/*.js': ['webpack', 'sourcemap'],
        },

        // test results reporter to use
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['logcapture', 'spec', 'junit', 'summary'],

        specReporter: {
            suppressErrorSummary: false, // do print error summary
            suppressFailed: false, // do print information about failed tests
            suppressPassed: false, // do print information about passed tests
            showSpecTiming: true, // print the time elapsed for each spec
        },

        client: {
            captureLogs: true,
        },

        // web server port
        port: 9876,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR ||
        // config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file
        // changes
        autoWatch: true,

        // start these browsers
        // available browser launchers:
        // https://npmjs.org/browse/keyword/karma-launcher
        browsers: [
            'Chrome',
            //'PhantomJS',
            //'ChromeHeadless'
        ],

        customLaunchers: {
            'ChromeHeadless': {
                base: 'Chrome',
                flags: [
                    // '--no-sandbox',
                    // See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
                    '--headless',
                    '--disable-gpu',
                    // Without a remote debugging port, Google Chrome exits immediately.
                    '--remote-debugging-port=9222',
                ],
            }
        },

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        // singleRun: false,

        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: Infinity,

        junitReporter: {
            outputDir: 'karma-reports',
        },

        webpack: webpack_config,

        webpackMiddleware: {
            stats: {
                // don't fill the console up with a mahoosive list of modules
                chunks: false,
            },
        },
    };

    // include the olm loader if we have it.
    if (olm_entry) {
        myconfig.files.unshift(olm_entry);
    }

    config.set(myconfig);
};
<commit_msg>make sure karma runs tests in dev mode to speed up build<commit_after>// karma.conf.js - the config file for karma, which runs our tests.

var path = require('path');
var webpack = require('webpack');
var webpack_config = require('./webpack.config');

/*
 * We use webpack to build our tests. It's a pain to have to wait for webpack
 * to build everything; however it's the easiest way to load our dependencies
 * from node_modules.
 *
 * If you run karma in multi-run mode (with `npm run test-multi`), it will watch
 * the tests for changes, and webpack will rebuild using a cache. This is much quicker
 * than a clean rebuild.
 */

// the name of the test file. By default, a special file which runs all tests.
var testFile = process.env.KARMA_TEST_FILE || 'test/all-tests.js';

process.env.PHANTOMJS_BIN = 'node_modules/.bin/phantomjs';
process.env.Q_DEBUG = 1;

/* the webpack config is based on the real one, to (a) try to simulate the
 * deployed environment as closely as possible, and (b) to avoid a shedload of
 * cut-and-paste.
 */

// find out if we're shipping olm, and where it is, if so.
const olm_entry = webpack_config.entry['olm'];

// remove the default entries - karma provides its own (via the 'files' and
// 'preprocessors' config below)
delete webpack_config['entry'];

// make sure we're flagged as development to avoid wasting time optimising
webpack_config.mode = 'development';

// add ./test as a search path for js
webpack_config.module.rules.unshift({
    test: /\.js$/, use: "babel-loader",
    include: [path.resolve('./src'), path.resolve('./test')],
});

// disable parsing for sinon, because it
// tries to do voodoo with 'require' which upsets
// webpack (https://github.com/webpack/webpack/issues/304)
webpack_config.module.noParse.push(/sinon\/pkg\/sinon\.js$/);

// ?
webpack_config.resolve.alias['sinon'] = 'sinon/pkg/sinon.js';

webpack_config.resolve.modules = [
    path.resolve('./test'),
    "node_modules"
];

webpack_config.devtool = 'inline-source-map';

module.exports = function (config) {
    const myconfig = {
        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['mocha'],

        // list of files / patterns to load in the browser
        files: [
            'node_modules/babel-polyfill/browser.js',
            testFile,

            // make the images available via our httpd. They will be avaliable
            // below http://localhost:[PORT]/base/. See also `proxies` which
            // defines alternative URLs for them.
            //
            // This isn't required by any of the tests, but it stops karma
            // logging warnings when it serves a 404 for them.
            {
                pattern: 'node_modules/matrix-react-sdk/res/img/*',
                watched: false, included: false, served: true, nocache: false,
            },
            {
                pattern: 'res/themes/**',
                watched: false, included: false, served: true, nocache: false,
            },
        ],

        proxies: {
            // redirect img links to the karma server. See above.
            "/img/": "/base/node_modules/matrix-react-sdk/res/img/",
            "/themes/": "/base/res/themes/",
        },

        // preprocess matching files before serving them to the browser
        // available preprocessors:
        // https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
            '{src,test}/**/*.js': ['webpack', 'sourcemap'],
        },

        // test results reporter to use
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['logcapture', 'spec', 'junit', 'summary'],

        specReporter: {
            suppressErrorSummary: false, // do print error summary
            suppressFailed: false, // do print information about failed tests
            suppressPassed: false, // do print information about passed tests
            showSpecTiming: true, // print the time elapsed for each spec
        },

        client: {
            captureLogs: true,
        },

        // web server port
        port: 9876,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR ||
        // config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file
        // changes
        autoWatch: true,

        // start these browsers
        // available browser launchers:
        // https://npmjs.org/browse/keyword/karma-launcher
        browsers: [
            'Chrome',
            //'PhantomJS',
            //'ChromeHeadless'
        ],

        customLaunchers: {
            'ChromeHeadless': {
                base: 'Chrome',
                flags: [
                    // '--no-sandbox',
                    // See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
                    '--headless',
                    '--disable-gpu',
                    // Without a remote debugging port, Google Chrome exits immediately.
                    '--remote-debugging-port=9222',
                ],
            }
        },

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        // singleRun: false,

        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: Infinity,

        junitReporter: {
            outputDir: 'karma-reports',
        },

        webpack: webpack_config,

        webpackMiddleware: {
            stats: {
                // don't fill the console up with a mahoosive list of modules
                chunks: false,
            },
        },
    };

    // include the olm loader if we have it.
    if (olm_entry) {
        myconfig.files.unshift(olm_entry);
    }

    config.set(myconfig);
};
<|endoftext|>


<commit_before>import { Posts } from './collection';
import Users from 'meteor/vulcan:users';
import { getSetting } from 'meteor/vulcan:core';
import { ensureIndex } from '../../collectionUtils';
import moment from 'moment';

/**
 * @summary Base parameters that will be common to all other view unless specific properties are overwritten
 */
Posts.addDefaultView(terms => {
  const validFields = _.pick(terms, 'userId', 'meta', 'groupId', 'af');
  // Also valid fields: before, after, timeField (select on postedAt), and
  // karmaThreshold (selects on baseScore).

  const alignmentForum = getSetting('AlignmentForum', false) ? {af: true} : {}
  let params = {
    selector: {
      status: Posts.config.STATUS_APPROVED,
      draft: {$in: [false,null]},
      isFuture: {$in: [false,null]}, // match both false and undefined
      unlisted: {$in: [false,null]},
      meta: {$in: [false,null]},
      groupId: {$exists: false},
      isEvent: {$in: [false,null]},
      ...validFields,
      ...alignmentForum
    }
  }
  if (terms.karmaThreshold && terms.karmaThreshold !== "0") {
    params.selector.maxBaseScore = {$gte: parseInt(terms.karmaThreshold, 10)}
  }
  if (terms.userId) {
    params.selector.hideAuthor = {$in: [false,null]}
  }
  return params;
})

export function augmentForDefaultView(indexFields)
{
  return { isFuture:1, status:1, draft:1, meta:1, groupId:1, af:1, ...indexFields, _id:1, unlisted:1, postedAt:1, baseScore:1 };
}

const commonPartialFilterExpression = {
};

/**
 * @summary User posts view
 */
Posts.addView("userPosts", terms => ({
  selector: {
    userId: terms.userId,
  },
  options: {
    limit: 5,
    sort: {
      score: -1,
    }
  }
}));
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, score: -1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);

const setStickies = (sortOptions, terms) => {
  if (terms.af && terms.forum) {
    return { afSticky: -1, ...sortOptions}
  } else if (terms.meta && terms.forum) {
    return { metaSticky: -1, ...sortOptions}
  }
  return sortOptions
}

const stickiesIndexPrefix = {
  afSticky: -1, metaSticky: -1
};

Posts.addView("magicalSorting", terms => ({
  options: {sort: setStickies({score: -1}, terms)}
}))
ensureIndex(Posts,
  augmentForDefaultView({ ...stickiesIndexPrefix, score:-1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, ...stickiesIndexPrefix, score:-1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);

Posts.addView("top", terms => ({
  options: {sort: setStickies({baseScore: -1}, terms)}
}))
ensureIndex(Posts,
  augmentForDefaultView({ ...stickiesIndexPrefix, baseScore:-1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, ...stickiesIndexPrefix, baseScore:-1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);

Posts.addView("new", terms => ({
  options: {sort: setStickies({postedAt: -1}, terms)}
}))
ensureIndex(Posts,
  augmentForDefaultView({ ...stickiesIndexPrefix, postedAt:-1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, ...stickiesIndexPrefix, postedAt:-1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);

Posts.addView("old", terms => ({
  options: {sort: setStickies({postedAt: 1}, terms)}
}))
// Covered by the same index as `new`

Posts.addView("daily", terms => ({
  selector: {
    baseScore: {$gt: terms.karmaThreshold || -100}
  },
  options: {
    sort: {score: -1}
  }
}));
ensureIndex(Posts,
  augmentForDefaultView({ postedAt:1, }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);

Posts.addView("frontpage", terms => ({
  selector: {
    frontpageDate: {$ne: null},
  },
  options: {
    sort: {sticky: -1, score: -1}
  }
}));
ensureIndex(Posts,
  augmentForDefaultView({ sticky: -1, score: -1 }),
  {
    partialFilterExpression: {
      ...commonPartialFilterExpression,
      frontpageDate: {$exists: true}
    }
  }
);

Posts.addView("frontpage-rss", terms => ({
  selector: {
    frontpageDate: {$ne: null},
  },
  options: {
    sort: {frontpageDate: -1, postedAt: -1}
  }
}));
// Covered by the same index as `frontpage`

Posts.addView("curated", terms => ({
  selector: {
    curatedDate: {$ne: null},
  },
  options: {
    sort: {sticky: -1, curatedDate: -1, postedAt: -1}
  }
}));
ensureIndex(Posts,
  augmentForDefaultView({ sticky: -1, curatedDate:-1 }),
  {
    partialFilterExpression: {
      ...commonPartialFilterExpression,
      curatedDate: {$exists: true}
    }
  }
);

Posts.addView("curated-rss", terms => ({
  selector: {
    curatedDate: {$ne: null},
  },
  options: {
    sort: {curatedDate: -1, postedAt: -1}
  }
}));
// Covered by the same index as `curated`

Posts.addView("community", terms => ({
  selector: {
    frontpageDate: null,
    meta: null,
  },
  options: {
    sort: {sticky: -1, score: -1}
  }
}));
// Can't usefully index `community` beyond sorting by sticky and score, because
// of liminations on partialFilterExpression.
ensureIndex(Posts,
  augmentForDefaultView({ sticky: -1, score: -1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression, } }
);

Posts.addView("community-rss", terms => ({
  selector: {
    frontpageDate: null,
    maxBaseScore: {$gt: 2}
  },
  options: {
    sort: {postedAt: -1}
  }
}));
// Covered by the same index as `new`

Posts.addView("meta-rss", terms => ({
  selector: {
    meta: true,
  },
  options: {
    sort: {
      postedAt: -1
    }
  }
}))
// Covered by the same index as `new`

Posts.addView('rss', Posts.views['community-rss']); // default to 'community-rss' for rss

/**
 * @summary Scheduled view
 */
Posts.addView("scheduled", terms => ({
  selector: {
    status: Posts.config.STATUS_APPROVED,
    isFuture: true
  },
  options: {
    sort: {postedAt: -1}
  }
}));
// Covered by the same index as `new`

/**
 * @summary Draft view
 */
Posts.addView("drafts", terms => {
  return {
    selector: {
      userId: terms.userId,
      draft: true,
      hideAuthor: {$in: [false,null]},
      unlisted: null,
      meta: null,
    },
    options: {
      sort: {createdAt: -1}
    }
}});
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, createdAt: -1 }),
  {
    partialFilterExpression: {
      draft: true
    }
  }
);

/**
 * @summary All drafts view
 */
Posts.addView("all_drafts", terms => ({
  selector: {
    draft: true
  },
  options: {
    sort: {createdAt: -1}
  }
}));
// Possibly unused view?

/**
 * @summary User upvoted posts view
 */
Posts.addView("userUpvotedPosts", (terms, apolloClient) => {
  // TODO: Delete, unused and broken. (Broken because user.upvotedPosts is no longer a field that exists).
  var user = apolloClient ? Users.findOneInStore(apolloClient.store, terms.userId) : Users.findOne(terms.userId);

  var postsIds = _.pluck(user.upvotedPosts, "itemId");
  return {
    selector: {_id: {$in: postsIds}, userId: {$ne: terms.userId}}, // exclude own posts
    options: {limit: 5, sort: {postedAt: -1}}
  };
});

/**
 * @summary User downvoted posts view
 */
Posts.addView("userDownvotedPosts", (terms, apolloClient) => {
  // TODO: Delete, unused and broken. (Broken because user.downvotedPosts is no longer a field that exists).
  var user = apolloClient ? Users.findOneInStore(apolloClient.store, terms.userId) : Users.findOne(terms.userId);

  var postsIds = _.pluck(user.downvotedPosts, "itemId");
  // TODO: sort based on votedAt timestamp and not postedAt, if possible
  return {
    selector: {_id: {$in: postsIds}},
    options: {limit: 5, sort: {postedAt: -1}}
  };
});

Posts.addView("slugPost", terms => ({
  selector: {
    slug: terms.slug,
  },
  options: {
    limit: 1,
  }
}));
ensureIndex(Posts,
  {"slug": "hashed"},
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);

Posts.addView("recentDiscussionThreadsList", terms => {
  return {
    selector: {
      baseScore: {$gt:0},
      hideFrontpageComments: {$in: [false,null]},
      meta: null,
      groupId: null,
      isEvent: null,
    },
    options: {
      sort: {lastCommentedAt:-1},
      limit: terms.limit || 12,
    }
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ lastCommentedAt:-1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);

Posts.addView("nearbyEvents", function (terms) {
  const yesterday = moment().subtract(1, 'days').toDate();
  let query = {
    selector: {
      location: {$exists: true},
      groupId: null,
      isEvent: true,
      $or: [{startTime: {$exists: false}}, {startTime: {$gt: yesterday}}],
      mongoLocation: {
        $near: {
          $geometry: {
               type: "Point" ,
               coordinates: [ terms.lng, terms.lat ]
          },
        },
      }
    },
    options: {
      sort: {
        createdAt: null,
        _id: null
      }
    }
  };
  if(Array.isArray(terms.filters) && terms.filters.length) {
    query.types = {$in: terms.filters};
  } else if (typeof terms.filters === "string") { //If there is only single value we can't distinguish between Array and value
    query.selector.types = {$in: [terms.filters]};
  }
  return query;
});
ensureIndex(Posts,
  augmentForDefaultView({ mongoLocation:"2dsphere" }),
  {
    partialFilterExpression: {
      location: {$exists: true},
      ...commonPartialFilterExpression,
      isEvent: true,
    }
  }
);

Posts.addView("events", function (terms) {
  const yesterday = moment().subtract(1, 'days').toDate();
  const twoMonthsAgo = moment().subtract(60, 'days').toDate();
  return {
    selector: {
      isEvent: true,
      createdAt: {$gte: twoMonthsAgo},
      groupId: terms.groupId ? terms.groupId : null,
      baseScore: {$gte: 1},
      $or: [{startTime: {$exists: false}}, {startTime: {$gte: yesterday}}],
    },
    options: {
      sort: {
        baseScore: -1,
        startTime: -1,
      }
    }
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ startTime:1 }),
  {
    partialFilterExpression: {
      ...commonPartialFilterExpression,
      isEvent: true,
    }
  }
);

Posts.addView("pastEvents", function (terms) {
  return {
    selector: {
      isEvent: true,
      groupId: terms.groupId ? terms.groupId : null,
      baseScore: {$gte: 1},
    },
    options: {
      sort: {
        baseScore: -1,
        startTime: -1,
      }
    }
  }
})
// Same index as events

Posts.addView("groupPosts", function (terms) {
  return {
    selector: {
      isEvent: null,
      groupId: terms.groupId,
    },
    options: {
      sort: {
        sticky: -1,
        createdAt: -1,
      }
    }
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ groupId: 1, sticky: -1, createdAt: -1 }),
  { partialFilterExpression: { ...commonPartialFilterExpression } }
);

Posts.addView("postsWithBannedUsers", function () {
  return {
    selector: {
      bannedUserIds: {$exists: true}
    },
  }
})
ensureIndex(Posts,
  augmentForDefaultView({}),
  {
    partialFilterExpression: {
      ...commonPartialFilterExpression,
      bannedUserIds: {$exists: true}
    }
  }
);

Posts.addView("communityResourcePosts", function () {
  return {
    selector: {
      _id: {$in: ['bDnFhJBcLQvCY3vJW', 'qMuAazqwJvkvo8teR', 'YdcF6WbBmJhaaDqoD']}
    },
  }
})
// No index needed

Posts.addView("sunshineNewPosts", function () {
  const twoDaysAgo = moment().subtract(2, 'days').toDate();
  return {
    selector: {
      reviewedByUserId: {$exists: false},
      frontpageDate: {$in: [false,null] },
      createdAt: {$gt: twoDaysAgo},
    },
    options: {
      sort: {
        createdAt: -1,
      }
    }
  }
})
// Covered by the same index as `new`

Posts.addView("sunshineCuratedSuggestions", function () {
  return {
    selector: {
      suggestForCuratedUserIds: {$exists:true, $ne: []},
      reviewForCuratedUserId: {$exists:false}
    },
    options: {
      sort: {
        createdAt: 1,
      }
    }
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ createdAt: 1 }),
  {
    partialFilterExpression: {
      ...commonPartialFilterExpression,
      suggestForCuratedUserIds: {$exists:true}, // Can't do no-empty-list filter :(
    }
  }
);

Posts.addView("afRecentDiscussionThreadsList", terms => {
  return {
    selector: {
      baseScore: {$gt:0},
      hideFrontpageComments: {$in: [false,null]},
      af: true,
      meta: null,
      groupId: null,
      isEvent: null,
    },
    options: {
      sort: {lastCommentedAt:-1},
      limit: terms.limit || 12,
    }
  }
})
// Covered by the same index as `recentDiscussionThreadsList`

// Used in Posts.find() in various places
ensureIndex(Posts, {userId:1, createdAt:-1});

// Used in routes
ensureIndex(Posts, {legacyId: "hashed"});
ensureIndex(Posts, {agentFoundationsId: "hashed"});

// Used in checkScheduledPosts cronjob
ensureIndex(Posts, {isFuture:1, postedAt:1});

// Used in scoring aggregate query
ensureIndex(Posts, {inactive:1,postedAt:1});<commit_msg>Restore view that was misidentified as unused<commit_after>import { Posts } from './collection';
import Users from 'meteor/vulcan:users';
import { getSetting } from 'meteor/vulcan:core';
import { ensureIndex } from '../../collectionUtils';
import moment from 'moment';

/**
 * @summary Base parameters that will be common to all other view unless specific properties are overwritten
 */
Posts.addDefaultView(terms => {
  const validFields = _.pick(terms, 'userId', 'meta', 'groupId', 'af');
  // Also valid fields: before, after, timeField (select on postedAt), and
  // karmaThreshold (selects on baseScore).

  const alignmentForum = getSetting('AlignmentForum', false) ? {af: true} : {}
  let params = {
    selector: {
      status: Posts.config.STATUS_APPROVED,
      draft: {$in: [false,null]},
      isFuture: {$in: [false,null]}, // match both false and undefined
      unlisted: {$in: [false,null]},
      meta: {$in: [false,null]},
      groupId: {$exists: false},
      isEvent: {$in: [false,null]},
      ...validFields,
      ...alignmentForum
    }
  }
  if (terms.karmaThreshold && terms.karmaThreshold !== "0") {
    params.selector.maxBaseScore = {$gte: parseInt(terms.karmaThreshold, 10)}
  }
  if (terms.userId) {
    params.selector.hideAuthor = {$in: [false,null]}
  }
  return params;
})

export function augmentForDefaultView(indexFields)
{
  return { isFuture:1, status:1, draft:1, meta:1, groupId:1, af:1, ...indexFields, _id:1, unlisted:1, postedAt:1, baseScore:1 };
}

const commonPartialFilterExpression = {
};

/**
 * @summary User posts view
 */
Posts.addView("userPosts", terms => ({
  selector: {
    userId: terms.userId,
  },
  options: {
    limit: 5,
    sort: {
      score: -1,
    }
  }
}));
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, score: -1 }),
  {
    name: "posts.userId_score",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);

const setStickies = (sortOptions, terms) => {
  if (terms.af && terms.forum) {
    return { afSticky: -1, ...sortOptions}
  } else if (terms.meta && terms.forum) {
    return { metaSticky: -1, ...sortOptions}
  }
  return sortOptions
}

const stickiesIndexPrefix = {
  afSticky: -1, metaSticky: -1
};

Posts.addView("magicalSorting", terms => ({
  options: {sort: setStickies({score: -1}, terms)}
}))
ensureIndex(Posts,
  augmentForDefaultView({ ...stickiesIndexPrefix, score:-1 }),
  {
    name: "posts.stickies_score",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, ...stickiesIndexPrefix, score:-1 }),
  {
    name: "posts.userId_stickies_score",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);

Posts.addView("top", terms => ({
  options: {sort: setStickies({baseScore: -1}, terms)}
}))
ensureIndex(Posts,
  augmentForDefaultView({ ...stickiesIndexPrefix, baseScore:-1 }),
  {
    name: "posts.stickies_baseScore",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, ...stickiesIndexPrefix, baseScore:-1 }),
  {
    name: "posts.userId_stickies_baseScore",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);

Posts.addView("new", terms => ({
  options: {sort: setStickies({postedAt: -1}, terms)}
}))
ensureIndex(Posts,
  augmentForDefaultView({ ...stickiesIndexPrefix, postedAt:-1 }),
  {
    name: "posts.stickies_postedAt",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, ...stickiesIndexPrefix, postedAt:-1 }),
  {
    name: "posts.userId_stickies_postedAt",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);

Posts.addView("old", terms => ({
  options: {sort: setStickies({postedAt: 1}, terms)}
}))
// Covered by the same index as `new`

Posts.addView("daily", terms => ({
  selector: {
    baseScore: {$gt: terms.karmaThreshold || -100}
  },
  options: {
    sort: {score: -1}
  }
}));
ensureIndex(Posts,
  augmentForDefaultView({ postedAt:1, baseScore:1, }),
  {
    name: "posts.postedAt_baseScore",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);

Posts.addView("frontpage", terms => ({
  selector: {
    frontpageDate: {$ne: null},
  },
  options: {
    sort: {sticky: -1, score: -1}
  }
}));
ensureIndex(Posts,
  augmentForDefaultView({ sticky: -1, score: -1, frontpageDate:1 }),
  { name: "posts.sticky_score_frontpageDate" }
);

Posts.addView("frontpage-rss", terms => ({
  selector: {
    frontpageDate: {$ne: null},
  },
  options: {
    sort: {frontpageDate: -1, postedAt: -1}
  }
}));
// Covered by the same index as `frontpage`

Posts.addView("curated", terms => ({
  selector: {
    curatedDate: {$ne: null},
  },
  options: {
    sort: {sticky: -1, curatedDate: -1, postedAt: -1}
  }
}));
ensureIndex(Posts,
  augmentForDefaultView({ sticky: -1, curatedDate:-1 }),
  { name: "posts.sticky_curatedDate" }
);

Posts.addView("curated-rss", terms => ({
  selector: {
    curatedDate: {$ne: null},
  },
  options: {
    sort: {curatedDate: -1, postedAt: -1}
  }
}));
// Covered by the same index as `curated`

Posts.addView("community", terms => ({
  selector: {
    frontpageDate: null,
    meta: null,
  },
  options: {
    sort: {sticky: -1, score: -1}
  }
}));
// Can't usefully index `community` beyond sorting by sticky and score, because
// of liminations on partialFilterExpression.
ensureIndex(Posts,
  augmentForDefaultView({ sticky: -1, score: -1 }),
  {
    name: "posts.community",
    partialFilterExpression: { ...commonPartialFilterExpression }
  }
);

Posts.addView("community-rss", terms => ({
  selector: {
    frontpageDate: null,
    maxBaseScore: {$gt: 2}
  },
  options: {
    sort: {postedAt: -1}
  }
}));
// Covered by the same index as `new`

Posts.addView("meta-rss", terms => ({
  selector: {
    meta: true,
  },
  options: {
    sort: {
      postedAt: -1
    }
  }
}))
// Covered by the same index as `new`

Posts.addView('rss', Posts.views['community-rss']); // default to 'community-rss' for rss

/**
 * @summary Scheduled view
 */
Posts.addView("scheduled", terms => ({
  selector: {
    status: Posts.config.STATUS_APPROVED,
    isFuture: true
  },
  options: {
    sort: {postedAt: -1}
  }
}));
// Covered by the same index as `new`

/**
 * @summary Draft view
 */
Posts.addView("drafts", terms => {
  return {
    selector: {
      userId: terms.userId,
      draft: true,
      hideAuthor: {$in: [false,null]},
      unlisted: null,
      meta: null,
    },
    options: {
      sort: {createdAt: -1}
    }
}});
ensureIndex(Posts,
  augmentForDefaultView({ userId: 1, createdAt: -1 }),
  { name: "posts.userId_createdAt" }
);

/**
 * @summary All drafts view
 */
Posts.addView("all_drafts", terms => ({
  selector: {
    draft: true
  },
  options: {
    sort: {createdAt: -1}
  }
}));

Posts.addView("unlisted", terms => {
  return {
    selector: {
      userId: terms.userId,
      unlisted: true
    },
    options: {
      sort: {createdAt: -1}
    }
}});

/**
 * @summary User upvoted posts view
 */
Posts.addView("userUpvotedPosts", (terms, apolloClient) => {
  // TODO: Delete, unused and broken. (Broken because user.upvotedPosts is no longer a field that exists).
  var user = apolloClient ? Users.findOneInStore(apolloClient.store, terms.userId) : Users.findOne(terms.userId);

  var postsIds = _.pluck(user.upvotedPosts, "itemId");
  return {
    selector: {_id: {$in: postsIds}, userId: {$ne: terms.userId}}, // exclude own posts
    options: {limit: 5, sort: {postedAt: -1}}
  };
});

/**
 * @summary User downvoted posts view
 */
Posts.addView("userDownvotedPosts", (terms, apolloClient) => {
  // TODO: Delete, unused and broken. (Broken because user.downvotedPosts is no longer a field that exists).
  var user = apolloClient ? Users.findOneInStore(apolloClient.store, terms.userId) : Users.findOne(terms.userId);

  var postsIds = _.pluck(user.downvotedPosts, "itemId");
  // TODO: sort based on votedAt timestamp and not postedAt, if possible
  return {
    selector: {_id: {$in: postsIds}},
    options: {limit: 5, sort: {postedAt: -1}}
  };
});

Posts.addView("slugPost", terms => ({
  selector: {
    slug: terms.slug,
  },
  options: {
    limit: 1,
  }
}));
ensureIndex(Posts, {"slug": "hashed"});

Posts.addView("recentDiscussionThreadsList", terms => {
  return {
    selector: {
      baseScore: {$gt:0},
      hideFrontpageComments: {$in: [false,null]},
      meta: null,
      groupId: null,
      isEvent: null,
    },
    options: {
      sort: {lastCommentedAt:-1},
      limit: terms.limit || 12,
    }
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ lastCommentedAt:-1, baseScore:1, hideFrontpageComments:1 }),
  { name: "posts.recentDiscussionThreadsList", }
);

Posts.addView("nearbyEvents", function (terms) {
  const yesterday = moment().subtract(1, 'days').toDate();
  let query = {
    selector: {
      location: {$exists: true},
      groupId: null,
      isEvent: true,
      $or: [{startTime: {$exists: false}}, {startTime: {$gt: yesterday}}],
      mongoLocation: {
        $near: {
          $geometry: {
               type: "Point" ,
               coordinates: [ terms.lng, terms.lat ]
          },
        },
      }
    },
    options: {
      sort: {
        createdAt: null,
        _id: null
      }
    }
  };
  if(Array.isArray(terms.filters) && terms.filters.length) {
    query.types = {$in: terms.filters};
  } else if (typeof terms.filters === "string") { //If there is only single value we can't distinguish between Array and value
    query.selector.types = {$in: [terms.filters]};
  }
  return query;
});
ensureIndex(Posts,
  augmentForDefaultView({ mongoLocation:"2dsphere", location:1, startTime:1 }),
  { name: "posts.2dsphere" }
);

Posts.addView("events", function (terms) {
  const yesterday = moment().subtract(1, 'days').toDate();
  const twoMonthsAgo = moment().subtract(60, 'days').toDate();
  return {
    selector: {
      isEvent: true,
      createdAt: {$gte: twoMonthsAgo},
      groupId: terms.groupId ? terms.groupId : null,
      baseScore: {$gte: 1},
      $or: [{startTime: {$exists: false}}, {startTime: {$gte: yesterday}}],
    },
    options: {
      sort: {
        baseScore: -1,
        startTime: -1,
      }
    }
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ startTime:1, createdAt:1, baseScore:1 }),
  { name: "posts.events" }
);

Posts.addView("pastEvents", function (terms) {
  return {
    selector: {
      isEvent: true,
      groupId: terms.groupId ? terms.groupId : null,
      baseScore: {$gte: 1},
    },
    options: {
      sort: {
        baseScore: -1,
        startTime: -1,
      }
    }
  }
})
// Same index as events

Posts.addView("groupPosts", function (terms) {
  return {
    selector: {
      isEvent: null,
      groupId: terms.groupId,
    },
    options: {
      sort: {
        sticky: -1,
        createdAt: -1,
      }
    }
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ groupId: 1, sticky: -1, createdAt: -1 }),
  { name: "posts.groupPosts" }
);

Posts.addView("postsWithBannedUsers", function () {
  return {
    selector: {
      bannedUserIds: {$exists: true}
    },
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ bannedUserIds:1 }),
  { name: "posts.postsWithBannedUsers" }
);

Posts.addView("communityResourcePosts", function () {
  return {
    selector: {
      _id: {$in: ['bDnFhJBcLQvCY3vJW', 'qMuAazqwJvkvo8teR', 'YdcF6WbBmJhaaDqoD']}
    },
  }
})
// No index needed

Posts.addView("sunshineNewPosts", function () {
  const twoDaysAgo = moment().subtract(2, 'days').toDate();
  return {
    selector: {
      reviewedByUserId: {$exists: false},
      frontpageDate: {$in: [false,null] },
      createdAt: {$gt: twoDaysAgo},
    },
    options: {
      sort: {
        createdAt: -1,
      }
    }
  }
})
// Covered by the same index as `new`

Posts.addView("sunshineCuratedSuggestions", function () {
  return {
    selector: {
      suggestForCuratedUserIds: {$exists:true, $ne: []},
      reviewForCuratedUserId: {$exists:false}
    },
    options: {
      sort: {
        createdAt: 1,
      }
    }
  }
})
ensureIndex(Posts,
  augmentForDefaultView({ reviewForCuratedUserId:1, suggestForCuratedUserIds:1, createdAt: 1 }),
  { name: "posts.sunshineCuratedSuggestions" }
);

Posts.addView("afRecentDiscussionThreadsList", terms => {
  return {
    selector: {
      baseScore: {$gt:0},
      hideFrontpageComments: {$in: [false,null]},
      af: true,
      meta: null,
      groupId: null,
      isEvent: null,
    },
    options: {
      sort: {lastCommentedAt:-1},
      limit: terms.limit || 12,
    }
  }
})
// Covered by the same index as `recentDiscussionThreadsList`

// Used in Posts.find() in various places
ensureIndex(Posts, {userId:1, createdAt:-1});

// Used in routes
ensureIndex(Posts, {legacyId: "hashed"});
ensureIndex(Posts, {agentFoundationsId: "hashed"});

// Used in checkScheduledPosts cronjob
ensureIndex(Posts, {isFuture:1, postedAt:1});

// Used in scoring aggregate query
ensureIndex(Posts, {inactive:1,postedAt:1});<|endoftext|>


<commit_before>"use strict"; // run code in ES5 strict mode

var expect = require("expect.js"),
    rewire = require("rewire"),
    path = require("path");

describe("runService", function(){

    var Request = require("../../../../lib/server/request/Request.class.js"),
        Response = require("../../../../lib/server/request/Response.class.js");

    var runService,
        Dog = require("./runService/Dog.class.js");

    describe("#serviceMiddleware", function() {

        var mockedServiceFunctions = {
            create : function(ids, model, callback){
                callback({ "status" : "success" });
            },
            read : function(ids, callback){
                callback({ "status" : "success", data : { da : "ta" }});
            },
            readCollection : function(ids, params, callback){
                callback({ "status" : "success", "data" : { "readCollection" : true }});
            },
            update : function(ids, model, callback){
                callback();
            }
            //destroy is not here because we need a missing method for the test
        };

        var servicesMock = {
            getService : function(path) {

                if(path === "test"){
                    return mockedServiceFunctions;
                }

                if(path === "test2"){
                    return {};
                }

                if(path === "syncasynctest") {
                    return {
                        create : function(ids, model) {
                            return { status : "success"};
                        },
                        destroy : function(ids, callback) {
                            callback({ status : "success" });
                        }
                    };
                }
                return null;
            }
        };

        beforeEach(function() {
            runService = rewire("../../../../lib/server/request/middleware/runService.js");
            runService.__set__("services", servicesMock);
        });

        it("should find the mocked CREATE service, run it and next afterwards", function (done) {

            var method = "create",
                path = "/services/test/",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            runService(request, response, function(err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });

        it("should call the CREATE service on the Model if Model was loaded", function (done) {

            var method = "create",
                path = "/services/test/";

            var dog = new Dog();
            dog.set("name", "snoop lion");
            dog.setService({
                create : function(ids, model, callback){
                    callback({ "status" : "success"});
                }
            });

            var request = new Request(method, path, {}),
                response = new Response();

            request.setModel(dog);

            runService(request, response, function(err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });

        it("should find the READ service, run it and next afterwards with data attached to response", function (done) {

            var method = "read",
                path = "/services/test/123",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function(err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                expect(response.getData()).to.eql(data);
                done();
            });
        });

        it("should call the READ-collection method without IDs set", function (done) {

            var method = "read",
                path = "/services/test",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function(err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                expect(response.getData()).to.eql({ "readCollection" : true });
                done();
            });
        });

        it("should next with an error code if the service for the given method is not allowed", function (done) {

            var method = "destroy",
                path = "/services/test",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            runService(request, response, function(err) {
                expect(err).not.to.be(null);
                expect(response.getStatusCode()).to.be(405);
                done();
            });
        });

        it("should next with error code 403 if no service is registered for a given path", function (done) {

            var method = "destroy",
                path = "/services/test2",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            runService(request, response, function(err) {
                expect(err).not.to.be(null);
                expect(response.getStatusCode()).to.be(403);
                done();
            });
        });

        it("should next with an err if path is not defined", function (done) {

            var method = "destroy",
                path = "/services/nonExistingPath",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function(err) {
                expect(err).not.to.be(null);
                expect(response.getStatusCode()).to.be(404);
                done();
            });
        });

        it("should accept synchronous functions as services", function(done) {
            var method = "create",
                path = "/services/syncasynctest",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function(err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });

        it("should accept asynchronous functions as services", function(done) {
            var method = "destroy",
                path = "/services/syncasynctest",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function(err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });

    });

    describe("#serviceFormat", function() {

        var runService;

        var servicesMock = {
            getService : function(path) {
                if(path === "servicea"){
                    var ServiceA = require("./runService/AService.server.class.js");
                    return new ServiceA();
                }
                return null;
            }
        };

        beforeEach(function() {
            runService = rewire("../../../../lib/server/request/middleware/runService.js");
            runService.__set__("services", servicesMock);
        });

        it("should accept classes as services", function(done) {

            var method = "update",
                path = "/services/servicea",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function(err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                expect(response.getData()).to.eql(data);
                done();
            });
        });
    });

    describe("#service with deeper hierarchy - embedded documents", function() {

        var runService;

        var servicesMock = {
            getService : function(path) {
                if(path === "blogpost/comments"){
                    var ServiceA = require("./runService/AService.server.class.js");
                    return new ServiceA();
                }
                return null;
            }
        };

        beforeEach(function() {
            runService = rewire("../../../../lib/server/request/middleware/runService.js");
            runService.__set__("services", servicesMock);
        });

        it("should accept services with deeper paths", function(done) {

            var method = "destroy",
                path = "/services/blogpost/123/comments/1245",
                data = {};

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function(err) {
                expect(request.getIds()).to.eql({ "blogpost": '123', "blogpost/comments": '1245' });
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });
    });

    describe("#Callback value assignment", function() {

        var runService;

        var servicesMock = {
            getService : function(path) {
                if(path === "blogpost"){
                    return {
                        "create" : function(ids, model, callback){
                            callback({"status" : "success", "message" : "my dummy error", "data" : { "da" : "ta" }});
                        },
                        "update" : function(ids, model, callback){
                            callback();
                        }
                    };
                }
                return null;
            }
        };

        beforeEach(function() {
            runService = rewire("../../../../lib/server/request/middleware/runService.js");
            runService.__set__("services", servicesMock);
        });

        it("should accept the values that have been set via callback", function(done) {

            var method = "create",
                path = "/services/blogpost/",
                data = {};

            var request = new Request(method, path, data),
                response = new Response();

            runService(request, response, function(err) {
                expect(request.getIds()).to.eql({});
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                expect(response.getStatus()).to.be("success");
                expect(response.getErrorMessage()).to.be("my dummy error");
                expect(response.getData()).to.eql({ "da" : "ta" });
                done();
            });
        });

        it("should throw an error with an empty callback", function(done) {

            var method = "update",
                path = "/services/blogpost/",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function(err) {
                expect(err).not.to.be(null);
                done();
            });
        });
    });
});<commit_msg>- removed some empty lines<commit_after>"use strict"; // run code in ES5 strict mode

var expect = require("expect.js"),
    rewire = require("rewire"),
    path = require("path");

describe("runService", function () {

    var Request = require("../../../../lib/server/request/Request.class.js"),
        Response = require("../../../../lib/server/request/Response.class.js");

    var runService,
        Dog = require("./runService/Dog.class.js");

    describe("#serviceMiddleware", function () {

        var mockedServiceFunctions = {
            create : function (ids, model, callback) {
                callback({ "status" : "success" });
            },
            read : function (ids, callback) {
                callback({ "status" : "success", data : { da : "ta" }});
            },
            readCollection : function (ids, params, callback) {
                callback({
                    "status" : "success",
                    "data" : [
                        { "readCollection1" : true },
                        { "readCollection2" : true }
                    ]
                });
            },
            update : function (ids, model, callback) {
                callback();
            }
            //destroy is not here because we need a missing method for the test
        };

        var servicesMock = {
            getService : function (path) {

                if (path === "test") {
                    return mockedServiceFunctions;
                }

                if (path === "test2") {
                    return {};
                }

                if (path === "syncasynctest") {
                    return {
                        create : function (ids, model) {
                            return { status : "success"};
                        },
                        destroy : function (ids, callback) {
                            callback({ status : "success" });
                        }
                    };
                }
                return null;
            }
        };

        beforeEach(function () {
            runService = rewire("../../../../lib/server/request/middleware/runService.js");
            runService.__set__("services", servicesMock);
        });

        it("should find the mocked CREATE service, run it and next afterwards", function (done) {

            var method = "create",
                path = "/services/test/",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            runService(request, response, function (err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });

        it("should call the CREATE service on the Model if Model was loaded", function (done) {

            var method = "create",
                path = "/services/test/";

            var dog = new Dog();
            dog.set("name", "snoop lion");
            dog.setService({
                create : function (ids, model, callback) {
                    callback({ "status" : "success"});
                }
            });

            var request = new Request(method, path, {}),
                response = new Response();

            request.setModel(dog);

            runService(request, response, function (err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });

        it("should find the READ service, run it and next afterwards with data attached to response", function (done) {

            var method = "read",
                path = "/services/test/123",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function (err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                expect(response.getData()).to.eql(data);
                done();
            });
        });

        it("should call the READ-Collection method without ID set", function (done) {

            var method = "read",
                path = "/services/test",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function (err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                expect(response.getData()).to.eql([
                    { "readCollection1" : true },
                    { "readCollection2" : true }
                ]);
                done();
            });
        });

        it("should next with an error code if the service for the given method is not allowed", function (done) {

            var method = "destroy",
                path = "/services/test",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            runService(request, response, function (err) {
                expect(err).not.to.be(null);
                expect(response.getStatusCode()).to.be(405);
                done();
            });
        });

        it("should next with error code 403 if no service is registered for a given path", function (done) {

            var method = "destroy",
                path = "/services/test2",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            runService(request, response, function (err) {
                expect(err).not.to.be(null);
                expect(response.getStatusCode()).to.be(403);
                done();
            });
        });

        it("should next with an err if path is not defined", function (done) {

            var method = "destroy",
                path = "/services/nonExistingPath",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function (err) {
                expect(err).not.to.be(null);
                expect(response.getStatusCode()).to.be(404);
                done();
            });
        });

        it("should accept synchronous functions as services", function (done) {
            var method = "create",
                path = "/services/syncasynctest",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function (err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });

        it("should accept asynchronous functions as services", function (done) {
            var method = "destroy",
                path = "/services/syncasynctest",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function (err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });

    });

    describe("#serviceFormat", function () {

        var runService;

        var servicesMock = {
            getService : function (path) {
                if (path === "servicea") {
                    var ServiceA = require("./runService/AService.server.class.js");
                    return new ServiceA();
                }
                return null;
            }
        };

        beforeEach(function () {
            runService = rewire("../../../../lib/server/request/middleware/runService.js");
            runService.__set__("services", servicesMock);
        });

        it("should accept classes as services", function (done) {

            var method = "update",
                path = "/services/servicea",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function (err) {
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                expect(response.getData()).to.eql(data);
                done();
            });
        });
    });

    describe("#service with deeper hierarchy - embedded documents", function () {

        var runService;

        var servicesMock = {
            getService : function (path) {
                if (path === "blogpost/comments") {
                    var ServiceA = require("./runService/AService.server.class.js");
                    return new ServiceA();
                }
                return null;
            }
        };

        beforeEach(function () {
            runService = rewire("../../../../lib/server/request/middleware/runService.js");
            runService.__set__("services", servicesMock);
        });

        it("should accept services with deeper paths", function (done) {

            var method = "destroy",
                path = "/services/blogpost/123/comments/1245",
                data = {};

            var request = new Request(method, path, data),
                response = new Response();
            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function (err) {
                expect(request.getIds()).to.eql({ "blogpost" : '123', "blogpost/comments" : '1245' });
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                done();
            });
        });
    });

    describe("#Callback value assignment", function () {

        var runService;

        var servicesMock = {
            getService : function (path) {
                if (path === "blogpost") {
                    return {
                        "create" : function (ids, model, callback) {
                            callback({"status" : "success", "message" : "my dummy error", "data" : { "da" : "ta" }});
                        },
                        "update" : function (ids, model, callback) {
                            callback();
                        }
                    };
                }
                return null;
            }
        };

        beforeEach(function () {
            runService = rewire("../../../../lib/server/request/middleware/runService.js");
            runService.__set__("services", servicesMock);
        });

        it("should accept the values that have been set via callback", function (done) {

            var method = "create",
                path = "/services/blogpost/",
                data = {};

            var request = new Request(method, path, data),
                response = new Response();

            runService(request, response, function (err) {
                expect(request.getIds()).to.eql({});
                expect(err).to.be(null);
                expect(response.getStatusCode()).to.be(200);
                expect(response.getStatus()).to.be("success");
                expect(response.getErrorMessage()).to.be("my dummy error");
                expect(response.getData()).to.eql({ "da" : "ta" });
                done();
            });
        });

        it("should throw an error with an empty callback", function (done) {

            var method = "update",
                path = "/services/blogpost/",
                data = { "da" : "ta" };

            var request = new Request(method, path, data),
                response = new Response();

            //we have no middleware for setting the model in this test!
            request.setModel(data);

            runService(request, response, function (err) {
                expect(err).not.to.be(null);
                done();
            });
        });
    });
});<|endoftext|>


<commit_before>'use strict'

const async = require('async')
const express = require('express')

const logger = require('../../../helpers/logger')
const friends = require('../../../lib/friends')
const middlewares = require('../../../middlewares')
const Pods = require('../../../models/pods')
const oAuth2 = middlewares.oauth2
const reqValidator = middlewares.reqValidators.pods
const secureMiddleware = middlewares.secure
const secureRequest = middlewares.reqValidators.remote.secureRequest
const videos = require('../../../lib/videos')
const Videos = require('../../../models/videos')

const router = express.Router()

router.get('/', listPods)
router.post('/', reqValidator.podsAdd, addPods)
router.get('/makefriends', oAuth2.authenticate, reqValidator.makeFriends, makeFriends)
router.get('/quitfriends', oAuth2.authenticate, quitFriends)
// Post because this is a secured request
router.post('/remove', secureRequest, secureMiddleware.decryptBody, removePods)

// ---------------------------------------------------------------------------

module.exports = router

// ---------------------------------------------------------------------------

function addPods (req, res, next) {
  const informations = req.body.data

  async.waterfall([
    function addPod (callback) {
      Pods.add(informations, function (err) {
        return callback(err)
      })
    },

    function createVideosOfThisPod (callback) {
      // Create the remote videos from the new pod
      videos.createRemoteVideos(informations.videos, function (err) {
        if (err) logger.error('Cannot create remote videos.', { error: err })

        return callback(err)
      })
    },

    function fetchMyCertificate (callback) {
      friends.getMyCertificate(function (err, cert) {
        if (err) {
          logger.error('Cannot read cert file.')
          return callback(err)
        }

        return callback(null, cert)
      })
    },

    function getListOfMyVideos (cert, callback) {
      Videos.listOwned(function (err, videosList) {
        if (err) {
          logger.error('Cannot get the list of owned videos.')
          return callback(err)
        }

        return callback(null, cert, videosList)
      })
    }
  ], function (err, cert, videosList) {
    if (err) return next(err)

    return res.json({ cert: cert, videos: videosList })
  })
}

function listPods (req, res, next) {
  Pods.list(function (err, podsList) {
    if (err) return next(err)

    res.json(podsList)
  })
}

function makeFriends (req, res, next) {
  friends.makeFriends(function (err) {
    if (err) return next(err)

    res.type('json').status(204).end()
  })
}

function removePods (req, res, next) {
  const url = req.body.signature.url

  async.waterfall([
    function (callback) {
      Pods.remove(url, function (err) {
        return callback(err)
      })
    },

    function (callback) {
      Videos.listFromUrl(url, function (err, videosList) {
        if (err) {
          logger.error('Cannot list videos from url.', { error: err })
          return callback(err)
        }

        return callback(null, videosList)
      })
    },

    function removeTheRemoteVideos (videosList, callback) {
      videos.removeRemoteVideos(videosList, function (err) {
        if (err) {
          logger.error('Cannot remove remote videos.', { error: err })
          callback(err)
        }

        return callback(null)
      })
    }
  ], function (err) {
    if (err) return next(err)

    return res.type('json').status(204).end()
  })
}

function quitFriends (req, res, next) {
  friends.quitFriends(function (err) {
    if (err) return next(err)

    res.type('json').status(204).end()
  })
}
<commit_msg>Return with callback with an error<commit_after>'use strict'

const async = require('async')
const express = require('express')

const logger = require('../../../helpers/logger')
const friends = require('../../../lib/friends')
const middlewares = require('../../../middlewares')
const Pods = require('../../../models/pods')
const oAuth2 = middlewares.oauth2
const reqValidator = middlewares.reqValidators.pods
const secureMiddleware = middlewares.secure
const secureRequest = middlewares.reqValidators.remote.secureRequest
const videos = require('../../../lib/videos')
const Videos = require('../../../models/videos')

const router = express.Router()

router.get('/', listPods)
router.post('/', reqValidator.podsAdd, addPods)
router.get('/makefriends', oAuth2.authenticate, reqValidator.makeFriends, makeFriends)
router.get('/quitfriends', oAuth2.authenticate, quitFriends)
// Post because this is a secured request
router.post('/remove', secureRequest, secureMiddleware.decryptBody, removePods)

// ---------------------------------------------------------------------------

module.exports = router

// ---------------------------------------------------------------------------

function addPods (req, res, next) {
  const informations = req.body.data

  async.waterfall([
    function addPod (callback) {
      Pods.add(informations, function (err) {
        return callback(err)
      })
    },

    function createVideosOfThisPod (callback) {
      // Create the remote videos from the new pod
      videos.createRemoteVideos(informations.videos, function (err) {
        if (err) logger.error('Cannot create remote videos.', { error: err })

        return callback(err)
      })
    },

    function fetchMyCertificate (callback) {
      friends.getMyCertificate(function (err, cert) {
        if (err) {
          logger.error('Cannot read cert file.')
          return callback(err)
        }

        return callback(null, cert)
      })
    },

    function getListOfMyVideos (cert, callback) {
      Videos.listOwned(function (err, videosList) {
        if (err) {
          logger.error('Cannot get the list of owned videos.')
          return callback(err)
        }

        return callback(null, cert, videosList)
      })
    }
  ], function (err, cert, videosList) {
    if (err) return next(err)

    return res.json({ cert: cert, videos: videosList })
  })
}

function listPods (req, res, next) {
  Pods.list(function (err, podsList) {
    if (err) return next(err)

    res.json(podsList)
  })
}

function makeFriends (req, res, next) {
  friends.makeFriends(function (err) {
    if (err) return next(err)

    res.type('json').status(204).end()
  })
}

function removePods (req, res, next) {
  const url = req.body.signature.url

  async.waterfall([
    function (callback) {
      Pods.remove(url, function (err) {
        return callback(err)
      })
    },

    function (callback) {
      Videos.listFromUrl(url, function (err, videosList) {
        if (err) {
          logger.error('Cannot list videos from url.', { error: err })
          return callback(err)
        }

        return callback(null, videosList)
      })
    },

    function removeTheRemoteVideos (videosList, callback) {
      videos.removeRemoteVideos(videosList, function (err) {
        if (err) {
          logger.error('Cannot remove remote videos.', { error: err })
          return callback(err)
        }

        return callback(null)
      })
    }
  ], function (err) {
    if (err) return next(err)

    return res.type('json').status(204).end()
  })
}

function quitFriends (req, res, next) {
  friends.quitFriends(function (err) {
    if (err) return next(err)

    res.type('json').status(204).end()
  })
}
<|endoftext|>