Skip to content

Releases: kriasoft/envars

v1.0.0

22 Oct 22:39
Compare
Choose a tag to compare

BREAKING CHANGE: This release drops support for custom encryption/decryption algorithms in favor of using a cloud secret manager — Google Secret Manager.

Usage

# .env
# Environment variables for the local development environment
# NOTE: Secret values need to follow this format:
#       secret://[provider]/[resource]
GOOGLE_CLOUD_PROJECT=example
DB_PASSWORD=secret://google/projects/example/secrets/db-password/latest
// core/env.ts
import { cleanEnv, str } from "envalid";

/**
 * Sanitized and validated environment variables.
 * @see https://github.com/af/envalid#readme
 */
export default cleanEnv(process.env, {
  GOOGLE_CLOUD_PROJECT: str(),
  DB_PASSWORD: str(),
});
import { loadEnv } from "envars";

const env = await loadEnv("production", {
  root: ".",
  schema: "./core/env.ts",
  mergeTo: process.env,
});

API

loadEnv(mode?, options?)

mode

Type: string (optional)

Default: undefined

Example: production, development, staging, etc.

options

Type: object (optional)

root

Type: string (optional)

Default: . (current working directory).

The root directory where it looks for .env files.

schema

Type: string (optional)

Default: undefined

Example: ./core/env.ts

The path to the TypeScript or JavaScript module exporting a sanitized environment object. Example:

import { cleanEnv, str } from "envalid";

export default cleanEnv(process.env, {
  GOOGLE_CLOUD_PROJECT: str(),
  DB_PASSWORD: str(),
});

Or, another example using Zod:

import { z } from "zod";

export const env = z
  .object({
    GOOGLE_CLOUD_PROJECT: z.string(),
    DB_PASSWORD: z.string(),
  })
  .parse(process.env);

files

Type: string[] (optional)

Default: [ ".env.<environment>.local", ".env.<environment>", ".env.local", ".env" ]

The list of file patterns where to look for .env files.

mergeTo

Type: object (optional)

Default: undefined
Example: process.env

The object where to merge the loaded environment variables.

Usage with Vite

import { defineConfig } from "vite";
import { loadEnv } from "envars";

export default defineConfig(async ({ mode }) => {
  const env = await loadEnv(mode, {
    root: "../",
    schema: "./core/env.ts",
    mergeTo: process.env,
  });

  return {
    build: {
      ssr: "index.ts",
      target: "esnext",
      sourcemap: true,
    },
  };
});

References

v0.4.0

11 Feb 11:53
Compare
Choose a tag to compare
  • Update dotenv to ^16.0.0
  • Fix the default export to make

v0.3.0

10 Dec 12:42
9269d4a
Compare
Choose a tag to compare
  • [#1] Fix importing from under ESM modules — @koistya
import envars from "envars";

envars.config({ env: "test" });

-- or --

import { config } from "envars";

config({ env: "test" });

-- or --

$ node -r envars/config ./server.js --env=test

v0.2.0

01 Oct 09:54
Compare
Choose a tag to compare

[BREAKING CHANGE] Change the default location where environment variables are being loaded from:

# BEFORE
.env.{envName}.override
.env.{envName}
.env.override
.env

# AFTER
.{envName}.override.env
.{envName}.env
.common.override.env
.common.env
.env

v0.1.1

20 Jul 20:40
Compare
Choose a tag to compare

Bump dotenv version to v10.0.0 (changelog)

v0.1.0

30 Apr 11:17
Compare
Choose a tag to compare

Envars is a Node.js module based on dotenv that loads and decrypts environment variables from .env.* files into process.env.

It allows to store application secrets in .env.* files encrypted making these files safe to be committed into a source control repository.

How to Install

# with NPM
$ npm install envars --save-dev

# with Yarn
$ yarn add envars --dev

Getting Started

Suppose you have local (local development), test (test/QA), and prod (production) application environments. For each of these environments you would create a separate .env.{envName} file in your project. For example:

# .env.local
APP_ORIGIN=http://localhost:8080
PGHOST=127.0.0.1
PGDATABASE=example_local
PGUSER=postgres
PGPASSWORD=
# .env.test
APP_ORIGIN=http://test.example.com
PGHOST=34.72.79.184
PGDATABASE=example_test
PGUSER=postgres
PGPASSWORD=enc::mxJIZ9/1uV/NDgwT:Seheo3XvJlbllbLg:M5kwPZ3XYK14rbUctbxN/3z18Q==
# .env.prod
APP_ORIGIN=http://example.com
PGHOST=34.72.79.1
PGDATABASE=example
PGUSER=postgres
PGPASSWORD=enc::oiF6UkepsP2l41Mt:Et1jQuh7Vw3X4UpA:Qv3Lhr45ZPA0jga5QKeg917UDg==

While the .env.local file, that is used during local development, will contain all the configuration settings in plain text, the other two may have some secret values such as live database password, JWT secret, etc. Since these values will be encrypted, it would be totally OK to commit these files into the source control repository without compromising security.

You can update and read secrets by using the envars CLI:

# Encrypt and save `PGPASSWORD` variable into the `.env.prod` file
$ yarn envars set PGPASSWORD "S^6wh:rruq!MS(Xd" --env=prod --secret

# Read and decrypt `PGPASSWORD` variable from the `.env.prod` file
$ yarn envars get PGPASSWORD --env=prod

Get more information by running yarn envars --help.

From there on, loading and passing the environment variables into your app would be as simple as requiring envars/config module at run-time.

# Load environment variables when launching a Node.js app
$ node -r envars/config ./server.js

# Load environment variables when launching a Node.js app via Nodemon
$ nodemon -r envars/config ./server.js

# Load environment variables for "prod" environment instead of "local" (default)
$ APP_ENV=prod nodemon -r envars/config ./server.js

Alternatively, you can load environment variables programmatically:

import { config } from "envars";

config({ env: "prod" });

Q&A

❓ In which order the .env files are being loaded?

1) .env.{envName}.override
2) .env.{envName}
3) .env.override
4) .env

Where {envName} is the name of the target environment (defaults to local).

❓ How to check which environment is being used at run-time

By reading the value of process.env.APP_ENV.

❓ Which files needs be included into the source control?

As long as you store secrets encrypted it is safe to commit all the .env.* files into the source control repository except for the .env.*.override and .env.override files.

❓ What's the purpose of .env.*.override files?

Sometimes it's required for a developer being able to override some of the configuration settings without pushing these changes to the upstream repository. These files also used to store encryption/decryption master password.

❓ How to customize where it looks for .env.* files?

You can customize it by adding envars settings to package.json:

{
  "name": "app",
  "dependencies": {
    "envars": "x.x.x",
    ...
  },
  "envars": {
    "cwd": "./env",       // defaults to "." when omitted
    "default": "dev",     // defaults to "local" when omitted
    "encoding": "latin1", // defaults to "utf-8" when omitted
    "debug": true         // defaults to "false" when omitted
  }
}