npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dotenv-extended

v3.1.0

Published

A module for loading .env files and optionally loading defaults and a schema for validating all values are present.

Readme

dotenv-extended

Extended .env loading with defaults and schema validation.

Supported Node Versions

  • Node 20.x
  • Node 22.x
  • Node 24.x

I've been a big fan of the dotenv for a quite some time (in fact, this library uses dotenv under the hood for the .env file parsing). However, while working on some bigger projects, we realized that the managing of the .env files became a bit of a chore. As the files changed in the development environments, it became a tedious manual process to compare and figure out what needed to be added or removed in the other environments.

This library solves some of these issues by introducing the concept of 3 files which are used together to provide environment-specific variables, default values and a validation schema:

.env

The environment specific file (not committed to source control). This file will have sensitive information such as usernames, passwords, api keys, etc. These would be specific to each environment and should not be committed to source control. The format is a series of key-value pairs. Any line starting with # or ; are commented out and ignored.

# .env file
MONGO_HOST=localhost
MONGO_DATABASE=TestDB
MONGO_USER=dbusername
MONGO_PASS=dbpassword!

.env.defaults

Common configuration defaults across all environments (commited to source control). This contains overall app configuration values that would be common across environments. The .env.defaults file is loaded first and then the .env file is loaded and will overwrite any values from the .env.defaults file. Format is identical to the .env file.

.env.schema

Defines a schema of what variables should be defined in the combination of .env and .env.defaults. Optionally, you can have the library throw an error if all values are not configured or if there are extra values that shouldn't be there.

The .env.schema file should only have the name of the variable and the = without any value:

MONGO_HOST=
MONGO_DATABASE=
MONGO_USER=
MONGO_PASS=

Additionally .env.schema can include regular expressions; see below for how to configure the library to throw an error upon failed regex validation.

I have tried to stay as compatible as possible with the dotenv library but there are some differences.

Installation

npm i --save dotenv-extended

Development

npm run check

npm run check runs linting, formatting checks, and tests.

Use individual commands only when needed:

npm run build
npm run lint
npm run format
npm run test:unit
npm test

Usage

As early as possible in your main script:

require('dotenv-extended').load();

Or if you prefer import syntax:

import dotEnvExtended from 'dotenv-extended';
dotEnvExtended.load();

Create a .env file in the root directory of your project. Add environment-specific variables on new lines in the form of NAME=VALUE.

For example:

MONGO_HOST=localhost
MONGO_DATABASE=TestDB
MONGO_USER=dbusername
MONGO_PASS=dbpassword!

process.env now has the keys and values you defined in your .env file.

mongoose.connect('mongodb://' + process.env.MONGO_HOST + '/' + process.env.MONGO_DATABASE, {
    user: process.env.MONGO_USER,
    pass: process.env.MONGO_PASS,
});

Load Configs from command line

You may also load the .env files from the command line. Add in the require dotenv-extended/config along with any of the options that the load method takes prefixed with dotenv_config_. e.g.:

node -r dotenv-extended/config your_script.js

Or to specify load options:

node -r dotenv-extended/config your_script.js dotenv_config_path=./env/.env dotenv_config_defaults=./env/.env.defaults

dotenv_config_* values are normalized to the same option names as load(), supporting both snake_case and kebab-case style keys.

Load Environment Variables and pass to non-NodeJS script

New in 2.0.0, is a feature inspired by cross-env to allow you to load environment variables from your .env files and then pass them into a non-NodeJS script such as a shell script. This can simplify the process of maintaining variables used in both your Node app and other scripts. To use this command line executable, you will either need to install globally with the -g flag, or install dotenv-extended in your project and reference it from your npm scripts.

The package exposes two equivalent CLI commands:

  • dotenv-extended (original)
  • dee (short alias)

Install Globally:

npm install -g dotenv-extended

Now call your shell scripts through dee (this uses the defaults):

dee ./myshellscript.sh --whatever-flags-my-script-takes

Configure dee (or dotenv-extended) by passing any of the dotenv-extended options before your command. Preceed each option with two dashes --:

dee --path=/path/to/.env --defaults=/path/to/.env.defaults --errorOnMissing=true ./myshellscript.sh --whatever-flags-my-script-takes

