<commit_before>/**
 * Configures a Landmark app in encapsulated mode, but does not start it.
 *
 * Connects to the database and runs updates and then calls back.
 *
 * This is the code-path to use if you'd like to mount the landmark app as a sub-app in another express application.
 *
 *   var app = express();
 *
 *   //...do your normal express setup stuff, add middleware and routes (but not static content or error handling middleware yet)
 *
 *   landmark.mount('/content', app, function() {
 *     //put your app's static content and error handling middleware here and start your server
 *   });
 *
 * Events are fired during initialisation to allow customisation, including:
 *
 *   - onMount
 *
 * If the events argument is a function, it is assumed to be the mounted event.
 *
 *
 * ####Options:
 *
 * Landmark supports the following options specifically for running in encapsulated mode (with no embedded server):
 *
 *   - name
 *   - port
 *   - views
 *   - view engine
 *   - compress
 *   - favico
 *   - less
 *   - static
 *   - headless
 *   - logger
 *   - cookie secret
 *   - session
 *   - 404
 *   - 500
 *   - routes
 *   - locals
 *   - auto update
 *
 *
 * @api public
 */

var _ = require('underscore'),
	express = require('express'),
	utils = require('landmark-utils');

var dashes = '\n------------------------------------------------\n';

exports = module.exports = function mount(mountPath, parentApp, events) {

	// Validate the express app instance

	if (!this.app) {
		console.error('\nLandmarkJS Initialisaton Error:\n\napp must be initialised. Call landmark.init() or landmark.connect(new Express()) first.\n');
		process.exit(1);
	}

	// Localise references to this for closures

	var landmark = this,
		app = this.app;

	// this.nativeApp indicates landmark has been mounted natively
	// (not as part of a custom middleware stack)
	//
	this.nativeApp = true;

	// Initialise the mongo connection url

	if (!this.get('mongo')) {
		var dbName = this.get('db name') || utils.slug(this.get('name'));
		var dbUrl = process.env.MONGO_URI || process.env.MONGO_URL || process.env.MONGOLAB_URI || process.env.MONGOLAB_URL || (process.env.OPENSHIFT_MONGODB_DB_URL || 'mongodb://localhost/') + dbName;
		this.set('mongo', dbUrl);
	}

	// Initialise and validate session options

	if (!this.get('cookie secret')) {
		console.error('\nLandmarkJS Configuration Error:\n\nPlease provide a `cookie secret` value for session encryption.\n');
		process.exit(1);
	}

	var sessionOptions = this.get('session options');

	if (!_.isObject(sessionOptions)) {
		sessionOptions = {};
	}

	if (!sessionOptions.key) {
		sessionOptions.key = 'landmark.sid';
	}

	sessionOptions.cookieParser = express.cookieParser(this.get('cookie secret'));

	var sessionStore = this.get('session store');

	if (sessionStore) {

		var sessionStoreOptions = this.get('session store options') || {};

		// Perform any session store specific configuration or exit on an unsupported session store

		switch (sessionStore) {

			case 'mongo':
				// default session store for using MongoDB
				sessionStore = 'connect-mongo';
			case 'connect-mongo':
				_.defaults(sessionStoreOptions, {
					collection: 'app_sessions',
					url: this.get('mongo')
				});
				break;

			case 'connect-mongostore':
				_.defaults(sessionStoreOptions, {
					collection: 'app_sessions'
				});
				if (!sessionStoreOptions.db) {
					if (throwSessionOptionsError) {
						console.error(
							'\nERROR: ' + sessionStore + ' requires `session store options` to be set.' +
							'\n' +
							'\nSee http://localhost:8080/docs/configuration#options-database for details.' +
						'\n');
						process.exit(1);
					}
				}
				break;

			case 'redis':
				// default session store for using Redis
				sessionStore = 'connect-redis';
			case 'connect-redis':
				break;

			default:
				console.error(
						'\nERROR: unsupported session store ' + sessionStore + '.' +
						'\n' +
						'\nSee http://localhost:8080/docs/configuration#options-database for details.' +
					'\n');
				process.exit(1);
				break;
		}

		// Initialize the session store
		try {

			var _SessionStore = require(sessionStore)(express);
			sessionOptions.store = new _SessionStore(sessionStoreOptions);

		} catch(e) {

			if (e.code === 'MODULE_NOT_FOUND') {

				// connect-redis must be explicitly installed @1.4.7, so we special-case it here
				var installName = (sessionStore === 'connect-redis') ? sessionStore + '@1.4.7' : sessionStore;

				console.error(
					'\nERROR: ' + sessionStore + ' not found.\n' +
					'\nPlease install ' + sessionStore + ' from npm to use it as a `session store` option.' +
					'\nYou can do this by running "npm install ' + installName + ' --save".' +
				'\n');
				process.exit(1);

			} else {
				throw e;
			}
		}
	}

	// expose initialised session options

	this.set('session options', sessionOptions);

	// wrangle arguments

	if (arguments.length === 1) {
		events = arguments[0];
		mountPath = null;
	}

	if ('function' === typeof events) {
		events = { onMount: events };
	}

	if (!events) events = {};

	/* Express sub-app mounting to external app at a mount point (if specified) */

	if (mountPath) {
		//fix root-relative landmark urls for assets (gets around having to re-write all the landmark templates)
		parentApp.all(/^\/landmark($|\/*)/, function(req, res, next) {
			req.url = mountPath + req.url;
			next();
		});

		parentApp.use(mountPath, app);
	}

	/* Landmark's encapsulated Express App Setup */

	// Allow usage of custom view engines

	if (this.get('custom engine')) {
		app.engine(this.get('view engine'), this.get('custom engine'));
	}

	// Set location of view templates and view engine

	app.set('views', this.getPath('views') || path.sep + 'views');
	app.set('view engine', this.get('view engine'));

	// Apply locals

	if (utils.isObject(this.get('locals'))) {
		_.extend(app.locals, this.get('locals'));
	}

	// Indent HTML everywhere, except production

	if (this.get('env') !== 'production') {
		app.locals.pretty = true;
	}

	// Default view caching logic

	app.set('view cache', this.get('env') === 'production' ? true : false);

	// Setup view caching from app settings

	if (this.get('view cache') !== undefined) {
		app.set('view cache', this.get('view cache'));
	}

	// Serve static assets

	if (this.get('compress')) {
		app.use(express.compress());
	}

	if (this.get('favico')) {
		app.use(express.favicon(this.getPath('favico')));
	}

	if (this.get('less')) {
		app.use(require('less-middleware')(this.getPath('less')));
	}

	if (this.get('sass')) {
		var sass;
		try {
			sass = require('node-sass');
		} catch(e) {
			if (e.code === 'MODULE_NOT_FOUND') {
				console.error(
					'\nERROR: node-sass not found.\n' +
					'\nPlease install the node-sass from npm to use the `sass` option.' +
					'\nYou can do this by running "npm install node-sass --save".\n'
				);
				process.exit(1);
			} else {
				throw e;
			}
		}
		app.use(sass.middleware({
			src: this.getPath('sass'),
			dest: this.getPath('sass'),
			outputStyle: this.get('env') === 'production' ? 'compressed' : 'nested'
		}));
	}

	// isArray check to provide fallback for old config files

	if (this.get('static')) {
		if (_.isArray(this.get('static'))) {
			var landmark = this;
			_.each(this.get('static'), function (value) {
				app.use(express.static(landmark.getPath('unsupported', value)));
			});
		} else {
			app.use(express.static(this.getPath('static')));
		}
	}

	if (!this.get('headless')) {
		this.static(app);
	}

	// Handle dynamic requests

	if (this.get('logger')) {
		app.use(express.logger(this.get('logger')));
	}

	if (this.get('file limit')) {
		app.use(express.limit(this.get('file limit')));
	}

	app.use(express.bodyParser());
	app.use(express.methodOverride());
	app.use(sessionOptions.cookieParser);
	app.use(express.session(sessionOptions));
	app.use(require('connect-flash')());

	if (this.get('session') === true) {
		app.use(this.session.persist);
	} else if ('function' === typeof this.get('session')) {
		app.use(this.get('session'));
	}

	// Process 'X-Forwarded-For' request header

	if (this.get('trust proxy') === true) {
		app.enable('trust proxy');
	} else {
		app.disable('trust proxy');
	}

	// Check for IP range restrictions

	if (this.get('allowed ip ranges')) {
		if (!app.get('trust proxy')) {
			console.log(
				'LandmarkJS Initialisaton Error:\n\n' +
				'to set IP range restrictions the "trust proxy" setting must be enabled.\n\n'
			);
			process.exit(1);
		}
		var ipRangeMiddleware = require('./lib/security/ipRangeRestrict')(
			this.get('allowed ip ranges'),
			this.wrapHTMLError
		);
		this.pre('routes', ipRangeMiddleware);
	}

	// Pre-route middleware

	this._pre.routes.forEach(function(fn) {
		try {
			app.use(fn);
		}
		catch(e) {
			if (landmark.get('logger')) {
				console.log('Invalid pre-route middleware provided');
			}
			throw e;
		}
	});

	// Route requests

	app.use(app.router);

	// Headless mode means don't bind the Landmark routes

	if (!this.get('headless')) {
		this.routes(app);
	}

	// Handle redirects before 404s

	if (Object.keys(this._redirects).length) {
		app.use(function(req, res, next) {
			if (landmark._redirects[req.path]) {
				res.redirect(landmark._redirects[req.path]);
			} else {
				next();
			}
		});
	}

	// Handle 404 (no route matched) errors

	var default404Handler = function(req, res, next) {
		res.status(404).send(landmark.wrapHTMLError('Sorry, no page could be found at this address (404)'));
	};

	app.use(function(req, res, next) {

		var err404 = landmark.get('404');

		if (err404) {
			try {
				if ('function' === typeof err404) {
					err404(req, res, next);
				} else if ('string' === typeof err404) {
					res.status(404).render(err404);
				} else {
					if (landmark.get('logger')) {
						console.log(dashes + 'Error handling 404 (not found): Invalid type (' + (typeof err404) + ') for 404 setting.' + dashes);
					}
					default404Handler(req, res, next);
				}
			} catch(e) {
				if (landmark.get('logger')) {
					console.log(dashes + 'Error handling 404 (not found):');
					console.log(e);
					console.log(dashes);
				}
				default404Handler(req, res, next);
			}
		} else {
			default404Handler(req, res, next);
		}

	});

	// Handle other errors

	var default500Handler = function(err, req, res, next) {

		if (landmark.get('logger')) {
			if (err instanceof Error) {
				console.log((err.type ? err.type + ' ' : '') + 'Error thrown for request: ' + req.url);
			} else {
				console.log('Error thrown for request: ' + req.url);
			}
			console.log(err.stack || err);
		}

		var msg = '';

		if (landmark.get('env') === 'development') {

			if (err instanceof Error) {
				if (err.type) {
					msg += '
' + err.type + '
';
				}
				msg += utils.textToHTML(err.message);
			} else if ('object' === typeof err) {
				msg += '' + JSON.stringify(err) + '';
			} else if (err) {
				msg += err;
			}
		}

		res.status(500).send(landmark.wrapHTMLError('Sorry, an error occurred loading the page (500)', msg));
	};

	app.use(function(err, req, res, next) {

		var err500 = landmark.get('500');

		if (err500) {
			try {
				if ('function' === typeof err500) {
					err500(err, req, res, next);
				} else if ('string' === typeof err500) {
					res.locals.err = err;
					res.status(500).render(err500);
				} else {
					if (landmark.get('logger')) {
						console.log(dashes + 'Error handling 500 (error): Invalid type (' + (typeof err500) + ') for 500 setting.' + dashes);
					}
					default500Handler(err, req, res, next);
				}
			} catch(e) {
				if (landmark.get('logger')) {
					console.log(dashes + 'Error handling 500 (error):');
					console.log(e);
					console.log(dashes);
				}
				default500Handler(err, req, res, next);
			}
		} else {
			default500Handler(err, req, res, next);
		}

	});

	// Configure application routes
	if ('function' === typeof this.get('routes')) {
		this.get('routes')(app);
	}

	// Connect to database

	var mongoConnectionOpen = false;

	this.mongoose.connect(this.get('mongo'));
	this.mongoose.connection.on('error', function(err) {

		if (landmark.get('logger')) {
			console.log('------------------------------------------------');
			console.log('Mongo Error:\n');
			console.log(err);
		}

		if (mongoConnectionOpen) {
			throw new Error('Mongo Error');
		} else {
			throw new Error('LandmarkJS (' + landmark.get('name') + ') failed to start');
		}

	}).on('open', function() {

		// app is mounted and db connection acquired, time to update and then call back

		// Apply updates?
		if (landmark.get('auto update')) {
			landmark.applyUpdates(events.onMount);
		} else {
			events.onMount && events.onMount();
		}

	});
};
<commit_msg>Cleaning up static array implementation<commit_after>/**
 * Configures a Landmark app in encapsulated mode, but does not start it.
 *
 * Connects to the database and runs updates and then calls back.
 *
 * This is the code-path to use if you'd like to mount the landmark app as a sub-app in another express application.
 *
 *   var app = express();
 *
 *   //...do your normal express setup stuff, add middleware and routes (but not static content or error handling middleware yet)
 *
 *   landmark.mount('/content', app, function() {
 *     //put your app's static content and error handling middleware here and start your server
 *   });
 *
 * Events are fired during initialisation to allow customisation, including:
 *
 *   - onMount
 *
 * If the events argument is a function, it is assumed to be the mounted event.
 *
 *
 * ####Options:
 *
 * Landmark supports the following options specifically for running in encapsulated mode (with no embedded server):
 *
 *   - name
 *   - port
 *   - views
 *   - view engine
 *   - compress
 *   - favico
 *   - less
 *   - static
 *   - headless
 *   - logger
 *   - cookie secret
 *   - session
 *   - 404
 *   - 500
 *   - routes
 *   - locals
 *   - auto update
 *
 *
 * @api public
 */

var _ = require('underscore'),
	express = require('express'),
	utils = require('landmark-utils');

var dashes = '\n------------------------------------------------\n';

exports = module.exports = function mount(mountPath, parentApp, events) {

	// Validate the express app instance

	if (!this.app) {
		console.error('\nLandmarkJS Initialisaton Error:\n\napp must be initialised. Call landmark.init() or landmark.connect(new Express()) first.\n');
		process.exit(1);
	}

	// Localise references to this for closures

	var landmark = this,
		app = this.app;

	// this.nativeApp indicates landmark has been mounted natively
	// (not as part of a custom middleware stack)
	//
	this.nativeApp = true;

	// Initialise the mongo connection url

	if (!this.get('mongo')) {
		var dbName = this.get('db name') || utils.slug(this.get('name'));
		var dbUrl = process.env.MONGO_URI || process.env.MONGO_URL || process.env.MONGOLAB_URI || process.env.MONGOLAB_URL || (process.env.OPENSHIFT_MONGODB_DB_URL || 'mongodb://localhost/') + dbName;
		this.set('mongo', dbUrl);
	}

	// Initialise and validate session options

	if (!this.get('cookie secret')) {
		console.error('\nLandmarkJS Configuration Error:\n\nPlease provide a `cookie secret` value for session encryption.\n');
		process.exit(1);
	}

	var sessionOptions = this.get('session options');

	if (!_.isObject(sessionOptions)) {
		sessionOptions = {};
	}

	if (!sessionOptions.key) {
		sessionOptions.key = 'landmark.sid';
	}

	sessionOptions.cookieParser = express.cookieParser(this.get('cookie secret'));

	var sessionStore = this.get('session store');

	if (sessionStore) {

		var sessionStoreOptions = this.get('session store options') || {};

		// Perform any session store specific configuration or exit on an unsupported session store

		switch (sessionStore) {

			case 'mongo':
				// default session store for using MongoDB
				sessionStore = 'connect-mongo';
			case 'connect-mongo':
				_.defaults(sessionStoreOptions, {
					collection: 'app_sessions',
					url: this.get('mongo')
				});
				break;

			case 'connect-mongostore':
				_.defaults(sessionStoreOptions, {
					collection: 'app_sessions'
				});
				if (!sessionStoreOptions.db) {
					if (throwSessionOptionsError) {
						console.error(
							'\nERROR: ' + sessionStore + ' requires `session store options` to be set.' +
							'\n' +
							'\nSee http://localhost:8080/docs/configuration#options-database for details.' +
						'\n');
						process.exit(1);
					}
				}
				break;

			case 'redis':
				// default session store for using Redis
				sessionStore = 'connect-redis';
			case 'connect-redis':
				break;

			default:
				console.error(
						'\nERROR: unsupported session store ' + sessionStore + '.' +
						'\n' +
						'\nSee http://localhost:8080/docs/configuration#options-database for details.' +
					'\n');
				process.exit(1);
				break;
		}

		// Initialize the session store
		try {

			var _SessionStore = require(sessionStore)(express);
			sessionOptions.store = new _SessionStore(sessionStoreOptions);

		} catch(e) {

			if (e.code === 'MODULE_NOT_FOUND') {

				// connect-redis must be explicitly installed @1.4.7, so we special-case it here
				var installName = (sessionStore === 'connect-redis') ? sessionStore + '@1.4.7' : sessionStore;

				console.error(
					'\nERROR: ' + sessionStore + ' not found.\n' +
					'\nPlease install ' + sessionStore + ' from npm to use it as a `session store` option.' +
					'\nYou can do this by running "npm install ' + installName + ' --save".' +
				'\n');
				process.exit(1);

			} else {
				throw e;
			}
		}
	}

	// expose initialised session options

	this.set('session options', sessionOptions);

	// wrangle arguments

	if (arguments.length === 1) {
		events = arguments[0];
		mountPath = null;
	}

	if ('function' === typeof events) {
		events = { onMount: events };
	}

	if (!events) events = {};

	/* Express sub-app mounting to external app at a mount point (if specified) */

	if (mountPath) {
		//fix root-relative landmark urls for assets (gets around having to re-write all the landmark templates)
		parentApp.all(/^\/landmark($|\/*)/, function(req, res, next) {
			req.url = mountPath + req.url;
			next();
		});

		parentApp.use(mountPath, app);
	}

	/* Landmark's encapsulated Express App Setup */

	// Allow usage of custom view engines

	if (this.get('custom engine')) {
		app.engine(this.get('view engine'), this.get('custom engine'));
	}

	// Set location of view templates and view engine

	app.set('views', this.getPath('views') || path.sep + 'views');
	app.set('view engine', this.get('view engine'));

	// Apply locals

	if (utils.isObject(this.get('locals'))) {
		_.extend(app.locals, this.get('locals'));
	}

	// Indent HTML everywhere, except production

	if (this.get('env') !== 'production') {
		app.locals.pretty = true;
	}

	// Default view caching logic

	app.set('view cache', this.get('env') === 'production' ? true : false);

	// Setup view caching from app settings

	if (this.get('view cache') !== undefined) {
		app.set('view cache', this.get('view cache'));
	}

	// Serve static assets

	if (this.get('compress')) {
		app.use(express.compress());
	}

	if (this.get('favico')) {
		app.use(express.favicon(this.getPath('favico')));
	}

	if (this.get('less')) {
		app.use(require('less-middleware')(this.getPath('less')));
	}

	if (this.get('sass')) {
		var sass;
		try {
			sass = require('node-sass');
		} catch(e) {
			if (e.code === 'MODULE_NOT_FOUND') {
				console.error(
					'\nERROR: node-sass not found.\n' +
					'\nPlease install the node-sass from npm to use the `sass` option.' +
					'\nYou can do this by running "npm install node-sass --save".\n'
				);
				process.exit(1);
			} else {
				throw e;
			}
		}
		app.use(sass.middleware({
			src: this.getPath('sass'),
			dest: this.getPath('sass'),
			outputStyle: this.get('env') === 'production' ? 'compressed' : 'nested'
		}));
	}

	// the static option can be a single path, or array of paths

	var staticPaths = this.get('static');

	if (_.isString(staticPaths)) {
		staticPaths = [staticPaths];
	}

	if (_.isArray(staticPaths)) {
		_.each(staticPaths, function(value) {
			app.use(express.static(this.getPath('unsupported', value)));
		}, this);
	}

	// unless the headless option is set (which disables the Admin UI),
	// bind the static handler for the Admin UI public resources

	if (!this.get('headless')) {
		this.static(app);
	}

	// Handle dynamic requests

	if (this.get('logger')) {
		app.use(express.logger(this.get('logger')));
	}

	if (this.get('file limit')) {
		app.use(express.limit(this.get('file limit')));
	}

	app.use(express.bodyParser());
	app.use(express.methodOverride());
	app.use(sessionOptions.cookieParser);
	app.use(express.session(sessionOptions));
	app.use(require('connect-flash')());

	if (this.get('session') === true) {
		app.use(this.session.persist);
	} else if ('function' === typeof this.get('session')) {
		app.use(this.get('session'));
	}

	// Process 'X-Forwarded-For' request header

	if (this.get('trust proxy') === true) {
		app.enable('trust proxy');
	} else {
		app.disable('trust proxy');
	}

	// Check for IP range restrictions

	if (this.get('allowed ip ranges')) {
		if (!app.get('trust proxy')) {
			console.log(
				'LandmarkJS Initialisaton Error:\n\n' +
				'to set IP range restrictions the "trust proxy" setting must be enabled.\n\n'
			);
			process.exit(1);
		}
		var ipRangeMiddleware = require('./lib/security/ipRangeRestrict')(
			this.get('allowed ip ranges'),
			this.wrapHTMLError
		);
		this.pre('routes', ipRangeMiddleware);
	}

	// Pre-route middleware

	this._pre.routes.forEach(function(fn) {
		try {
			app.use(fn);
		}
		catch(e) {
			if (landmark.get('logger')) {
				console.log('Invalid pre-route middleware provided');
			}
			throw e;
		}
	});

	// Route requests

	app.use(app.router);

	// Headless mode means don't bind the Landmark routes

	if (!this.get('headless')) {
		this.routes(app);
	}

	// Handle redirects before 404s

	if (Object.keys(this._redirects).length) {
		app.use(function(req, res, next) {
			if (landmark._redirects[req.path]) {
				res.redirect(landmark._redirects[req.path]);
			} else {
				next();
			}
		});
	}

	// Handle 404 (no route matched) errors

	var default404Handler = function(req, res, next) {
		res.status(404).send(landmark.wrapHTMLError('Sorry, no page could be found at this address (404)'));
	};

	app.use(function(req, res, next) {

		var err404 = landmark.get('404');

		if (err404) {
			try {
				if ('function' === typeof err404) {
					err404(req, res, next);
				} else if ('string' === typeof err404) {
					res.status(404).render(err404);
				} else {
					if (landmark.get('logger')) {
						console.log(dashes + 'Error handling 404 (not found): Invalid type (' + (typeof err404) + ') for 404 setting.' + dashes);
					}
					default404Handler(req, res, next);
				}
			} catch(e) {
				if (landmark.get('logger')) {
					console.log(dashes + 'Error handling 404 (not found):');
					console.log(e);
					console.log(dashes);
				}
				default404Handler(req, res, next);
			}
		} else {
			default404Handler(req, res, next);
		}

	});

	// Handle other errors

	var default500Handler = function(err, req, res, next) {

		if (landmark.get('logger')) {
			if (err instanceof Error) {
				console.log((err.type ? err.type + ' ' : '') + 'Error thrown for request: ' + req.url);
			} else {
				console.log('Error thrown for request: ' + req.url);
			}
			console.log(err.stack || err);
		}

		var msg = '';

		if (landmark.get('env') === 'development') {

			if (err instanceof Error) {
				if (err.type) {
					msg += '
' + err.type + '
';
				}
				msg += utils.textToHTML(err.message);
			} else if ('object' === typeof err) {
				msg += '' + JSON.stringify(err) + '';
			} else if (err) {
				msg += err;
			}
		}

		res.status(500).send(landmark.wrapHTMLError('Sorry, an error occurred loading the page (500)', msg));
	};

	app.use(function(err, req, res, next) {

		var err500 = landmark.get('500');

		if (err500) {
			try {
				if ('function' === typeof err500) {
					err500(err, req, res, next);
				} else if ('string' === typeof err500) {
					res.locals.err = err;
					res.status(500).render(err500);
				} else {
					if (landmark.get('logger')) {
						console.log(dashes + 'Error handling 500 (error): Invalid type (' + (typeof err500) + ') for 500 setting.' + dashes);
					}
					default500Handler(err, req, res, next);
				}
			} catch(e) {
				if (landmark.get('logger')) {
					console.log(dashes + 'Error handling 500 (error):');
					console.log(e);
					console.log(dashes);
				}
				default500Handler(err, req, res, next);
			}
		} else {
			default500Handler(err, req, res, next);
		}

	});

	// Configure application routes
	if ('function' === typeof this.get('routes')) {
		this.get('routes')(app);
	}

	// Connect to database

	var mongoConnectionOpen = false;

	this.mongoose.connect(this.get('mongo'));
	this.mongoose.connection.on('error', function(err) {

		if (landmark.get('logger')) {
			console.log('------------------------------------------------');
			console.log('Mongo Error:\n');
			console.log(err);
		}

		if (mongoConnectionOpen) {
			throw new Error('Mongo Error');
		} else {
			throw new Error('LandmarkJS (' + landmark.get('name') + ') failed to start');
		}

	}).on('open', function() {

		// app is mounted and db connection acquired, time to update and then call back

		// Apply updates?
		if (landmark.get('auto update')) {
			landmark.applyUpdates(events.onMount);
		} else {
			events.onMount && events.onMount();
		}

	});
};
<|endoftext|>


<commit_before>'use strict';
var React = require('react');
var globals = require('./globals');
var fetched = require('./fetched');
var TabbedArea = require('react-bootstrap').TabbedArea;
var TabPane = require('react-bootstrap').TabPane;
var url = require('url');
var search = require('./search');

var FacetList = search.FacetList;
var Facet = search.Facet;
var TextFilter = search.TextFilter;
var Listing = search.Listing;
var BatchDownload = search.BatchDownload;
var FetchedData = fetched.FetchedData;
var Param = fetched.Param;

var AutocompleteBox = React.createClass({
    render: function() {
        var terms = this.props.auto['@graph']; // List of matching terms from server
        var userTerm = this.props.userTerm && this.props.userTerm.toLowerCase(); // Term user entered

        if (!this.props.hide && userTerm && userTerm.length && terms && terms.length) {
            return (

                    {terms.map(function(term) {
                        var matchStart, matchEnd;
                        var preText, matchText, postText;

                        // Boldface matching part of term
                        matchStart = term.text.toLowerCase().indexOf(userTerm);
                        if (matchStart >= 0) {
                            matchEnd = matchStart + userTerm.length;
                            preText = term.text.substring(0, matchStart);
                            matchText = term.text.substring(matchStart, matchEnd);
                            postText = term.text.substring(matchEnd);
                        } else {
                            preText = term.text;
                        }
                        return
{preText}{matchText}{postText}
;
                    }, this)}

            );
        } else {
            return null;
        }
    }
});

var AdvSearch = React.createClass({
    getInitialState: function() {
        return {
            disclosed: false,
            showAutoSuggest: false,
            searchTerm: '',
            terms: {}
        };
    },

    contextTypes: {
        autocompleteTermChosen: React.PropTypes.bool,
        autocompleteHidden: React.PropTypes.bool,
        onAutocompleteHiddenChange: React.PropTypes.func,
        location_href: React.PropTypes.string
    },

    handleDiscloseClick: function(e) {
        this.setState({disclosed: !this.state.disclosed});
    },

    handleChange: function(e) {
        this.setState({showAutoSuggest: true});
        this.newSearchTerm = e.target.value;
    },

    handleAutocompleteClick: function(term, id, name) {

        var newTerms = {};
        var inputNode = this.refs.annotation.getDOMNode();
        inputNode.value = this.newSearchTerm = term;
        newTerms[name] = id;
        this.setState({terms: newTerms});
        this.setState({showAutoSuggest: false});
        inputNode.focus();
        // Now let the timer update the terms state when it gets around to it.
    },

    componentDidMount: function() {
        // Use timer to limit to one request per second
        this.timer = setInterval(this.tick, 1000);
    },

    componentWillUnmount: function() {
        clearInterval(this.timer);
    },

    tick: function() {
        if (this.newSearchTerm !== this.state.searchTerm) {
            this.setState({searchTerm: this.newSearchTerm});
        }
    },

    render: function() {
        var context = this.props.context;
        var id = url.parse(this.context.location_href, true);
        var region = id.query['region'] || '';

        return (

                <form id="panel1" ref="adv-search" role="form" autoComplete="off" aria-labeledby="tab1">

                            <input type="hidden" name="genome" value="hg19" />
                            {Object.keys(this.state.terms).map(function(key) {
                                return <input type="hidden" name={key} value={this.state.terms[key]} />;
                            }, this)}
                            <input ref="annotation" defaultValue={region} name="region" type="text" className="form-control" onChange={this.handleChange}
                                placeholder="Enter any one of human Gene name, Symbol, Synonyms, Gene ID, HGNC ID, coordinates, rsid, Ensemble ID" />
                            {(this.state.showAutoSuggest && this.state.searchTerm) ?
                                <FetchedData loadingComplete={true}>
                                    <Param name="auto" url={'/suggest/?q=' + this.state.searchTerm} />
                                    <AutocompleteBox name="annotation" userTerm={this.state.searchTerm} handleClick={this.handleAutocompleteClick} />
                                </FetchedData>
                            : null}

                            <input type="submit" value="Search" className="btn btn-sm btn-info adv-search-submit" />

                </form>

        );
    }
});

var RegionSearch = module.exports.RegionSearch = React.createClass({
    onFilter: function(e) {
        var search = e.currentTarget.getAttribute('href');
        this.props.onChange(search);
        e.stopPropagation();
        e.preventDefault();
    },
    contextTypes: {
        location_href: React.PropTypes.string,
        navigate: React.PropTypes.func
    },
    render: function() {
        var context = this.props.context;
        var results = context['@graph'];
        var columns = context['columns'];
        var notification = context['notification'];
        var assembly = ['hg19'];
        var files = [];
        var id = url.parse(this.context.location_href, true);
        var region = context['region'] || '';
        var searchBase = url.parse(this.context.location_href).search || '';
        var trimmedSearchBase = searchBase.replace(/[\?|\&]limit=all/, "");
        var filters = context['filters'];
        var facets = context['facets'];
        var total = context['total'];
        var batch_hub_disabled = total > 500;
        return (

Region search

              <AdvSearch {...this.props} />
              {results.length ?

                              <FacetList {...this.props} facets={facets} filters={filters}
                                  searchBase={searchBase ? searchBase + '&' : searchBase + '?'} onFilter={this.onFilter} />

                                  Showing {results.length} of {total}
                                  {total > results.length && searchBase.indexOf('limit=all') === -1 ?

                                          View All

                                  :

                                          {results.length > 25 ?

                                                  View 25

                                          : null}

                                  }

                                  {context['batch_download'] ?

                                          <BatchDownload context={context} />

                                  : null}

                                  {context['batch_hub'] ?

                                          {batch_hub_disabled ? 'Filter to 500 to visualize' :'Visualize'}

                                  :null}

                                  {results.map(function (result) {
                                      return Listing({context:result, columns: columns, key: result['@id']});
                                  })}

              :
{notification}
}

        );
    }
});

globals.content_views.register(RegionSearch, 'region-search');
<commit_msg>add Modal<commit_after>'use strict';
var React = require('react');
var Modal = require('react-bootstrap/lib/Modal');
var globals = require('./globals');
var fetched = require('./fetched');
var TabbedArea = require('react-bootstrap').TabbedArea;
var TabPane = require('react-bootstrap').TabPane;
var url = require('url');
var search = require('./search');

var FacetList = search.FacetList;
var Facet = search.Facet;
var TextFilter = search.TextFilter;
var Listing = search.Listing;
var BatchDownload = search.BatchDownload;
var FetchedData = fetched.FetchedData;
var Param = fetched.Param;

var AutocompleteBox = React.createClass({
    render: function() {
        var terms = this.props.auto['@graph']; // List of matching terms from server
        var userTerm = this.props.userTerm && this.props.userTerm.toLowerCase(); // Term user entered

        if (!this.props.hide && userTerm && userTerm.length && terms && terms.length) {
            return (

                    {terms.map(function(term) {
                        var matchStart, matchEnd;
                        var preText, matchText, postText;

                        // Boldface matching part of term
                        matchStart = term.text.toLowerCase().indexOf(userTerm);
                        if (matchStart >= 0) {
                            matchEnd = matchStart + userTerm.length;
                            preText = term.text.substring(0, matchStart);
                            matchText = term.text.substring(matchStart, matchEnd);
                            postText = term.text.substring(matchEnd);
                        } else {
                            preText = term.text;
                        }
                        return
{preText}{matchText}{postText}
;
                    }, this)}

            );
        } else {
            return null;
        }
    }
});

var AdvSearch = React.createClass({
    getInitialState: function() {
        return {
            disclosed: false,
            showAutoSuggest: false,
            searchTerm: '',
            terms: {}
        };
    },

    contextTypes: {
        autocompleteTermChosen: React.PropTypes.bool,
        autocompleteHidden: React.PropTypes.bool,
        onAutocompleteHiddenChange: React.PropTypes.func,
        location_href: React.PropTypes.string
    },

    handleDiscloseClick: function(e) {
        this.setState({disclosed: !this.state.disclosed});
    },

    handleChange: function(e) {
        this.setState({showAutoSuggest: true});
        this.newSearchTerm = e.target.value;
    },

    handleAutocompleteClick: function(term, id, name) {

        var newTerms = {};
        var inputNode = this.refs.annotation.getDOMNode();
        inputNode.value = this.newSearchTerm = term;
        newTerms[name] = id;
        this.setState({terms: newTerms});
        this.setState({showAutoSuggest: false});
        inputNode.focus();
        // Now let the timer update the terms state when it gets around to it.
    },

    componentDidMount: function() {
        // Use timer to limit to one request per second
        this.timer = setInterval(this.tick, 1000);
    },

    componentWillUnmount: function() {
        clearInterval(this.timer);
    },

    tick: function() {
        if (this.newSearchTerm !== this.state.searchTerm) {
            this.setState({searchTerm: this.newSearchTerm});
        }
    },

    render: function() {
        var context = this.props.context;
        var id = url.parse(this.context.location_href, true);
        var region = id.query['region'] || '';

        return (

                <form id="panel1" ref="adv-search" role="form" autoComplete="off" aria-labeledby="tab1">

                            <input type="hidden" name="genome" value="hg19" />
                            {Object.keys(this.state.terms).map(function(key) {
                                return <input type="hidden" name={key} value={this.state.terms[key]} />;
                            }, this)}
                            <input ref="annotation" defaultValue={region} name="region" type="text" className="form-control" onChange={this.handleChange}
                                placeholder="Enter any one of human Gene name, Symbol, Synonyms, Gene ID, HGNC ID, coordinates, rsid, Ensemble ID" />
                            {(this.state.showAutoSuggest && this.state.searchTerm) ?
                                <FetchedData loadingComplete={true}>
                                    <Param name="auto" url={'/suggest/?q=' + this.state.searchTerm} />
                                    <AutocompleteBox name="annotation" userTerm={this.state.searchTerm} handleClick={this.handleAutocompleteClick} />
                                </FetchedData>
                            : null}

                            <input type="submit" value="Search" className="btn btn-sm btn-info adv-search-submit" />

                </form>

        );
    }
});

var RegionSearch = module.exports.RegionSearch = React.createClass({
    onFilter: function(e) {
        var search = e.currentTarget.getAttribute('href');
        this.props.onChange(search);
        e.stopPropagation();
        e.preventDefault();
    },
    contextTypes: {
        location_href: React.PropTypes.string,
        navigate: React.PropTypes.func
    },
    render: function() {
        var context = this.props.context;
        var results = context['@graph'];
        var columns = context['columns'];
        var notification = context['notification'];
        var assembly = ['hg19'];
        var files = [];
        var id = url.parse(this.context.location_href, true);
        var region = context['region'] || '';
        var searchBase = url.parse(this.context.location_href).search || '';
        var trimmedSearchBase = searchBase.replace(/[\?|\&]limit=all/, "");
        var filters = context['filters'];
        var facets = context['facets'];
        var total = context['total'];
        var batch_hub_disabled = total > 500;
        return (

Region search

              <AdvSearch {...this.props} />
              {results.length ?

                              <FacetList {...this.props} facets={facets} filters={filters}
                                  searchBase={searchBase ? searchBase + '&' : searchBase + '?'} onFilter={this.onFilter} />

                                  Showing {results.length} of {total}
                                  {total > results.length && searchBase.indexOf('limit=all') === -1 ?

                                          View All

                                  :

                                          {results.length > 25 ?

                                                  View 25

                                          : null}

                                  }

                                  {context['batch_download'] ?

                                          <BatchDownload context={context} />

                                  : null}

                                  {context['batch_hub'] ?

                                          {batch_hub_disabled ? 'Filter to 500 to visualize' :'Visualize'}

                                  :null}

                                  {results.map(function (result) {
                                      return Listing({context:result, columns: columns, key: result['@id']});
                                  })}

              :
{notification}
}

        );
    }
});

globals.content_views.register(RegionSearch, 'region-search');
<|endoftext|>


<commit_before>/*
 * Breach: core_store.js
 *
 * Copyright (c) 2014, Stanislas Polu. All rights reserved.
 *
 * @author: spolu
 *
 * @log:
 * - 2014-05-18 spolu   Creation
 */
"use strict"

var common = require('./common.js');
var async = require('async');
var api = require('exo_browser');
var vm = require('vm');

// ## core_store
//
// Breach `core` module store implementation.
//
// The `core_store` object is in charge of exposing data storage capabilities to
// the modules. It relies on the session gigfs `module` channel. The module name
// is prepended to any path used by a module.
//
// ```
// @spec { core_module, session }
// @inherits {}
// ```
var core_store = function(spec, my) {
  var _super = {};
  my = my || {};
  spec = spec || {};

  my.core_module = spec.core_module;
  my.session = spec.session;

  //
  // #### _public_
  //
  var init;                      /* init(cb_); */
  var kill;                      /* kill(cb_); */

  var store_register;            /* store_register(src, args, cb_); */
  var store_get;                 /* store_get(src, args, cb_); */
  var store_push;                /* store_push(src, args, cb_); */

  //
  // #### _private_
  //

  //
  // #### _that_
  //
  var that = {};

  /****************************************************************************/
  /* PRIVATE HELPERS */
  /****************************************************************************/

  /****************************************************************************/
  /* EXPOSED PROCEDURES */
  /****************************************************************************/
  // ### store_register
  //
  // Registers a new type for the calling module. The type is prepended with the
  // module name so that type do not conflict across modules.
  //
  // Additionally we're running untrusted code coming from the modules here but
  // as the modules have full access to the system for now, this does not really
  // matter. The code is nonetheless encapsulated in a `vm` as of now.
  // /* TODO(spolu): Check/Elaborate security model here */
  // ```
  // @src  {string} the source module
  // @args {object} { type, reduce } reduce is the code of the reduce function
  // @cb_  {function(err, res)}
  // ```
  store_register = function(src, args, cb_) {
    if(typeof args.type !== 'string') {
      return cb_(common.err('Invalid `type`: ' + args.type,
                            'core_store:invalid_type'));
    }
    if(typeof args.reduce !== 'string') {
      return cb_(common.err('Invalid `reduce`: ' + args.reduce,
                            'core_store:invalid_reduce'));
    }

    var type = 'modules:' + src + ':' + args.type;

    my.session.gig().register(type, function(oplog) {
      var sandbox = { oplog: oplog };
      var code = 'value = (' + args.reduce + ')(oplog);';
      vm.runInNewContext(code, sandbox);
      return sandbox.value || null;
    });

    return cb_();
  };

  // ### store_get
  //
  // Retrieves the value for the given type and path for the calling module. The
  // registered reducer provided by the module is used to compute the value.
  // ```
  // @src  {string} the source module
  // @args {object} { type, path } the type and path to retrieve
  // @cb_  {function(err, res)}
  // ```
  store_get = function(src, args, cb_) {
    if(typeof args.type !== 'string') {
      return cb_(common.err('Invalid `type`: ' + args.type,
                            'core_store:invalid_type'));
    }
    if(typeof args.path !== 'string') {
      return cb_(common.err('Invalid `path`: ' + args.path,
                            'core_store:invalid_path'));
    }

    var type = 'modules:' + src + ':' + args.type;
    var path = require('path').join(src, args.path);

    my.session.gig().get('modules', type, path, cb_);
  };

  // ### store_push
  //
  // Pushes a new payload on the gigfs oplog associated with this type and path.
  // ```
  // @src  {string} the source module
  // @args {object} { type, path, payload } the type, path and payload to push
  // @cb_  {function(err, res)}
  // ```
  store_push = function(src, args, cb_) {
    if(typeof args.type !== 'string') {
      return cb_(common.err('Invalid `type`: ' + args.type,
                            'core_store:invalid_type'));
    }
    if(typeof args.path !== 'string') {
      return cb_(common.err('Invalid `path`: ' + args.path,
                            'core_store:invalid_path'));
    }

    var type = 'modules:' + src + ':' + args.type;
    var path = require('path').join(src, args.path);
    var payload = args.payload || null;

    my.session.gig().push('modules', type, path, payload, cb_);
  };

  /****************************************************************************/
  /* INITIALIZATION */
  /****************************************************************************/
  // ### init
  //
  // Initialializes the core store module
  // ```
  // @cb_ {function(err)} asynchronous callback
  // ```
  init = function(cb_) {
    return cb_();
  };

  // ### kill
  //
  // Kills the core store module
  // ```
  // @cb_ {function(err)} asynchronous callback
  // ```
  kill = function(cb_) {
    /* TODO(spolu): unregister types. */
    return cb_();
  };

  common.method(that, 'init', init, _super);
  common.method(that, 'kill', kill, _super);

  common.method(that, 'store_register', store_register, _super);
  common.method(that, 'store_get', store_get, _super);
  common.method(that, 'store_push', store_push, _super);

  return that;
};

exports.core_store = core_store;
<commit_msg>Session isolate core_store data<commit_after>/*
 * Breach: core_store.js
 *
 * Copyright (c) 2014, Stanislas Polu. All rights reserved.
 *
 * @author: spolu
 *
 * @log:
 * - 2014-05-18 spolu   Creation
 */
"use strict"

var common = require('./common.js');
var async = require('async');
var api = require('exo_browser');
var vm = require('vm');

// ## core_store
//
// Breach `core` module store implementation.
//
// The `core_store` object is in charge of exposing data storage capabilities to
// the modules. It relies on the session gigfs `module` channel. The module name
// is prepended to any path used by a module.
//
// ```
// @spec { core_module, session }
// @inherits {}
// ```
var core_store = function(spec, my) {
  var _super = {};
  my = my || {};
  spec = spec || {};

  my.core_module = spec.core_module;
  my.session = spec.session;

  //
  // #### _public_
  //
  var init;                      /* init(cb_); */
  var kill;                      /* kill(cb_); */

  var store_register;            /* store_register(src, args, cb_); */
  var store_get;                 /* store_get(src, args, cb_); */
  var store_push;                /* store_push(src, args, cb_); */

  //
  // #### _private_
  //

  //
  // #### _that_
  //
  var that = {};

  /****************************************************************************/
  /* PRIVATE HELPERS */
  /****************************************************************************/

  /****************************************************************************/
  /* EXPOSED PROCEDURES */
  /****************************************************************************/
  // ### store_register
  //
  // Registers a new type for the calling module. The type is prepended with the
  // module name so that type do not conflict across modules.
  //
  // Additionally we're running untrusted code coming from the modules here but
  // as the modules have full access to the system for now, this does not really
  // matter. The code is nonetheless encapsulated in a `vm` as of now.
  // /* TODO(spolu): Check/Elaborate security model here */
  // ```
  // @src  {string} the source module
  // @args {object} { type, reduce } reduce is the code of the reduce function
  // @cb_  {function(err, res)}
  // ```
  store_register = function(src, args, cb_) {
    if(typeof args.type !== 'string') {
      return cb_(common.err('Invalid `type`: ' + args.type,
                            'core_store:invalid_type'));
    }
    if(typeof args.reduce !== 'string') {
      return cb_(common.err('Invalid `reduce`: ' + args.reduce,
                            'core_store:invalid_reduce'));
    }

    var type = 'modules:' + src + ':' + args.type;

    my.session.gig().register(type, function(oplog) {
      var sandbox = { oplog: oplog };
      var code = 'value = (' + args.reduce + ')(oplog);';
      vm.runInNewContext(code, sandbox);
      return sandbox.value || null;
    });

    return cb_();
  };

  // ### store_get
  //
  // Retrieves the value for the given type and path for the calling module. The
  // registered reducer provided by the module is used to compute the value.
  // ```
  // @src  {string} the source module
  // @args {object} { type, path } the type and path to retrieve
  // @cb_  {function(err, res)}
  // ```
  store_get = function(src, args, cb_) {
    if(typeof args.type !== 'string') {
      return cb_(common.err('Invalid `type`: ' + args.type,
                            'core_store:invalid_type'));
    }
    if(typeof args.path !== 'string') {
      return cb_(common.err('Invalid `path`: ' + args.path,
                            'core_store:invalid_path'));
    }

    var type = 'modules:' + src + ':' + args.type;
    var path = require('path').join(my.session.session_id(), src, args.path);

    my.session.gig().get('modules', type, path, cb_);
  };

  // ### store_push
  //
  // Pushes a new payload on the gigfs oplog associated with this type and path.
  // ```
  // @src  {string} the source module
  // @args {object} { type, path, payload } the type, path and payload to push
  // @cb_  {function(err, res)}
  // ```
  store_push = function(src, args, cb_) {
    if(typeof args.type !== 'string') {
      return cb_(common.err('Invalid `type`: ' + args.type,
                            'core_store:invalid_type'));
    }
    if(typeof args.path !== 'string') {
      return cb_(common.err('Invalid `path`: ' + args.path,
                            'core_store:invalid_path'));
    }

    var type = 'modules:' + src + ':' + args.type;
    var path = require('path').join(my.session.session_id(), src, args.path);
    var payload = args.payload || null;

    my.session.gig().push('modules', type, path, payload, cb_);
  };

  /****************************************************************************/
  /* INITIALIZATION */
  /****************************************************************************/
  // ### init
  //
  // Initialializes the core store module
  // ```
  // @cb_ {function(err)} asynchronous callback
  // ```
  init = function(cb_) {
    return cb_();
  };

  // ### kill
  //
  // Kills the core store module
  // ```
  // @cb_ {function(err)} asynchronous callback
  // ```
  kill = function(cb_) {
    /* TODO(spolu): unregister types. */
    return cb_();
  };

  common.method(that, 'init', init, _super);
  common.method(that, 'kill', kill, _super);

  common.method(that, 'store_register', store_register, _super);
  common.method(that, 'store_get', store_get, _super);
  common.method(that, 'store_push', store_push, _super);

  return that;
};

exports.core_store = core_store;
<|endoftext|>


<commit_before>

function ReferenceDataManager(url, auth, auth_cb, timeout, async_job_check_time_ms, async_version) {
    var self = this;

    this.url = url;
    var _url = url;

    this.timeout = timeout;
    var _timeout = timeout;

    this.async_job_check_time_ms = async_job_check_time_ms;
    if (!this.async_job_check_time_ms)
        this.async_job_check_time_ms = 5000;
    this.async_version = async_version;

    var _auth = auth ? auth : { 'token' : '', 'user_id' : ''};
    var _auth_cb = auth_cb;

     this.list_reference_genomes = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.list_reference_genomes",
            [params], 1, _callback, _errorCallback);
    };

     this.list_loaded_genomes = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.list_loaded_genomes",
            [params], 1, _callback, _errorCallback);
    };

     this.load_genomes = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.load_genomes",
            [params], 1, _callback, _errorCallback);
    };

     this.index_genomes_in_solr = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.index_genomes_in_solr",
            [params], 1, _callback, _errorCallback);
    };

     this.update_loaded_genomes = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.update_loaded_genomes",
            [params], 1, _callback, _errorCallback);
    };

    /*
     * JSON call using jQuery method.
     */
    function json_call_ajax(method, params, numRets, callback, errorCallback, json_rpc_context) {
        var deferred = $.Deferred();

        if (typeof callback === 'function') {
           deferred.done(callback);
        }

        if (typeof errorCallback === 'function') {
           deferred.fail(errorCallback);
        }

        var rpc = {
            params : params,
            method : method,
            version: "1.1",
            id: String(Math.random()).slice(2),
        };
        if (json_rpc_context)
            rpc['context'] = json_rpc_context;

        var beforeSend = null;
        var token = (_auth_cb && typeof _auth_cb === 'function') ? _auth_cb()
            : (_auth.token ? _auth.token : null);
        if (token != null) {
            beforeSend = function (xhr) {
                xhr.setRequestHeader("Authorization", token);
            }
        }

        var xhr = jQuery.ajax({
            url: _url,
            dataType: "text",
            type: 'POST',
            processData: false,
            data: JSON.stringify(rpc),
            beforeSend: beforeSend,
            timeout: _timeout,
            success: function (data, status, xhr) {
                var result;
                try {
                    var resp = JSON.parse(data);
                    result = (numRets === 1 ? resp.result[0] : resp.result);
                } catch (err) {
                    deferred.reject({
                        status: 503,
                        error: err,
                        url: _url,
                        resp: data
                    });
                    return;
                }
                deferred.resolve(result);
            },
            error: function (xhr, textStatus, errorThrown) {
                var error;
                if (xhr.responseText) {
                    try {
                        var resp = JSON.parse(xhr.responseText);
                        error = resp.error;
                    } catch (err) { // Not JSON
                        error = "Unknown error - " + xhr.responseText;
                    }
                } else {
                    error = "Unknown Error";
                }
                deferred.reject({
                    status: 500,
                    error: error
                });
            }
        });

        var promise = deferred.promise();
        promise.xhr = xhr;
        return promise;
    }
}

