Configuration
In FoalTS, configuration refers to any parameter that may vary between deploy environments (production, development, test, etc). It includes sensitive information, such as your database credentials, or simple settings, such as the server port.
The framework encourages a strict separation between configuration and code and allows you to define your configuration in environment variables, in .env files and in files in the config/ directory.
Config directory structure
|- config/
| |- e2e.json
| |- default.json
| |- development.json
| |- production.json
| |- ...
| '- test.json
|- src/
'- .env
Configuration Files
Configuration values are provided using configuration files in the config/ directory. Several formats are supported: YAML, JSON and JS files.
config/default.yml
settings:
session:
store: "@foal/typeorm"
config/default.json
{
"settings": {
"session": {
"store": "@foal/typeorm"
}
}
}
config/default.js
module.exports = {
settings: {
session: {
store: "@foal/typeorm"
}
}
}
YAML support
The use of YAML for configuration requires the installation of the package
yamljs.npm install yamljsWhen creating a new project, you can also add the flag
--yamlto have all the configuration directly generated in YAML.foal createapp my-app --yamlThe extension of the YAML files must be
.yml.
Deployment Environments
The default configuration files are used regardless of the environment, i.e. regardless of the value assigned to the NODE_ENV environment variable.
Configuration values can also be set or overridden for a specific environment using the filename syntax: config/<environment-name>.{json|yml|js}. If no value is assigned to NODE_ENV, the environment considered is development.
The environment name can be provided in two ways in Foal: via the
NODE_ENVenvironment variable or viaFOAL_ENV. If both of these variables are set, then the value ofFOAL_ENVis used by the configuration system.
Reserved Parameters
All parameters under the keyword settings are reserved for the operation of the framework. You can assign values to those given in the documentation, but you cannot create new ones.
{
"settings": {
"session": {
"store": "@foal/typeorm"
}
},
"customConfiguration": {
"message": "hello world"
}
}
Accessing Configuration Values
The Config class provides two static methods get and getOrThrow for reading configuration values.
The Config.get method
This function takes the configuration key as first parameter.
import { Config } from '@foal/core';
const secret = Config.get('settings.jwt.secret');
The algorithm below is used to retrieve the configuration value:
- Return the value specified in the environment config file if it exists.
- Return the value specified in the default config file it is exists.
- Return
undefinedotherwise.
Specifying a type
The method also accepts a second optional parameter to define the type of the returned value.
import { Config } from '@foal/core';
const foobar = Config.get('settings.foobar', 'boolean|string');
// foobar is of type boolean|string|undefined
When it is set, Foal checks that the configuration value has the correct type and if it does not, it will try to convert it to the desired type (e.g. "true" becomes true). If it does not succeed, a ConfigTypeError is thrown.
| Allowed types |
|---|
| string |
| number |
| boolean |
| boolean|string |
| number|string |
| any |
Specifying a default value
The third optional parameter of the method allows you to define a default value if none is found in the configuration.
const foobar = Config.get('settings.foobar', 'boolean', false);
// foobar is of type boolean
The Config.getOrThrow method
const foobar = Config.getOrThrow('settings.foobar', 'boolean');
// foobar is of type boolean
This method has the same behavior as Config.get except that it does not accept a default value. If no value is found, the method will throw a ConfigNotFoundError.
Environment Variables and .env Files
Configuration files in the config/ directory are usually committed and therefore should not contain sensitive information (such as database credentials).
The recommended approach to provide sensitive information to the application is to use environment variables and .env files which are not committed. Then, in the configuration files, the values are retrieved.
.env
JWT_SECRET="Ak0WcVcGuOoFuZ4oqF1tgqbW6dIAeSacIN6h7qEyJM8="
{
"settings": {
"jwt": {
"secret": "env(JWT_SECRET)",
"secretEncoding": "base64"
}
}
}
If the same variable is provided both as environment variable and in the .env file, then the value of the environment variable is used.
Deployment Environments
Just like the configuration files in the config/ directory, the .env files can be used for several environments: .env.production, .env.test, etc.
Using *.local files
In case you want to have two .env files, one to define the default env vars needed by the application and another to override these values on your local machine, you can use a .env.local file.
If a variable is defined in both files, the value in the .env.local file will take precedence.
Similarly, you can define environment-specific local files (.env.development.local, .env.production.local, etc).
Note on the use of dotenv
Many NodeJS applications use the dotenv library to manage the environment configuration. It loads variables from the .env file if it exists and assigns their values to the process.env object.
When using Foal, it is strongly recommended that you do not use this library as it may break some functionality. For example, you will not be able to use other files such as .env.production and .env.local.
The recommended approach to loading environment variables from .env files is to use Foal's configuration system using the Config or Env class.
Example
// dotenv
const value = process.env.FOO_BAR;
// Foal
import { Env } from '@foal/core';
const value = Env.get('FOO_BAR');