--path and --defaults also support comma-separated layered files:

dee \
  --defaults=./env/.env.defaults.base,./env/.env.defaults.local \
  --path=./env/.env.base,./env/.env.development \
  ./myshellscript.sh

You can also print the merged dotenv configuration (without full process.env) instead of executing a command:

dee --print
dee --print=dotenv
  • --print outputs JSON
  • --print=dotenv outputs KEY=value lines

The following are the flags you can pass to the dotenv-extended cli with their default values. these options detailed later in this document:

--encoding=utf8
--silent=true
--path=.env
--defaults=.env.defaults
--schema=.env.schema
--errorOnMissing=false     # or --error-on-missing=false
--errorOnExtra=false       # or --error-on-extra=false
--errorOnRegex=false       # or --error-on-regex=false
--includeProcessEnv=false  # or --include-process-env=false
--assignToProcessEnv=true  # or --assign-to-process-env=true
--overrideProcessEnv=false # or --override-process-env=true

Options

Defaults are shown below:

require('dotenv-extended').load({
    encoding: 'utf8',
    silent: true,
    path: '.env',
    defaults: '.env.defaults',
    schema: '.env.schema',
    schemaExtends: undefined, // string | string[]
    errorOnMissing: false,
    errorOnExtra: false,
    errorOnRegex: false,
    errorOnMissingFiles: false,
    includeProcessEnv: false,
    returnSchemaOnly: false,
    assignToProcessEnv: true,
    overrideProcessEnv: false,
});

Configure via Environment Variables (New in 2.8.0)

You may also set the configuration values via environment variables loaded from process.env shown below with defaults:

DOTENV_CONFIG_ENCODING=utf8
DOTENV_CONFIG_SILENT=true
DOTENV_CONFIG_PATH=.env
DOTENV_CONFIG_DEFAULTS=.env.defaults
DOTENV_CONFIG_SCHEMA=.env.schema
DOTENV_CONFIG_SCHEMA_EXTENDS=
DOTENV_CONFIG_ERROR_ON_MISSING=false
DOTENV_CONFIG_ERROR_ON_EXTRA=false
DOTENV_CONFIG_ERROR_ON_REGEX=false
DOTENV_CONFIG_ERROR_ON_MISSING_FILES=false
DOTENV_CONFIG_INCLUDE_PROCESS_ENV=false
DOTENV_CONFIG_RETURN_SCHEMA_ONLY=false
DOTENV_CONFIG_ASSIGN_TO_PROCESS_ENV=true
DOTENV_CONFIG_OVERRIDE_PROCESS_ENV=false

DOTENV_CONFIG_PATH, DOTENV_CONFIG_DEFAULTS, and DOTENV_CONFIG_SCHEMA_EXTENDS can each be set to comma-separated file paths for layered loading.

The load() function always returns an object containing the variables loaded from the .env and .env.defaults files. By default the returned object does not contain the properties held in process.env but rather only the ones that are loaded from the .env and .env.defaults files.

const myConfig = require('dotenv-extended').load();

encoding (default: utf8)

Sets the encoding of the .env files

silent (default: true)

Sets whether a log message is shown when missing the .env or .env.defaults files.

path (default: .env)

The main .env file that contains your variables.

  • Accepts string or string[] in code.
  • Accepts comma-separated paths via environment variable:
    • DOTENV_CONFIG_PATH=./.env.base,./.env.dev
  • Merge order is deterministic:
    • load each path entry in order
    • later entries override earlier keys

defaults (default: .env.defaults)

The file that default values are loaded from.

  • Accepts string or string[] in code.
  • Accepts comma-separated paths via environment variable:
    • DOTENV_CONFIG_DEFAULTS=./.env.defaults.base,./.env.defaults.shared
  • Merge order is deterministic:
    • load each defaults entry in order
    • later entries override earlier keys
    • path layers are applied after all defaults layers, so path still overrides defaults

schema (default: .env.schema)

The file that contains the schema of what values should be available from combining .env and .env.defaults

schemaExtends (default: undefined)

