Skip to content

API Documentation

Mario Casciaro edited this page Jun 27, 2014 · 7 revisions
Clone this wiki locally

API

  1. Scatter
  2. __module descriptor
  3. Dependency loaders
  4. Particle descriptor(particle.json)

Scatter

The Scatter object is the entry point to create a brand new DI container for an application.

new Scatter(options)

Create a new Scatter DI container.

Arguments

  • options - An object containing a set of config options
    • log - [optional] A function in the format function(level, message) that will be used by Scatter to log messages. level is one of the log levels (trace, debug, info ,warn, error).
    • startProfiling - [optional] A function with the format function([sessionName, logLevel]) which returns an object used for profiling some of the Scatter internals. This object should contain 3 methods:
      • start()
      • pause()
      • end()
    • instantiateTimeout - [optional] The number of milliseconds to wait for a module to be instantiated. Defaults to 5000ms.
    • initializeTimeout - [optional] The number of milliseconds to wait for a module to be initialized. Defaults to 5000ms.
    • plugins - [optional] An array of plugins to be used by Scatter. Defaults to [].

Example

var scatter = new Scatter({
   log: function(level, message) {
       console.log(level + ": " + message);
   }
});

scatter.registerParticles(particlesDirs)

Register one or more particles with the Scatter container.

Arguments

  • particlesDirs - A String (or Array of Strings) representing the particle(s) directories to add. Supports glob syntax.

Example

var scatter = new Scatter();
scatter.registerParticles([__dirname + '/components/*', __dirname + '/core']);

scatter.registerParticle(particleDir)

Alias of scatter.registerParticles

scatter.setNodeModulesDir(nodeModulesDir)

Tells Scatter where to find the node_modules directory. This enable the use of npm! dependencies, to require normal npm modules from the DI container. Also it will register all the Scatter particles found inside the npm modules.

Arguments

  • nodeModulesDir - Path to the node_modules directory of the project

scatter.load(name)

Manually load a dependency (or set of dependencies) from the DI container.

Arguments

  • name - [String] The dependency name, or [Array] of dependencies.

Returns

A promise for the loaded module or for an [Array] of the loaded modules.

Example

