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

modlo

v1.2.2

Published

A dynamic module loader built on fount

Downloads

8

Readme

modlo

A dynamic module loader that uses fount for dynamic load and initialization of modules

Build Status Coverage Status

Precautions and disclaimers: modlo is experimental, use only as directed, call your doctor or pharmacist if you experience any of the following:

  • heightened delusions of grandeur
  • spontaneous dental hydroplosion
  • tingling in your extremeties
  • lack of tingling in your extremeties
  • rapid increase in knuckle hair growth

Purpose

Loads npm modules and modules dynamically based on glob patterns and registers them with fount. Instantiates modules that return a function and satisfies argument list from a fount container. Functions returned can result in a promise or value.

Naming

Make sure to consider how modlo names. It's going to load a bunch of modules for you and, while that's nice, if you don't understand how it goes about naming them in fount, you're going to have a bad time. Here's how modlo attempts to determine the name of each module's instance (or factory):

  • does the module return an instance?
    • use the name property if it is not null or empty
    • otherwise delimit the file name by . and use the first part
  • does the module return a function?
    • use the name property on the result of the function if it is not null or empty
    • otherwise check to see if the function is named and use that
    • lastly, fall back on using the same file name approach

Recommended

module.exports = function superAwesomeThing () {
	// because the function is named, it will be registered in fount
	// as `superAwesomeThing`.
}

Namespaces

Have several modules that take different configurations but all use the same argument name? Fount already has the concept of named containers. You can register these kinds of values namespaced to the module that will need them:

// what if you have several modules that will all get loaded that use the
// same argument name but expect different values specific to them?

// myModule.js
module.exports = function myModule (config) {
	
}

// myOtherModule.js
module.exports = function myOtherModule (config) {
	
}

// when modlo is looking at each module's arguments
// it will check to see if a `config` was registered
// under the namespace of the module first before checking
// the default container for that argument name.
// this way you can have `myModule.config` and `myOtherModule.config`
// registered and resolved correctly.

// you can register to those namespaces explicitly:
fount('myModule').register('config', {})

// or you can return a `_` delimited name from a module and
// fount will treat the first part as the namespace and the second
// part as the key:

// myModule_config.js
module.exports = function myModule_config() {
	return {}
}

Factories vs. Instances

When fount cannot supply all arguments for a module function, the function will be registered as a factory rather than storing the result of the module function call.

But Why?

I have a few libs that exhibit this kind of behavior in order to make it easy to extend with plugins or by sharing code between things. It seemed like a good opportunity to pull the code into a single lib and improve the feature set, testing and documentation.

I also hate boilerplate code. Any time I think there's a chance to reduce the tons of wire-up code required so a project can just focus on the interesting stuff, I chase that opportunity. YMMV :)

API

( [defaults] )

Requiring modlo returns an initializer that allows you to provide defaults that will be used when calling load later. The primary use for this is providing an external fount instance so it only needs to be done once:

// no defaults - modlo will use an internal fount instance
const loader = modlo()

// providing your fount instance
const fount = require('fount')
const loader = modlo({ fount: fount })

load(config)

Load takes a config hash and returns a promise that will resolve to a list of registered keys and the fount instance they were registered in.

config hash format

{
	namespace: '', // a namespace prefix to prefix all loaded modules with
	patterns: []|'', // one or more file globs to load
	modules: []|''. // one or more npm modules to load
	fount: undefined|instance // optional way to provide what fount instance gets used
}

result hash format

	loaded: [], // the list of keys registered with fount
	fount: instance // the fount instance used for registration

example - no defaults during init

// no defaults - modlo will use an internal fount instance
const loader = modlo()

// load all `.plugin.js` files from the plugin folder
loader.load({
	patterns: './plugin/*.plugin.js'
}).then(result => {
	// this is why its unlikely you'd want to use
	// modlo's fount instance, you have to capture and
	// pass it on then keep passing it around
	doSomethingWithFount(result.fount)
})

example - providing your fount instance during init

const fount = require('fount')
const loader = modlo({ fount: fount })

// load all `.plugin.js` files from the plugin folder
// load all `resource.js` files from a folder structure under `./resources`
loader.load({
	patterns: [ './plugin/*.plugin.js', './resources/**/resource.js' ]
}).then(result => {
	// now it's less critical that you capture anything at this stage,
	// it's really more just about waiting for the promise to resolve
	// before completing your service's initialization
})

example - providing a fount instance at load time

const fount = require('fount')
const loader = modlo()

// you can wait to provide your fount instance when calling load
// load all `.plugin.js` files from the plugin folder
// load all `resource.js` files from a folder structure under `./resources`
// load and register `when` and `postal` from the npm modules folder
loader.load({
	fount: fount,
	patterns: [ './plugin/*.plugin.js', './resources/**/resource.js' ],
	modules: [ "when", "postal" ]
}).then(result => {
})