<commit_msg>Added the second version of update_loaded_genomes method with two new private methods, while keeping the first version for now.<commit_after>

function ReferenceDataManager(url, auth, auth_cb, timeout, async_job_check_time_ms, async_version) {
    var self = this;

    this.url = url;
    var _url = url;

    this.timeout = timeout;
    var _timeout = timeout;

    this.async_job_check_time_ms = async_job_check_time_ms;
    if (!this.async_job_check_time_ms)
        this.async_job_check_time_ms = 5000;
    this.async_version = async_version;

    var _auth = auth ? auth : { 'token' : '', 'user_id' : ''};
    var _auth_cb = auth_cb;

     this.list_reference_genomes = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.list_reference_genomes",
            [params], 1, _callback, _errorCallback);
    };

     this.list_loaded_genomes = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.list_loaded_genomes",
            [params], 1, _callback, _errorCallback);
    };

     this.load_genomes = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.load_genomes",
            [params], 1, _callback, _errorCallback);
    };

     this.index_genomes_in_solr = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.index_genomes_in_solr",
            [params], 1, _callback, _errorCallback);
    };

     this.update_loaded_genomes = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.update_loaded_genomes",
            [params], 1, _callback, _errorCallback);
    };

     this.update_loaded_genomes_v1 = function (params, _callback, _errorCallback) {
        if (typeof params === 'function')
            throw 'Argument params can not be a function';
        if (_callback && typeof _callback !== 'function')
            throw 'Argument _callback must be a function if defined';
        if (_errorCallback && typeof _errorCallback !== 'function')
            throw 'Argument _errorCallback must be a function if defined';
        if (typeof arguments === 'function' && arguments.length > 1+2)
            throw 'Too many arguments ('+arguments.length+' instead of '+(1+2)+')';
        return json_call_ajax("ReferenceDataManager.update_loaded_genomes_v1",
            [params], 1, _callback, _errorCallback);
    };

    /*
     * JSON call using jQuery method.
     */
    function json_call_ajax(method, params, numRets, callback, errorCallback, json_rpc_context) {
        var deferred = $.Deferred();

        if (typeof callback === 'function') {
           deferred.done(callback);
        }

        if (typeof errorCallback === 'function') {
           deferred.fail(errorCallback);
        }

        var rpc = {
            params : params,
            method : method,
            version: "1.1",
            id: String(Math.random()).slice(2),
        };
        if (json_rpc_context)
            rpc['context'] = json_rpc_context;

        var beforeSend = null;
        var token = (_auth_cb && typeof _auth_cb === 'function') ? _auth_cb()
            : (_auth.token ? _auth.token : null);
        if (token != null) {
            beforeSend = function (xhr) {
                xhr.setRequestHeader("Authorization", token);
            }
        }

        var xhr = jQuery.ajax({
            url: _url,
            dataType: "text",
            type: 'POST',
            processData: false,
            data: JSON.stringify(rpc),
            beforeSend: beforeSend,
            timeout: _timeout,
            success: function (data, status, xhr) {
                var result;
                try {
                    var resp = JSON.parse(data);
                    result = (numRets === 1 ? resp.result[0] : resp.result);
                } catch (err) {
                    deferred.reject({
                        status: 503,
                        error: err,
                        url: _url,
                        resp: data
                    });
                    return;
                }
                deferred.resolve(result);
            },
            error: function (xhr, textStatus, errorThrown) {
                var error;
                if (xhr.responseText) {
                    try {
                        var resp = JSON.parse(xhr.responseText);
                        error = resp.error;
                    } catch (err) { // Not JSON
                        error = "Unknown error - " + xhr.responseText;
                    }
                } else {
                    error = "Unknown Error";
                }
                deferred.reject({
                    status: 500,
                    error: error
                });
            }
        });

        var promise = deferred.promise();
        promise.xhr = xhr;
        return promise;
    }
}

