[Deprecated] App configuration made simple for Node.js. Now moved to
Supports:
- app configuration file of type
json
orenv
(custom type parser can also be implemented through implementingIParser
& usingsetparser
) Environment
specific configuration overloading- Now with the power of interpolate-json to support interpolation (or parameter substitution) inside app-configuration (strongly recommend to go through the documentation to know the full power of interpolation)
# with npm
npm install @terran-source/dotconfig
# or with Yarn
yarn add @terran-source/dotconfig
// declare the variable at the beginning
const { loadConfig } = require('@terran-source/dotconfig');
/**
* App Directory structure
*
* app/
* | -- package.json
* | -- index.js
* | -- app-config.json
* | -- app-config.dev.json
* | -- app-config.test.json
* | -- app-config.prod.json
*
*/
// ** app-config.json **
{
"scheme": "http",
"server": "localhost",
"port": "8080",
"baseKey": "baseValue",
"user": {
"name": "${USER_NAME}",
"password": "${USER_PASSWORD}"
},
"url": "${scheme}://${=${user.name}.toLowerCase()=}:${= encodeURIComponent(${user.password}) =}@${server}:${port}"
}
// ** app-config.dev.json **
{
"baseKey": "devValue",
"someDevKey": "someDevValue"
}
// ** app-config.test.json **
{
"scheme": "https",
"server": "test.example.com",
"baseKey": "testValue"
}
// ** app-config.prod.json **
{
"scheme": "https",
"server": "${APP_SERVER_NAME}",
"port": "${APP_PORT}",
"baseKey": "${BASE_KEY}"
}
// ** index.js **
// declare the variable at the beginning
const { loadConfig } = require('@terran-source/dotconfig');
// load process.appConfig
let { parsed, error } = loadConfig('app-config.json');
if (error) {
console.log(error);
}
// now either use parsed or process.appConfig (recommended)
console.log(`parsed: ${JSON.stringify(parsed, null, 2)}`);
console.log(`url: ${process.appConfig.url}`);
# execute using:
USER_NAME=DevUser USER_PASSWORD=P@ssw0rd node index.js
# output:
parsed: {
"scheme": "http",
"server": "localhost",
"port": "8080",
"baseKey": "devValue",
"user": {
"name": "DevUser",
"password": "P@ssw0rd"
},
"url": "http://devuser:P%40ssw0rd@localhost:8080",
"someDevKey": "someDevValue"
}
url: http://devuser:P%40ssw0rd@localhost:8080
Let's break it up:
USER_NAME
& USER_PASSWORD
are set through environment variable. This will replace the placeholders ${USER_NAME}
& ${USER_PASSWORD}
in app-config.json. The environment
is not specified. Hence, it'll be set as default value dev
. Now, the loadConfig
function will search for any dev
environment specific configuration (i.e. any file with name app-config.dev
.json in the same directory, where it finds the original app-config.json). If it finds the additional file, it loads the details & overwrite anything, that matches with the base configuration or add anything, that is not present. i.e.
"baseKey": "baseValue"
becomes"baseKey": "devValue"
- additional
"someDevKey": "someDevValue"
key is added
To load environment specific configurations:
let { parsed, error } = loadConfig({ env: 'test', path: 'app-config.json' });
// or
let { parsed, error } = loadConfig('test', { path: 'app-config.json' });
// or
// set Environment variable `NODE_ENV=test` and then run (recommended)
let { parsed, error } = loadConfig(true, { path: 'app-config.json' });
console.log(`parsed: ${JSON.stringify(parsed, null, 2)}`);
console.log(`url: ${process.appConfig.url}`);
# execute: for loadConfig(true, { path: 'app-config.json' })
NODE_ENV=test USER_NAME=TestUser USER_PASSWORD=P@ssw0rd node index.js
# output:
parsed: {
"scheme": "https",
"server": "test.example.com",
"port": "8080",
"baseKey": "testValue",
"user": {
"name": "TestUser",
"password": "P@ssw0rd"
},
"url": "https://testuser:P%40ssw0rd@test.example.com:8080"
}
url: https://testuser:P%40ssw0rd@test.example.com:8080
/**
* App Directory structure
*
* app/
* | -- package.json
* | -- index.js
* | -- .env
* | -- dev.env
* | -- test.env
* | -- prod.env
*
*/
// ** .env **
key = "value"
"baseKey"= "baseValue"
'subKey'="subValue"
"someKey"= 'someValue'
// ** dev.env **
devKey=devValue
"baseKey"= "devValue"
'subKey'="subDevValue"
"someKey"= 'someDevValue'
// ** test.env **
testKey=testValue
"baseKey"= "testValue"
'subKey'="subTestValue"
"someKey"= 'someTestValue'
// ** prod.env **
"baseKey"= "${BASE_KEY}"
'subKey'="${SUB_KEY}"
"someKey"= '${SOME_KEY}'
// ** index.js **
// declare the variable at the beginning
const { loadConfig } = require('@terran-source/dotconfig');
// load process.appConfig
let { parsed, error } = loadConfig(true, { path: '.env' });
if (error) {
console.log(error);
}
// now either use parsed or process.appConfig (recommended)
console.log(`parsed: ${JSON.stringify(parsed, null, 2)}`);
console.log(`baseKey: ${process.appConfig.baseKey}`);
For the Production environment, set the proper ENVIRONMENT_VARIABLE
to be interpolated.
# execute: for loadConfig(true, { path: '.env' })
NODE_ENV=prod BASE_KEY='some base key' SUB_KEY='some sub key' SOME_KEY='some other key' node index.js
# output:
parsed: {
"key": "value",
"baseKey": "some base key",
"subKey": "some sub key",
"someKey": "some other key"
}
baseKey: some base key
Syntax: loadConfig([true | env | file.extension], options);
The loadConfig
function takes at most 2 parameters
If the NODE_ENV
environment variable is set as the environment
, then passing true
as first parameter signifies to get env
from NODE_ENV
environment value.
// ** index.js **
const { loadConfig } = require();
loadConfig(true, { path: 'app-config.json' });
// do your job
db.connect(process.appConfig.url);
# to load test config
NODE_ENV=test node index.js
# to load uat config
NODE_ENV=uat node index.js
# to load prod config
NODE_ENV=prod node index.js
- example:
dev
,test
,uat
,staging
,prod
etc.
The application environment name, which to load the configuration file for. Should be lowercase (by tradition) & not contain any space or special character.
- example: "custom-config-file.ext"
The configuration file path (either relative or absolute).
const { loadConfig } = require('@terran-source/dotconfig');
loadConfig('app-config.json');
- type:
json
- default:
{
debug: false,
encoding: 'utf8',
env: 'dev',
path: 'config.json',
type: 'json'
}
more in Configurations
- type:
json
{
parsed: {}, // same as process.appConfig if succeed
error: null // or an Error object with `message` if anything goes wrong
}
If it succeeds to load the configuration file & to parse the information containing within, it sets the process.appConfig
with the value & will return with an Object with
parsed
key with the same value asprocess.appConfig
.error
key, which isnull
if succeeds or the error details if fails.
The options
setup.
-
type:
boolean
-
default:
false
Set it true
to turn on logging to help debug why certain things are not working as expected. Can be turned on globally.
- type:
string
- default:
utf8
The encoding of the configuration file, supplied in path
.
- type:
string
- default:
dev
In a multi-environment setup (e.g. dev, test, uat, prod), this is the specifier for environment type. In practical case, it seems more logical to not set this one through options
, but to set the NODE_ENV
environment variable and pass true as first parameter to loadConfig
function (see Example).
- type:
string
- default:
config.json
The path of the configuration file. It can either be a relative path or an absolute one.
- type:
string
- default:
json
- supported types:
json
,env
The configuration file extension.
// When declared as a variable at the beginning
const dotconfig = require('@terran-source/dotconfig');
Described so far since Declaration
& Definition
.
// Syntax I
const dotconfig = require('@terran-source/dotconfig');
dotconfig.loadConfig(opt);
// Syntax II
const { loadConfig } = require('@terran-source/dotconfig');
loadConfig(opt);
IParser lets others to implement a custom type of parser (like toml, xml etc.)
// ** custom-parser.js **
const { IParser } = require('@terran-source/dotconfig');
// declare a class that extends IParser
class CustomParseClass extends IParser {
constructor() {
super();
}
// declare a parse function, that takes two parameters
parse(filePath, encoding) {
let json = // read filePath & create a json Object
return json;
}
}
module.exports = new CustomParseClass();
// ** somewhere.js **
const { loadConfig, setParser } = require('@terran-source/dotconfig');
const customParser = require('/path/to/custom-parser');
// define customParser for customType
setParser('customType', customParser);
// now a configuration file with extension `.customType` can be loaded
loadConfig('custom-app-config.customType');
db.connect(process.appConfig.url);
-
syntax: setParser(customType, customParser, defaultFileName = null, resetType = false)
-
customType - {type:
string
} It generally represents the file extension -
defaultFileName - {type:
string
, default:null
} (optional) default configuration filename (without extension) -
resetType - {type:
Boolean
} (optional) make the supplied customType as the default type when the config.loadConfig() runs next time
-
// ** somewhere.js **
const { loadConfig, setParser } = require('@terran-source/dotconfig');
const customParser = require('/path/to/custom-parser'); // custom-parser should implement IParser
// define customParser for customType & make it default
setParser('customType', customParser, 'custom-config-file', true);
// The following command now loads
// - `custom-config-file.customType`
// - `custom-config-file.dev.customType`
loadConfig();
// or if NODE_ENV is set to a different environment, e.g. 'test'
// it loads
// - `custom-config-file.customType`
// - `custom-config-file.test.customType`
loadConfig(true);
// Now process.appConfig is available
db.connect(process.appConfig.url);
Globally turn on debug
flag.
// to globally turn it on
const dotconfig = require('@terran-source/dotconfig').debug();
// to globally turn off
dotconfig.debug(false);
Resets the options.
const dotconfig = require('@terran-source/dotconfig');
// do some custom job
let result = dotconfig.loadConfig({
debug: true, // globally turn it on
env: 'test', // globally set environment
path: 'app-config.json', // not affecting next call
});
// start using process.appConfig or result.parsed
let result2 = dotconfig.loadConfig(); // `debug` is still set as true, `env` is still 'test', but, `path` will be default, i.e. `config.json`
// now if you want to reset debug & all other options
interpolation.reset();