Node.js Plug-And-Play package
Easily create hooks and let users plug their own logic across your code to make it extensible by everyone with new features.
Main features
- Extention points definition
Simple to declare new extention points, yet a lot of flexibility to the plugin authors. - Hook definition
Plugin writer can intercept calls to a function by placing their own logicl before, after and even switching the default implementation. - Dependency management
Plugins can require other plugins as required dependencies as well as choose the order of execution of each hook. - Promise support
Hook can be synchronous and asynchronous when returning a promise. - Nested/hierachical
Instanciate plugin instances with a parent reference and parent hooks will also be available inside the children.
Learning
We encourage your to read the detailed tutorial on how to create a plugin architected with Plug and Play published by Adaltas.
Quick example
Library and application authors must define hooks, see ./sample/lib.js
:
const plugandplay = require('plug-and-play')
const plugins = plugandplay()
module.exports = {
plugins: plugins,
print: function() {
plugins.call({
name: 'hooks:print',
args: {
data: { message: 'hello' }
},
handler: ({data}) => {
console.log(data.message)
}
})
}
}
Users and pluging authors can now register their own hooks, see ./sample/index.js
:
const mysuperlibrary = require('./lib')
mysuperlibrary.plugins.register({
hooks: {
'hooks:print': ({data}, handler) => {
data.message = 'Hello World'
console.log('>>>>>>>>>>>')
const result = handler.call(null, {data: data})
console.log('<<<<<<<<<<<')
return result
}
}
})
mysuperlibrary.print()
While the original print
function was only printing Hello
to stdout, the introduction of this new plugin prints:
>>>>>>>>>>>
Hello world
<<<<<<<<<<<
API
The package export a function to create a new instance:
const plugandplay = require('plug-and-play')
const plugins = plugandplay()
It accepts an option object with the properties:
args
([string])
Arguments to pass to the plugin when they are instantiated, only apply if the plugin is defined as a function.chain
(any)
The value returned by Plug-And-Play register
function, default to the Plug-And-Play instance.parent
(plugandplay)
A parent instance of Plug-And-Play to inherit plugins from.plugins
([plugin])
List of plugins to register
Plugin object
A plugin is an object literal with the properties:
hooks
({name: hook})
List of hooks identified by hook names.name
(string)
Name of the plugin.
Alternatively, a plugin can be defined as a function which return the same plugin object and receive the args
property from the Plug-And-Play function.
Hook object
A hook is an object literal with the properties:
after
([string])
List of plugin names with hook of the same name are to be executed before, a string is coerced to an array.name
(string)
The name of the hook.before
([string])
List of plugin names with hook of the same name are to be executed after, a string is coerced to an array.
Note, when referencing plugins with after
and before
, the plugins do not need to exists. If they do, they are required to export a hook of the same name.
Call function
The function signature is:
call({args = [], handler, hooks = [], name})
Execute a hander function and its associated hooks. The first argument is an object with the properties:
args
(any)
The argument pass to the handler function as well as all hook handlershandler
(function)
The function to decorate, receive the value assocaited with the args
property.name
(string)
The plugin hook to refer to.hooks
([hook])
List of completary hooks from the end user.
Get function
The function signature is:
get({name, hooks, sort})
The get
function return hooks. It expects a property option
which is a literal object with the properties:
name
(string)
Name of the hook.hooks
([hook])
List of completary hooks from the end user.sort
(boolean)
Sort the hooks relatively to each other using the after
and before
properties.
Register function
The function signature is:
register(plugin)
Plugin can be provided when instantiating Plug-And-Play by passing the plugins
property or they can be provided later on by calling the register
function. The function only accept one argument, the plugin
property:
plugin
(plugin)
A plugin object.
Roadmap
Worth considering: move the name
property of get
and call
into the first argument and move the other properties into a second argument named option.