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

layered-config

v0.10.1

Published

A simple configuration system allowing multiple configuration layers

Downloads

2

Readme

node-layered-config

Build Status Dependency Status

A simple configuration system allowing multiple configuration layers (e.g. defaults, user-defined config)

Each layer is treated independently. If the configuration is queried, all layers are scanned from the layer with the highest priority to the one with the lowest. The first layer that can resolve the queried path will be the one returning the configured value.

Usage

By default, an instance of LayeredConfiguration is created when the module is required.

// Load a ready-to-use LayeredConfiguration instance
let config = require('layered-config');

// If you want to create your own instance, use this instead:
let LayeredConfig = require('layered-config').LayeredConfiguration;
let myConfig = new LayeredConfig();

Adding layers

Before any configuration values can be read or written, we need to add one or more layers to the configuration.

If added by using addlayer(), every new layer will have a higher priority than the ones that were added before.

// Add a first layer including some data
config.addLayer(
    'layerOne',
    {
        one: 1,
        two: 2,
        three: {
            foo: 'bar'
        }
    }
);

// Add another layer
// This one has a higher priority than "layerOne"
config.addLayer(
    'layerTwo',
    {
        three: {
            foo: 'overwritten', // This value overwrites the one in layerOne
            bar: 'baz'
        }
    }
);

console.dir(config.getLayerNames()); // ["layerTwo", "layerOne"]

getLayerNames() returns the names of the layers inside the configuration ordered from highest to lowest priority.

Querying data

Each value inside the configuration hierarchy can be addressed by using a configuration path that describes the position you want to access. By default, configuration paths use "." as separator. To get the value of "bar" in our example above, the corresponding configuration path would be three.bar.

Querying the configuration is done by using get():

let valueOfBar = config.get('three.bar');
console.log(valueOfBar);                  // Output: 'baz'

// This will output "overwritten", since layerTwo has the highest priority
console.log(config.get('three.foo'));

If you want to query data from a specific layer, just add the layer name as second parameter:

console.log(config.get('three.foo', 'layerOne')); // Output: 'bar'

You can even change the priority by passing the layer names in the order they should be queried:

console.log(config.get('three.foo', ['layerOne', 'layerTwo'])); // Output: 'bar'

Writing data

Data is written to the config using the set() method. It takes up to three parameters: The path to write to, the value to write and the layer the value shall be stored in. If the layer name is omitted, the new value will be written into the layer with the highest priority:

config.set('my.precious.data', 'This is my value'); // Writes to "layerTwo"

config.set('some.other.data', 'Hello', 'layerOne'); // Writes to "layerOne"

You can write complete object hierarchies, too:

config.set('my.data', {hello: {world: '!'});

let value = config.get('my.data.hello.world');
console.log(value); // Output: '!'

Loading configuration data

From the filesystem

layered-config reads and writes its configuration data using Hjson. This way, the configuration files can be written in a little bit more relaxed way and contain - for example - comments.

For more information about Hjson, see the Hjson website.

You can choose to either load each layer one by one using loadFromFile() or to fill the whole configuration by reading all .json and .hjson files from a directory using loadFromDirectory(). Both function return Promises that resolve when the load operations have completed.

// Load the contents of userData.hjson into a new layer named "userData"
config.loadFromFile('./data/userData.hjson')
    .then(/* ... */);

// Load the same file into a layer named "foo"
config.loadFromFile('./data/userData.hjson', 'foo')
    .then(/* ... */);

// Cleanup
config.removeAllLayers();

// Load all (h)json files from ./data into the configuration
// Files will be loaded in alphabetical order
config.loadFromDirectory('./data')
    .then(/* ... */);

// Assuming that the directory contains the files "foo.hjson", "bar.json" and "baz.hjson",
let names = config.getLayerNames(); // ["foo", "baz", "bar"]

Attention: If both, a .hjson and a .json file exist having the same filename, the resulting configuration will only contain the data from the .json file, because it will be loaded after the .hjson one, thus overwriting its data.

From environment variables

You can also load configuration data from environment variables using loadFromEnv(). This function takes an option object which configures the way, the environment variables are processed.

The available options are:

  • lowerCase (Boolean): convert environment variable names to lowercase? (default: true)
  • separator (String): if set, the variable name will be split into a path using the separator (default: '_')
  • whitelist (String[]): if set, only the variables inside this array will be loaded into the layer (default undefined)
  • match (regex): if set, only variables that match the regular expression will be loaded into the layer (default: undefined)

If neither whitelist nor match are set, all environment variables will be imported into the configuration layer.

// Add a layer containing process.env variables
// If no layer name is given, a new layer named 'process_env' will be created
config.loadFromEnv();
console.log(config.get('home'))

Saving configuration data into files

When saving the configuration data you can either write the data of one layer into a single file using saveToFile() or write the data of all layers into Hjson files inside a directory, each having the layers' name by using saveToDirectory().

Just like the load methods, each save method returns a Promise.

When using saveToDirectory(), only those layers will be written to disk that have their writeToDisk property set to true (default: false).

// Add some layers with data
config.addLayer('one', {a: 1}).writeToDisk = true;
config.addLayer('two', {b: 2});
config.addLayer('three', {c: 3}).writeToDisk = true;

// Write layer "two" to disk
config.saveToFile('two', 'myConfigFile.hjson')
    .then(/* ... */);

// This will write layers "one" and "three" to the target directory
config.saveToDirectory('./data')
    .then(/* ... */);

// The "data" directory now contains the files "one.hjson" and "three.hjson"