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

in

v0.19.0

Published

Plugin loader. Plays with Ware

Downloads

12,053

Readme

in

Generic plugin loader facility.

Getting Started

Install the module with: npm install in

const PluginLoader = require('in');

A plugin should expose a init function.

module.exports.init = function(app, config){};

A module can expose a priority value:

module.exports.priority = 5000;

A negative value indicates a higher priority

A module can expose a 'dependencies' value:

module.exports.dependencies = ['logger'];

Documentation

A plugin is nothing more than a regular Node module. By default, we expect plugins to expose an init function that takes two arguments:

constructor options

context

This is where all plugins will be mounted. This would normally be your application instance.

mountDirectory(directory,options,context)

It will mount all plugins found in directory into the provided context.

This is in effect applying find, filter, load, sort, and mount in that order.

find(directory)

Scans a directory for files and directories, returning a list of absolute paths to the files. It target is not an absolute path, we resolve it against basepath.

sort(plugins)

Sorts an array of plugins after they have been loaded. By default it uses sortFilter:

sortFilter

It will looks for module.exports.priority and sort based on that:

function _sortFilter(plugins){
	function filter(a, b) {
		function p(i){
			return i.priority === undefined ? 0 : i.priority;
		}
		return p(a) < p(b) ? -1 : 1;
	}
	return plugins.sort(filter);
}
sortByDependencies

The library also exposes a sortByDependencies filter, which you can use instead of the default sortFilter.

const loader = new PluginLoader({
    sortFilter: require('in').sortByDependencies
});

Modules should expose a dependencies array listing the ids of depended modules.

module.exports.dependencies = ['logger', 'persistence'];

normalize(plugins)

When we call load we apply the normalize function which will ensures that plugins can be any of the following:

String

const plugins = '/Users/application/plugins/authentication';

Output after calling normalize:

[
    {
        "id": "authentication",
        "path": "/Users/application/plugins/authentication",
        "config": {}
    }
]

Array

const plugins = ['/Users/application/plugins/authentication'];

Output after calling normalize:

[
    {
        "id": "authentication",
        "path": "/Users/application/plugins/authentication",
        "config": {}
    }
]

Object

const plugins = {
    '/Users/application/plugins/authentication': { hash: 'sh1' }
};

Output after calling normalize:

[
    {
        "id": "authentication",
        "path": "/Users/application/plugins/authentication",
        "config": {
            "hash": "sh1"
        }
    }
]

Mixed

const plugins = [
    {'/Users/application/plugins/authentication':{ hash: 'sh1' }},
    'debug'
];

Output after calling normalize:

[
    {
        "id": "authentication",
        "path": "/Users/application/plugins/authentication",
        "config": {
            "hash": "sh1"
        }
    },
    {
        "id": "debug",
        "path": "debug",
        "config": {}
    }
]

filter(plugins)

Public: Apply minimatch patterns against paths, an array of paths. The default pattern is ['**', '!node_modules', '!.git'] Returns a Promise which once resolved will contain an Array of filtered paths.

load(plugins, options={})

Given a list of plugins, create a plugin object with metadata and the result of requireing the module.

We create a bean per plugin:

{
    id: 'logger',
    path: '/Users/in/examples/plugins/logger.js',
    config: {},
    plugin: { init: [Function], priority: -100 },
    isLocal: true
}

mount

Makes plugins available to the provided context by calling mountHandler to previously loaded plugins.

mountHandler

Adds a plugin to the provided context.

function _mount(bean, context, config={}){
	config = extend({}, bean.config, config);
	var plugin = bean.plugin;
	if(typeof bean.config === 'function') return bean.config(plugin, context, config);
	if(typeof bean.config.mount === 'function') return bean.config.mount(plugin, context, config);
	if(typeof plugin.init === 'function') return plugin.init(context, config);
	return context[bean.id] = plugin;
}

afterMount(context)

Function that will be called right after mount

Examples

Look at the examples directory. Run it with node examples/index.js.

Directory structure:

  • index.js
  • plugins
    • repl.js
    • pubsub.js
    • logger.js
    • authentication
      • index.js
const PluginManager = require('..');
const EventEmitter = require('events');

const app = new EventEmitter();

app.on('plugins.ready', _ => {
    app.logger.info('Application plugins loaded');
});

const manager = new PluginManager({
    context: app,
    basepath: __dirname,
	afterMount: (context) => context.emit('plugins.ready')
});

manager.mountDirectory('./plugins')
    .catch(console.error);

logger.js:

module.exports.init = function(app, config) {
    app.logger = console;
    app.logger.info('Plugin logger loaded!');
};

module.exports.priority = -100;

repl.js:

module.exports.init = function(app, config) {

    app.repl = {
        context: {app}
    };

    app.logger.info('Plugin REPL loaded!');
};

pubsub.js:

module.exports.init = function(app, config) {
    app.pubsub = {
        publibsh: function(type, event){
            app.logger.warn('publish: %s. payload: %s', type, event);
        },
        subscribe: function(type, handler){
            app.logger.warn('subscribe to %s', type);
        }
    };
    app.logger.info('Plugin pubsub loaded!');
};

authentication/index.js:

module.exports.init = function(app, config) {
    app.auth = {
        check: function(){}
    };
    app.logger.info('Plugin auth loaded!');
};

module.exports.priority = 500;

node examples/load/index.js:

Plugin logger loaded!
Plugin REPL loaded!
Plugin pubsub loaded!
Plugin auth loaded!
Application plugins loaded

Release History

  • 2020-06-04: v0.18.2 hotfix release
  • 2020-06-04: v0.18.0 Add support for sub directories in plugins target dir
  • 2019-09-08: v0.17.0 Update version of dependencies
    • Export normalizePath from lib/normalizeArguments.js
    • Export getIdFromPath from lib/normalizeArguments.js
  • 2019-08-26: v0.16.2 Update version of dependencies
  • 2019-07-13: v0.16.0 Remove synchronous file access
  • 2019-07-13: v0.15.0 Update version of dependencies
  • 2016-11-24: v0.9.0 Added sortByDependencies
  • 2016-11-18: v0.8.0 Update mount to take in afterMount in options
  • 2016-11-14: v0.7.0 normalizePath use basepath from argument
  • 2016-11-13: v0.6.0 Refactoring mount
  • 2016-10-24: v0.5.0 Added afterMount
  • 2016-10-23: v0.4.0 Big update
    • Added examples
    • Added documentation
    • Added mountDirectory

License

Copyright (c) 2015 goliatone
Licensed under the MIT license.