{ "name": "sl-module-loader", "description": "sl-module-loader", "version": "0.0.1", "scripts": { "test": "mocha" }, "dependencies": { "debug": "latest", "sl-config-loader": "git+ssh://git@github.com:strongloop/sl-config-loader.git" }, "devDependencies": { "mocha": "latest" }, "readme": "# sl-module-loader\nv0.0.1\n\n## Purpose\n\nThe `sl-module-loader` allows your program to register classes (or types) that are instantiated via configuration files. Configuration files point to an implementation `module` constructor. The `module`'s job is to construct a useful instance with the given configuration options. This allows programs to be free from bootstrapping code and manageable via config.\n\n## Install\n\n slnode install sl-module-loader\n \n## Example\n\nGiven a simple `Dog` module:\n\n function Dog(options) {\n this.options = options;\n }\n \n Dog.prototype.speak = function() {\n console.log('roof', 'my name is', this.options.name);\n }\n \n module.exports = Dog;\n\nAnd a set of `config.json` files:\n\n /my-app\n /fido\n config.json\n /santas-little-helper\n config.json\n /rex\n config.json\n /node_modules\n /dog\n index.js\n package.json\n\nWhere a `config.json` looks like this:\n\n {\n \"module\": \"dog\", // the \"dog\" module\n \"options\": {\n \"name\": \"fido\"\n }\n }\n\nWe can load up all the dogs like so (app.js):\n\n var moduleLoader = require('sl-module-loader').create('my-app');\n\n moduleLoader.load(function (err, modules) {\n if(err) throw err;\n \n moduleLoader\n .instanceOf('dog') // a module in node_modules or declared as a dependency in package.json\n .forEach(function (m) {\n m.speak();\n });\n });\n \nThe above calls a method on all module instances that inherit from `Dog` and outputs:\n\n roof my name is fido\n roof my name is santa's little helper\n roof my name is rex\n\n## Creating Module Classes\n\nThe purpose of a module class is to take meaningful input (configuration, options, dependencies) and create a useful output: a module instance.\n\n### Module Classes\n\nA module class is a `node_module` that exports a constructor inheriting from the `Module` class.\n\n var inherits = require('util').inherits;\n var Module = require('sl-module-loader').Module;\n\n module.exports = Dog;\n\n function Dog(options) {\n this.options = options;\n }\n\n inherits(Dog, Module);\n\n Dog.prototype.speak = function() {\n console.log('roof', 'my name is', this.options.name);\n }\n\nModule classes may define dependency contracts that tell the module loader to provide dependencies of a given module class during construction.\n\n function MyComplexModule() {\n Module.apply(this, arguments);\n console.log('loaded dependencies', this.dependencies); // {'my-dependency': }\n }\n\n MyComplexModule.dependencies = {\n 'my-dependency': 'another-module-class'\n }\n\n#### Module Class Options\n\nModule classes may also describe the options they accept. This will validate the configuration of module instance and guarantee the module class constructor has enough information to construct an instance.\n\nHere is an example options description for a database connection module class.\n\n DatabaseConnection.options = {\n 'hostname': {type: 'string', required: true},\n 'port': {type: 'number', min: 10, max: 99999},\n 'username': {type: 'string'},\n 'password': {type: 'string'}\n };\n\n**key** the option name given in `config.json`.\n\n**type** must be one of:\n\n - string\n - boolean\n - number\n - array\n\n**min/max** depend on the option type\n\n {\n min: 10, // minimum length or value\n max: 100, // max length or value\n }\n\n#### Module Events\n\nModule classes may also emit and listen to events. By default a Module will emit the following events:\n\n**destroy**\n\nEmitted when a module instance is being destroyed during a `moduleLoader.reset()`. Modules should cleanup any connections and unbind all event listeners.\n\n### Configuration\n\nEach module instance is defined by creating a `config.json` file in a directory with the module's name.\n\n /my-module-instance\n config.json\n other-files.txt\n index.js\n \nThis directory should contain files related to the module instance. For example it might contain a script that `require()`s the module instance. \n\n#### config.module\n\nThe node module name that exports the module class that constructs the config's module instance.\n\n {\n \"module\": \"my-module-class\"\n }\n\n#### config.options\n\nDefines arbitrary options. A `file-upload` module might have an `uploads` option.\n\n {\n \"module\": \"file-upload\",\n \"options\": {\n \"uploads\": \"/tmp\"\n }\n }\n\n#### config.dependencies\n\nDefines other module instances the configured instance depends on.\n\n {\n \"module\": \"collection\"\n \"dependencies\": {\n \"db\": \"my-db-module\"\n },\n \"options\": {\n \"collection-name\": \"my-collection\"\n }\n }\n\nWhere `my-db-module`'s config looks like this:\n\n {\n \"module\": \"couchdb-connector\",\n \"options\": {\n \"database\": \"my-db\"\n }\n }\n \n#### config.env.json\n\nSeparate file that overrides `config.json` depending on the current `NODE_ENV`. Useful for including config information that is environment specific or should not be committed to source control.\n\n {\n // overrides for all envs\n \"*\": {\n \"options\": {\n \"upload-dir\": \"/uploads\"\n }\n },\n \"dev\": {\n \"options\": {\n \"upload-dir\": \"/dev-uploads\"\n }\n }\n }\n\n## Requiring Modules\n\nTo use module instances, you can `require()` them anywhere in your program like you normally would require a node module. For example, you can get a reference to the `fido` object like this:\n\n var fido = require('fido'); // `fido` is the directory name containing the fido module config\n\n### Require Behavior\n\nAfter your program runs `require('sl-module-loader')` the `require()` function's behavior will change slightly to make referencing module instances simpler. Since some module instances may not have any program specific code, they can't be `require()`d with `node`'s existing require() implementation.\n \n## Config Loader\n\n`sl-module-loader` inherits from [sl-config-loader](https://github.com/strongloop/sl-config-loader).\n\n\n## Bundled Modules / Aliasing\n\nSome modules need to be distributed together. For example, you have a set of related modules that all live under a single version number since they depend on features from each other. In this case you should bundle your sub modules using the package.json `bundledDependencies` array.\n\nReference bundled modules by relative location (just like require).\n\n // config.json\n {\n \"module\": \"myBundle/node_modules/foo\"\n }\n\nYou may also provide aliases to any module path when creating a `ModuleLoader`.\n\n var moduleLoader = require('sl-module-loader').create('my-app', {alias: {'foo': 'myBundle/node_modules/foo'}});\n\nNow the config can reference `foo` instead of the qualified path.\n\n // config.json\n {\n \"module\": \"foo\"\n }", "readmeFilename": "README.md", "_id": "sl-module-loader@0.0.1", "dist": { "shasum": "f51c63bcb10ea2a21b672346d0341b51d1ef8fb1" }, "_resolved": "git+ssh://git@github.com/:strongloop/sl-module-loader.git#0484e56ee411b6e97aab5b5b9548854784b0781c", "_from": "sl-module-loader@git+ssh://git@github.com:strongloop/sl-module-loader.git" }