Source: lib/init.js

/*------------------------------------*\
	$%INIT
\*------------------------------------*/
/* jslint node: true */

/**
 * Represent options passed through API.
 * @private
 * @alias configuration
 * @type {Object}
 * @memberOf NA#
 * @example {
 *     path: <string>,
 *     webconfig: <string>,
 *     browse: <boolean|string>,
 *     httpHostname: <string>,
 *     httpPort: <number>,
 *     generate: <boolean>,
 *     cache: <boolean>,
 *     lang: <string>,
 *     create: <string>,
 *     httpSecure: <boolean|string>
 * }
 */
exports.configuration = {};

/**
 * Represent the function called after all assets generation.
 * @private
 * @alias afterGeneration
 * @type {Object}
 * @memberOf NA#
 */
exports.afterGeneration = null;

/**
 * Represent the function called after create a project.
 * @private
 * @alias afterNewProject
 * @type {Object}
 * @memberOf NA#
 */
exports.afterNewProject = null;

/**
 * Represent the function called after the server was started.
 * @private
 * @alias afterRunning
 * @type {Object}
 * @memberOf NA#
 */
exports.afterRunning = null;

/**
 * Represent the function called after the server was stoped.
 * @private
 * @alias afterClosing
 * @type {Object}
 * @memberOf NA#
 */
exports.afterClosing = null;

/**
 * Set private `NA#configuration`.
 * @public
 * @function init
 * @memberOf NA#
 * @this NA
 * @param {Object} options CLI Parameters as JSON object.
 * @example require('node-atlas')().init({
 *     webconfig: "webconfig.alternatif.json",
 *     httpPort: 7778,
 *     generate: true,
 *     browse: true
 * }).start();
 * @return {Object} The NA instance for chained functions.
 */
exports.init = function (options) {
	var NA = this,
		configuration = options || {};

	NA.configuration = configuration;

	return NA;
};

/**
 * Set private `NA#afterGeneration`.
 * @public
 * @function generated
 * @memberOf NA#
 * @this NA
 * @param {function} callback Instruction to execute after generation of generates.
 * @example require('node-atlas')().generated(function () {
 *     // Update all files on a server...
 *     // or
 *     // Generate a documentation...
 *     // or
 *     // ...
 * }).run({
 *     generate: true
 * });
 * @return {Object} The NA instance for chained functions.
 */
exports.generated = function (callback) {
	var NA = this;

	NA.afterGeneration = callback;

	return NA;
};

/**
 * Set private `NA#afterNewProject`.
 * @public
 * @function created
 * @memberOf NA#
 * @this NA
 * @param {function} callback Instruction to execute after server was started.
 * @example require('node-atlas')().created(function () {
 *     // Run a server...
 *     // or
 *     // ...
 * }).run({
 *     generate: true
 * });
 * @return {Object} The NA instance for chained functions.
 */
exports.created = function (callback) {
	var NA = this;

	NA.afterNewProject = callback;

	return NA;
};

/**
 * Set private `NA#afterClosing`.
 * @public
 * @function stopped
 * @memberOf NA#
 * @this NA
 * @param {function} callback Instruction to execute after server was stopped.
 * @example require('node-atlas')().stopped(function () {
 *     // Re-run server...
 *     // or
 *     // ...
 * }).start();
 * @return {Object} The NA instance for chained functions.
 */
exports.stopped = function (callback) {
	var NA = this;

	NA.afterClosing = callback;

	return NA;
};

/**
 * Set private `NA#afterRunning`.
 * @public
 * @function started
 * @memberOf NA#
 * @this NA
 * @param {function} callback Instruction to execute after started a webserver.
 * @example require('node-atlas')().started(function () {
 *     // Run another server...
 *     // or
 *     // ...
 * }).run({
 *     generate: true
 * });
 * @return {Object} The NA instance for chained functions.
 */
exports.started = function (callback) {
	var NA = this;

	NA.afterRunning = callback;

	return NA;
};

/**
 * Change the default language used by NodeAtlas CLI and keep it.
 * @private
 * @function changeLanguage
 * @memberOf NA#
 * @this NA
 * @param {NA~callback} next Called in all cases.
 */