scatter.load('foo/bar').then(function(mod) {
    // do something amazing with mod
}

scatter.registerModule(name, rawModule [, descriptor])

Register a raw module that is not yet instantiated nor initialized. Scatter will take care to instantiate and initialize it when needed, using the information in the __module descriptor.

Arguments

  • name - Full name of the module (complete with namespace)
  • rawModule - The raw module object
  • descriptor - If provided it will be used in place of the __module property.

Returns

A newly created Module object.

Example

var mod = function(foo) {
    return {
        hello: function() {
            console.log("Hello " + foo.name);
        }
    };
};
mod.__module = {
    args: ['foo']
}

scatter.registerModule('bar/mod', mod);

scatter.registerModuleInstance(name, instance[, descriptor])

Registers a module instance already initialized and wired outside the Scatter container.

Arguments

  • name - The full name of the module
  • instance - The module instance
  • descriptor - The module descriptor, in place of the __module property that usually is part of the raw module, not the module instance. At this stage only the provides property of the descriptor is relevant.

Returns

A newly created Module object.

Example

var instance = {
hello: function() {
        console.log('hello everybody!');
    }
}

scatter.registerModuleInstance('bar/mod', instance, {});

scatter.initializeAll()

Load and initialize all the modules in the registered particles. By default Scatter loads your dependencies on-demand, but by using this method you will force the loading of every module.

Arguments

None

Returns

A promise which resolves at the end of initialization.

The __module descriptor

The __module descriptor is a property of the raw module object used by Scatter to determine how to wire the module, how to instantiate it and what services provides.

Examples Using an object literal:

module.exports = {
    //... put your module content here
};
module.exports.__module = {
    //descriptor
}

Using a factory:

module.exports = function() {
    return {
        //... put your module content here
    }
};
module.exports.__module = {
    //descriptor
}

__module.type

String. The type specifies how the module will be instantiated. There are 3 possible values:

  • factory: The module will be instantiated by invoking the module object as a function. The return value of the invocation will become the module instance.
  • constructor: The module will be instantiated by invoking new on the module object.
  • object: The module will be taken as-is, no instantiation step will occur.

Scatter automatically determines the type of a module, so usually there is no need to specify the type, unless you don't want to force the autodetected value. Scatter detects the type following those simple rules:

  • If the module is a Function without a prototype, then type='factory'
  • If the module is a Function with a non-empty prototype then type='constructor'
  • All the rest defaults to type: 'object'

__module.initialize

Array: [[String], String|Function]. A function to be executed as the last step of the module instantiation/initialization. The function can receive as arguments a set of injected dependencies, using the format: [[<list of dependencies>], function(<injected dependencies>) {}]

The function can also be a String, in which case module_instance[<function name>] will be invoked.

The initialize function is executed in the context of the module instance.

Example

module.exports = {
    verb: "Hello",
    name: "World",
    punctuation: "!"
}
module.exports.__module = {
    initialize: [['utilities/joiner'], function(joiner) {
        this.phrase = joiner(this.verb, this.World, this.punctuation);
    }]
}

__module.args

Array of Strings. Lists the dependencies to be injected as arguments when invoking the module factory or the module constructor.

Example

module.exports = function(fooBar) {
    //awesome stuff
};
module.exports.__module = {
    args: ['foo/bar']
}

__module.properties

Object. Inject dependencies as module instance properties. The properties object, is a map where the keys are the names of the properties and the values are the dependencies to inject.

The properties will be injected into the module instance in case a module is instantiated with a factory or a constructor.

Example

module.exports = function() {
    var self = {
        doSomething: function() {
            return self.injectedProperty;
        }
    };
    return self
};
module.exports.__module = {
    properties: {
        injectedProperty: 'foo/bar'
    }
}

__module.provides

Object. Specifies the Services exposed by the module. A service name is in the form <namespace>/<method>, where <namespace> is the scope in which Scatter looks for the service (it can be nested as you like) and <method> is a service identifier. If no handler is specified the provides descriptor, <method> will be used to resolve the method to invoke on the module when the service is invoked.

Before/After

In the provides descriptor it is also possible to force the order of execution of the service, specifying if it should execute after or before the same service is invoked on the list of modules specified respectively in the after and before parameters. Globs are allowed when specifying modules in after and before.

Formats

  • Long format:
    provides: {
        "aNamespace/foo": {
            after: ["aNamespace/mod1"],
            before: ["./*"],
            handler: "objectFoo" //Optional
        }
    }
  • Short format (if only after needs to be specified):
    provides: {
        "aNamespace/foo": ["mod1", "mod2"]
    }
  • Very short format (if no before/after needs to be specified):
provides: ["mod1", "mod2"]

Examples

module.exports = {
    helloService: function() {
        //baboooom
    }
};
module.exports.__module = {
    provides: {
        "aNamespace/helloService": {
            after: ['namespace/to/module/*'],
            before: ['foo/bar/AModule']
        }
    }
}

__module.overrideProvides

Boolean, default: false. If the module is extending/overriding another module, this flag tells Scatter if the parent provides descriptor has to be overridden (true) or merged (false)

Dependency loaders

Scatter comes with a versatile and extensible dependency loader. With this feature, the DI container can inject not only modules but any sort of objects.

It is possible to invoke a specific loader with the syntax: <loader name>|<loader params>!<dependency name>

Now follows a list of loaders shipped with Scatter.

Default Loader

By default, if no loader is specified in the dependency, a module will be loaded.

Example

module.exports = function(moduleDependency) {
    [...]
}
module.exports.__module = {
    args: ['a/module/dependency']
}

svc!

The svc! loader allows to load Services. It will load a function representing the Service that when invoked will return a promise for the service execution.

Syntax

svc|[<mode>]!<service name>

Where:

  • <mode>: Optional, if not specified the default mode is sequence. Modes can be:
    • sequence: the methods in the service will be invoked sequentially
    • pipeline: the methods in the service will be invoked in pipeline where the return value of a method will be given as input to the next one.
    • any: the Service invocation will return immediately as soon as the first method invocation in the chain will return a non undefined value.
    • invoke: Alias of sequence, to be used when the executing mode is not relevant.
  • <service name> is the name of the service in the form <namespace>/<service name>. The Service will invoke <service name> over all the modules providing <service name> under the namespace <namespace> recursively.

Example

module.exports = function(service) {
    return {
        hello: function() {
            service("hello").then(function() {
                //done
            });
        }
    }
}
module.exports.__module = {
    args: ['svc|any!foo/bar/helloService']
}

npm!

The npm! loader allows to inject an npm module from the node_modules directory specified in the Scatter object (see setNodeModulesDir).

This is different from invoking require('module'), since the module will not be resolved using the default Node.js convensions (e.g. no relative dirs allowed, does not load the module from the module's local node_modules dir). Instead, the npm module will always be resolved from the node_modules directory configured when the Scatter container is initialized.

The advantage of this, is that different Scatter modules will always access the same version (and same instance!) of the npm module they require with npm!. Although this is not always desirable, sometimes can be very useful when your modules need to share an npm module across all the application they are injected to.

Syntax

npm!<npm module name>

Example

module.exports = function(express) {
    [...]
}
module.exports.__modules = {
    args = ['npm!express']
}

container!

Will load a private version of the Scatter container for the module requiring it. The loaded container will only have the load method.

Example

module.exports = function(container) {
    [...]
}
module.exports.__modules = {
    args = ['container!']
}

delayInit!

This loader will cause the DI container to load a not initialized module (only instantiated). This might be useful in case there are loops into module dependencies and delaying the initialization of the module can solve the loop. Please look at module lifecycle for some use cases.

particle.json

The particle.json file describes and configures a Scatter component.

  • name: The name of the particle. Optional if subparticles defined.
  • subparticles: Array, Optional. A list of relative paths pointing to other directories containing a particle (and therefore a particle.json file).
  • overrides: Array, Optional. A list of components (particle names) that this particle is overriding/extending.
  • exclude: Array, Optional. An list of files to exclude from being considered for DI (e.g. client side js). Uses Globs.
Something went wrong with that request. Please try again.