9

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.

3
  • Thats just using fs module to read the data and change the data and saving, so just look up how to use the fs module. Commented Nov 24, 2020 at 22:51
  • 1
    Not sure what's the use of this, but don't forget that once the .env file is updated you need to restart your server to use the new environment variables. Commented Nov 24, 2020 at 22:55
  • You could try npmjs.com/package/parsenv Commented Nov 24, 2020 at 22:55

5 Answers 5

23

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 ;)

Sign up to request clarification or add additional context in comments.

Comments

10

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)); } 

1 Comment

Works great, found small visual issue, if file is empty, it will always write on second line and skip the first one.
1

Simple and it works: for typescript

import fs from 'fs' import os from 'os' import path from 'path' function setEnvValue(key: string, value: string): void { const environment_path = path.resolve('config/environments/.env.test') const ENV_VARS = fs.readFileSync(environment_path, 'utf8').split(os.EOL) const line = ENV_VARS.find((line: string) => { return line.match(`(?<!#\\s*)${key}(?==)`) }) if (line) { const target = ENV_VARS.indexOf(line as string) if (target !== -1) { ENV_VARS.splice(target, 1, `${key}=${value}`) } else { ENV_VARS.push(`${key}=${value}`) } } fs.writeFileSync(environment_path, ENV_VARS.join(os.EOL)) } 

Comments

0
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.

Comments

0

By using the RegExp constructor we can achieve an even smaller solution than the accepted answer while also fixing the prefix problem mentioned by jp06:

const fs = require("fs"); function setEnvValue(key, value) { const file = fs.readFileSync(".env", "utf8"); // ^ Matches the start of a line due to the 'm' multiline flag // = Matches the literal equal sign character // .+ Matches any set of characters except for newlines const newFile = file.replace(new RegExp(`^${key}=.+`, 'm'), `${key}=${newValue}`); fs.writeFileSync(".env", newFile); } setEnvValue("A", "1"); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.