kerimdzhanov / dotenv-flow

Loads environment variables from .env.[development|test|production][.local] files for Node.js® projects.
MIT License
862 stars 35 forks source link

Is DOTENV_FLOW_SILENT supposed to suppress "already defined" messages? #52

Closed Asuza closed 1 year ago

Asuza commented 3 years ago

I've tried a few different ways to silence these types of messages:

dotenv-flow: "DATABASE_HOST" is already defined in `process.env` and will not be overwritten
dotenv-flow: "DATABASE_PORT" is already defined in `process.env` and will not be overwritten
dotenv-flow: "DATABASE_NAME" is already defined in `process.env` and will not be overwritten
dotenv-flow: "DATABASE_USERNAME" is already defined in `process.env` and will not be overwritten
dotenv-flow: "DATABASE_PASSWORD" is already defined in `process.env` and will not be overwritten

Because I use dotenv-flow in several files, these messages get repeated many times.

I've tried setting DOTENV_FLOW_SILENT in my environment via PowerShell, and confirmed that it is indeed there. The documentation isn't clear on what the value is supposed to be, so I've set it to "silent" based on skimming the code.

PS C:\dev\myproject> Get-ChildItem Env:DOTENV_FLOW_SILENT

Name                           Value
----                           -----
DOTENV_FLOW_SILENT             silent

Adding the environment variable to my .env file also does not seem to do anything.

I am using version 3.2.0.

Am I doing something wrong with this setting?

kerimdzhanov commented 3 years ago

Hi John,

Just to make it clear, you don't have to require('dotenv-flow').config() several times in different files of your application. When you require it once it loads environment variables to process.env object that is shared between all the files of a single process.

As for environment variables kind of boolean, it is supposed to be working with any value that evaluates to true. So your example should work. I'm not an expert on Windows' Power Shell, probably environment variable you specified is not visible in the Node.js application you're running, to check this you can simply print out the process.env.DOTENV_FLOW_SILENT to the console within your js application, like:

console.log(process.env.DOTENV_FLOW_SILENT);
Asuza commented 3 years ago

Thank you for the quick response, Dan.

In my case, these are TestCafe test files which can be run in various ways, rather than from a single entrypoint as most applications would be. I need to spend more time on that so it works better.

The result from

console.log(process.env.DOTENV_FLOW_SILENT);

is silent, so I tried a few different things to see if I could get the result to be different. I noticed that I'm only seeing the "is already defined" messages when initializing dotenv-flow multiple times.

This hides the messages (DOTENV_FLOW_SILENT is set to "silent"):

require('dotenv-flow').config();
require('dotenv-flow').config({
  silent: process.env.DOTENV_FLOW_SILENT
});

And this does not hide messages:

process.env.DOTENV_FLOW_SILENT = 'silent';
// process.env.DOTENV_FLOW_SILENT = true; ends up with the same result
require('dotenv-flow').config();
require('dotenv-flow').config();

Is there another way to set the silent config? In the meantime, I'm going to see if I can avoid initializing the package more than once.

kerimdzhanov commented 3 years ago

Ohh, I've just tried and realized that it might be not quite clear.

Preconfiguring "dotenv-flow" using environment variables or command-line switches is the part of the dotenv-flow/config preload file. So, if you want to use the DOTENV_FLOW_SILENT environment variable you need to use a different approach rather than require('dotenv-flow').config(). You need to remove it from your code and run your app using:

$ node -r dotenv-flow/config your_script.js

In that case, since you don't have require('dotenv-flow').config() anywhere in your code, you cannot provide any options there, so the solution is to specify all the possible options via environment variables or command-line switches.

Hope that makes sense.

You can read more about it here:

Asuza commented 3 years ago

So it was my doing all along! Thank you for the clarification. I did not realize those environment variables were restricted to that specific method of using the package.

I don't believe I'll be able to use that method in all environments in my case, so I ended up doing the following:

I set this in my .env file: DOTENV_FLOW_CHECK=1 Then, use this line in each file instead of the usual require:

process.env.DOTENV_FLOW_CHECK || require('dotenv-flow').config();

Now as long as the package initialized once, the variable will be set and it won't initialize again.

kerimdzhanov commented 1 year ago

Hei @Asuza,

Sorry for disappearing 😅.

So yeah, you just need to make sure that require('dotenv-flow').config(); is specified at least once in your Node.js process. You don't need to check for environment variables before requiring it. By Node.js's design, I'd recommend the following:

  1. Somhere in your project, create an initialization file, for example lib/dotenv-flow.js, with the following one-liner code:

    require('dotenv-flow').config();
  2. From the other files within your project, you can just require your lib/dotenv-flow.js to make sure that it's loaded and initialized. As easy as follows:

require('./lib/dotenv-flow');

Node.js will not re-initialize the file again if it has already been done by the other "require" instruction before. So, you can make sure that the file is loaded and initialized without any unnecessary warnings or pre-checks.

Asuza commented 1 year ago

Thank you for the response, @kerimdzhanov! I'm hoping to give your latest suggestion a try. No worries at all about the delay.

merlox commented 1 year ago

I personally think it's a terrible design decision. Most other dotenv libraries simply allow you to specify require('dotenv...') in every file that needs to access those variables. Nobody is tryint to "override" process.env variables.

I suggest you to make the functionality identical to all other dotenv libraries to avoid confusion because it took me a while to figure the right way to import this since I have multiple entry files.

kerimdzhanov commented 1 year ago

Hi @merlox,

Thanks for the suggestion and a bit of criticism 😜

With regards to "require in every file", it is totally fine but the problem is in .config() every time we "require", since it assigns process.env which is shared within the node's process (so, it's kinda designed to be the same as dotenv).

Above, I am just suggesting having a shared (single point of configuration) file basically for your own .config() call in case if you'd like to have some custom configuration for dotenv-flow. And, btw, if you're okay with all the default options, you could just do require('dotenv-flow/config'); in every file where you need to access process.env.*, and there won't be any warnings and redundant fs hits.

As for the "is already defined" warning, it's actually made for another purpose, Now I realize that the message is not very clear, thanks for mentioning it 👍.

I am thinking of better documentation for dotenv in general. We have a lot of different use cases and "best practices", so I just need a bit more time to create a wiki and totally rework the README ðŸ˜