npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typhonjs-plugin-manager

v0.2.0

Published

Provides a plugin manager that dispatches events to loaded plugins.

Downloads

81,089

Readme

typhonjs-plugin-manager

NPM Documentation Code Style License Gitter

Build Status Coverage Dependency Status

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 - invokes PluginManager#add

plugins:add:all - invokes PluginManager#addAll

plugins:async:add - invokes PluginManager#addAsync

plugins:async:add:all - invokes PluginManager#addAllAsync

plugins:async:destroy:manager - invokes PluginManager#destroyAsync

plugins:async:invoke - invokes PluginManager#invokeAsync

plugins:async:invoke:event - invokes PluginManager#invokeAsyncEvent

plugins:async:remove - invokes PluginManager#removeAsync

plugins:async:remove:all - invokes PluginManager#removeAllAsync

plugins:create:event:proxy - invokes PluginManager#createEventProxy

plugins:destroy:manager - invokes PluginManager#destroy

plugins:get:all:plugin:data - invokes PluginManager#getAllPluginData

plugins:get:extra:event:data - invokes PluginManager#getExtraEventData

plugins:get:method:names - invokes PluginManager#getMethodNames

plugins:get:options - invokes PluginManager#getOptions

plugins:get:plugin:data - invokes PluginManager#getPluginData

plugins:get:plugin:enabled - invokes PluginManager#getPluginEnabled

plugins:get:plugin:method:names - invokes PluginManager#getPluginMethodNames

plugins:get:plugin:names - invokes PluginManager#getPluginNames

plugins:get:plugin:options - invokes PluginManager#getPluginOptions

plugins:get:plugins:enabled - invokes PluginManager#getPluginsEnabled

plugins:has:method - invokes PluginManager#hasMethod

plugins:has:plugin - invokes PluginManager#hasPlugin

plugins:has:plugin:method - invokes PluginManager#hasPluginMethod

plugins:invoke - invokes PluginManager#invoke

plugins:is:valid:config - invokes PluginManager#isValidConfig

plugins:remove - invokes PluginManager#remove

plugins:remove:all - invokes PluginManager#removeAll

plugins:set:extra:event:data - invokes PluginManager#setExtraEventData

plugins:set:plugin:enabled - invokes PluginManager#setPluginEnabled

plugins:set:plugins:enabled - invokes PluginManager#setPluginsEnabled

plugins:sync:invoke - invokes PluginManager#invokeSync

plugins:sync:invoke:event - invokes PluginManager#invokeSyncEvent

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.

The plugin manager also supports asynchronous operation with the methods ending in Async along with event bindings that include async. For asynchronous variations of add, destroy, and remove the lifecycle methods onPluginLoad and onPluginUnload will be awaited on such that if a plugin returns a Promise or is an async method then it must complete before execution continues. One can use Promises to interact with the plugin manager asynchronously, but usage via async / await is recommended.

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.

Please see the following NPM modules for eventbus info:

Examples follow:

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 defines a pass through object hash and the 4th will make a copy of the 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!