auto-config-js
v1.3.0
Published
Hierarchical NodeJS configuration with Yaml files, environment variables and config merging.
Maintainers
Readme
auto-config-js
Hierarchical NodeJS configuration with Yaml files, environment variables and config merging. Much of this library was inspired on SpringBoot Externalized Configuration.
Usually the configuration files are used externalize default configuration values that can be overridden by system environment variables. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology.
This lib has a single dependency: js-yaml
Quick Features
- Hierarchical configuration
- Configuration tree is available as a javascript object
- Relaxed binding of System Variables
Install
npm install auto-config-jsUsage
Create a YAML file named app.config.yaml in your application current directory:
application: 'my-app'
database:
host: 127.0.0.1
port: 8080As early as possible in your application, import and initialise auto-config-js. Then retrieve the configuration with getConfig wherever you need it:
JavaScript
import { init, getConfig } from 'auto-config-js';
init();
const config = getConfig();
console.log(config.application); // 'my-app'
console.log(config.database.host); // 127.0.0.1TypeScript
import { init, getConfig, type ConfigObject } from 'auto-config-js';
interface AppConfig extends ConfigObject {
application: string;
database: {
host: string;
port: number;
};
}
init();
const config = getConfig<AppConfig>();
console.log(config.application); // 'my-app'
console.log(config.database.host); // 127.0.0.1Configuration file
Content Format
The file content format must be a valid YAML format.
YAML is a superset of JSON and, as such, is a convenient format for specifying hierarchical configuration data in a more human-readable way.
⚠️ Note that the use of kebap-case is supported but it requires the use of bracket notation when using the configuration object. Example:
config['my-app-name'];⚠️ Although Javascript and YAML are case sensitive and accept properties with same name but different case in the same object (e.g. variable/VARiable, this lib will throw an error in such cases. This constraint has the goal to improve the configuration readability and to make it possible the override of such properties by system variables.
Name Convention
Each configuration file in auto-config-js is called a profile configuration. Because of that, configuration files are named using the following convention:
app.<PROFILE>.config.yamlThe <PROFILE> placeholder uses by default the NODE_ENV value. It can be overridden by passing the optional profile parameter to init (check API).
Profiles can be defined hierarchically using the include keyword. The include keyword expects an array of profiles names (strings) to be included. The configuration loads each file and merges with the current configuration. Example:
include: ['base', 'staging']
application: 'my-app'
database:
host: 127.0.0.1
port: 8080This configuration will merge the base and staging profiles (profiles on the right override the profiles on the left), then merge the result with this defined profile to build the configuration object. As a last step the auto configuration reads the system variables looking for values to be overridden.
Location
auto-config-js loads configuration files from the directory specified via configDirectory (defaults to process.cwd()).
Type conversion
The type conversion is controlled by js-yaml. This lib uses the default schema (all supported YAML types, without unsafe ones).
If necessary a few internals can be exposed in the future for further configuration and JSON support.
Access to the configuration
The configuration will be available to the application as a javascript object, having the same hierarchical structure defined in the YAML file. This means the following configuration:
session:
cookie:
maxAge: 86400000
secure: trueCan be accessed like:
config.session.cookie.maxAge; // 86400000
config.session.cookie.secure; // trueRelaxed Binding
Most operating systems impose strict rules around the names that can be used for environment variables. For example, Linux shell variables can contain only letters (a to z or A to Z), numbers (0 to 9) or the underscore character (_). By convention, Unix shell variables will also have their names in UPPERCASE.
auto-config-js relaxed binding rules are, as much as possible, designed to be compatible with these naming restrictions.
To convert a property name in the canonical-form to an environment variable name you can follow these rules:
- Replace dots (
.) with underscores (_). - Remove any dashes (
-). - Convert to uppercase.
For example, we could bind the following properties with the environment variables:
| Property | Environment variable |
| ----------------- | -------------------- |
| oauth.client-id | OAUTH_CLIENTID |
| oauth.clientId | OAUTH_CLIENTID |
⚠️️ Underscores cannot be used to replace the dashes in property names. If you attempt to use
OAUTH_CLIENT_IDwith the example above, no value will be bound.
API
init
init(options?: InitOptions): voidParameters
profile?: string- Optional
- Name of the profile to be loaded
- Defaults to the value of
NODE_ENV
configDirectory?: string- Optional
- The relative or absolute path to the directory where the configuration files are located
- Defaults to
process.cwd()
Example
JavaScript
import { init } from 'auto-config-js';
init({
profile: 'development',
configDirectory: './config/',
});TypeScript
import { init, type InitOptions } from 'auto-config-js';
const options: InitOptions = {
profile: 'development',
configDirectory: './config/',
};
init(options);getConfig
getConfig<T extends ConfigObject = ConfigObject>(): TParameters
- None
Return
- The configuration as a plain object with the same structure defined in the YAML file
Example
JavaScript
import { init, getConfig } from 'auto-config-js';
init({ profile: 'development', configDirectory: './config/' });
const config = getConfig();
console.log(config.database.host);TypeScript
import { init, getConfig, type ConfigObject } from 'auto-config-js';
interface AppConfig extends ConfigObject {
database: {
host: string;
port: number;
};
}
init({ profile: 'development', configDirectory: './config/' });
const config = getConfig<AppConfig>();
console.log(config.database.host); // typed as string
console.log(config.database.port); // typed as numberContributing Guide
See CONTRIBUTING.md
