-
Notifications
You must be signed in to change notification settings - Fork 6
Module configuration options
- Module setup - options overview
- envKey option
- Methods for determining location of the env file
- Other module configuration options
- Asynchronous Registration
Normal operation is to set up the NestjsConfigManager using the
register()
method. This step is sometimes referred to as "configure"
with other Nest modules, but since "configure" is part of the name of this module,
we'll use the term set up. Rest assured, this is the exact same way you normally configure an add-on Nest module. Note also that add-on modules vary between using the
method name register()
and forRoot()
for this configuration method, but
they are otherwise equivalent in function.
You saw an example of this setup step in the Quick Start with code like:
@Module({
imports: [
ConfigManagerModule.register({
useEnv: {
folder: 'config',
}
}),
],
providers: [ConfigService],
exports: [ConfigService],
})
The NestJSConfigManager is a fully asynchronous and dynamic module,
which means that you can do this registration synchronously (using the register()
method shown above) or asynchronously (registerAsync()
as described later on this page).
To use register()
, pass it an options object of type ConfigOptions
. ConfigOptions
is defined as follows:
interface ConfigOptions {
envKey?: string;
useFile?: string;
useEnv?: boolean | { folder?: string; };
useFunction?: (rootFolder: string, environment: string) => string;
defaultEnvironment?: string;
allowExtras?: boolean;
allowMissingEnvFile?: boolean;
}
The envKey
option takes a string naming the environment variable that is used
to determine the current environment.
The term current environment corresponds to the
conventional use of the environment variable
NODE_ENV
to designate whether a
particular runtime environment is something like 'production'
or 'development'
.
As mentioned, this is just a convention, and you can easily extend the set of
possible values to model other environments like 'staging'
, etc.
NestJSConfigManager uses the current environment to help determine the
location of the .env
file, as you'll see below.
The default value for envKey
is NODE_ENV
, following the above convention.
This means NestJSConfigManager will check the value of the NODE_ENV
environment variable to determine the current environment.
However, you may choose any environment variable to model your current
environment. For example, you may choose to use the environment variable
MY_ENVIRON
, in which case you would:
- First, ensure that this variable is set to the proper value (such as
'development'
,'test'
or'production'
). - Register this with the
ConfigManagerModule
using theuseEnv
option.
Note that envKey
(and the current environment) is used by
NestJSConfigManager when the useEnv
or useFunction
methods
of determining the location of the .env
file is employed, but is ignored
for the useFile
method.
There are three mutually exclusive options for determining the location of the
.env
file. Choose one of these. For each, the concept of root folder is
important. NestJSConfigManager determines the root folder as either:
- The project root folder (this applies to running in development mode)
- The current working directory - if it cannot determine the project root
folder, it will use the current working directory (
process.cwd()
), which is the directory where thenode
command was invoked.
With useFile
you supply a path and filename relative to the root folder.
envKey
is ignored.
The value of useEnv
can either be a boolean (true
to enable it, and accept
the default folder setting), or an options object specifying a folder
.
For example:
// no folder specified; folder sub-option will default to using the `config`
// subfolder below the 'root folder'
ConfigManagerModule.register({
useEnv: true
})
or
ConfigManagerModule.register({
useEnv: {
folder: 'myconfigs'
}
})
With useEnv
, NestJSConfigManager uses the environment variable specified
in envKey
(or NODE_ENV
if envKey
is omitted) to build the name of the
.env
file. It does so by prepending the value of the envKey
with the
string .env
. For example, if the envKey
is NODE_ENV
, and its current
value is 'production'
, the filename portion of the .env
file that it will
look for is
production.env
useEnv
has a sub-option (folder
) that specifies the path, relative to the
root path, in which NestJSConfigManager will look for the .env
file.
If omitted, the folder used will be the root path concatenated with /config
.
Usually you want to specify a folder
when using the useEnv
option.
The useFunction
method takes as its value a function with the following signature
(rootFolder: string, environment: string) => string;
If using this method, you must supply a function that constructs and returns
the appropriate full file path (an absolute file path, based on the
rootFolder
value, including a filename). For example, take a look at the
configResolver
function below:
import { Module, Global } from '@nestjs/common';
import { ConfigManagerModule } from '@nestjsplus/config';
import { ConfigService } from './config.service';
function configResolver(rootFolder, environment) {
return `${rootFolder}/config/${environment}.env`;
}
@Global()
@Module({
imports: [
ConfigManagerModule.register({
useFunction: configResolver,
}),
],
providers: [ConfigService],
exports: [ConfigService],
})
export class ConfigModule {}
Using this mechanism, NestJSConfigManager will look for different .env
files based on runtime information. For example, if running inside a Docker
container with the NODE_ENV
variable set to production
, and the Docker
WORKDIR
set to /app
, NestJSConfigManager with this resolver
function
will look for the file
/app/config/production.env
On the other hand, if the app is running in development and the project root
folder is /home/john/myapp
, and NODE_ENV
is set to development
, it will
look for the file
/home/john/myapp/config/development.env
With this mechanism, you can both preserve the relative location of the
env file (for both environments, it's in the /config
sub-folder which in turn
is is within the root folder) and dynamically
determine the name of the file (e.g., vary it from development
to production
).
In other words, the function you supply delivers a mapping that supplies
the appropriate .env
file for each environment.
This, in conjunction with the cascade,
should allow you to manage deployment by simply switching out your environment
(e.g., possibly using a .env
file in development, but external environment
variables in production).
Imagine you do not want to use .env
files in production (some consider
it best practice to avoid doing so), but do want to use them in development.
So far so good. However, this means that you will need to ensure that an
environment variable (typically NODE_ENV
) is set in everyone's development
environment. While this is certainly common and not too complicated, it can
be convenient to bypass this requirement and simply establish a default value
for the current environment. Use the defaultEnvironment
option to do so.
When it is set, if no NODE_ENV
(or alternative environment variable you have
chosen to indicate the current environment) value is set, the defaultEnvironment
will be used. If a value is found for the NODE_ENV
(or your alternative)
environment variable, that will be used. If you set this option, ensure that you
override its behavior in production by setting the value for NODE_ENV
(or
your alternative).
This optional boolean field determines whether the NestJSConfigManager
will allow extra variables (those not defined in the schema)
in the .env
file.
Defaults to false
. When true
, will take the exit action
(see onError below) if the .env
file has variables not
declared in the schema.
This can be useful during rapid prototyping when you just want to quickly add a new environment variable. Note that, because there is no schema validation for such extra variables, their values will not be validated.
This optional string field determines the exit action: namely, what happens
when NestJSConfigManager
encounters an error. You want to consider this setting carefully.
The default action is exit
, which causes the process to exit (process.exit(0)
).
This is the default because normally, if you have an invalid configuration,
the application is in an unknown state. Since typically the rest of your code
assumes the application is configured correctly, you probably want to avoid being
in this unknown state.
You may also choose one of two other alternatives:
-
throw
- instead of exiting, your config service will throw anInvalidConfigurationError
error. This can be useful when running unit tests, as it's easier to test for exceptions than process exits. If the configuration service throws due to failed variable validations, theInvalidConfigurationError
will have two properties (missingKeys
andvalidationErrors
) that you can inspect to determine the nature of the failure. -
continue
- instead of exiting or throwing, the application will continue, ignoring any configuration errors. This mode is not recommended except for testing/prototyping.
If false (the default), the configuration service will take the exit action
if there is no .env
file found.
If true, the configuration service will ignore the fact that a .env
file is
missing and simply proceed to load using just the external environment.
For example, if your policy is to not use .env
files in production,
but only use external environment variables, you should set this option to
true.
In development, failure to resolve a .env
file might be considered an error.
NestJSConfigManager also supports asynchronous registration using the
registerAsync()
method. As with other modules, you can use any of the following
methods:
useFactory
useClass
useExisting