how to load different env files and store them on separate objects in Node.js

358 Views Asked by At

Using dotenv, we can do something like this:

const dotenv = require('dotenv');

// Load the first .env file (e.g., .env.production)
const result1 = dotenv.config({ path: '.env.production' });

if (result1.error) {
  throw result1.error;
}

// Load the second .env file (e.g., .env.development)
const result2 = dotenv.config({ path: '.env.development' });

if (result2.error) {
  throw result2.error;
}

// Now, you can access the environment variables from both files
console.log(process.env.VARIABLE_FROM_ENV_PRODUCTION);
console.log(process.env.VARIABLE_FROM_ENV_DEVELOPMENT);

however, as you can see, it's writing to process.env on my behalf which I don't want, how can I store the results onto a separate variable?

1

There are 1 best solutions below

0
Alexander Mills On

In short, you can use dotenv like this to parse files to a specific object like so:

function loadEnvFile(filePath) {
    const envContents = fs.readFileSync(filePath, 'utf8');
    return dotenv.parse(envContents);
}

as in:

const myEnvObj = loadEnvFile(path.resolve(process.cwd() + '/local.env'));

and this doesn't mutate process.env as a side-effect for example, this script will load two different env files at the command line and diff them:

#!/usr/bin/env node
'use strict';

/*
*  Note you may need to do:
*   npm i -g dotenv
*   npm link dotenv
*   (in order to run this script)
*    RUN IT LIKE:
*   ./diff-envs.js  <file1.env> <file2.env>
*/

const dotenv = require('dotenv');
const fs = require('fs');
const path = require('path');

let diffCount = 0;

// Function to load and parse a .env file into an object
function loadEnvFile(filePath) {
    const envContents = fs.readFileSync(filePath, 'utf8');
    return dotenv.parse(envContents);
}

const env1Path = path.resolve(process.cwd() + '/' + process.argv[2]);
const env1Name = (path.basename(path.dirname(env1Path)) + '/' + path.basename(env1Path));

var env1 = {};
try {
    // Load the first .env file (e.g., .env.production)

     env1 = loadEnvFile(env1Path);
} catch(err){
    console.error('Please add an env file as the first argument.');
    console.error(err);
    process.exit(1);
}


const env2Path = path.resolve(process.cwd() + '/' + process.argv[3]);
const env2Name = path.basename(path.dirname(env2Path)) + '/' + path.basename(env2Path);

var env2 = {};
try {
    // Load the second .env file (e.g., .env.development)
    env2 = loadEnvFile(env2Path);
} catch(err){
    console.error('Please add an env file as the second argument.');
    console.error(err);
    process.exit(1);
}


// Now, you have the contents of each .env file in separate objects
// console.log('Environment variables from .env.production:');
// console.log(env1);

let keySet = new Set();

console.log('---begin env var diffs ---')

for(const [k,v] of Object.entries(env1)){
    if(! (k in env2)){
        diffCount++;
        console.log('-------');
        console.log(env1Name, 'has extra var:', k, v)
        continue;
    }

    if(env2[k] !== v){
       keySet.add(k);
        diffCount++;
       console.log('-------');
        console.log(env1Name, `'${k}'`, `'${v}'`);
        console.log(env2Name, `'${k}'`, `'${env2[k]}'`);
    }

}


for(const [k,v] of Object.entries(env2)){

    if(keySet.has(k)){
        continue;
    }

    if(! (k in env1)){
        diffCount++;
        console.log('-------');
        console.log(env2Name, 'has extra var:', k, v)
        continue;
    }

    if(env1[k] !== v){
        diffCount++;
        console.log('-------');
        console.log(env1Name, `'${k}'`, `'${v}'`);
        console.log(env2Name, `'${k}'`, `'${env1[k]}'`);
    }
}

console.log('---end env var diffs--')
console.log('difference count:', diffCount);
if(diffCount === 0){
    console.log('(there were no differences in the env files)');
} else {
    console.log('(there was at least one difference in the env files).')
}

// console.log('Environment variables from .env.development:');
// console.log(env2);