Skip to content

rhangai/config-builder

Repository files navigation

ConfigBuilder

Create your configuration files with ease.

Installation

npm install --save-dev "@renanhangai/config-builder"
# or
yarn add --dev "@renanhangai/config-builder"

Usage

config-builder [inputs...] -o outputfile

Types

Every file will be parsed/written according to its extension. The following types are supported:

Type Input Output
js Y Y
json Y Y
json5 Y N
yaml Y Y
php N Y
# Reading
config-builder input.json
config-builder input.default.json +input.yml
config-builder input.default.json input2.yml +custom.json +env.json

# Writing
config-builder [inputs...] -o file.js
config-builder [inputs...] -o file.yml
config-builder [inputs...] -o file.php

Processing

Inputs will merged, and processed by using the doT template syntax. And keys starting with $ are skipped.

input.json

{
  "$database": {
    "name":     "my_database",
    "host":     "localhost",
    "username": "root",
    "password": "root"
  },
  "mysql": {
    "dns": "mysql:dbname={{= it.$database.name }};host={{= it.$database.host }};port={{= it.$database.port || 3316 }};charset=utf8",
    "username": "{{= it.$database.username }}",
    "password": "{{= it.$database.password }}"
  },
  "sh": {
    "cmd": "mysql",
    "args": [
      "-u", "{{= it.$database.username }}",
      "-p{{= it.$database.password }}",
      "{{= it.$database.name }}"
    ]
  }
}

When run config-builder input.json, will output

{
  "mysql": {
    "dns": "mysql:dbname=my_database;host=localhost;port=3316;charset=utf8",
    "username": "root",
    "password": "root"
  },
  "sh": {
    "cmd": "mysql",
    "args": [
      "-u",
      "root",
      "-proot"
      "my_database"
    ]
  }
}

You can access the environment variables with it.$env (Therefore you cannot overwrite it with your settings)

Inline Configuration

Inline configuration is a way to provide inline

config-builder debug=false
# { debug: false }

config-builder input.json '$database.password=123456'
# {
#   "mysql": {
#     "dns": "mysql:dbname=my_database;host=localhost;port=3316;charset=utf8",
#     "username": "root",
#     "password": "123456"
#   },
#   "sh": {
#     "cmd": "mysql",
#     "args": [
#       "-u",
#       "root",
#       "-p123456",
#       "my_database"
#     ]
#   }
# }

Optional Inputs

All inputs are mandatory, but sometimes it is useful to have optional config files to overwrite your configuration if they exist. In that case, you can:

config-builder input.default.json +input.json

Then, the file input.json will not be required, and will not throw in the case it does not exists.

Environment variable inputs

If the input begins with $, then it will be read directly from process.env

config-builder \$MY_CONFIG_FILE

Then, the input will be used as process.env.MY_CONFIG_FILE

Asking for questions

This modules also uses the inquirer to prompt for values

Create a questions.js file:

module.exports = [{
  "type": "input",
  "name": "username",
  "message": "What is your username?"
}]

Then an input config:

{
  "db": {
    "username": "{{= it.$answers.name }}",
  }
}

If the name is something like: $env.MY_VAR, then the environment variable will be overwritten and the default value will be the current environment value

Output directory

You can pass an --output-dir parameter to output files on the given directory

config-builder test.json --output-dir build/configs -o config.json -o config.yml

The files will be generated as build/configs/config.json and build/configs/config.yml

There is an option to pass an output dir as a list of paths, so the last valid path will be used (good with environmental variables). Ex:

config-builder test.json --output-dir "dist:config" -o output.json
config-builder test.json --output-dir "dist:$OUTPUT_DIR" -o output.json

On the first case dist:config will be split into [ "dist", "config" ], as both are valid paths, but config comes after, the file will be generated as config/output.json

On the second one dist:$OUTPUT_DIR will be expandaded, and if OUTPUT_DIR is empty, it will be dist: -> ["dist", ""]

Extending configuration

If the input configuration have the property $extends it will be loaded before the current file. May be anything such as the arguments above.

{
  "$extends": "other.json",
  "debug": false
}
// other.json
{
  "$extends": "other.json",
  "debug": true,
  "example": 10
}

If you run config-build input.json the output will be { debug: false, example: 10 }

Advanced options

A file can also be of another type, by using the : modifier.

By running config-builder test.txt:json, the file test.txt will be treated as a json. The same is valid for output files: config-build input.json -o output.ext:yaml

Template compiling

You can also use the config builder to compile template files using the dot compiler

# Generate the file.txt by compiling the file.template.txt
config-builder input.json -t ./file.template.txt:./file.txt

Template compiling .env files

Supose you have an env file: env.template

# Mode
APP_ENV=development
DB_HOST=my-db-host
config-builder input.json -t env.template:.env:env

API

You can also use the builder programatically.

const ConfigBuilder = require( "@renanhangai/config-builder" );

ConfigBuilder.run( [ "fileA.json", "fileB.yml" ], "output.json" )
	.then( function( config ) {
		console.log( "Files written." );
	});

Docker

There is an image available to use with docker if you do not wish to install node on your machine.

docker run --rm -i renanhangai/config-builder --help

You can even alias it: alias config-builder="docker run --rm -i renanhangai/config-builder"

In case you are developing automated scripts with it, i recommend you sourcing:

# Include script
CONFIG_BUILDER_IMAGE=renanhangai/config-builder
eval $(docker run --rm -i "${CONFIG_BUILDER_IMAGE}" --shell docker-bash)

# Run the config-builder
config-builder ...

# If you with to pass environment variables to the build, you must whitelist as docker does not read by default the current env
CONFIG_BUILDER_WHITELIST="DEBUG MY_VAR" config-builder ...