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

tennu-modules

v2.1.0

Published

Tennu module subsystem.

Downloads

3

Readme

This is the Modules subsystem of the Tennu IRC Framework for Node.

This module creates a module systems that handles loading, dependencies, and roles.

The main features of this module system are:

  • Loading of dependencies
  • Initialization of modules
  • Module roles, where modules of that role expose a common interface.
  • Module hooks, where modules can hook into each loading module.

Multiple examples use Tennu, since this module system module was designed for it.

Installation

npm install tennu-modules

Initialization of Module System

require('tennu-modules')(systemname: string, context: any)

The name is the name of the module system, and declares the directory type it will look for modules in.

The context is the first argument passed the module initialization functions.

For Tennu, where the client is passed to each module, and modules are stored in tennu_modules, the initialization is:

var modules = require('tennu-modules')('tennu', client, logger)

What's a Module?

A Module is an object with the following properties:

{
    init: function,
    name: string
    role: string?,
    requires: [string]?,
    requiresRoles: [string]?
}

The init function must return an object. This object is known as the module instance.

Note: The name must exist for initialization. When using the use() method, the modules will have their name property rewritten. As such, you don't have to worry about the property if you only use use().

The following is the minimally viable module:

{
    init: function () {
        return {};
    },
    name: 'bare'
}

The module instance can export values for other modules to use. To do so, these values must be located on the exports property.

The module instance can also hook into modules that require it. To do so, the properties to hook onto must be defined on the hooks property.

Exports Property

The exports property is given to modules that depend on your module through the init function. For example, let's say we have two modules, A and B. Module B depends on Module A. Module A exports a property exists: true. Module B loads module A and then logs A's exist property to the console.


// Module A
{
    init: function () {
        return {
            exports: {exists: true}
        };
    },
    name: 'A'
}

// Module B
{
    init: function (context, imports) {
        console.log(imports['B'].exists);
        return {
            exports: {}
        };
    },
    name: 'B'
    requires: ['A']
}

Hooks Property

Sometimes a module wants to do something with every module that uses it. For example, Tennu has a help module that hooks into the 'help' property. So, let's say there's a time module that wants to use this hook.

The time module puts 'help' in the dependencies list, and adds a help property to the module instance with the help message.

This is what it looks like:


// Module 'help'
{
    init: function (client, imports) {
        // ... initialization code.

        return {
            // ... other properties
            hooks: {
                help: function (moduleName, helpobj) {
                    // Does stuff with helpobj
                }
            }
        };
    },
    name: 'help'
}

// Module 'time'
{
    init: function (client, imports) {
        // ... initialization code.

        return {
            // ... other properties
            help: "Stuff about time."
        }
    },
    name: 'time'
}

Note: In this example, the module name and hook name are the same. This is not a requirement. You can name your hooks whatever you want.

Global Hooks

The creator of the module system can add hooks that apply to all modules.

Global hooks should be added before loading any modules.

To do so, use addHook(hook: String, fn: string -> any -> void).

For example, Tennu adds a 'handlers' global hook.

var modules = require('tennu-modules')('tennu', client, logger);
modules.addHook('handlers', function (module, handlers) {
   client.on(handlers); 
});

Loading Modules

var modules = require('tennu-modules')('tennu', client, logger);
var builtins = ['server', 'actions', 'help', 'user', 'channel'];
var toUse = [].concat(builtins, client.config(modules));
modules.use(toUse);

Create a list of modules that you want to use, and then pass them to modules.use(names: [String], path: String).

The module system will then locate and load the modules in a way that all dependencies are properly met.

This module can throw various errors. The constructors for these errors can be found on the exports object of this module.

  • UnmetDependency
  • NoSuchModule
  • NoSuchRole (Not yet used)
  • CyclicicDependency (Not yet used)
  • ModuleInitializationError
  • RegistryKeyAlreadySet
  • HookAlreadyExists

Locating Modules

The second parameter to use() is a path. The module system will look for the following places for your module:

%path%/%systemname%_modules/%modulename%.js %path%/%systemname%_modules/%modulename%/index.js %path%/node_modules/%systemname%-%modulename%/

If it cannot find the module there, it will then go up the parent directory, and repeat, until it either finds the module or is at the root.

If the module cannot be found, a NoSuchModule error will be thrown.

Other Functions

  • hasModule(name: string): boolean
  • hasRole(name: string): boolean
  • isInitializable(module: Module): boolean
  • initialize(module: Module): void