Update attributes in .env file in Node JS

Viewed 2954

I am wrting a plain .env file as following:

VAR1=VAL1
VAR2=VAL2

I wonder if there's some module I can use in NodeJS to have some effect like :

somefunction(envfile.VAR1) = VAL3

and the resulted .env file would be

VAR1=VAL3
VAR2=VAL2

i.e., with other variables unchanged, just update the selected variable.

4 Answers

You can use the fs, os module and some basic array/string operations.

const fs = require("fs");
const os = require("os");


function setEnvValue(key, value) {

    // read file from hdd & split if from a linebreak to a array
    const ENV_VARS = fs.readFileSync("./.env", "utf8").split(os.EOL);

    // find the env we want based on the key
    const target = ENV_VARS.indexOf(ENV_VARS.find((line) => {
        return line.match(new RegExp(key));
    }));

    // replace the key/value with the new value
    ENV_VARS.splice(target, 1, `${key}=${value}`);

    // write everything back to the file system
    fs.writeFileSync("./.env", ENV_VARS.join(os.EOL));

}


setEnvValue("VAR1", "ENV_1_VAL");

.env

VAR1=VAL1
VAR2=VAL2
VAR3=VAL3

Afer the executen, VAR1 will be ENV_1_VAL

No external modules no magic ;)

I think the accepted solution will suffice for most use cases, but I encountered a few problems while using it personally:

  • It will match keys that is prefixed with your target key if it is found first (e.g. if ENV_VAR is the key, ENV_VAR_FOO is also a valid match).
  • If the key does not exist in your .env file, it will replace the last line of your .env file. In my case, I wanted to do an upsert instead of just updating existing env var.
  • It will match commented lines and update them.

I modified a few things from Marc's answer to solve the above problems:

function setEnvValue(key, value) {
  // read file from hdd & split if from a linebreak to a array
  const ENV_VARS = fs.readFileSync(".env", "utf8").split(os.EOL);

  // find the env we want based on the key
  const target = ENV_VARS.indexOf(ENV_VARS.find((line) => {
    // (?<!#\s*)   Negative lookbehind to avoid matching comments (lines that starts with #).
    //             There is a double slash in the RegExp constructor to escape it.
    // (?==)       Positive lookahead to check if there is an equal sign right after the key.
    //             This is to prevent matching keys prefixed with the key of the env var to update.
    const keyValRegex = new RegExp(`(?<!#\\s*)${key}(?==)`);

    return line.match(keyValRegex);
  }));

  // if key-value pair exists in the .env file,
  if (target !== -1) {
    // replace the key/value with the new value
    ENV_VARS.splice(target, 1, `${key}=${value}`);
  } else {
    // if it doesn't exist, add it instead
    ENV_VARS.push(`${key}=${value}`);
  }

  // write everything back to the file system
  fs.writeFileSync(".env", ENV_VARS.join(os.EOL));
}

It looks like - you want to read your current .env file, after you want to change some values and save it.

You should use the fs module from standard Node.js module library: https://nodejs.org/api/fs.html

var updateAttributeEnv = function(envPath, attrName, newVal){
    var dataArray = fs.readFileSync(envPath,'utf8').split('\n');

    var replacedArray = dataArray.map((line) => {
        if (line.split('=')[0] == attrName){
            return attrName + "=" + String(newVal);
        } else {
            return line;
        }
    })

    fs.writeFileSync(envPath, "");
    for (let i = 0; i < replacedArray.length; i++) {
        fs.appendFileSync(envPath, replacedArray[i] + "\n"); 
    }
}

I wrote this function to solve my issue.

Related