cycle-plugins
Provides observable-based plugins to cycle.js applications.
Installation
npm i cycle-plugins --save
Scripts
NOTE: Make sure you've installed all dependencies using npm install
first.
To generate documentation: npm run doc
. This will create documentation in the
build/docs
folder.
To run unit tests: npm test
API
Plugins
Static class for registering and consuming Plugin instances dynamically.
Kind: global namespace
plugins.register(plugins)
Makes one or more Plugins available to consumers.
Kind: instance method of Plugins
Param | Type | Description |
---|---|---|
plugins |
Plugin | Array.<Plugin>
|
One or more Plugin instances to make available to consumers. |
Example
Plugins.register(new Plugin({
name: 'console',
log: function log(msg) { ... }
}));
Plugins.get({name: 'console'}).first()
.tap(console => console.log('hello'));
plugins.unregister(plugins)
Makes a Plugin unavailable to consumers.
Kind: instance method of Plugins
Param | Type | Description |
---|---|---|
plugins |
Plugin | Array.<Plugin>
|
One or more Plugin instances to unregister. |
Example
var plugin = new Plugin({name: 'temp'});
Plugins.register(plugin); // available to consumers
Plugins.unregister(plugin); // unavailable to consumers
plugins.get(criteria)
Returns an Observable populated with an array of
Plugin instances matching the specified criteria.
The array contains a utility method called toDAG
that will return a DAG instance you can use to
iterate safely over the returned Plugin instances
in a way that respects the index
and after
properties of each Plugin.
Kind: instance method of Plugins
Throws:
-
Error
Invalid criteria was specified.
Param | Type | Description |
---|---|---|
criteria | Object |
A map of criteria to apply against each registered Plugin. Only Plugin instances matching the specified criteria will be included in the resulting Observable. |
Example
// retrieve a single Plugin by name
var single$ = Plugins.get({name: 'my-one-plugin'}).first();
Example
// retrieve all registered Plugin instances
var allPlugins$ = Plugins.get(); // or Plugins.get({})
Example
// retrieve all Plugin instances targeting a specific type
var targeted$ = Plugins.get({targetType: MyClass});
Example
// retrieve Plugin instances matching a specific filter;
// the Plugin would need 'my-criteria' in its `filter.any`
// string array and NOT in its `filter.none` string array.
var filtered$ = Plugins.get({filter: 'my-criteria'});
Example
// iterating through Plugins concurrently and in a
// dependency-safe order:
let savePlugins$ = Plugins.get({
targetType: MyClass, filter: 'save'
});
function save() {
return savePlugins$.map(plugins =>
new Observable(observer =>
plugins.toDAG().forEach(
(plugin, next) => plugin.doSomething(), next(),
(err) => err ? observer.error(err) : observer.next()
);
));
}
Plugin
Kind: global class
Inherits: Broker
Properties
Name | Type | Default | Description |
---|---|---|---|
name | String |
The name of this plugin. | |
index | Number |
0 |
Provides a way to order multiple Plugins whenever a sequence is requested. |
after | Array.<String> |
[] |
Provides a way to order multiple Plugins based on dependencies. Ensures that this Plugin will be sequenced after the specified Plugin names. If you prepend a name with ?, it will be treated as an optional dependency. |
enabled | Boolean |
true |
Some consumers may use this property to determine which Plugins should be consumed or which can be skipped during iteration. |
targetType | function |
Object |
Used in conjunction with Plugins.get to ensure both Plugin creators and Plugin consumers agree on who can consume this Plugin instance. |
filter | Filter |
{any:[], none:[]} |
A way to restrict the list of Plugins retrieved by Plugins.get at runtime. |
-
Plugin
- new Plugin(props)
-
.Events :
Object
new Plugin(props)
An extensible object.
Param | Type | Description |
---|---|---|
props | Object |
A map of property names and values to apply to the Plugin instance. The only required property is name . |
Example
import {extend, matches} from 'lodash';
const COMMAND_PROPS = { ... };
class Command extends Plugin
constructor(props) {
super(extend({}, COMMAND_PROPS, props));
Plugins.register(this);
}
execute() {}
undo() {}
}
class RecordCommand extends Command {
constructor(props) {
super({
targetType: Record,
enabled: User.hasPrivilege(props.name)
});
}
}
class SaveRecord extends RecordCommand
constructor() {
super({name: 'save-record');
}
execute() { ... }
undo() { ... }
}
class DeleteRecord extends RecordCommand
constructor() {
super({name: 'delete-record');
}
execute() { ... }
undo() { ... }
}
class Record extends Broker {
constructor() {
this.commands$ = Plugins.get({
baseType: RecordCommand,
targetType: Record,
enabled: true
});
}
save() {
return this.commands$
.filter(matches({name: 'save-record'}))
.map(command => command.execute(this))
.tap(() => this.emit('record-saved'))
.toPromise();
}
}
Object
Plugin.Events : Events specific to Plugins.
Kind: static property of Plugin
Properties
Name | Type | Description |
---|---|---|
PLUGIN_CHANGED | String |
A property on the plugin has changed. Emit this event when you wish for any search criteria passed to Plugins.get to be re-evaluated, with observers notified of any changes. |
DAG (Directed Acyclic Graph)
Kind: global class
new DAG(plugins)
Provides a dependency-safe way to iterate through plugins.
Throws:
-
Error
If a dependent Plugin is not optional and not in the set of Plugins provided to the constructor, an error will be thrown. You can mark a dependency as optional by prepending it with a question mark. See the documentation for Plugin for more information.
Param | Type | Description |
---|---|---|
plugins |
Plugin | Array.<Plugin>
|
One or more Plugin instances the DAG should manage. |
Example
var dag = new DAG(pluginA, pluginB, pluginC);
dag.forEach(function iterate(plugin, next) {
// do something with plugin
next(); // invoke this callback with the next plugin
// if you wish to stop iteration immediately, invoke
// next with an argument: next(0) or next('stop') or
// next(new Error()) -- the argument will be passed
// to your success handler function
}, function finished(err) {
if (err) {
console.log('An error occurred:', err);
}
});
Array.<Plugin>
daG.toArray() ⇒ Converts the DAG into a dependency-safe sequence of Plugin instances.
Kind: instance method of DAG
Returns: Array.<Plugin>
- An array of Plugin instances in dependency-safe order.
Example
var dag = new DAG(pluginA, pluginB, pluginC);
var names = dag.toArray().map(function(plugin) {
return plugin.name;
});
log(names);
daG.forEach(callback, [finish], [concurrency])
Iterates through the DAG in dependency-safe order using the specified callback function and concurrency settings.
Kind: instance method of DAG
Throws:
-
Error
Parametercallback
must be a function. -
Error
Parameterconcurrency
must be a positive integer.
Param | Type | Default | Description |
---|---|---|---|
callback | function |
A method that will be invoked for each Plugin instance. Arguments will be: - {Plugin} plugin - the current plugin - {Function} next - method to invoke to continue iteration - {Number} percent - a number between 0 and 100 indicating how much of the DAG has been processed | |
[finish] | function |
An optional method to invoke when the DAG has been completely processed. If an error has occurred or the iteration ended early, the only argument will be the exit reason. | |
[concurrency] | Number |
5 |
How many Plugins to iterate concurrently. The number must be a positive integer. |
Example
new DAG(pluginA, pluginB, pluginC)
.forEach((plugin, next, percent) => {
log(`running ${plugin.name} - ${percent}% complete`);
next('stop'); // stop iterating early
}, err => {
if (err) {
log('stopped early because:', err);
}
});