Optional schema extension file(s) layered on top of schema.

  • Accepts string or string[] in code.
  • Accepts comma-separated paths via environment variable:
    • DOTENV_CONFIG_SCHEMA_EXTENDS=./.env.production.schema,./.env.region.schema
  • Merge order is deterministic:
    • load base schema first
    • then apply schemaExtends in order
    • later layers override earlier keys

errorOnMissing (default: false)

Causes the library to throw a MISSING CONFIG VALUES error listing all of the variables missing the combined .env and .env.defaults files.

errorOnExtra (default: false)

Causes the library to throw a EXTRA CONFIG VALUES error listing all of the extra variables from the combined .env and .env.defaults files.

errorOnRegex (default: false)

Causes the library to throw a REGEX MISMATCH error listing all of the invalid variables from the combined .env and .env.defaults files. Also a SyntaxError is thrown in case .env.schema contains a syntactically invalid regex.

errorOnMissingFiles (default: false)

Causes the library to throw a MISSING CONFIG FILE error when configured dotenv files cannot be found. This applies to path, defaults, and schema when they are loaded.

includeProcessEnv (default: false)

Causes the library add process.env variables to error checking. The variables in process.env overrides the variables in .env and .env.defaults while checking

returnSchemaOnly (default: false)

Causes the returned object to include only variables present in .env.schema. This is useful when using includeProcessEnv for validation but you only want schema-defined keys in the final result.

assignToProcessEnv (default: true)

Sets whether the loaded values are assigned to the process.env object. If this is false, values are only available in the returned object from .load().

overrideProcessEnv (default: false)

By defaut, dotenv-entended will not overwrite any varibles that are already set in the process.env object. If you would like to enable overwriting any already existing values, set this value to true.

Layered File Precedence

When using multiple files, merge precedence is:

  1. defaults layers in order (last wins)
  2. path layers in order (last wins)
  3. process.env values, if includeProcessEnv is true and overrideProcessEnv is false

Example:

const config = require('dotenv-extended').load({
    defaults: ['./env/.env.defaults.base', './env/.env.defaults.region'],
    path: ['./env/.env.base', './env/.env.production'],
});

Equivalent via environment variables:

DOTENV_CONFIG_DEFAULTS=./env/.env.defaults.base,./env/.env.defaults.region \
DOTENV_CONFIG_PATH=./env/.env.base,./env/.env.production \
node app.js

Examples

Consider the following three files:

# .env file
DB_HOST=localhost
DB_USER=databaseuser-local
DB_PASS=databasepw!
SHARE_URL=http://www.example.com
# .env.defaults
DB_USER=databaseuser
DB_DATABASE=MyAppDB
# .env.schema
DB_HOST=[a-z]+
DB_USER=[a-z]+
DB_PASS=
DB_DATABASE=
API_KEY=

Load files with default options

const myConfig = require('dotenv-extended').load();

(myConfig.DB_HOST === process.env.DB_HOST) === 'localhost';
(myConfig.DB_USER === process.env.DB_USER) === 'databaseuser-local';
(myConfig.DB_PASS === process.env.DB_PASS) === 'localhost';
(myConfig.DB_DATABASE === process.env.DB_DATABASE) === 'MyAppDB';
(myConfig.SHARE_URL === process.env.SHARE_URL) === 'http://www.example.com';

Load files with errorOnMissing

const myConfig = require('dotenv-extended').load({
    errorOnMissing: true,
});

// Throws ERROR `MISSING CONFIG VALUES: API_KEY`

Load files with errorOnExtra

const myConfig = require('dotenv-extended').load({
    errorOnExtra: true,
});

// Throws ERROR `EXTRA CONFIG VALUES: SHARE_URL`

Load files with errorOnRegex

const myConfig = require('dotenv-extended').load({
    errorOnRegex: true,
});

// Throws ERROR `REGEX MISMATCH: DB_USER`

Contributing

See CONTRIBUTING.md

Migration Notes

Migrating from legacy 2.x tooling

  • Node >=20 is now required.
  • Build/test tooling no longer uses gulp, Babel, esm, or Mocha/NYC.
  • The project now uses:
    • tsup for build output in lib/
    • vitest for tests
    • modern eslint config and prettier
  • Public API is kept compatible (load, config, parse, CLI behavior, and dotenv-extended/config preload entry).

Change Log

See CHANGELOG.md

License

See LICENSE