<|endoftext|>


<commit_before>var embeddedRegexp = /data:(.*?);base64,/;
var commentRegexp = /\/\*([\s\S]*?)\*\//g;
var urlsRegexp = /((?:@import\s+)?url\s*\(['"]?)(\S*?)(['"]?\s*\))|(@import\s+['"]?)([^;'"]+)/ig;

function isEmbedded (src) {
	return embeddedRegexp.test(src);
}

function getUrls (text) {
	var urls = [];
	var urlMatch, url, isEmbeddedUrl, isDuplicatedUrl;

	text = text.replace(commentRegexp, '');

	while (urlMatch = urlsRegexp.exec(text)) {
		// Match 2 group if '[@import] url(path)', match 5 group if '@import path'
		url = urlMatch[2] || urlMatch[5];

		isEmbeddedUrl = isEmbedded(url);
		isDuplicatedUrl = urls.indexOf(url) !== -1;

		if (url && !isEmbeddedUrl && !isDuplicatedUrl) {
			urls.push(url);
		}
	}

	return urls;
}

module.exports = getUrls;
<commit_msg>Check isEmbedded and isDuplicate only when needed<commit_after>var embeddedRegexp = /data:(.*?);base64,/;
var commentRegexp = /\/\*([\s\S]*?)\*\//g;
var urlsRegexp = /((?:@import\s+)?url\s*\(['"]?)(\S*?)(['"]?\s*\))|(@import\s+['"]?)([^;'"]+)/ig;

function isEmbedded (src) {
	return embeddedRegexp.test(src);
}

function getUrls (text) {
	var urls = [];
	var urlMatch, url;

	text = text.replace(commentRegexp, '');

	while (urlMatch = urlsRegexp.exec(text)) {
		// Match 2 group if '[@import] url(path)', match 5 group if '@import path'
		url = urlMatch[2] || urlMatch[5];

		if (url && !isEmbedded(url) && urls.indexOf(url) === -1) {
			urls.push(url);
		}
	}

	return urls;
}

module.exports = getUrls;
<|endoftext|>


<commit_before>/**
 * The mongodb module implements all of the operations needed to interface our cms with mongo.
 * @param config Database configuration values.
 * @returns {{}}
 */
module.exports = function initMongo(config){
    "use strict";

    var LOGGING_CATEGORY = 'MONGO-DRIVER',
        client = require('mongodb').MongoClient,
        db = {},
        internal = {};

    internal.config = config;

    function log(data) {
        internal.app.log.info(LOGGING_CATEGORY, data);
    }

    /**
     * The public init method binds the application to the db object.
     * @param app App object with references to our db, logging and caching modules.
     */
    db.init = function(app, callback){
        internal.app = app;

        var conf = {
            "url" : config.host.replace('{dbuser}', config.username).replace('{dbpassword}', config.password),
            "client" : client,
            "log" : internal.app.log
        };

        db.users = require('./mongodb/users')(conf);
        db.contentTypes = require('./mongodb/contentTypes')(conf);

        if(callback){
            //This is required to be async for the event emmitter to work properly
            setTimeout(function(){
                //The 2nd parameter is always here for errors.
                callback.call(this, null);
            },0);
        }
    };

    return db;
};

<commit_msg>Added tokens to db manifest.<commit_after>/**
 * The mongodb module implements all of the operations needed to interface our cms with mongo.
 * @param config Database configuration values.
 * @returns {{}}
 */
module.exports = function initMongo(config){
    "use strict";

    var LOGGING_CATEGORY = 'MONGO-DRIVER',
        client = require('mongodb').MongoClient,
        db = {},
        internal = {};

    internal.config = config;

    function log(data) {
        internal.app.log.info(LOGGING_CATEGORY, data);
    }

    /**
     * The public init method binds the application to the db object.
     * @param app App object with references to our db, logging and caching modules.
     */
    db.init = function(app, callback){
        internal.app = app;

        var conf = {
            "url" : config.host.replace('{dbuser}', config.username).replace('{dbpassword}', config.password),
            "client" : client,
            "log" : internal.app.log
        };

        db.tokens = require('./mongodb/tokens')(conf);
        db.users = require('./mongodb/users')(conf);
        db.contentTypes = require('./mongodb/contentTypes')(conf);

        if(callback){
            //This is required to be async for the event emmitter to work properly
            setTimeout(function(){
                //The 2nd parameter is always here for errors.
                callback.call(this, null);
            },0);
        }
    };

    return db;
};

<|endoftext|>


<commit_before>'use strict';

/**
 * Deploy a software package.
 * (C) 2013 Alex Fernández.
 */

// requires
var childProcess = require('child_process');
var util = require('util');
var async = require('async');
var testing = require('testing');
var Log = require('log');

// globals
var log = new Log('info');
var originalLog = log;

// constants
var DEFAULT_TIMEOUT_SECONDS = 10;

/**
 * A deployment of a software package, using the same options as exports.run().
 */
var Deployment = function(options, log)
{
	// self-reference
	var self = this;

	// init
	if (options.quiet)
	{
		log.level = 'notice';
	}
	if (!options.testDirectory && !options.directory)
	{
		log.warning('No directories given; no deployment done');
	}

	/**
	 * Run the deployment.
	 */
	self.run = function(callback)
	{
		var tasks = [];
		if (options.testDirectory)
		{
			tasks.push(self.updateTestDirectory);
			tasks.push(self.runTests);
		}
		if (options.directory)
		{
			tasks.push(self.updateDeploymentDirectory);
		}
		if (options.deploymentCommand)
		{
			tasks.push(self.runDeploymentCommand);
		}
		async.waterfall(tasks, callback);
	};

	/**
	 * Update the test directory.
	 */
	self.updateTestDirectory = function(callback)
	{
		update(options.testDirectory, callback);
	};

	/**
	 * Run package tests.
	 */
	self.runTests = function(callback)
	{
		execIn('npm test', options.testDirectory, callback);
	};

	/**
	 * Update the deployment directory.
	 */
	self.updateDeploymentDirectory = function(callback)
	{
		update(options.directory, callback);
	};

	/**
	 * run a deployment command, if configured.
	 */
	self.runDeploymentCommand = function(callback)
	{
		var directory = options.directory || process.cwd();
		execIn(options.deploymentCommand, directory, callback);
	};

	/**
	 * Update the given directory.
	 */
	function update(directory, callback)
	{
		log.info('Updating %s', directory);
		execIn('git pull', directory, function(error)
		{
			if (error)
			{
				return callback(error);
			}
			execIn('npm install', directory, callback);
		});
	}

	/**
	 * Exec a command in the given directory.
	 */
	function execIn(command, directory, callback)
	{
		var params = {
			cwd: directory,
			timeout: 1000 * (options.timeout || DEFAULT_TIMEOUT_SECONDS),
		};
		childProcess.exec(command, params, function(error, stdout, stderr)
		{
			if (error)
			{
				return callback(command + ': ' + stdout + '\n' + error + ', ' + stderr);
			}
			log.info(command + ': ' + stdout);
			if (stderr)
			{
				log.error(command + ': ' + stderr);
			}
			callback(null);
		});
	}
};

/**
 * Run a test deployment.
 */
function testDeployment(callback)
{
	var options = {
		directory: '.',
		testDirectory: '.',
		deploymentCommand: 'ls .',
	};
	var deployment = new Deployment(options, new Log('error'));
	var tasks = [
		deployment.updateTestDirectory,
		deployment.updateDeploymentDirectory,
		deployment.runDeploymentCommand,
	];
	async.waterfall(tasks, callback);
}

/**
 * Run a deployment. Options has these attributes:
 *	- directory: the directory where the package currently resides.
 *	- testDirectory: the directory where the test version of the package resides.
 *	- deploymentCommand: a command to run after a successful deployment,
 *	e.g. "sudo restart myService".
 *	- packageName: the name of the package to show in logs.
 *	- timeout: seconds to wait for all comands, default 10 seconds.
 * An optional log object is used to send messages.
 * An optional callback will be called after the deployment finishes.
 */
exports.run = function(options, log, callback)
{
	if (typeof log == 'function')
	{
		callback = log;
		log = null;
	}
	if (!log)
	{
		log = originalLog;
	}
	var start = Date.now();
	if (options.packageName)
	{
		log.notice('Starting deployment for %s', options.packageName);
	}
	var deployment = new Deployment(options, log);
	deployment.run(function(error)
	{
		var message;
		var elapsed = Math.round((Date.now() - start) / 10) / 100;
		if (error)
		{
			log.error(error);
			message = util.format('Error running deployment after %s seconds; finishing', elapsed);
			if (callback)
			{
				return callback(message);
			}
			log.error(message);
			return;
		}
		message = util.format('Deployment success! in %s seconds', elapsed);
		if (callback)
		{
			return callback(null, message);
		}
		log.notice(message);
	});
};

/**
 * Run all tests.
 */
exports.test = function(callback)
{
	testing.run({
		run: testDeployment,
	}, 10000, callback);
};

// start if invoked directly
if (__filename == process.argv[1])
{
	exports.test(testing.show);
}

<commit_msg>Increased default seconds to 60.<commit_after>'use strict';

/**
 * Deploy a software package.
 * (C) 2013 Alex Fernández.
 */

// requires
var childProcess = require('child_process');
var util = require('util');
var async = require('async');
var testing = require('testing');
var Log = require('log');

// globals
var log = new Log('info');
var originalLog = log;

// constants
var DEFAULT_TIMEOUT_SECONDS = 60;

/**
 * A deployment of a software package, using the same options as exports.run().
 */
var Deployment = function(options, log)
{
	// self-reference
	var self = this;

	// init
	if (options.quiet)
	{
		log.level = 'notice';
	}
	if (!options.testDirectory && !options.directory)
	{
		log.warning('No directories given; no deployment done');
	}

	/**
	 * Run the deployment.
	 */
	self.run = function(callback)
	{
		var tasks = [];
		if (options.testDirectory)
		{
			tasks.push(self.updateTestDirectory);
			tasks.push(self.runTests);
		}
		if (options.directory)
		{
			tasks.push(self.updateDeploymentDirectory);
		}
		if (options.deploymentCommand)
		{
			tasks.push(self.runDeploymentCommand);
		}
		async.waterfall(tasks, callback);
	};

	/**
	 * Update the test directory.
	 */
	self.updateTestDirectory = function(callback)
	{
		update(options.testDirectory, callback);
	};

	/**
	 * Run package tests.
	 */
	self.runTests = function(callback)
	{
		execIn('npm test', options.testDirectory, callback);
	};

	/**
	 * Update the deployment directory.
	 */
	self.updateDeploymentDirectory = function(callback)
	{
		update(options.directory, callback);
	};

	/**
	 * run a deployment command, if configured.
	 */
	self.runDeploymentCommand = function(callback)
	{
		var directory = options.directory || process.cwd();
		execIn(options.deploymentCommand, directory, callback);
	};

	/**
	 * Update the given directory.
	 */
	function update(directory, callback)
	{
		log.info('Updating %s', directory);
		execIn('git pull', directory, function(error)
		{
			if (error)
			{
				return callback(error);
			}
			execIn('npm install', directory, callback);
		});
	}

	/**
	 * Exec a command in the given directory.
	 */
	function execIn(command, directory, callback)
	{
		var params = {
			cwd: directory,
			timeout: 1000 * (options.timeout || DEFAULT_TIMEOUT_SECONDS),
		};
		childProcess.exec(command, params, function(error, stdout, stderr)
		{
			if (error)
			{
				return callback(command + ': ' + stdout + '\n' + error + ', ' + stderr);
			}
			log.info(command + ': ' + stdout);
			if (stderr)
			{
				log.error(command + ': ' + stderr);
			}
			callback(null);
		});
	}
};

/**
 * Run a test deployment.
 */
function testDeployment(callback)
{
	var options = {
		directory: '.',
		testDirectory: '.',
		deploymentCommand: 'ls .',
	};
	var deployment = new Deployment(options, new Log('error'));
	var tasks = [
		deployment.updateTestDirectory,
		deployment.updateDeploymentDirectory,
		deployment.runDeploymentCommand,
	];
	async.waterfall(tasks, callback);
}

/**
 * Run a deployment. Options has these attributes:
 *	- directory: the directory where the package currently resides.
 *	- testDirectory: the directory where the test version of the package resides.
 *	- deploymentCommand: a command to run after a successful deployment,
 *	e.g. "sudo restart myService".
 *	- packageName: the name of the package to show in logs.
 *	- timeout: seconds to wait for all comands, default 10 seconds.
 * An optional log object is used to send messages.
 * An optional callback will be called after the deployment finishes.
 */
exports.run = function(options, log, callback)
{
	if (typeof log == 'function')
	{
		callback = log;
		log = null;
	}
	if (!log)
	{
		log = originalLog;
	}
	var start = Date.now();
	if (options.packageName)
	{
		log.notice('Starting deployment for %s', options.packageName);
	}
	var deployment = new Deployment(options, log);
	deployment.run(function(error)
	{
		var message;
		var elapsed = Math.round((Date.now() - start) / 10) / 100;
		if (error)
		{
			log.error(error);
			message = util.format('Error running deployment after %s seconds; finishing', elapsed);
			if (callback)
			{
				return callback(message);
			}
			log.error(message);
			return;
		}
		message = util.format('Deployment success! in %s seconds', elapsed);
		if (callback)
		{
			return callback(null, message);
		}
		log.notice(message);
	});
};

/**
 * Run all tests.
 */
exports.test = function(callback)
{
	testing.run({
		run: testDeployment,
	}, 10000, callback);
};

// start if invoked directly
if (__filename == process.argv[1])
{
	exports.test(testing.show);
}

<|endoftext|>