Skip to content

How it works

John Biundo edited this page Jul 14, 2019 · 12 revisions

Table of Contents

General concept

Here we'll talk about how NestJSConfigManager interacts with the environment. While you control the details of this with a schema and module configuration options, the basic mechanics are built into the module.

Basic environment variables and Node

Loosely speaking, when your app starts, node reads the environment and loads it into a hash that is available to your app at process.env. If you dump process.env, you'll see something like this:

{
  LESSOPEN: '| /usr/bin/lesspipe %s',
  npm_package_dependencies__nestjs_platform_express: '^6.0.0',
  npm_package_devDependencies__types_node: '^10.12.18',
  npm_package_devDependencies__types_supertest: '^2.0.7',
  npm_package_devDependencies_ts_node: '8.1.0',
  MAIL: '/var/mail/john',
  USER: 'john',
  npm_package_scripts_start_prod: 'node dist/main.js',
  npm_package_dependencies_rxjs: '^6.3.3',
  HOME: '/home/john',
   npm_config_editor: 'vi',
  npm_config_timing: '',
  LANG: 'en_US.UTF-8',
  PWD: '/home/john/',
  INIT_CWD: '/home/john/code',
  DB_USERNAME: 'john',
  DB_PASSWORD: 'mypassword',
  DB_NAME: 'mydb'
}

dotenv provides what I call a shim on the environment. If you want to create environment variables that are visible inside node, you typically define them in the environment itself:

linux example

export MY_NAME=John

Windows example

set MYNAME=John

This can be a nuisance because:

  • environment variables are ephemeral -- they go away when you reboot or open a new shell/terminal window (unless you make them permanent with something like a .bashrc file, which makes it harder to toggle them with ease)
  • what if you want to have different environment variable values in development, stage, test, etc.?

How dotenv helps

dotenv solves this problem. Instead of using the external environment system shown above, you create a .env file with these values. To add new environment variables, just add a new value to the file. To have different environment variables on different platforms, just create new .env files.

// /project/config/development.env
DB_PASS=secret
DB_NAME=mydb
...

What you get with dotenv

Using dotenv, when you read process.env, dotenv will fill in any missing environment variables. There's a sort of "cascade" going on:

Note that dotenv will never override an environment variable that is present in the actual external environment. In the example above, DB_PASS appears both in the external environment and in the .env file. What's visible after dotenv processes the environment is the value from the external environment.

Building on dotenv

NestJSConfigManager builds on top of dotenv by:

  • Making it easy to dynamically locate the actual .env file (which can be named anything you want)
  • Providing a convenient way to validate environment variable values
  • Allowing you to make variables required or optional. Optional values (required set to false) must have a default value.

We discuss dynamic file location determination in Module Configuration Options.

We discuss validation in Schemas.

We also discuss the required setting in Schemas, which has an effect on the cascade. If you read that section now, you'll see a variation on the diagram shown above that illustrates handling optional environment variables with default values.