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

a-configuration

v1.3.1

Published

For quick configurations based on a set file structure

Downloads

13

Readme

A Configuration

Version npm

In Brief; This module exists to simplify and consolidate various files in a directory and to leverage other paths for generalized configuration and extends the NodeJS EventEmitter class to offer update events.

Specifically, this module merges JSON and Javascript files in various directories ("app/configuration/" by default) into a single exported module for reference while also merging default "global" JSON and Javascript files (Unspecified by default) as well to allow for "system" level configuration to be applied as well.

Getting Started

Installation

npm install a-configuration

Usage

var configuration = require("a-configuration");

See NodeJS documentation for the methods and properties provided by the EventEmitter parent.

See GitHub Pages for the a-configuration API.

Note that files in a directory are ordered lexicographically, so if priority between files is needed, use numeric prefixing to guarantee load order; ie. [ "00-package.js", "10-logger.js", "20-database.js" ] .

Simple Case

In your Node project, create an app directory and in that directory create a configuration directory [app/configuration] and place any JSON or javascript files in that directory that you wish to use to specify configuration values.

See the examples below or check out the Wiki on Github for additional information.

Process Case

The local and global configuration directories can be specified in the process arguments.

  • --config:global For the relative path to the global configuration directory
  • --config:local For the relative path to the local configuration directory

Custom Case

Modify your package.json file by adding the key aconfiguration and then specify the keys you wish to override:

(Note that specification through environment variables is planned for V1.2)

final

Type: String
Aliases: finish
Default: -

Relative file path to configurations to be loaded last and will overwrite any previously written values.

application

Type: String
Aliases: app, locals, directory
Default: "app/configuration/"

Relative file path to where the "app" configurations are located. These configurations are applied second to last and will overwrite any previously written values.

files

Type: Array of Strings
Aliases: -
Default: -

An array of relative or absolute file paths to apply to the configuration in the specified order. These are applied after the system configurations and before the application configurations.

system

Type: String
Aliases: sys, globals
Default: null

Relative or absolute file path to where the configurations the host are located. These configurations are applied second and can be overwritten by similar keys in later configurations.

masks

Type: String
Aliases: initial
Default: -

Relative or absolute file path that specifies an initial mask for the configuration. This is applied first and can be overwritten by similar keys in later configurations.

ignore

Type: String
Aliases: -
Default: "_"

Used to determine if the first character of a key indicates if that key should be ignored. By default, only the '' character indicates that a key should be ignored. So if a configuration file has the key '' at the top level, then that key will not be added to the configuration. The ignore character does not apply to key names below the top level. For instance {"_key": "..."} would be ignored, however {"key": {"_subkey": "..."}} would not result in "_subkey" being ignored.

Implementing Configurations

JSON Files

JSON files are used directly and can simply be edited for configuration reloading.

Javascript Modules

Javascript files must specify a module.exports.resolve function that returns an object or a promise and optionally takes an argument for the configuration object to be passed to it (This is the recommended way to get the Configuration object instead of "require('a-configuration')" in the module itself). If the exported module does not have a resolve function, then the configuration will not attempt to use that module. If the "resolve" field exists but is not a function, then an error will be thrown.

If a Promise is returned by resolve, it must complete with an object representing the configuration to be applied. The returned object acts the same as a JSON file as far as applying values to the exported configuration is concerned.

If a Promise is used and there is a problem with generating the configuration in the module, fail the Promise and the configuration will error out accordingly. Note that this will result in an error event, but it will not block the configuration from loading JSON files and thus having configuration data that can be used.

Additionally, note that resolve may be called multiple times during the application's execution. Subsequent calls are how the module handles "reloading" the configuration. Along that point, changing the code for an included javascript file will not make any difference in the configuration.

Examples

Multiple JSON Files for Database Connections

For this example lets assume there is the following:

  • app/configuration/mongo.json
{
	"mongo": {
		"host": "mongo.example.com"
	}
}
  • app/configuration/redis.json
{
	"redis": {
		"host": "redis.example.com"
	}
}

Then the configuration will resolve as:

{
	"mongo": {
		"host": "mongo.example.com"
	},
	"redis": {
		"host": "redis.example.com"
	}
}

Now if we add another file; app/configuration/login.json:

{
	"_note": "Do not add this file to the repository",
	"mongo": {
		"user": "mongo-user",
		"pass": "mongo-pass"
	},
	"redis": {
		"user": "redis-user",
		"pass": "redis-pass"
	}
}

Then the configuration will resolve as:

{
	"mongo": {
		"host": "mongo.example.com",
		"user": "mongo-user",
		"pass": "mongo-pass"
	},
	"redis": {
		"host": "redis.example.com",
		"user": "redis-user",
		"pass": "redis-pass"
	}
}

Configuring a Server to hold shared information

For this example lets assume there is the following:

  • /opt/system-configurations/databases.json
{
	"_note": "Managed by Puppet",
	"mongo": {
		"host": "mongo.example.com",
		"user": "mongo-user",
		"pass": "mongo-pass"
	}
}
  • app/configuration/mongo.json
{
	"mongo": {
		"database": "myapp"
	}
}

To leverage the shared system configuration, the package.json would need to be updated to have an aconfiguration key at the top level that specifies the relative or absolute path to the relevent configuration files.

Relative paths should start with a "." (ie. "./" or "../"), otherwise the path is assumed to be absolute.

./package.json

{
	...
	"aconfiguration": {
		"system": "/opt/system-configurations/"
	}
}

Then the configuration will resolve as:

{
	"mongo": {
		"host": "mongo.example.com",
		"user": "mongo-user",
		"pass": "mongo-pass",
		"database": "myapp"
	}
}

JSON and Javascript Files

For this example lets assume there is the following:

  • app/configuration/databases.json
{
	"mongo": {
		"host": "mongo.example.com"
	},
	"redis": {
		"host": "redis.example.com"
	}
}
  • app/configuration/connect.js
var mongo = require("mongo");
var redis = require("redis");

module.exports.resolve = function(configuration) {
	return new Promise(function(done, fail) {
		Promise.all([
			mongo.connect(configuration.mongo),
			redis.connect(configuration.redis)
		])
		.then(function(connections) {
			configuration.mongo.connection = connections[0];
			configuration.redis.connection = connections[1];
			done();
		})
		.catch(fail);
	});
};

Then the configuration will initially resolve as:

{
	"mongo": {
		"host": "mongo.example.com"
	},
	"redis": {
		"host": "redis.example.com"
	}
}

The connections will still be processing when require("a-configuration") finishes. Once _await completes or the "loaded" event fires, the configuration will finally resolve as something similar to:

{
	"mongo": {
		"host": "mongo.example.com",
		"connection": [object MongoConnection]
	},
	"redis": {
		"host": "redis.example.com",
		"connection": [object RedisConnection]
	}
}

⚠ Note!

The "Mongo" and "Redis" modules in the example above do NOT reflect how those modules are actually used. See their documentation for usage and examples.