Modulapp
Modular application framework for node.js
Overview
Modulapp is a framework for defining application in a modular way.
It provides an App
class and a Module
class.
Module concept
Basically a module is an autonomous part of the application. It could be a npm package or it could be a dedicated file in the app's repository. A module can have dependencies (ie. other modules) and can also provides its own API to other dependants.
A module is an instance of the Module
class (which extends EventEmitter). You can add any property and functions to that instance.
Modulapp allows to define hooks for a module. The lifecycle of a module has 4 steps: setup
, enable
, disable
and destroy
. A specific behavior of the module can be defined during those 4 steps. It's during those hooks that dependencies and options are injected to the module.
The App
instance is managing the lifecycle of all modules and dealing with the dependencies and options.
App concept
The App manages the dependencies and the lifecycle of the modules.
An app is an instance of the App
class (which extends EventEmitter). The modules must be declared to the app. Then the lifecycle of the app can be performed. The app's lifecycle is composed of 5 steps:
resolve
: Checks the modules and resolve the dependency treesetup
: Synchronously execute thesetup
hook of every module following the dependency tree orderstart
: Synchronously execute theenable
hook of every module following the dependency tree orderstop
: Synchronously execute thedisable
hook of every module following the dependency tree reverse orderdestroy
: Synchronously execute thedestroy
hook of every module following the dependency tree reverse order
As the modules are processed synchronously following the dependency tree, the dependencies of a particular module have already been processed before it.
Usage
Install from npm
npm install modulapp
To write a module, import the Module
class.
const Module = Module;
To write an app, import the App
class.
const App = App;
Example
Module class
// myModule.jsconst Module = Module;let myModule = "myModule"; // define the dependencies by referencing other modulapp modules' idmyModuledependencies = 'server' 'db'; // custom propertymyModulefoo = 'foo'; // custom functionmyModule { myModule; // Module extends EventEmitter}; // overwrite the setup hookmyModule { console; ; // executing the done callback is required}; // overwrite the enable hookmyModule { console; let db = importsdb; db; let server = importsserver server;}; // myModule.disable can also be overwritten// myModule.destroy can also be overwritten moduleexports = myModule;
App class
// app.jsconst App = App;let app = ; // Get the moduleslet server = ;let db = ;let myModule = ; // set the configurationapp; // start the application// start() will itself execute resolve() and setup() if not doneappstart { if err console; else console; }; someListener;
API References
Classes
EventEmitter
App ⇐ Class representing an App.
Kind: global class
Extends: EventEmitter
Emits: resolving
, resolved
, setting_up
, setup
, starting
, started
, stopping
, stopped
, destroying
, destroyed
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
- App ⇐
EventEmitter
- new App([config], [options])
- instance
- .id :
String
- .config :
Array.<Module>
- .options :
Object
- .status :
String
- .addOptions([options])
- .addConfig([...config])
- events
- lifecycle management
- .id :
- static
new App([config], [options])
Provide a new instance of App. The config and options are optionnal.
Throws:
Error
ERR_APP_011 if options is not an Object.Error
ERR_APP_013 if a module is not a Module instance.
Param | Type | Default | Description |
---|---|---|---|
[config] | Module | Array.<Module> |
[] |
The list of modules. |
[options] | Object |
{} |
Options for the modules. |
Example
const App = App;let app = ; let serverModule = ;let dbModule = ; app; appstart { console;};
String
app.id : The id of the app, randomly generated.
Kind: instance property of App
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
console; // -> '123456789'appid = 'anotherId'; // -> throw Error read-only
Array.<Module>
app.config : The configuration of the app. Getting config never return null, at least an empty Array []. Setting null or undefined replaces the current config by an empty Array []. Setting a module will build an Array with that single module.
Kind: instance property of App
Throws:
Error
ERR_APP_013 if a module is not a Module instance.Error
ERR_APP_014 if the module is not in created status.
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Default | Description |
---|---|---|---|
[newConfig] | Module | Array.<Module> |
[] |
The new config. |
Example
console; // -> [loggerModule]appconfig = serverModule dbModule; // -> [serverModule, dbModule]appconfig = null; // -> []appconfig = serverModule; // -> [serverModule]
Object
app.options : The options of the app's modules. Read-write property. Getting options never return null, at least an empty Object {}. Setting null or undefined replaces the current options by an empty Object {}.
Kind: instance property of App
Throws:
Error
ERR_APP_009 if the app is not in created status.Error
ERR_APP_008 if not an Object
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Default | Description |
---|---|---|---|
[newOptions] | Object |
{} |
The new options. |
Example
console; // -> {server: {port: 8080}}appoptions = server: host: 'localhost'; // -> {server: {host: 'localhost'}}appoptions = null; // -> {}
String
app.status : The status of the module. The value is part of the supported status.
Kind: instance property of App
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
console; // -> 'created'appstatus = AppstatusRESOLVED; // -> throw Error read-only
app.addOptions([options])
Add options to the app's modules. Merge with existing options.
Kind: instance method of App
Throws:
Error
ERR_APP_008 if the options parameter is not an Object.
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Default | Description |
---|---|---|---|
[options] | Object |
{} |
The options to add. |
Example
console; // -> {server: {port: 8080}}app; // -> {server: {port: 8080, host: 'localhost'}}app; // -> {server: {port: 8080, host: 'localhost'}}app; // -> {server: {port: 8080, host: 'localhost'}}app; // -> {server: {port: 8080, host: 'localhost'}, db: {host: '127.0.0.0'}}
app.addConfig([...config])
Add modules to the app's configuration. Merge with existing config and check the new modules and remove duplicates and null.
Kind: instance method of App
Throws:
Error
ERR_APP_013 if a module is not a Module instance.
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
[...config] | Module | Array.<Module> |
The modules to add. |
Example
console; // -> [loggerModule]app; // -> [loggerModule, serverModule]app; // -> [loggerModule, serverModule]app; // -> [loggerModule, serverModule]app; // -> [loggerModule, serverModule, socketModule]app; // -> [loggerModule, serverModule, socketModule, utilsModule, dbModule]
"resolving"
Resolving event. When the app is about to be resolved.
Kind: event emitted by App
Category: events
Since: 1.0.0
"resolved"
Resolved event. When the app has been resolved.
Kind: event emitted by App
Category: events
Since: 1.0.0
"setting_up"
Setting up event. When the app is about to be setup.
Kind: event emitted by App
Category: events
Since: 1.0.0
"setup"
Setup event. When the app has been setup.
Kind: event emitted by App
Category: events
Since: 1.0.0
"starting"
Starting event. When the app is about to be started.
Kind: event emitted by App
Category: events
Since: 1.0.0
"started"
Started event. When the app has been started.
Kind: event emitted by App
Category: events
Since: 1.0.0
"stopping"
Stopping event. When the app is about to be stopped.
Kind: event emitted by App
Category: events
Since: 1.0.0
"stopped"
Stopped event. When the app has been stopped.
Kind: event emitted by App
Category: events
Since: 1.0.0
"destroying"
Destroying event. When the app is about to be destroyed.
Kind: event emitted by App
Category: events
Since: 1.0.0
"destroyed"
Destroyed event. When the app has been destroyed.
Kind: event emitted by App
Category: events
Since: 1.0.0
app.resolve([callback])
Resolve the dependencies of the modules. This method is synchronous, callback is not required.
Kind: instance method of App
Category: lifecycle management
Throws:
Error
ERR_APP_001 if the app is startedError
ERR_APP_006 in case of dependency cycleError
ERR_APP_007 in case of missing module
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
[callback] | function |
The callback executed after resolving. Raised error is passed as first argument, no other argument: callback(err) |
Example
const App = App; let serverModule = ;let dbModule = ; let app = serverModule dbModule; app;
Example (resolve with callback)
app;
Example (resolve with no callback)
try app; catch err console; // -> in case of error in resolve, the error is thrown
app.setup([callback])
Setup every modules following the dependency graph.
Kind: instance method of App
Category: lifecycle management
Access: public
See: Module#setup
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
[callback] | function |
The callback executed after setting up. Raised error is passed as first argument, no other argument: callback(err) |
Example
const App = App; let serverModule = ;let dbModule = ; let app = serverModule dbModule; app;// setup() will resolve() itself if not done before
app.start([callback])
Enable every modules following the dependency graph.
Kind: instance method of App
Category: lifecycle management
Access: public
See: Module#enable
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
[callback] | function |
The callback executed after starting. Raised error is passed as first argument, no other argument: callback(err) |
Example
const App = App; let serverModule = ;let dbModule = ; let app = serverModule dbModule; appstart { console;};// start() will setup() and resolve() itself if not done before
app.stop([callback])
Disable every modules following the dependency graph.
Kind: instance method of App
Category: lifecycle management
Access: public
See: Module#disable
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
[callback] | function |
The callback executed after stopping. Raised error is passed as first argument, no other argument: callback(err) |
Example
const App = App; let serverModule = ;let dbModule = ; let app = serverModule dbModule; appstart { console; // Do some stuff app;};// app has to be started to be stopped
app.destroy([callback])
Destroy every modules following the dependency graph.
Kind: instance method of App
Category: lifecycle management
Access: public
See: Module#destroy
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
[callback] | function |
The callback executed after destroying. Raised error is passed as first argument, no other argument: callback(err) |
Example
const App = App; let serverModule = ;let dbModule = ; let app = serverModule dbModule; appstart { console; // Do some stuff app;};// app has to be stopped to be destroyed
enum
App.events : All supported events of App class.
RESOLVING: 'resolving' RESOLVED: 'resolved' SETTING_UP: 'setting_up' SETUP: 'setup' STARTING: 'starting' STARTED: 'started' STOPPING: 'stopping' STOPPED: 'stopped' DESTROYING: 'destroying' DESTROYED: 'destroyed'
Kind: static enum of App
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
app;
enum
App.status : All supported status of App class.
Don't confuse this static method App.status with the instance method status.
CREATED: 'created' RESOLVED: 'resolved' SETUP: 'setup' STARTED: 'started' STOPPED: 'stopped'
Kind: static enum of App
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
if appstatus === AppstatusENABLED app;
EventEmitter
Module ⇐ Class representing a Module.
Kind: global class
Extends: EventEmitter
Emits: setting_up
, setup
, enabling
, enabled
, disabling
, disabled
, destroying
, destroyed
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
- Module ⇐
EventEmitter
- new Module(id, [initialOptions])
- instance
- .id :
String
- .status :
String
- .version :
String
- .options :
Object
- .dependencies :
Array.<String>
- .addOptions([options])
- .addDependencies([...dependencies])
- events
- lifecycle hooks
- .id :
- static
new Module(id, [initialOptions])
Create a new instance of Module. The id parameter is required, it could be either a String or an Object representing the package.json.
In case of the package.json is provided, the id, version, dependencies and options will be extracted from this Object.
Throws:
Error
ERR_MOD_001 if the id parameter is null or undefinedError
ERR_MOD_005 if something wrong on the dependency
Param | Type | Default | Description |
---|---|---|---|
id | String | Object |
Either a String id of the module or an Object representing the package.json | |
[initialOptions] | Object |
{} |
Options for the module |
Example
const Module = Module;let myModule = 'myModule'; myModulefoo = 'foo';myModule { // this is a custom method}; myModule { // this is overriding the setup method let logger = importslogger; logger; ;}; moduleexports = myModule;
Example (constructor with a String argument)
const Module = Module;let myModule = 'myModule';console; // -> 'myModule'console; // -> 'created'console; // -> undefinedconsole; // -> {}console; // -> []
Example (constructor with a Object argument)
const packagejson = ;// {// name: 'myModule',// version: '1.0.0',// module: {// dependencies: ['logger'],// options: {// port: 8080// }// }// } const Module = Module;let myModule = 'myModule';console; // -> 'myModule'console; // ->'created'console; // -> '1.0.0'console; // -> {port: 8080}console; // -> ['logger']
String
module.id : The id of the module.
Kind: instance property of Module
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
console; // -> 'myModule'myModuleid = 'anotherId'; // -> throw Error read-only
String
module.status : The status of the module. The value is part of the supported status.
Kind: instance property of Module
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
console; // -> 'created'myModulestatus = ModulestatusSETUP; // -> throw Error read-only
String
module.version : The version of the module.
Kind: instance property of Module
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
console; // -> '1.0.0'myModuleversion = '1.0.1'; // -> throw Error read-only
Object
module.options : The options of the module. Getting options never return null, at least an empty Object {}. Setting null or undefined replaces the current options by an empty Object {}.
Kind: instance property of Module
Throws:
Error
ERR_MOD_002 if the module is not in created statusError
ERR_MOD_004 if not an Object
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Default | Description |
---|---|---|---|
[newOptions] | Object |
{} |
The new options |
Example
console; // -> {port: 8080}myModuleoptions = host: 'localhost'; // -> {host: 'localhost'}myModuleoptions = null; // -> {}
Array.<String>
module.dependencies : The dependencies of the module. Getting dependencies never return null, at least an empty Array []. Setting null or undefined replaces the current config by an empty Array []. Setting a String will build an Array with that single String.
Kind: instance property of Module
Throws:
Error
ERR_MOD_003 if the module is not in created statusError
ERR_MOD_005 if a non-String dependency is found
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Default | Description |
---|---|---|---|
[newDependencies] | String | Array.<String> |
[] |
The new dependencies |
Example
console; // -> ['logger']myModuledependencies = 'server' 'db'; // -> ['server', 'db']myModuledependencies = null; // -> []myModuledependencies = 'server'; // -> ['server']
module.addOptions([options])
Add options to the module. Merge with existing options.
Kind: instance method of Module
Throws:
Error
ERR_MOD_004 if the options parameter is not an Object
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Default | Description |
---|---|---|---|
[options] | Object |
{} |
The options to add |
Example
console; // -> {port: 8080}myModule; // -> {port: 8080, host: 'localhost'}myModule; // -> {port: 8080, host: 'localhost'}myModule; // -> {port: 8080, host: 'localhost'}
module.addDependencies([...dependencies])
Add dependencies to the module. Merge with existing dependencies and check the new dependencies, flatten the Array and remove duplicates and null.
Kind: instance method of Module
Throws:
Error
ERR_MOD_005 if a non-String dependency is found
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
[...dependencies] | String | Array.<String> |
The dependencies to add |
Example
console; // -> ['logger']myModule; // -> ['logger', 'server']myModule; // -> ['logger', 'server']myModule; // -> ['logger', 'server']myModule; // -> ['logger', 'server', 'socket']myModule; // -> ['logger', 'server', 'socket', 'utils', 'db']
"setting_up"
Setting up event. When the module is beginning its setup.
Kind: event emitted by Module
Category: events
"setup"
Setup event. When the module has been setup.
Kind: event emitted by Module
Category: events
"enabling"
Enabling event. When the module is about to be enabled.
Kind: event emitted by Module
Category: events
"enabled"
Enabled event. When the module has been enabled.
Kind: event emitted by Module
Category: events
"disabling"
Disabling event. When the module is about to be disabled.
Kind: event emitted by Module
Category: events
"disabled"
Disabled event. When the module has been disabled.
Kind: event emitted by Module
Category: events
"destroying"
Destroying event. When the module is about to be destroyed.
Kind: event emitted by Module
Category: events
"destroyed"
Destroyed event. When the module has been destroyed.
Kind: event emitted by Module
Category: events
module.setup(app, options, imports, done)
The setup function of the module. Executed while the app is being setup. Could be overriden, does nothing by default. Once the app is resolved, this method is not available anymore.
Kind: instance method of Module
Category: lifecycle hooks
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
app | App |
The App instance |
options | Object |
The options of the module |
imports | Object |
The dependencies of the module |
done | function |
Callback to return passing any error as first argument done(err) |
Example
const Module = Module;let myModule = 'myModule'; // override the default setup functionmyModule { // place your custom code to be executed when myModule is setup}
module.enable(app, options, imports, done)
The enable function of the module. Executed while the app is being started. Could be overriden, does nothing by default. Once the app is resolved, this method is not available anymore.
Kind: instance method of Module
Category: lifecycle hooks
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
app | App |
The App instance |
options | Object |
The options of the module |
imports | Object |
The dependencies of the module |
done | function |
Callback to return passing any error as first argument done(err) |
Example
const Module = Module;let myModule = 'myModule'; // override the default enable functionmyModule { // place your custom code to be executed when myModule is enable}
module.disable(app, options, imports, done)
The disable function of the module. Executed while the app is being stopped. Could be overriden, does nothing by default. Once the app is resolved, this method is not available anymore.
Kind: instance method of Module
Category: lifecycle hooks
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
app | App |
The App instance |
options | Object |
The options of the module |
imports | Object |
The dependencies of the module |
done | function |
Callback to return passing any error as first argument done(err) |
Example
const Module = Module;let myModule = 'myModule'; // override the default disable functionmyModule { // place your custom code to be executed when myModule is disabled}
module.destroy(app, options, imports, done)
The destroy function of the module. Executed while the app is being destroyed. Could be overriden, does nothing by default. Once the app is resolved, this method is not available anymore.
Kind: instance method of Module
Category: lifecycle hooks
Access: public
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Param | Type | Description |
---|---|---|
app | App |
The App instance |
options | Object |
The options of the module |
imports | Object |
The dependencies of the module |
done | function |
Callback to return passing any error as first argument done(err) |
Example
const Module = Module;let myModule = 'myModule'; // override the default destroy functionmyModule { // place your custom code to be executed when myModule is destroyed}
enum
Module.events : All supported events of Module class.
SETTING_UP: 'setting_up' SETUP: 'setup' ENABLING: 'enabling' ENABLED: 'enabled' DISABLING: 'disabling' DISABLED: 'disabled' DESTROYING: 'destroying' DESTROYED: 'destroyed'
Kind: static enum of Module
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
myModule;
enum
Module.status : All supported status of Module class.
Don't confuse this static method Module.status with the instance method status.
CREATED: 'created' SETUP: 'setup' ENABLED: 'enabled' DISABLED: 'disabled' DESTROYED: 'destroyed'
Kind: static enum of Module
Access: public
Read only: true
Since: 1.0.0
Author: nauwep nauwep.dev@gmail.com
Example
if myModulestatus === ModulestatusENABLED myModule;