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

rucola

v1.1.4

Published

Runtime configuration loader that supports command-line flags, environment variables and config files alike

Downloads

55

Readme

rucola

Build Status codebeat badge Codacy Badge Coverage Status

rucola is a unix-style runtime configuration loader for Node.js apps that allows you to configure your application using configuration files in JSON, INI and YAML format, command-line arguments, and environment variables.
It's heavily inspired by the amazing rc module but it does things differently.

Sample Usage

Absolute Minimal Setup

You don't need more than this to add runtime configuration with command-line flags, environment variables and config files in INI, YAML and JSON to your app.

import rucola from 'rucola';

const conf = rucola('myapp');
conf.get('myvalue');

Slightly More Comprehensive Setup

The only argument required is appname. But in this example we're also providing default values and defining some aliases.

// Import the module
import rucola from 'rucola';

// The name of your app. It should be a string with no spaces and
// special characters. Kind of like an npm module name.
const appname = 'myapp';

// An object containing your default values. Make sure you cover
// everything essential to your app.
const defaults = {
  connection: {
    port: 1337,
    host: '127.0.0.1',
  },
};

// An object mapping aliases to config properties. Use the dot-notation
// to define aliases for nested properties.
const aliases = {
  p: 'connection.port',
  h: 'connection.host',
  r: 'color.red',
  R: 'recursive',
  v: 'version',
};

// Load the configuration.
const conf = rucola(appname, defaults, aliases);

// use conf.get() to read config variables 
// without throwing TypeErrors.
conf.get('connection.port')
// 1337

conf.connection.port;
// 1337

conf.get('i.dont.exist');
// undefined

conf.i.dont.exist
// TypeError: Cannot read property 'dont' of undefined

Documentation

API

conf = rucola(appname [, defaults [, aliases]])

Loads your configuration from all sources and returns an object containing all values.

import rucola from 'rucola';
const conf = rucola('myapp', defaults, aliases);

appname

The appname is your application's name. It will be used as a prefix for environment variables and in the name of your configuration files. It should be lower-cased without any spaces and other special characters. Kind of like you would name a module on npm.

defaults

The default values for your configuration. You don't have to cover every possible value but you should provide default values for all essential settings so your app can run without a configuration file.

The defaults can be either an object, or a string in any of the supported formats.

Using an object:

import rucola from 'rucola';

const defaults = {
  connection: {
    host: 'localhost',
    port: 8080,
  },
};

const conf = rucola('myapp', defaults);

Reading the defaults as a string from an INI file:

import path from 'path';
import fs from 'fs';
import rucola from 'rucola';

// Load defaults from an external file in any supported format.
const defaults = fs.readFileSync(path.join(__dirname, 'defaults.ini'), 'utf-8');

const conf = rucola('myapp', defaults);

aliases

An object to define short aliases (like -R for --recursive or -u for --user) for command-line arguments. If you want to define an alias for a nested property use the dot-notation.

import rucola from 'rucola';

const defaults = {
  connection: {
    host: 'localhost',
    port: 8080,
  },
};

const aliases = {
  h: 'connection.host',
  p: 'connection.port',
  v: 'version',
  V: 'verbose',
};

const conf = rucola('myapp', defaults, aliases);

Now you can use them as command-line arguments:

$ myapp -h 127.0.0.1 -p 8000 -V

which is the same as:

$ myapp --connection-host 127.0.0.1 --connection-port 8000 --verbose

value = conf.get(key)

conf.get() is a method to safely read config values of nested objects without throwing TypeErrors. You can use the dot-notation to access nested properties.

import rucola from 'rucola';

const defaults = {
  connection: {
    host: 'localhost',
    port: 8080,
  },
};

const conf = rucola('myapp', defaults);

conf.get('connection.host');
// 'localhost'

conf.get('server.hostname');
// undefined

Accessing conf.server.hostname directly would throw a TypeError because conf.server is undefined.

arr = conf.checkedConfigs

The conf.checkedConfigs property is an array containing all file paths that have been checked.

import rucola from 'rucola';

const conf = rucola('myapp');
console.log(conf.checkedConfigs);

// [ '/etc/myapp/config',
//   '/etc/myapprc',
//   '/etc/xdg/myapp/myapp.rc',
//   '/home/user/.config/myapp/config',
//   '/home/user/.config/myapp',
//   '/home/user/.myapp/config',
//   '/home/user/.myapprc' ]

arr = conf.usedConfigs

The conf.usedConfigs property is an array containing all file paths from which values have been loaded from.

import rucola from 'rucola';

const conf = rucola('myapp');
console.log(conf.usedConfigs);

// [ '/etc/myapprc', '/home/user/.config/myapp' ]

Normalization

