PluginManager
Provides a lightweight plugin manager for Node / NPM with optional backbone-esnext-events
integration for plugins in a safe and protected manner across NPM modules, local files, and preloaded object
instances. This pattern facilitates message passing between modules versus direct dependencies / method invocation.
It isn't necessary to use an eventbus associated with the plugin manager though invocation then relies on invoking methods directly with the plugin manager instance.
When passing in an eventbus from backbone-esnext-events
the plugin manager will register by default under these
event categories:
plugins:add
- PluginManager#add
plugins:add:all
- PluginManager#addAll
plugins:create:event:proxy
- PluginManager#createEventProxy
plugins:destroy:manager
- PluginManager#destroy
plugins:get:all:plugin:data
- PluginManager#getAllPluginData
plugins:get:extra:event:data
- PluginManager#getExtraEventData
plugins:get:method:names
- PluginManager#getMethodNames
plugins:get:options
- PluginManager#getOptions
plugins:get:plugin:data
- PluginManager#getPluginData
plugins:get:plugin:enabled
- PluginManager#getPluginEnabled
plugins:get:plugin:event:names
- PluginManager#getPluginEventNames
plugins:get:plugin:method:names
- PluginManager#getPluginMethodNames
plugins:get:plugin:names
- PluginManager#getPluginNames
plugins:get:plugin:options
- PluginManager#getPluginOptions
plugins:get:plugins:enabled
- PluginManager#getPluginsEnabled
plugins:get:plugins:by:event:name
- PluginManager#getPluginsByEventName
plugins:get:plugins:event:names
- PluginManager#getPluginsEventNames
plugins:has:method
- PluginManager#hasMethod
plugins:has:plugin
- PluginManager#hasPlugin
plugins:has:plugin:method
- PluginManager#hasPluginMethod
plugins:invoke
- PluginManager#invoke
plugins:invoke:async
- PluginManager#invokeAsync
plugins:invoke:sync
- PluginManager#invokeSync
plugins:invoke:sync:event
- PluginManager#invokeSyncEvent
plugins:is:valid:config
- PluginManager#isValidConfig
plugins:remove
- PluginManager#remove
plugins:remove:all
- PluginManager#removeAll
plugins:set:extra:event:data
- PluginManager#setExtraEventData
plugins:set:plugin:enabled
- PluginManager#setPluginEnabled
plugins:set:plugins:enabled
- PluginManager#setPluginsEnabled
Automatically when a plugin is loaded and unloaded respective callbacks onPluginLoad
and onPluginUnload
will
be attempted to be invoked on the plugin. This is an opportunity for the plugin to receive any associated eventbus
and wire itself into it. It should be noted that a protected proxy around the eventbus is passed to the plugins
such that when the plugin is removed automatically all events registered on the eventbus are cleaned up without
a plugin author needing to do this manually in the onPluginUnload
callback. This solves any dangling event binding
issues.
If eventbus functionality is enabled it is important especially if using a process / global level eventbus such as
backbone-esnext-eventbus
to call PluginManager#destroy to clean up all plugin eventbus resources and
the plugin manager event bindings.
See:
Example:
import Events from 'backbone-esnext-events'; // Imports the TyphonEvents class for local usage.
::or alternatively::
import eventbus from 'backbone-esnext-eventbus'; // Imports a global / process level eventbus.
import PluginManager from 'typhonjs-plugin-manager';
const pluginManager = new PluginManager({ eventbus });
pluginManager.add({ name: 'an-npm-plugin-enabled-module' });
pluginManager.add({ name: 'my-local-module', target: './myModule.js' });
// Let's say an-npm-plugin-enabled-module responds to 'cool:event' which returns 'true'.
// Let's say my-local-module responds to 'hot:event' which returns 'false'.
// Both of the plugin / modules will have 'onPluginLoaded' invoked with a proxy to the eventbus and any plugin
// options defined.
// One can then use the eventbus functionality to invoke associated module / plugin methods even retrieving results.
assert(eventbus.triggerSync('cool:event') === true);
assert(eventbus.triggerSync('hot:event') === false);
// One can also indirectly invoke any method of the plugin via:
eventbus.triggerSync('plugins:invoke:sync:event', 'aCoolMethod'); // Any plugin with a method named `aCoolMethod` is invoked.
eventbus.triggerSync('plugins:invoke:sync:event', 'aCoolMethod', {}, {}, 'an-npm-plugin-enabled-module'); // specific invocation.
// The 3rd parameter will make a copy of the hash and the 4th defines a pass through object hash sending a single
// event / object hash to the invoked method.
// -----------------------
// Given that `backbone-esnext-eventbus` defines a global / process level eventbus you can import it in an entirely
// different file or even NPM module and invoke methods of loaded plugins like this:
import eventbus from 'backbone-esnext-eventbus';
eventbus.triggerSync('plugins:invoke', 'aCoolMethod'); // Any plugin with a method named `aCoolMethod` is invoked.
assert(eventbus.triggerSync('cool:event') === true);
eventbus.trigger('plugins:remove', 'an-npm-plugin-enabled-module'); // Removes the plugin and unregisters events.
assert(eventbus.triggerSync('cool:event') === true); // Will now fail!
// In this case though when using the global eventbus be mindful to always call `pluginManager.destroy()` in the main
// thread of execution scope to remove all plugins and the plugin manager event bindings!
Constructor Summary
Public Constructor | ||
public |
constructor(options: object, extraEventData: object) Instantiates PluginManager |
Member Summary
Private Members | ||
private |
Stores the prepend string for eventbus registration. |
|
private |
Stores any associated eventbus. |
|
private |
Stores any extra options / data to add to PluginEvent callbacks. |
|
private |
Defines options for throwing exceptions. |
|
private |
Stores the plugins by name with an associated PluginEntry. |
Method Summary
Public Methods | ||
public |
add(pluginConfig: PluginConfig): PluginData | undefined Adds a plugin by the given configuration parameters. |
|
public |
addAll(pluginConfigs: Array<PluginConfig>): Array<PluginData> Initializes multiple plugins in a single call. |
|
public |
If an eventbus is assigned to this plugin manager then a new EventProxy wrapping this eventbus is returned. |
|
public |
destroy() Destroys all managed plugins after unloading them. |
|
public |
getAllPluginData(enabled: boolean | undefined): Array<PluginData> Returns all plugin data or if a boolean is passed in will return plugin data by current enabled state. |
|
public |
getEventbus(): TyphonEvents | null Returns any associated eventbus. |
|
public |
getExtraEventData(): * Returns any extra event data associated with PluginEvents. |
|
public |
Returns all method names or if a boolean is passed in will return method names for plugins by current enabled state. |
|
public |
Returns a copy of the plugin manager options. |
|
public |
getPluginData(pluginName: string): PluginData | undefined Gets the plugin data for a plugin by name. |
|
public |
getPluginEnabled(pluginName: string): boolean Returns the enabled state of a plugin. |
|
public |
getPluginEventNames(pluginName: string): string[] Returns the event binding names registered on any associated plugin EventProxy. |
|
public |
getPluginMethodNames(enabled: boolean | undefined): Array<{plugin: string, method: string}>{plugin:> Returns all plugin names or if a boolean is passed in will return plugin names by current enabled state. |
|
public |
getPluginNames(enabled: boolean | undefined): Array<string> Returns all plugin names or if a boolean is passed in will return plugin names by current enabled state. |
|
public |
getPluginOptions(pluginName: string): * Returns a copy of the given plugin options. |
|
public |
getPluginsByEventName(eventName: string): Array<string[]> Returns the plugin names that registered the given event binding name. |
|
public |
getPluginsEnabled(pluginNames: Array<string>): Array<{pluginname: string, enabled: boolean}>{pluginname:> Returns the enabled state of a list of plugins. |
|
public |
getPluginsEventNames(nameOrList: string | string[]): Array<{pluginname: string, events: string[]}>{pluginname:> Returns the event binding names registered from each plugin. |
|
public |
Returns true if there is at least one plugin loaded with the given method name. |
|
public |
Returns true if there is a plugin loaded with the given plugin name. |
|
public |
hasPluginMethod(pluginName: string, methodName: string): boolean Returns true if there is a plugin loaded with the given plugin name that also has a method with the given method name. |
|
public |
This dispatch method simply invokes any plugin targets for the given methodName.. |
|
public |
invokeAsync(methodName: string, args: * | Array<*>, nameOrList: string | Array<string>): * | Array<*> This dispatch method uses ES6 Promises and adds any returned results to an array which is added to a Promise.all construction which passes back a Promise which waits until all Promises complete. |
|
public |
invokeSync(methodName: string, args: * | Array<*>, nameOrList: string | Array<string>): * | Array<*> This dispatch method synchronously passes back a single value or an array with all results returned by any invoked targets. |
|
public |
invokeSyncEvent(methodName: string, copyProps: object, passthruProps: object, nameOrList: string | Array<string>): PluginEvent | undefined This dispatch method synchronously passes to and returns from any invoked targets a PluginEvent. |
|
public |
isValidConfig(pluginConfig: PluginConfig): boolean Performs validation of a PluginConfig. |
|
public |
Removes a plugin by name after unloading it and clearing any event bindings automatically. |
|
public |
Removes all plugins after unloading them and clearing any event bindings automatically. |
|
public |
setEventbus(targetEventbus: TyphonEvents, eventPrepend: string): PluginManager Sets the eventbus associated with this plugin manager. |
|
public |
setExtraEventData(extraEventData: *) Sets any extra event data attached to PluginEvent |
|
public |
setOptions(options: PluginManagerOptions) Set optional parameters. |
|
public |
setPluginEnabled(pluginName: string, enabled: boolean): boolean Enables or disables a single plugin. |
|
public |
setPluginsEnabled(pluginNames: Array<string>, enabled: boolean): boolean Enables or disables a set of plugins given an array or iterabe of plugin names. |
Private Methods | ||
private |
_addAllEventbus(pluginConfigs: Array<PluginConfig>): Array<PluginData> Provides the eventbus callback which may prevent addition if optional |
|
private |
_addEventbus(pluginName: string): boolean Provides the eventbus callback which may prevent addition if optional |
|
private |
Provides the eventbus callback which may prevent plugin mananger destruction if optional |
|
private |
Provides the eventbus callback which may prevent removal if optional |
|
private |
_removeEventbus(pluginName: string): boolean Provides the eventbus callback which may prevent removal if optional |
Public Constructors
public constructor(options: object, extraEventData: object) source
Instantiates PluginManager
Params:
Name | Type | Attribute | Description |
options | object |
|
Provides various configuration options: |
options.eventbus | TyphonEvents |
|
An instance of 'backbone-esnext-events' used as the plugin eventbus. |
options.eventPrepend | string |
|
A customized name to prepend PluginManager events on the eventbus. |
options.throwNoMethod | boolean |
|
If true then when a method fails to be invoked by any plugin an exception will be thrown. |
options.throwNoPlugin | boolean |
|
If true then when no plugin is matched to be invoked an exception will be thrown. |
extraEventData | object |
|
Provides additional optional data to attach to PluginEvent callbacks. |
Private Members
private _extraEventData: Object source
Stores any extra options / data to add to PluginEvent callbacks.
private _options: PluginManagerOptions source
Defines options for throwing exceptions. Turned off by default.
private _pluginMap: Map<string, PluginEntry> source
Stores the plugins by name with an associated PluginEntry.
Public Methods
public add(pluginConfig: PluginConfig): PluginData | undefined source
Adds a plugin by the given configuration parameters. A plugin name
is always required. If no other options
are provided then the name
doubles as the NPM module / local file to load. The loading first checks for an
existing instance
to use as the plugin. Then the target
is chosen as the NPM module / local file to load.
By passing in options
this will be stored and accessible to the plugin during all callbacks.
Params:
Name | Type | Attribute | Description |
pluginConfig | PluginConfig | Defines the plugin to load. |
public addAll(pluginConfigs: Array<PluginConfig>): Array<PluginData> source
Initializes multiple plugins in a single call.
Params:
Name | Type | Attribute | Description |
pluginConfigs | Array<PluginConfig> | An array of plugin config object hash entries. |
public createEventProxy(): EventProxy source
If an eventbus is assigned to this plugin manager then a new EventProxy wrapping this eventbus is returned.
public getAllPluginData(enabled: boolean | undefined): Array<PluginData> source
Returns all plugin data or if a boolean is passed in will return plugin data by current enabled state.
public getExtraEventData(): * source
Returns any extra event data associated with PluginEvents.
Return:
* |
public getMethodNames(enabled: boolean | undefined, pluginName: string | undefined): Array<string> source
Returns all method names or if a boolean is passed in will return method names for plugins by current enabled state.
public getPluginData(pluginName: string): PluginData | undefined source
Gets the plugin data for a plugin by name.
Params:
Name | Type | Attribute | Description |
pluginName | string | A plugin name. |
public getPluginEnabled(pluginName: string): boolean source
Returns the enabled state of a plugin.
Params:
Name | Type | Attribute | Description |
pluginName | string | Plugin name to set state. |
public getPluginEventNames(pluginName: string): string[] source
Returns the event binding names registered on any associated plugin EventProxy.
Params:
Name | Type | Attribute | Description |
pluginName | string | Plugin name to set state. |
public getPluginMethodNames(enabled: boolean | undefined): Array<{plugin: string, method: string}>{plugin:> source
Returns all plugin names or if a boolean is passed in will return plugin names by current enabled state.
public getPluginNames(enabled: boolean | undefined): Array<string> source
Returns all plugin names or if a boolean is passed in will return plugin names by current enabled state.
public getPluginOptions(pluginName: string): * source
Returns a copy of the given plugin options.
Params:
Name | Type | Attribute | Description |
pluginName | string | Plugin name to retrieve. |
Return:
* |
public getPluginsByEventName(eventName: string): Array<string[]> source
Returns the plugin names that registered the given event binding name.
Params:
Name | Type | Attribute | Description |
eventName | string | An event name that plugins may have registered. |
public getPluginsEnabled(pluginNames: Array<string>): Array<{pluginname: string, enabled: boolean}>{pluginname:> source
Returns the enabled state of a list of plugins.
public getPluginsEventNames(nameOrList: string | string[]): Array<{pluginname: string, events: string[]}>{pluginname:> source
Returns the event binding names registered from each plugin.
public hasMethod(methodName: string): boolean source
Returns true if there is at least one plugin loaded with the given method name.
Params:
Name | Type | Attribute | Description |
methodName | string | Method name to test. |
public hasPlugin(pluginName: string): boolean source
Returns true if there is a plugin loaded with the given plugin name.
Params:
Name | Type | Attribute | Description |
pluginName | string | Plugin name to test. |
public hasPluginMethod(pluginName: string, methodName: string): boolean source
Returns true if there is a plugin loaded with the given plugin name that also has a method with the given method name.
public invoke(methodName: string, args: * | Array<*>, nameOrList: string | Array<string>) source
This dispatch method simply invokes any plugin targets for the given methodName..
public invokeAsync(methodName: string, args: * | Array<*>, nameOrList: string | Array<string>): * | Array<*> source
This dispatch method uses ES6 Promises and adds any returned results to an array which is added to a Promise.all construction which passes back a Promise which waits until all Promises complete. Any target invoked may return a Promise or any result. This is very useful to use for any asynchronous operations.
public invokeSync(methodName: string, args: * | Array<*>, nameOrList: string | Array<string>): * | Array<*> source
This dispatch method synchronously passes back a single value or an array with all results returned by any invoked targets.
public invokeSyncEvent(methodName: string, copyProps: object, passthruProps: object, nameOrList: string | Array<string>): PluginEvent | undefined source
This dispatch method synchronously passes to and returns from any invoked targets a PluginEvent.
Params:
Name | Type | Attribute | Description |
methodName | string | Method name to invoke. |
|
copyProps | object |
|
plugin event object. |
passthruProps | object |
|
if true, event has plugin option. |
nameOrList | string | Array<string> |
|
An optional plugin name or array / iterable of plugin names to invoke. |
public isValidConfig(pluginConfig: PluginConfig): boolean source
Performs validation of a PluginConfig.
Params:
Name | Type | Attribute | Description |
pluginConfig | PluginConfig | A PluginConfig to validate. |
public remove(pluginName: string): boolean source
Removes a plugin by name after unloading it and clearing any event bindings automatically.
Params:
Name | Type | Attribute | Description |
pluginName | string | The plugin name to remove. |
public removeAll() source
Removes all plugins after unloading them and clearing any event bindings automatically.
public setEventbus(targetEventbus: TyphonEvents, eventPrepend: string): PluginManager source
Sets the eventbus associated with this plugin manager. If any previous eventbus was associated all plugin manager
events will be removed then added to the new eventbus. If there are any existing plugins being managed their
events will be removed from the old eventbus and then onPluginLoad
will be called with the new eventbus.
Params:
Name | Type | Attribute | Description |
targetEventbus | TyphonEvents | The target eventbus to associate. |
|
eventPrepend | string |
|
An optional string to prepend to all of the event binding targets. |
public setExtraEventData(extraEventData: *) source
Sets any extra event data attached to PluginEvent extra
field.
Params:
Name | Type | Attribute | Description |
extraEventData | * | Adds extra data to PluginEvent |
public setOptions(options: PluginManagerOptions) source
Set optional parameters. All parameters are off by default.
Params:
Name | Type | Attribute | Description |
options | PluginManagerOptions | Defines optional parameters to set. |
public setPluginEnabled(pluginName: string, enabled: boolean): boolean source
Enables or disables a single plugin.
public setPluginsEnabled(pluginNames: Array<string>, enabled: boolean): boolean source
Enables or disables a set of plugins given an array or iterabe of plugin names.
Private Methods
private _addAllEventbus(pluginConfigs: Array<PluginConfig>): Array<PluginData> source
Provides the eventbus callback which may prevent addition if optional noEventAdd
is enabled. This disables
the ability for plugins to be added via events preventing any external code adding plugins in this manner.
Params:
Name | Type | Attribute | Description |
pluginConfigs | Array<PluginConfig> | An array of plugin config object hash entries. |
private _addEventbus(pluginName: string): boolean source
Provides the eventbus callback which may prevent addition if optional noEventAdd
is enabled. This disables
the ability for plugins to be added via events preventing any external code adding plugins in this manner.
Params:
Name | Type | Attribute | Description |
pluginName | string | The plugin name to remove. |
private _destroyEventbus() source
Provides the eventbus callback which may prevent plugin mananger destruction if optional noEventDestroy
is
enabled. This disables the ability for the plugin mananger to be destroyed via events preventing any external
code removing plugins in this manner.
private _removeAllEventbus() source
Provides the eventbus callback which may prevent removal if optional noEventRemoval
is enabled. This disables
the ability for plugins to be removed via events preventing any external code removing plugins in this manner.
private _removeEventbus(pluginName: string): boolean source
Provides the eventbus callback which may prevent removal if optional noEventRemoval
is enabled. This disables
the ability for plugins to be removed via events preventing any external code removing plugins in this manner.
Params:
Name | Type | Attribute | Description |
pluginName | string | The plugin name to remove. |