IoC container and out-of-the-box extensibility for Node.js applications
Scatter is an Inversion of Control (IoC) container for Node.js. Scatter allows you to split your project in particles (components), and then uses Dependency Injection and Service locator to link your modules together.
Applications created with Scatter are extensible out-of-the box. Since every dependency is "virtual", you can override and extend every module. In addition by using Scatter Services you can provide explicit extension points to your application.
__module to extract the information to initialize the module and inject dependencies.
Although Scatter can be used as a "traditional" IoC container and has many usage patterns, the main reason for his existence is to allow the federation of multiple project directories into one. Dependency Injection, in fact, is not the reason Scatter was created but only a tool which allows to transparently map multiple components, called particles (which may also be distributed as npm pagackes), into one virtual namespace. It doesn't matter where a module is created, when used with Scatter it will always have a federated view over all the other modules in the project.
Where is the advantage of this you may ask...well imagine those components as plugins, you app would become immediately extensible with minimal effort and no boilerplate code to support the plugin infrastructure.
The use cases? Here are some:
If you prefer to go straight to the code then take a look at some examples.
The directory structure below shows 3 particles (Scatter components):
corethe the main application
All the 3 components define some routes. The Scatter container allows you to write each component as if it they were all included in a single app root, as if all the sources were actually contained in a single directory (and not scattered across different components).
In this examples
routes is for Scatter a
namespace not a physical directory, it is a federated container of modules.
app.jscore|-- particle.json|-- expressApp.js|-- routes <--- Routes|-- home.js`-- profiles.js|-- data`-- db.jsplugins|-- privateProfiles|-- particle.json`-- routes <--- Routes|-- profiles.js <--- an override`-- private.js|-- admin|-- particle.json`-- routes <--- Routes`-- admin.js
Now if we wanted to register all the routes in our express application, the file
core/expressApp.js.js would look like:
// file "core/expressApp.js.js"var express = require'express'http = require'http';returnvar app = express;appuse;middlewareappuseapprouter;//now we register our routeshomeRouterregisterapp;profileRouterregisterapp;privateRouterregisterapp;adminRouterregisterapp;httpcreateServerapplistenappget'port'console.log'Express server listening on port ' + appget'port';;;;//The Scatter annotationmoduleexports__module =//Inject this modules as argumentsargs: "routes/home" "routes/profiles" "routes/private" "routes/admin";
Then at last the file
app.js would bootstrap the Scatter container and start the express app:
var scatter = ;scatterregisterParticles__dirname + '/plugins/*'__dirname + '/core';//The application entry point, the dependency is loaded explicitlyscatterload"expressApp"thenexpressAppstart;;
You will notice in the example above that if a new plugins is added and a new route is introduced it will not be
registered, because we reference directly the routes in the file
core/expressApp. To solve this problem Scatter
supports a pattern that is a mix between DI and service locator.
svc (Service) plugin will allow you to require a method defined in multiple modules as a dependency!
Using Scatter Services the
core/expressApp would now look like:
// file "core/expressApp.js.js"var express = require'express'http = require'http';returnvar app = express;appuse;middlewareappuseapprouter;//now we register our routesregisterAllRoutesapp;httpcreateServerapplistenappget'port'console.log'Express server listening on port ' + appget'port';;;;//The Scatter annotationmoduleexports__module =//Inject a service as dependencyargs: "svc!routes/register";
There is a lot more to know! Take a look at the guide and the API docs.
sequenceservice invocator will be returned instead of the full service object. In practice now
logobject provided to the Scatter constructor must expect
trace, debug, info, warn, erroras levels instead of
silly, verbose, info, warn, error.
The API is in the process of settling, but has not yet had sufficient real-world testing to be considered stable.