Constructor
new Plugin(name, metadata)
Initialize a new Plugin instance.
Parameters:
Name | Type | Description |
---|---|---|
name |
string | The name of the plugin |
metadata |
Object | The plugin metadata |
Example
{
version: '0.0.1',
dependencies: {
'<PLUGIN NAME>': '>=1.2.3'
}
}
Methods
adapter(name, fn) → {this}
Create factories that determine which implementation to use at injection time.
Parameters:
Name | Type | Description |
---|---|---|
name |
string | Dependency name |
fn |
function | Factory function |
Returns:
- Type
- this
Example
plugin
.factory('RedisResource', function () {})
.factory('MongoResource', function () {})
.adapter('Resource', function (injector, settings) {
// where settings.property is 'RedisResource' or 'MongoResource'
return injector.get(settings.property)
})
.factory('User', function (Resource) {})
alias(alias, name) → {this}
Alias creates a reference to another item on the injector within its own injector object. When the alias is injected through the use of the injector.get() method it calls the aliased dependency and creates a reference to the instance in the dependency.value field.
Parameters:
Name | Type | Description |
---|---|---|
alias |
string | New dependency name |
name |
string | Existing dependency name |
Returns:
- Type
- this
Example
plugin
.factory('myDependency', function () {
// ...
})
.alias('myAlias', 'myDependency')
assembler(name, fn) → {this}
This can be used to define new types of components. For example, the core framework probably doesn't need any knowledge of Express routers, but if you wanted to define a specialized factory registrar for routers, you could do it like so:
app.plugin('server', {
version: '0.0.0'
})
.initializer(function (plugin) {
plugin.assembler('router', function (injector) {
let plugin = this
return function (name, factory) {
injector.register({
name,
type: 'router',
plugin: plugin.name,
factory
})
})
})
})
This makes a new dependency registrar called 'router' that can be used as follows:
app.plugin('other', {
version: '0.0.0'
})
.initializer(function (plugin) {
plugin.router('SomeRouter', function (Router, SomeResource) {
let router = new Router()
router.get('endpoint', function () {
SomeResource
.list(req.query)
.then(function (results) {
res.json(results)
})
.catch(error => next(error))
})
return router
})
})
The dependency inject can then be queried by this new "type" value.
injector.filter({ type: 'router' })
Parameters:
Name | Type | Description |
---|---|---|
name |
string | Dependency name |
fn |
function | Assembler function |
- Source:
- To Do:
-
- there should possibly be a way to create a starter method automatically for an assembler to save that boilerplate
Returns:
- Type
- this
extension(name, fn) → {this}
The idea of an extension is that you can access some component to use it's API without registering anything on the injector.
This is useful for things like modifying a model's schema or registering event handlers on an event emitter.
Parameters:
Name | Type | Description |
---|---|---|
name |
string | Dependency name |
fn |
function | Mutator function |
Returns:
- Type
- this
Examples
// Given a plugin created as follows
app.plugin('Default API', <METADATA>)
.initializer(function (plugin) {
.factory('User', function (Resource) {
class User extends Resource {
static get schema () {
return Object.assign({}, super.schema, {
name: { type: 'string' },
email: { type: 'string', format: 'email' }
})
}
}
return User
})
})
app.plugin('My Project', <METADATA>)
.initializer(function (plugin) {
plugin.extension('UserExtension', function (User) {
User.extendSchema({
domainSpecificAttribute: { type: 'whatever', ... }
})
})
})
app.plugin(<NAME>, <METADATA>)
.initializer(function (plugin) {
plugin.factory('emitter', function () {
return new EventEmitter()
})
})
app.plugin('My Project', <METADATA>)
.initializer(function (plugin) {
plugin.extension('CustomEventHandlers', function (emitter) {
emitter.on('ready', function (event) {
// do something
})
})
})
factory(name, fn) → {this}
The factory method registers a new dependency on the injector, validates it, and determines which other dependencies it requires.
The first argument is the name of the new dependency and the second argument is a function that returns the value of the dependency. However, this dependency is not invoked at the time the dependency is registered.
Getting a dependency from the Injector invokes the function and stores the return value.
Parameters:
Name | Type | Description |
---|---|---|
name |
string | Dependency name |
fn |
function | Factory function |
Returns:
- Type
- this
Example
plugin
.factory('one', function () {
return 1
})
.factory('two', function () {
return 2
})
.factory('oneplustwo', function (one, two) {
return one + two
})
include(filename) → {this}
The bootstrapping process searches through the plugins directory looking for plugins to load. To make a new plugin you simply create a sub-directory with an index.js file. Additional files in the directory are incorporated using the include method. This allows developers to separate out one plugin into an arbitrary number of files.
Parameters:
Name | Type | Description |
---|---|---|
filename |
string | Relative path to included file. |
Returns:
- Type
- this
Example
// index.js
'use strict'
module.exports = function (sunstone) {
app.plugin('MyResource', {
version: '0.0.1',
dependencies: {
'Server': '0.0.1'
}
})
.initializer(function (plugin) {
plugin
.include('./other')
.include('./yetanother')
})
}
// other.js
'use strict'
module.exports = function (plugin) {
plugin
.factory('MyModel', function (a, b) {
// ...
})
.router('MyModelRouter', function (MyModel) {
// ...
})
}
initialize() → {this}
Invoke the initializer function, if it exists.
Returns:
- Type
- this
initializer(callback) → {this}
Register an initializer function.
Parameters:
Name | Type | Description |
---|---|---|
callback |
callback | Initializer function |
Returns:
- Type
- this
Example
module.exports = function (app) {
app.plugin('MyResource', {
version: '0.0.1',
dependencies: {
'Server': '0.0.1'
}
})
.initializer(function (plugin) {
.include('./other')
.include('./yetanother')
})
}
require(modules) → {this}
Adds dependencies to the injector by loading node modules. Accepts a string, array or object. By passing an object you can alias the package name.
Parameters:
Name | Type | Description |
---|---|---|
modules |
string | Array | Object | Modules to require |
Returns:
- Type
- this
Example
app.plugin(<NAME>, <METADATA>)
.initializer(function (plugin) {
plugin.require('express')
plugin.require([
'crypto',
'ioredis'
])
plugin.require({
'_': 'lodash',
'fs': 'fs-extra',
'myLibrary': './myLibrary'
})
})
start() → {this}
Invoke the starter function, if it exists.
Returns:
- Type
- this
starter(callback) → {this}
Register an starter function.
Parameters:
Name | Type | Description |
---|---|---|
callback |
function | Starter function |
Returns:
- Type
- this
Example
app.plugin(<NAME>, <METADATA>)
.initializer(function (plugin) {
plugin.starter(function (injector, server) {
injector
.filter({ plugin: this.name, type: 'router' })
.values()
.forEach(router => {
router.mount(server)
})
})
})
stop() → {this}
Invoke the stopper function, if it exists.
Returns:
- Type
- this
stopper(callback) → {this}
Register an initializer function.
Parameters:
Name | Type | Description |
---|---|---|
callback |
function | Stopper function |
Returns:
- Type
- this
Example
app.plugin(<NAME>, <METADATA>)
.initializer(function (plugin) {
plugin.stopper(function (injector, server) {
// code to disable plugin
})
})