All configuration options are normalized into a nested object structure with lower-case keys. Regardless of file format, environment variable, or command-line argument.

The following all translate into the following object:

{
  server: {
    connection: {
      host: "localhost",
      port: "9000"
    }
  }
}

Environment Variables

MYAPP_SERVER_CONNECTION_HOST=localhost \
MYAPP_SERVER_CONNECTION_PORT=9000 \
myapp
MYAPP_sErVeR_CoNNEcTION_hOsT=localhost \
MYAPP_SerVer_coNneCtiOn_PorT=9000 \
myapp

Command-Line Arguments

myapp --server-connection-host localhost \
      --server-connection-port 9000
myapp --sERvER-COnNEcTIoN-hOSt localhost \
      --SErVEr-CoNNeCtIOn-pOrt 9000

Config Files

JSON:

{
  "server": {
    "connection": {
      "host": "localhost",
      "port": "9000"
    }
  }
}
{
  "Server.Connection": {
    "Host": "localhost",
    "Port": "9000"
  }
}
{
  "SERVER.Connection.host": "localhost",
  "SERVER.Connection.port": "9000"
}

INI:

[server]
connection.host = localhost
connection.port = 9000
[Server.Connection]
host = localhost
port = 9000
SERVER.connection.host = localhost
SERVER.connection.port = 9000

YAML:

server:
  connection:
    host: localhost
    port: 9000
Server.Connection:
  Host: localhost
  Port: 9000
SERVER.Connection.Host: localhost
SERVER.Connection.Port: 9000

Configuration Sources

Given your application name is "myapp", rucola will load configuration values from the following sources in this paricular order from bottom to top, and merge the values in the same order.

  • command-line arguments
  • environment variables
  • if you passed an option --config file then from that file
  • a local .myapprc or the first found looking in ./ ../ ../../ ../../../ etc
  • $HOME/.myapprc
  • $HOME/.myapp/config
  • $HOME/.config/myapp
  • $HOME/.config/myapp/config
  • /etc/xdg/myapp/myapp.rc (unix-style only)
  • /etc/myapprc (unix-style only)
  • /etc/myapp/config (unix-style only)
  • defaults

File Formats

rucola supports JSON (with comments), INI and YAML, and auto-detects the format.

Example INI file:

; this is a comment

yolo = true

[connection]
port = 1337
host = 127.0.0.1

; nested sections

[nice.foods]
green = broccoli
orange = carrots

[nice.colors]
emerald = true
turquoise = false

Same example in JSON:

// this is a comment

{
  "yolo": true,
  "connection": {
    "port": "1337",
    "host": "127.0.0.1"
  },

// nested sections

  "nice": {
    "foods": {
      "green": "broccoli",
      "orange": "carrots"
    },
    "colors": {
      "emerald": true,
      "turquoise": false
    }
  }
}

Same example in YAML:

---
# this is a comment

yolo: true

connection:
  port: 1337
  host: 127.0.0.1

# nested sections

nice.foods:
  green: broccoli
  orange: carrots

nice.colors:
  emerald: true
  turquoise: false

Environment Variables

Environment variables need to be prefixed with the application name and are upper case. Keep in mind that environment variables always have string values. So you may have to type cast the values into whetever you need.

MYAPP_CONNECTION_PORT=1337 YOLO=true myapp

becomes:

{
  connection: {
    port: "1337"
  },
  yolo: "true",
}

Command-line Arguments

myapp --connection-port 1337 --yolo

becomes:

{
  connection: {
    port: 1337
  },
  yolo: true
}

Difference Between rucola And rc

The big difference between rucola and rc is that rucola normalizes everything so you can use environment variables and command-line arguments in a way a user would expect to use them.

If your app name is "myapp" and you wanted the following config object,

{
  connection: {
    host: "localhost",
    port: 9000
  }
}

in rc you would have to use environment variables like this (with double unserscores for nested properties):

myapp_connection__host=localhost \
myapp_connection__port=9000 \
myapp

and command-line arguments like this:

myapp --connection.host localhost --connection.port 9000

which is not what you'd expect in a unix-like environment.

With rucola you can use environment variables like this:

MYAPP_CONNECTION_HOST=localhost \
MYAPP_CONNECTION_PORT=9000 \
myapp

and command-line arguments like this:

myapp --connection-host localhost --connection-port 9000

which is much closer to what a user might expect.

Things that rucola can and rc can't:

  • Nice command-line arguments and environment variables
  • Provides .get() function to access values without throwing TypeErrors
  • Provide a list of files from which values were read from
  • Support for aliases
  • Support YAML format

Things that rc can and rucola can't:

  • Swap out minimist for a different option parser

License

Copyright (c) 2015 - 2018 Max Kueng and contributors

MIT License