exports.changeLanguage = function (next) {
	var NA = this,
		fs = NA.modules.fs,
		path = NA.modules.path,
		source = path.join(__dirname, "..", "languages", NA.configuration.lang + ".json"),
		dest = path.join(__dirname, "..", "languages", NA.cliLanguage + ".json");

	if (NA.configuration.lang) {
		fs.readFile(source, "utf-8", function (error, file) {
			var errorMessages = {
				language: NA.configuration.lang
			};

			if (error) {
				NA.log(NA.cliLabels.languageNotFound.replace(/%([\-a-zA-Z0-9_]+)%/g, function (regex, matches) { return errorMessages[matches]; }));
				return next();
			}

			fs.writeFile(dest, file, function (error) {
				if (error) {
					errorMessages.language = "default";
					NA.log(NA.cliLabels.languageNotFound.replace(/%([\-a-zA-Z0-9_]+)%/g, function (regex, matches) { return errorMessages[matches]; }));
					return next();
				}

				NA.cliLabels = JSON.parse(file);

				NA.log(NA.cliLabels.languageChanged);
				next();
			});
		});
	} else {

		/**
		 * Continue after synchronous/asynchronous operations done.
		 * @callback NA~callback
		 */
		next();
	}
};

/**
 * Catch exit / SIGINT / uncaughtException at the end of program.
 * @private
 * @function exit
 * @memberOf NA#
 * @this NA
 */
exports.exit = function () {
	var NA = this,
		limit,
		separator = "",
		i,
		data = {
			httpPort: NA.webconfig.httpPort
		},
		message = NA.cliLabels.closing.replace(/%([\-a-zA-Z0-9_]+)%/g, function (regex, matches) { return data[matches]; });

	process.stdin.resume();

	process.on('cleanup', function () {
		if (NA.afterClosing) {
			NA.afterClosing.call(NA);
		}
	});

	process.on('exit', function () {
		process.emit('cleanup');
	});

	process.on('SIGINT', function () {
		limit = message.length + 2;
		for (i = 0; i < limit; i++) {
			separator += "=";
		}
		NA.log("");
		NA.log("\u001B[32m", separator);
		NA.log(" " + message);
		NA.log("\u001B[32m", " Ctrl + C");
		NA.log("\u001B[32m", separator);
		NA.log("");
		process.exit(2);
	});

	process.on('uncaughtException', function (error) {
		limit = NA.cliLabels.uncaughtException.length + 2;
		for (i = 0; i < limit; i++) {
			separator += "=";
		}
		NA.log("");
		NA.log("\u001B[32m", separator);
		NA.log(" " + NA.cliLabels.uncaughtException);
		NA.log("\u001B[31m", " " + error.stack);
		NA.log("\u001B[32m", separator);
		NA.log("");

		process.exit(99);
	});
};

/**
 * Initialize a NA instance.
 * @public
 * @function start
 * @memberOf NA#
 * @this NA
 * @example require('node-atlas')().start();
 * @return {Object} The NA instance for chained functions.
 */
exports.start = function () {
	var NA = this;

	NA.initNodeModules();
	NA.initRequiredVars();
	NA.initNpmModules();
	NA.initCliConfiguration();
	NA.initRequiredNpmModulesVars();
	NA.changeLanguage(function () {
		NA.createTemplateProject(function () {
			NA.initWebsite(function () {
				NA.exit();
				NA.initServerModules();
				NA.nodeAtlasWebServer(function () {
					NA.initStatics();
					NA.initRoutes();
				}, function () {
					NA.initOutputs();
				});
			});
		});
	});

	return NA;
};

/**
 * Close the NA  this NA instance.
 * @public
 * @function close
 * @memberOf NA#
 * @this NA
 * @example require('node-atlas')().close();
 * @return {Object} The NA instance for chained functions.
 */
exports.close = function () {
	var NA = this,
		limit,
		separator = "",
		i,
		data = {
			httpPort: NA.webconfig.httpPort
		},
		message = NA.cliLabels.closing.replace(/%([\-a-zA-Z0-9_]+)%/g, function (regex, matches) { return data[matches]; });

	limit = message.length + 2;
	for (i = 0; i < limit; i++) {
		separator += "=";
	}

	NA.log("");
	NA.log("\u001B[32m", separator);
	NA.log(" " + message);
	NA.log("\u001B[32m", " API");
	NA.log("\u001B[32m", separator);
	NA.log("");

	NA.server.close();

	return NA;
};

/**
 * Execute both `NA#init()` and `NA#start()` functions.
 * @public
 * @function run
 * @memberOf NA#
 * @this NA
 * @param {Object} options CLI Parameters as JSON object.
 * @example require('node-atlas').run({
 *        webconfig: "webconfig.alternatif.json",
 *        httpPort: 7778,
 *        generate: true
 * });
 * @return {Object} The NA instance for chained functions.
 */
exports.run = function (options) {
	var NA = this;

	NA.init(options);
	NA.start();

	return NA;
};