electrode-io / electrode-confippet

node.js environment aware application configuration
Other
108 stars 18 forks source link
config config-composition configuration-management node nodejs

Electrode Confippet NPM version Build Status

Confippet is a versatile, flexible utility for managing configurations of Node.js applications. It's simple to get started, and can be customized and extended to meet the needs of your app.


Contents

Features

Getting Started

In this example, we'll create two config files: a default file that always loads, and a production file that loads only when the NODE_ENV environment variable is set to production. We'll then import those files into a standard Node.js app.

Installation

npm install electrode-confippet --save

Basic Use

Make a config/ directory inside the main app directory, and put the following into a file named default.json in that directory:

{
  "settings": {
    "db": {
      "host": "localhost",
      "port": 5432,
      "database": "clients"
    }
  }
}

Next, add another file called production.json to the config/ directory, with this content:

{
  "settings": {
    "db": {
      "host": "prod-db-server"
    }
  }
}

Finally, in our Node.js app, we can import Confippet and use the configuration we've created:

const config = require("electrode-confippet").config;
const db = config.$("settings.db");

In this example, default.json will be loaded in all environments, whereas production.json will be loaded only when the NODE_ENV environment variable is set to production. In that case, the value of host in the db object will be overwritten by the value in production.json.

Config Composition

Confippet's presetConfig composes together files in the config/ directory, in the following order:

This is the same as node-config files.

  1. default.EXT
  2. default-{instance}.EXT
  3. {deployment}.EXT
  4. {deployment}-{instance}.EXT
  5. {short_hostname}.EXT
  6. {short_hostname}-{instance}.EXT
  7. {short_hostname}-{deployment}.EXT
  8. {short_hostname}-{deployment}-{instance}.EXT
  9. {full_hostname}.EXT
  10. {full_hostname}-{instance}.EXT
  11. {full_hostname}-{deployment}.EXT
  12. {full_hostname}-{deployment}-{instance}.EXT
  13. local.EXT
  14. local-{instance}.EXT
  15. local-{deployment}.EXT
  16. local-{deployment}-{instance}.EXT

Where:

Overridden values are handled as follows:

After Confippet loads all available configuration files, it will look for override JSON strings from the NODE_CONFIG and CONFIPPET* environment variables. See the next section for details.

Environment Variables

Confippet reads the following environment variables when composing a config store:

Using Templates

Values in your config files can be templates, which will be resolved with a preset context. See processConfig for more information about how to use config value templates.

Usage in Node Modules

If you have a Node.js module that has its own configurations based on environment variables, like NODE_ENV, you can use Confippet to load config files for your module.

The example below will use the default compose options to compose configurations from the directory config under the script's directory (__dirname).

const Confippet = require("electrode-confippet");

const options = {
  dirs: [Path.join(__dirname, "config")],
  warnMissing: false,
  context: {
    deployment: process.env.NODE_ENV
  }
};

const defaults = {
  foo: "bar"
};

const config = Confippet.loadConfig(options, defaults /* refresh: true */);

Customization

The composeConfig feature supports a fully customizable and extendable config structure. Even Confippet's own preset config structure can be extended, since it's composed using the same feature.

If you want to use the preset config, but add an extension handler or insert a source, you can turn off auto loading, and load it yourself with your own options.

NOTE: This has to happen before any other file accesses Confippet.config. You should do this in your startup index.js file.

For example:

process.env.AUTO_LOAD_CONFIG_OFF = true;

const JSON5 = require("json5");
const fs = require("fs");
const Confippet = require("electrode-confippet");
const config = Confippet.config;

const extHandlers = Confippet.extHandlers;
extHandlers.json5 = (fullF) => JSON5.parse(fs.readFileSync(fullF, "utf8"));

Confippet.presetConfig.load(config, {
  extSearch: ["json", "json5", "yaml", "js"],
  extHandlers,
  providers: {
    customConfig: {
      name: "{{env.CUSTOM_CONFIG_SOURCE}}",
      order: 300,
      type: Confippet.providerTypes.required
    }
  }
});

The above compose option adds a new provider that looks for a file named by the environment variable CUSTOM_CONFIG_SOURCE and will be loaded after all default sources are loaded (controlled by order).

It also adds a new extension handler, json5, to be loaded after json.

To further understand the _$ and the compose options, please see the documentation for store, composeConfig, and processConfig.

Built with :heart: by Team Electrode @WalmartLabs.