Ehsan Ali
Ehsan Ali

Reputation: 1432

How to save changes in .env file in node.js

I use dotenv for read environment variable. like this:

let dotenv = require('dotenv').config({ path: '../../.env' });
console.log(process.env.DB_HOST);

Now I wanna to save changes in .env file. I can't find any way to save variable in .env file. What should I do?

process.env.DB_HOST = '192.168.1.62';

Upvotes: 12

Views: 24645

Answers (5)

iOSCodeJunkie
iOSCodeJunkie

Reputation: 201

Update : March 2022 - Typescript Example

Please see @Codebling post regarding why you should NOT do this, however you may be using this as some form of testing. whatever the use case see below.

Using the library envfile

Install package: npm i envfile

OR as dev dependency: npm i envfile --save-dev

import { resolve } from 'path';
import { readFile, writeFileSync } from 'fs';
import * as envfile from 'envfile';

export const writeEnvToFile = (
  envVariables: { key: string; value: any }[],
): void => {
  // get `.env` from path of current directory
  const path = resolve(__dirname, '../../.env');
  readFile(path, 'utf8', (err, data) => {
    if (err) {
      console.error(err);
      return;
    }

    const parsedFile = envfile.parse(data);
    envVariables.forEach((envVar: { key: string; value: any }) => {
      if (envVar.key && envVar.value) {
        parsedFile[envVar.key] = envVar.value;
      }
    });
    writeFileSync(path, envfile.stringify(parsedFile));

    // NB: You should now be able to see your .env with the new values,
    // also note that any comments or newlines will be stripped from 
    // your .env after the writeFileSync, but all your pre-existing
    // vars should still appear the .env.

    console.log('Updated .env: ', parsedFile);
  });
};

Example usage

  writeEnvToFile([
    {
      key: 'YOUR_NEW_ENV_VAR',
      value: 'SOME_VALUE',
    },
    {
      key: 'FOO',
      value: 'BAR',
    },
    {
      key: 'TIME_STAMP',
      value: 1647934964293,
    },
  ]);

.env BEFORE write

# Some comments about API KEY
API_KEY=xxxabc

.env AFTER write

API_KEY=xxxabc
YOUR_NEW_ENV_VAR=SOME_VALUE
FOO= BAR
TIME_STAMP=1647934964293

Upvotes: 4

Codebling
Codebling

Reputation: 11397

Do not save data to a .env file.

What is a .env file?

'env' stands for environment variables. Environment variables are shell-based key-value pairs that provide configuration to running applications.

.env file is meant to provide easy mechanism for setting these environment variables during development (usually because a developer machine is constantly being restarted, has multiple shells open, and a developer must switch between projects requiring different environment variables). In production, these parameters will typically be passed by actual environment variables (which, in a cloud configuration, are often easier to manage than file-based solutions, and prevent any secrets from being saved on disk)

Why can't you modify environment variables?

Environment variables can be modified at the command line, but once a running process is started, it can't/won't affect the parent process' environment variables. If your program exits and restarts, the changes will be lost.

Why can't you modify a .env file?

If you set a value in the .env file, it will be used only if an environment variable of the same name does not already exist. If it does, the value of that variable in .env file won't be loaded.

Additionally, any changes to written to the .env file won't be reflected in your application when reading process.env until the application is restarted.

Use a config file instead

A config file is just a regular file containing configuration. It's like a .env file, but it doesn't represent environment variables. It's safe to change it, and safe to use in production.

Upvotes: 8

Rupam
Rupam

Reputation: 1672

Update : August 2021

No external dependency

I was looking for similar solution to read and write key/value to .env file. I read other solutions and have written the 2 functions getEnvValue and setEnvValue to simplify read/write operations.

To use getEnvValue, the .env file should be formatted like the following (i.e. no spaces around = sign):

KEY_1="value 1"
KEY_2="value 2"
const fs = require("fs");
const os = require("os");
const path = require("path");

const envFilePath = path.resolve(__dirname, ".env");

// read .env file & convert to array
const readEnvVars = () => fs.readFileSync(envFilePath, "utf-8").split(os.EOL);

/**
 * Finds the key in .env files and returns the corresponding value
 *
 * @param {string} key Key to find
 * @returns {string|null} Value of the key
 */
const getEnvValue = (key) => {
  // find the line that contains the key (exact match)
  const matchedLine = readEnvVars().find((line) => line.split("=")[0] === key);
  // split the line (delimiter is '=') and return the item at index 2
  return matchedLine !== undefined ? matchedLine.split("=")[1] : null;
};

/**
 * Updates value for existing key or creates a new key=value line
 *
 * This function is a modified version of https://stackoverflow.com/a/65001580/3153583
 *
 * @param {string} key Key to update/insert
 * @param {string} value Value to update/insert
 */
const setEnvValue = (key, value) => {
  const envVars = readEnvVars();
  const targetLine = envVars.find((line) => line.split("=")[0] === key);
  if (targetLine !== undefined) {
    // update existing line
    const targetLineIndex = envVars.indexOf(targetLine);
    // replace the key/value with the new value
    envVars.splice(targetLineIndex, 1, `${key}="${value}"`);
  } else {
    // create new key value
    envVars.push(`${key}="${value}"`);
  }
  // write everything back to the file system
  fs.writeFileSync(envFilePath, envVars.join(os.EOL));
};

// examples
console.log(getEnvValue('KEY_1'));
setEnvValue('KEY_1', 'value 1')

Upvotes: 10

Abdul Aleem
Abdul Aleem

Reputation: 361

.env file

VAR1=var1Value
VAR_2=var2Value

index.js file

    const fs = require('fs') 
    const envfile = require('envfile')
    const sourcePath = '.env'
    console.log(envfile.parseFileSync(sourcePath))
    let parsedFile = envfile.parseFileSync(sourcePath);
    parsedFile.NEW_VAR = 'newVariableValue'
    fs.writeFileSync('./.env', envfile.stringifySync(parsedFile)) 
    console.log(envfile.stringifySync(parsedFile))

final .env file install required modules and execute index.js file

VAR1=var1Value
VAR_2=var2Value
NEW_VAR=newVariableValue

Upvotes: 8

Ehsan Ali
Ehsan Ali

Reputation: 1432

I solve problem with envfile module:

const envfile = require('envfile');
const sourcePath = '../../.env';
let sourceObject = {};
// Parse an envfile path
// async
envfile.parseFile(sourcePath, function (err, obj) {
  //console.log(err, obj)
  sourceObject = obj;
  sourceObject.DB_HOST = '192.168.1.62';

  envfile.stringify(sourceObject, function (err, str) {
      console.log( str);
      fs.writeFile(sourcePath, str, function(err) {
          if(err) {
              return console.log(err);
          }

          console.log("The file was saved!");
       });
   });
});

Upvotes: 2

Related Questions