1.0.2 • Published 8 years ago

moduli v1.0.2

Weekly downloads
3
License
MIT
Repository
github
Last release
8 years ago

moduli

As your Node.js project gets larger, you will face some dependency issues: Where to initiate required modules/components, how to exports those modules in order to use them correctly or dealing with stubs within your tests. In Java for example, you got frameworks like Spring for handling the issues mentioned above.

Your project modules will look like this:

function MessageService($db, $utils, $logger, $userService) {
    this.db = $db;
    //...
}

MessageService.prototype.getAllMessages = function () {
    return this.db.messages.find();  
};

// ...

module.exports = MessageService;

As you can see it cleans your code - zero lines for require/resolve/initiate dependencies

Usage

First, install via npm:

  • npm: npm install moduli --save

You can find an example in this repo under example/ Besides configurations, this is the only code you will need to run your app:

  var moduli = require('moduli');
  // initialize moduli with configuration file (or object..)
  moduli.initInjector(__dirname, "/modules.json")
    .then(function () {
      // initialize base dependencies
      moduli.init("db", ["dummy-connection-string"]);
      //...
      // trigger app initialization
      moduli.init("app");
    });

Configure Modules

Project modules config has the following structure

{
 "mode": "string" // "strict" (default) | "tolerant" - if mode is strict, moduli will throw exceptions if you are trying to have a circular reference 
 "groups": {
   "GROUP_NAME": {
     "dir": "string", // optional - dir of the desired group from the root of the project (your package.json)
     "ignore": ["/IgnoredModule.js"], // optional - modules/directories to ignore within current group
     "postfix": "string", // optional - postfix for all child modules
     "prefix": "string", // optional - prefix for all child modules
     "alias": { // optional - modules renaming
       "REAL_MODULE_NAME": "DESIRED_MODULE_NAME"
     },
     "data": { // REQUIRED - module configurations to apply on all group modules
       "type": "class",
       "initiate": "multiple"
     },
     "extends": ["string"] // optional - array of groups to inherit from (only 'data' property)
   }
   // other groups 
 },
 "modules": {
   "MODULE_NAME": {
     "module": "string", // REQUIRED - path to the module from the root of the project (your package.json)
     "type": "string", // optional - "object" (default) | "function" | "class"
     "postConstructor": "string", // optional - an init method to call after require & instantiation 
     "initiate": "string", // optional - "singleton" (default) | "multiple" - if multiple, each time moduli.get() is called - a new instance will be created. relevant only for 'class'
     "injections": { // optional - injections can be defined by adding '$' before param name 
       "ARG_NAME": "MODULE_NAME"
       // other injections..
     },
     "extends": ["string"] // optional - array of groups to inherit from (only module config - 'data' property in group)
   }
   // other modules...
 },
 "npm": { // optional - use when you want moduli to resolve npm dependencies
   "MODULE_NAME": {
       // custom config for npm module
   }
 },
 "node": { // optional - use when you want moduli to resolve node core modules
     "MODULE_NAME": {
         // custom config for npm module
     }
 }
}

There are several types of configurations:

  • inline

    // your module
    // ... 
    module.export["@moduli"] = {
     // configurations..
    };
  • json file modules.json:

     {
       "mode": ".."
       "modules": {
         // ...
       }
     }

    main.js:

    var moduli = require('moduli');
    // initialize moduli with configuration file (or object..)
    moduli.initInjector(__dirname, "/modules.json");
    //....
  • js object
     var config = {
       "mode": ".."
       "modules": {
         // ...
       }
     }
     moduli.initInjector(__dirname, config);

Note that:

  • all modules names should be defined in the configuration object.
  • specific configurations can be defined inline.
  • inline config will override json/object config.

Dependency Injection

Lets look at the following exmaple, AuthService depeneds on: db, utils and UserService instance. with moduli it can be achived by simply declaring those modules as injections for AuthService:

function AuthService(secret, mydb, utils, userService) {
   // ...
}

// ....
module.exports = AuthService;
// NOTE that this can be written in the config json:
module.export["@moduli"] = {
	injections: {
		"mydb": "db",
		"utils": "utils",
		"userService": "userService"
	}
};

it can be achived also be using '$' before arg name (the arg name without the '$' must match the desired module name):

function AuthService(secret, $db, $utils, $userService) {
   // ...
}

// ....
module.exports = AuthService;

API