Commander-plus with gulp - node.js

I'm writing a node cli tool with commander-plus.
import program from 'commander-plus';
const prompts = ['a', 'b', 'c'];
program.choose(prompts, (index) => {
// never returns;
});
And want to run it with a gulp task, mostly because its convenient and we're loading .env variables, but on development only.
import env from 'gulp-env';
gulp.task('env', () => {
env();
});
At first i've been trying with gulp-shell. I'm actually using a similar script to kick-off nodemon, which works fine. The cli script runs just fine but commander-plus won't listen to the keyboard input.
import shell from 'gulp-shell';
import gulp from 'gulp';
gulp.task('cli', ['env'], shell.task([
'babel-node src/cli',
]))
Later i found that, either this is how its supposed to work or perhaps its now fixed.
https://github.com/sun-zheng-an/gulp-shell/issues/10
But also that gulp-shell is blacklisted, and thought to try with gulp-exec or child_process.exec instead.
import { exec } from 'child_process';
gulp.task('cli', ['env'], done => {
exec('babel-node src/server/cli', done);
});

Not sure if it qualifies as an answer, but i found way around with node-dotenv. Just without gulp.
First i have a config file that looks like
// only set default for env
configExport.env = process.env.NODE_ENV || 'development';
// and a lot of other variables
And then both in my server and cli tool i load the .env only if its needed.
import dotenv from 'dotenv'
import config from '../server/config';
if(config.env === 'development'){
dotenv.load();
}
dotenv will not fail if .env file is not found, but the reason for the extra if check, is i'm worried a .env might get deployed by accident.
We will also need to make sure .env is not deployed with all appropriate .ignores (.gitignore, modulusignore, .dockerignore) and that should do the job.

Apparently gulp-bg is a working option. With that we can still continue running developer tasks with gulp and avoid dotenv entirely on production.
import bg from 'gulp-bg';
import gulp from 'gulp';
gulp.task('cli', ['env'], bg('node', './src/cli'));

Related

Express +Jest. Test files are running sequentially instead of in parallel

I have an Express.JS server which uses jest and supertest as a testing framework.
It has been working excellently.
When I call my test npm script, it runs npx jest and all of my test files run in parallel.
However I ran my tests recently and they ran sequentially which takes a very long time, they have done this ever since.
I haven't changed any jest or npm configuration, nor have I changed my test files themselves.
Has anyone experienced this? Or is it possible that something in my configuration is incorrect?
jest.config
export default {
setupFilesAfterEnv: ['./__tests__/jest.setup.js'],
}
jest.setup.js
import { connectToDatabase } from '/conn'
// Override the dotenv to use different .env file
require('dotenv').config({
path: '.env.test',
})
beforeAll(() => {
connectToDatabase()
})
test('', () => {
// just a dummy test case
})
EDIT: Immediately after posting the question, I re ran the tests and they ran in parallel, without me changing anything. If anyone has any knowledge around this i'd be interested to get a second opinion
After intermittent switching between parallel and sequential for unknown reasons. I have found it work consistently by adding the --no-cache arg to the npx jest call.
See below where I found the answer
Github -> jest not always running in parallel

How can I run a Typescript script on Node without importing anything from it?

Typescript handbook mentions scripts, as opposed to modules:
Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).
I have a couple of scripts that don't import anything, just iteratively do some work, like this:
// script.ts
console.log('test')
I want to run them all one by one from the index.ts (which is defined as main in package.json). However, when I just import them:
// index.ts
console.log(1)
import {} from './script'
console.log(2)
It does not do anything in the compiled JS:
// index.js (compiled)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
console.log(1);
// << shouldn't there be something here?
console.log(2);
//# sourceMappingURL=index.js.map
How can I properly call that script so it root content runs when I run my compiled index.js?
Scripts are imported like this:
import './script'
without using from

node dotenv files not loading for test env

