# MODULAR Path abstraction and mocks for NodeJS. ## Functionalities * Automatically load javascript modules * Abstract modules path. Access any module using namespace and module name * Easy mock * Live reload of changes ## Quickstart ```javascript var Modular = require('modular.js'); var application = new Modular({ files : './app', liveReload : true, restartOnChanges : true, }).on ('start', function(modular) { modular('main').start(); }).on ('stop', function(modular) { modular('main').stop(); }).on ('log', function (modular, level, message, error) { console.log(error); }).start(); ``` ## Settings The modular constructor accept several settings : ```javascript { /* files can be a string for one file or folder */ files : 'app/module.js', /* or an array to load several files or folders */ files : [ 'app/module.js', 'app/module2.js', 'app/subfolder' ], /* an object allowing to setup the way the modules are loaded */ files : { /* the path is either a string for one file or folder */ path : 'app/module.js', /* or an array */ path : [ 'app/module.js', 'app/module2.js', 'app/subfolder' ] override : true, /* modules override already loaded modules in case of collision default value : false */ namespace : 'namespace', /* specify the namespace of the module */ baseNamespace : 'base', /* base namespace appended to module namespace */ basePath : 'path/path2', /* the base path used to deduce the namespace of modules default value : path value (when path is a directory) */ name : 'name', /* specify the name of the module Only when path is one file. Doesn't work with namespace setting */ liveReload : true, /* enable or disable liveReload on a file/folder basis default value : false */ }, basePath : /* Path used to deduce the namespace default value : path of the file that load Modular */ liveReload : true, /* enable live modification reload for whole application default value : false */ restartOnChange : true, /* automaticaly restart application when a module is reloaded default value : liveReload value */ exclude : ['app/module3.js'], /* those files won't be loaded */ default value : file that load Modular logLevel : 0 /* level of logging. 0 : error, 1 : info, 2 : verbose default value : 0 */ ``` ## Events Modular communicate through messages. Those event aren't asynchronous. This way, modular won't try to start application before it stopped. If start or stop event return a Promise object, modular will wait for the Promise to be fulfilled to continue. ### start Emitted when the application must be started. * Parameter : modular * Return : Promise (optional) ### stop Emitted when the application must be stopped. This event is optional * Parameter : modular * Return : Promise (optional) ### restart Emitted when the application must be restarted. This event is optional If this event is not used, modular will emit the stop event followed by start * Parameter : modular * Return : Promise (optional) ### log Emitted whenever log occurs. This event is optional. If this event is not defined, logs are written on stdout. * Parameter : modular, message, error * Return : nothing ### loadModule Emitted whenever a module will be loaded. This event is optional. You can change the settings used to load the module. * Parameter : modular, settings (module parameters) * Return : false to cancel module loading ## Modules Modular modules must look likes ```javascript 'use strict'; module.exports = function (modular) { var mod = modular('namespace.module'); } ``` Or ```javascript 'use strict'; module.exports.onLoad = function (modular) { var mod = modular('namespace.module'); } ``` Modular will simply call those functions each time the module is required by another. Those function are never invoked using the new statement and are called even if the nodejs module is already cached. This means that each module manage its instance (a module can act as a singleton for example, another can always return a new instance). If the module does not directly exports a function or does not export onLoad function, the module is return as it is, but won't be able to load any modular module. ## Tips ### Exclude your main javascript file Loading the main javascript file with Modular is useless, watching it for changes can lead to weird behavior. If no file is excluded, Modular will exclude its parent by default. You can still load the directory containing your main file by excluding it. The easiest way is to use the node __filename property : ```javascript var Modular = require('modular.js'); var application = new Modular({ files : './', exclude : [ __filename], liveReload : true, restartOnChange : true, }).on ('start', function(modular) { modular('main').start(); }).on ('stop', function(modular) { modular('main').stop(); }).on ('log', function (modular, level, message, err) { if (err) { console.log(err); } }).start(); ``` ###