I have two dotenv files, one for development and another for test.
const dotenv = require('dotenv');
if (process.env && process.env.NODE_ENV) {
dotenv.config({path: '.env.' + process.env.NODE_ENV});
} else {
dotenv.config({path: '.env.development'});
}
const http = require('http');
const app = require('../src/app');
const port = parseInt(process.env.PORT, 10) || 8000;
app.set('port', port);
const server = http.createServer(app);
server.listen(port);
Here are my questions:
When does server load dotenv files in my case? If I run in test env, why do I get undefined for those process.env variables?
It seems to me this file only runs once, when I change NODE_ENV, it does not change which file to load.
So in short:
My development dotenv is working, but just having trouble when changing it to test dotenv
Please take a look at the dotenv-flow package.
This module extends dotenv adding the ability to have multiple .env* files like .env.development, .env.test, .env.production, etc., also allowing defined variables to be overwritten individually in the appropriate .env*.local file that is untracked by VCS.
Regarding to the recommendation against having multiple env files, dotenv-flow has a slightly different approach to manage .env* files under version control. Please refer the Files under version control section to understand the motivation of this approach.
Should I have multiple .env files?
No. We strongly recommend against having a "main" .env file and an
"environment" .env file like .env.test. Your config should vary
between deploys, and you should not be sharing values between
environments.
From dotenv documentation
custom-env also solves this problem, it allows multiple configurations file for different environments. npm install custom-env.
You can also specify which .env file to use on the go. require('custom-env').env('test');.
Full Docs here: https://www.npmjs.com/package/custom-env

How can I bundle a precompiled binary with electron

I am trying to include a precompiled binary with an electron app. I began with electron quick start app and modified my renderer.js file to include this code that is triggered when a file is dropped on the body:
spawn = require('child_process').spawn,
ffmpeg = spawn('node_modules/.bin/ffmpeg', ['-i', clips[0], '-an', '-q:v', '1', '-vcodec', 'libx264', '-y', '-pix_fmt', 'yuv420p', '-vf', 'setsar=1,scale=trunc(iw/2)*2:trunc(ih/2)*2,crop=in_w:in_h-50:0:50', '/tmp/out21321.mp4']);
ffmpeg.stdout.on('data', data => {
console.log(`stdout: ${data}`);
});
ffmpeg.stderr.on('data', data => {
console.log(`stderr: ${data}`);
});
I have placed my precompiled ffmpeg binary in node_modules/.bin/. Everything works great in the dev panel, but when I use electron-packager to set up the app, it throws a spawn error ENOENT to the console when triggered. I did find a very similar question on SO, but the question doesn't seem to be definitively answered. The npm page on electron-packager does show that they can be bundled, but I cannot find any documentation on how to do so.
The problem is that electron-builder or electron-packager will bundle your dependency into the asar file. It seems that if the dependency has a binary into node_modules/.bin it is smart enough to not package it.
This is the documentation for asar packaging for electron-builder on that topic. It says
Node modules, that must be unpacked, will be detected automatically
I understand that it is related to existing binaries in node_modules/.bin.
If the module you are using is not automatically unpacked you can disable asar archiving completely or explicitly tell electron-builder to not pack certain files. You do so in your package.json file like this:
"build": {
"asarUnpack": [
"**/app/node_modules/some-module/*"
],
For your particular case
I ran into the same issue with ffmpeg and this is what I've done:
Use ffmpeg-static. This package bundles statically compiled ffmpeg binaries for Windows, Mac and Linux. It also provides a way to get the full path of the binary for the OS you are running: require('ffmpeg-static').path
This will work fine in development, but we still need to troubleshoot the distribution problem.
Tell electron-builder to not pack the ffmpeg-static module:
"build": {
"asarUnpack": [
"**/app/node_modules/ffmpeg-static/*"
],
Now we need to slightly change the code to get the right path to ffmpeg with this code: require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked') (if we are in development the replace() won't replace anything which is fine).
If you are using webpack (or other javascript bundler)
I ran into the issue that require('ffmpeg-static').path was returning a relative path in the renderer process. But the issue seemed to be that webpack changes the way the module is required and that prevents ffmpeg-static to provide a full path. In the Dev Tools the require('ffmpeg-static').path was working fine when run manually, but when doing the same in the bundled code I was always getting a relative path. So this is what I did.
In the main process add this before opening the BrowserWindow: global.ffmpegpath = require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked'). The code that runs in the main process is not bundled by webpack so I always get a full path with this code.
In the renderer process pick the value this way: require('electron').remote.getGlobal('ffmpegpath')
I know I'm a bit late but just wanted to mention ffbinaries npm package I created a while ago exactly for this purpose.
It'll allow you to download ffmpeg/ffplay/ffserver/ffprobe binaries to specified location either during application boot (so you don't need to bundle it with your application) or in a CI setup. It can autodetect platform, you can also specify it manually.
If anyone happens to need an answer to this question: I do have a solution to this, but I have no idea if this is considered best practice. I couldn't find any good documentation for including 3rd party precompiled binaries, so I just fiddled with it until it finally worked. Here's what I did (starting with the electron quick start, node.js v6):
From the app directory I ran the following commands to include the ffmpeg binary as a module:
mkdir node_modules/ffmpeg
cp /usr/local/bin/ffmpeg node_modules/ffmpeg/
ln -s ../ffmpeg/ffmpeg node_modules/.bin/ffmpeg
(replace /usr/local/bin/ffmpeg with your current binary path, download it from here) Placing the link allowed electron-packager to include the binary I saved to node_modules/ffmpeg/.
Then to get the bundled app path I installed the npm package app-root-dir by running the following command:
npm i -S app-root-dir
Since I could then get the app path, I just appended the subfolder for my binary and spawned from there. This is the code that I placed in renderer.js:.
var appRootDir = require('app-root-dir').get();
var ffmpegpath=appRootDir+'/node_modules/ffmpeg/ffmpeg';
console.log(ffmpegpath);
const
spawn = require( 'child_process' ).spawn,
ffmpeg = spawn( ffmpegpath, ['-i',clips_input[0]]); //add whatever switches you need here
ffmpeg.stdout.on( 'data', data => {
console.log( `stdout: ${data}` );
});
ffmpeg.stderr.on( 'data', data => {
console.log( `stderr: ${data}` );
});
This is how I would do it:
Taking cues from tsuriga's answer, here is my code:
Note: replace or add OS path accordingly.
Create a directory ./resources/mac/bin
Place you binaries inside this folder
Create file ./app/binaries.js and paste the following code:
'use strict';
import path from 'path';
import { remote } from 'electron';
import getPlatform from './get-platform';
const IS_PROD = process.env.NODE_ENV === 'production';
const root = process.cwd();
const { isPackaged, getAppPath } = remote.app;
const binariesPath =
IS_PROD && isPackaged
? path.join(path.dirname(getAppPath()), '..', './Resources', './bin')
: path.join(root, './resources', getPlatform(), './bin');
export const execPath = path.resolve(path.join(binariesPath, './exec-file-name'));
Create file ./app/get-platform.js and paste the following code:
'use strict';
import { platform } from 'os';
export default () => {
switch (platform()) {
case 'aix':
case 'freebsd':
case 'linux':
case 'openbsd':
case 'android':
return 'linux';
case 'darwin':
case 'sunos':
return 'mac';
case 'win32':
return 'win';
}
};
Add the following code inside the ./package.json file:
"build": {
....
"extraFiles": [
{
"from": "resources/mac/bin",
"to": "Resources/bin",
"filter": [
"**/*"
]
}
],
....
},
import binary file path as:
import { execPath } from './binaries';
#your program code:
var command = spawn(execPath, arg, {});
Why this is better?
Most of the answers require an additional package called app-root-dir
The original answer doesn't handle the (env=production) build or the pre-packed versions properly. He/she has only taken care of development and post-packaged versions.

How do I setup the dotenv file in Node.js?

I am trying to use the dotenv NPM package and it is not working for me. I have a file config/config.js with the following content:
'use strict';
var dotenv = require('dotenv');
dotenv.load();
console.log('config');
I have another file .env at the root of my application folder. I also have an environment variable TWILIO_ACCOUNT_SID.
This is the process I go through while trying to use the environment variables in a certain function:
$ node
> require('./config/config.js');
config
{}
> process.env.TWILIO_ACCOUNT_SID
undefined
I defined the TWILIO_ACCOUNT_SID in my .env file but as soon as I try to output the value in my console, I get an error stating that the variable is undefined.
I will be very grateful for any support in troubleshooting this issue.
In my case, every time I tried to get a key from the .env file using process.env.MY_KEY, it returned undefined.
I suffered from this problem for two hours just because I named the file something like keys.env which is not considered to be a .env file.
So here is the troubleshooting list:
The filename should be .env (I believe .env.test is also acceptable).
Make sure you are requiring it as early as possible in your application using this statement require('dotenv').config();
The .env file should be in the root directory of your project.
Follow the "file writing rules" like DB_HOST=localhost, no need to wrap values in double/single quotes.
Also, check the documentation of the package on the NPM site.
I solved this using:
require('dotenv').config({path: __dirname + '/.env'})
or with an absolute path:
C:\\asd\\auhsd\\.env
If it does not find the .env file, it will return undefined.
Save yourself some troubleshooting time and log your require call, like so:
console.log(require('dotenv').config())
You should see an error with more detailed info on the problem.
Had the same issue recently. Check your .env file and use equal sign not colon. Here's an example:
key=value
instead of:
key:value
I had the same problem. I realized my file was somehow encoded in UCS-2 BE BOM. Converting my .env file to UTF-8 fixed it (you can easily do that using Notepad++, for example).
i didn't put my environment variables in the right format as was in the dotenv module documentation e.g. i was doing export TWILIO_CALLER_ID="+wwehehe" and so the dotenv module wasn't parsing my file correctly. When i noticed that i removed the export keyword from the declarations and everything worked fine.
I had the same problem and I tried 4 hours to find the fault. In my case, it was bizarre.
When I tried "node app.js", it worked. When I wanted a daemon to start it, it did not work.
How did I solve my problem?
I replaced:
var dotenv = require('dotenv');
dotenv.load();
with:
var dotenv = require('dotenv').config({path: path.join(__dirname, '.env')})
Make sure that variables are not already set. Dotenv won't override them.
If variables are set then you will have to remove them. In powershell you can use the following command - as mentioned here:
Remove-Item Env:\MyTestVariable
I had a problem also with .env variables not loading and being undefined.
What I tried:
index.js:
import dotenv from 'dotenv';
dotenv.config();
import models from './models';
models.js
import Sequelize from 'sequelize';
const sequelize = new Sequelize(
process.env.DATABASE,
process.env.DATABASE_USER,
process.env.DATABASE_PASSWORD,
{
dialect: 'postgres',
}
);
Apparently, because of how loading the imports works in nodejs, the import of models in index.js caused that the models.js was executed before dotenv.config(). Therefore I got undefined values from process.env.
When I changed models.js to do the dotenv configuration like:
import Sequelize from 'sequelize';
import dotenv from 'dotenv';
dotenv.config();
const sequelize = new Sequelize(
process.env.DATABASE,
process.env.DATABASE_USER,
process.env.DATABASE_PASSWORD,
{
dialect: 'postgres',
}
);
it started to work!
Take care that you also execute your Node script from the ROOT folder.
E.g. I was using a testing script in a subfolder called ./bin/test.js.
Calling it like: node ./bin/test.js worked totally fine.
Calling it from the subfolder like:
$ pwd
./bin
$ node ./test.js
causes dotenv to not find my ./.env file.
I am using NodeJS on windows 10. I used process.env.var-name to access the variables but failed because it gives me windows path variables as a JSON object, so I installed dotenv ( npm install dotenv ). dotenv gets process envirnoment variables from your project's .evn file
npm install dotenv or yarn add dotenv
const dotenv = require('dotenv');
dotenv.config();
process.env.variable_name
output
Make sure to set cwd in the pm2 config to the correct directory for any calls to dotenv.config().
Example:
Your index.js file is in /app/src, your .env file is in /app. Your index.js file has this
dotenv.config({path: "../.env"});
Your pm2 json config should have this:
"cwd": "/app/src", "script": "index.js"
You could also use dotenv.config({path: path.join(__dirname, "../.env")}); to avoid the CWD issue. You will still have a problem if you move the .env or the index.js file relative to each other.
Working Solution:
If you are using webpack (which you definitely should), use a very handy plugin dotenv-webpack which solves the issue of reading environment variables from .env file
Make sure .env is in root directory of your project.
Steps to install the plugin:
npm i -D dotenv-webpack
In webpack.config file:
const Dotenv = require('dotenv-webpack');
module.exports = {
...
plugins: [
new Dotenv(),
...
],
...
};
Now you can call any environment variable defined in .env file using process.env in any js file
My code structure using is as shown below
-.env
-app.js
-build
-src
|-modules
|-users
|-controller
|-userController.js
I have required .env at the top of my app.js
require('dotenv').config();
import express = require('express');
import bodyParser from 'body-parser';
import mongoose = require('mongoose');
The process.env.PORT works in my app.listen function. However, on my userController file not sure how this is happening but my problem was I was getting the secretKey value and type as string when I checked using console.log() but getting undefined when trying it on jwt.sign() e.g.
console.log('Type: '+ process.env.ACCESS_TOKEN_SECRET)
console.log(process.env.ACCESS_TOKEN_SECRET)
Result:
string
secret
jwt.sign giving error
let accessToken = jwt.sign(userObj, process.env.ACCESS_TOKEN_SECRET); //not working
Error was
Argument of type 'string | undefined' is not assignable to parameter of type 'Secret'.
Type 'undefined' is not assignable to type 'Secret'.
My Solution:
After reading the documentation. I required the env again in my file( which I probably should have in the first place ) and saved it to variable 'environment'
let environment = require('dotenv').config();
console logging environment this gives:
{
parsed: {
DB_HOST: 'localhost',
DB_USER: 'root',
DB_PASS: 'pass',
PORT: '3000',
ACCESS_TOKEN_SECRET: 'secretKey',
}
}
Using it on jwt.sign not works
let accessToken = jwt.sign(userObj, environment.parsed.ACCESS_TOKEN_SECRET);
Hope this helps, I was stuck on it for hours. Please feel free to add anything to my answer which may help explain more on this.
There's a lot of confusion about this topic and in these answers. I'm not surprised, that no single answer was accepted. Hopefully yet.
The answer by Basheer indeed solves most of the problems. However, there are few things you still need to know. Especially, if you're coming, like me, from frontend background and wants to add secrets to your frontend. Possibly, related to the introduction of some Server-Side Rendering (SSR) logic in the app.
Most probably you've seen this code in your webpack settings in a frontend app to solve the issue, as a frontend developer.
/* Custom webpack properties. */
const dotenv = require('dotenv-webpack');
module.exports = {
plugins: [
new dotenv(), // Handle environemntal variables on localhost, but on the Server-Side Rendering (SSR). There's no access to "process.env" on the browser.
],
};
Now, it'll work out fine, if you render on the server (SSR) across your app if the .env file is in the root of your project. However, it might not work if you have some custom server-related settings. An example of such situation is Angular Universal, Nuxt.js handles this much easier in which require('dotenv').config() in your next.config.js and makes you good to go. That's due to difference in philosophies between how Angular and Vue.js are handling SSR. To get Angular Universal app from Angular that's just 1 command, but the SSR app isn't as nicely organized as Nuxt.js. It comes with a price that to generate Nuxt.js app from Vue.js, you basically have to generate a new Nuxt.js project and copy files due to quite some differences between Nuxt.js and Vue.js setup. Don't know how React/Next.js and Svelte/Sapper solves this, but if similarly to Angular then you also might consider reading further.
Now, you've some server-related logic in a separated folder called server and let say the file is called main.ts. Maybe apart SSR in that file, you can also have sending mail (nodemailer?) logic. Then you'd like to use process.env, but apparently it doesn't work, even though you have the logic defined in webpack. That's where the require('dotenv').config(); is needed, even if you're using different syntax for import (such as import { Express } from 'express'; for example), require('dotenv').config(); will work like that. Don't feel confused. As long as .env is in the root of your app (don't confuse with server folder) and the variables have correct syntax inside that file, e.g.
MAIL_ACCOUNT=mymail#mydomain.com
MAIL_HOST=smtp.mydomain.com
MAIL_PORT=587
It'll work.
Last scenario, in the SSR app you realised that to host this app you need something called Serverless/Cloud Functions/FaaS. Here, I know only Firebase scenario. In your project, to deploy such app you might have functions folder, from which you deploy the SSR app to the Cloud Functions for Firebase, in this example. What a surprise, on a deployment mail is not working and after hours of figuring out what's happening in the logs you can see process.env.VARIABLE_NAME returning undefined. The reason is that as of today the CLI cannot merge files from other locations and indeed the .env file has to be manually copied to the functions folder. Once copy/paste the .env file to functions and deploy, it'll work.
What you can use for debugging is one of those:
console.log(require('dotenv').config());
console.log(require('dotenv').config({debug: true}));
However, be careful with your secrets, because these will be revealed when your .env setup will be done. Trying to access one of the secrets and trying to log its value in the logs might be more secure option. Especially, if you have many secrets and don't want to rewrite all.
Hope so this one post will cover most of the scenarios.
My problem was stupid. I created the .env in a text editor, and when I saved it it actually saved as
'.env.txt'
which was only visible after I did a
'ls -a'
in terminal and saw the file name.
A quick:
mv .env.txt .env
And I was in business
The '.env' file should be in the root directory of your node js server file (server.js or for me).
If you placed the '.env' file at the root of your project, it won't work. My mistake was that I have the server.js file nested in a folder named 'controller'.
So I had to fix it by placing the .env file in the same directory as the server.js file.
For React apps created with the create-react-app template, you don't need to use dotenv directly. react-scripts does that for you.
Simply creates a .env file in the top level directory of your project and add all your envs there, but notice that they MUST start with REACT_APP prefix, otherwise they will be ignored.
More details in their documentation. I just spent a couple of hours dealing with this and hope it will save you some time.
Had the same problem. I used dotenv-webpack and need to define
plugins: [
new Dotenv()
]
in both webpack production and webpack base files (I use webpack merge).
If was not defined in both files then it did not work.
If you are facing this problem it could be that the environment variable(s) is added/loaded after the file that requires the specific variable
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const dotenv = require('dotenv');
const morgan = require('morgan');
const passport = require('passport'); //you want to use process.env.JWT_SECRET (you will get undefined)
dotenv.config();
in the above case, you will get undefined for the process.env.JWT_SECRET
So the solution is that you put dotenv.config() before const passport = require('passport');
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const dotenv = require('dotenv');
const morgan = require('morgan');
dotenv.config();
const passport = require('passport'); //you want to use process.env.JWT_SECRET (you will get the value for the enviroment variable)
In my case, I've created a wrapper JS file in which I have the logic to select the correct variables according to my environment, dynamically.
I have these two functions, one it's a wrapper of a simple dotenv functionality, and the other discriminate between environments and set the result to the process.env object.
setEnvVariablesByEnvironment : ()=>{
return new Promise((resolve)=>{
if (process.env.NODE_ENV === undefined || process.env.NODE_ENV ==='development'){
logger.info('Lower / Development environment was detected');
environmentManager.getEnvironmentFromEnvFile()
.then(envFile => {
resolve(envFile);
});
}else{
logger.warn('Production or Stage environment was detected.');
resolve({
payload: process.env,
flag: true,
status: 0,
log: 'Returned environment variables placed in .env file.'
});
}
});
} ,
/*
Get environment variables from .env file, using dotEnv npm module.
*/
getEnvironmentFromEnvFile: () => {
return new Promise((resolve)=>{
logger.info('Trying to get configuration of environment variables from .env file');
env.config({
debug: (process.env.NODE_ENV === undefined || process.env.NODE_ENV === 'development')
});
resolve({
payload: process.env,
flag: true,
status: 0,
log: 'Returned environment variables placed in .env file.'
});
});
},
So, in my server.js file i only added the reference:
const envManager = require('./lib/application/config/environment/environment-manager');
And in my entry-point (server.js), it's just simple as use it.
envManager.setEnvVariablesByEnvironment()
.then(envVariables=>{
process.env= envVariables.payload;
const port = process.env.PORT_EXPOSE;
microService.listen(port, '0.0.0.0' , () =>{
let welcomeMessage = `Micro Service started at ${Date.now()}`;
logger.info(welcomeMessage);
logger.info(`${configuration.about.name} port configured -> : ${port}`);
logger.info(`App Author: ${configuration.about.owner}`);
logger.info(`App Version: ${configuration.about.version}`);
logger.info(`Created by: ${configuration.about.author}`);
});
});
I had to literally use no name for the .env file, just have the .env extension and save the file like that and it worked.
I solved this just renaming the file to .env
to y file was named config.env , when I renamed to .env , it works.
I spent a lot of time going through these fixes. I was developing locally and just had to restart the server because the .env file isn't hot reloaded.
is dotenv installed in your project?
Try to install it using npm install dotenv in your project.
Once it is installed load it in any files where you need it using const env = require('dotenv').config().
You can then use in any line where you need to. For example to call port from .env use: process.env.PORT
If you use "firebase-functions" to host your sever-side-rendered application, you should be aware of this one:
error: Error: ENOENT: no such file or directory, open 'C:\Codes\url_shortener\functions\.env'
Means you have to store the .env file in the functions folder as well.
Found this one by:
console.log(require('dotenv').config())
I cloned a repo from Github and went through every one of the suggestions here. After a lot of frustration, I realized that npm install did not install any of the modules and my node_modules folder was empty the whole time.
QUICK FIX:
1) delete your node_modules folder
2) delete your package-lock.json
3) run npm install
const dotenv = require('dotenv'),
path = require('path')
dotenv.config({path: path.join(__dirname, '../.env')})
I had the same problem. I had created a file named .env, but in reality the file ended up being .env.txt.
I created a new file, saved it in form of 'No Extension' and boom, the file was real .env and worked perfectly.
This is how i fix my issue
Intially had this in .env of the root of my project
const db_port = 90101
const db_host="localhost"
const db_username="name"
const db_password="pwd"
const db_name="db"
And all my env variables where undefined.
I fixed it by removing all the const and using just key=value insted of
const key="value"
db_port = 90101
db_host=localhost
db_username=name
db_password=pws
db_name=db

Resources