NodeJS environment variables undefined - javascript

I'm trying to create some envrioment variables but when I create the file and run the server the seem to be undefined. I'm using nodemon. I have restarted my server and no luck.
UPDATED
.env
MONGO_ATLAS_PW = "xxxx";
JWT_KEY = "secret_this_should_be_longer";
package.json
...
"scripts": {
...
"start:server": "nodemon ./server/server.js"
}
app.js
require('dotenv').config();
...
console.log(process.env.JWT_KEY); //undefined

I believe the nodemon.json file is only for setting nodemon specific configuration. If you look at the nodemon docs for a sample nodemon.json file, the only env variable they mention setting is NODE_ENV.
Have you considered putting these environment variables for your app in a .env file instead? There is a package called dotenv that is helpful for managing env variables in Node.
First, install dotenv using the command npm install dotenv
Then, create a file called .env in the root directory with the following:
MONGO_ATLAS_PW=xxxxx
JWT_KEY=secret_this_should_be_longer
Finally, inside your app.js file after your imports add the following line:
require('dotenv').config()

I believe you're referring to the dotenv package. To configure it, first create a file called .env with your keys and values stored like so:
MONGO_ATLAS_PW=xxxxx
JWT_KEY=secret_this_should_be_longer
Then, in your server.js, add this near the top:
require("dotenv").config();
Then the process.env variable will be an object containing the values in .env.

This needed to be in the root directory of my project.
nodemon.json
{
"env": {
"MONGO_ATLAS_PW": "xxxx",
"JWT_KEY": "secret_this_should_be_longer"
}
}

The env variable do not contain the trailing white spaces and also remove the quotes
MONGO_ATLAS_PW = "xxxx";
JWT_KEY = "secret_this_should_be_longer";
to
MONGO_ATLAS_PW=xxxx
JWT_KEY=secret_this_should_be_longer
and restart the server
or you can also try using the nodemon.json - create a new file called nodemon.json in your root directory
{
"env": {
"MONGO_ATLAS_PW" : "xxxx",
"JWT_KEY" : "secret_this_should_be_longer"
}
}
and restart the server
for accessing the variable
process.env.MONGO_ATLAS_PW
process.env.JWT_KEY

Related

Load a variable from dotenv file when starting PM2

I am starting instances of my app as a package.json script with PM2 this way:
"start:pm2": "pm2 start -i max node myapp.js"
I found out that not all members in the team always want to use max as a value for instances number while developing, but prefer to use some lower value.
To not change package.json I would better let them change the value inside .env file because we already use it so that the value from it would be used as the parameter to pm2.
I know I can create a wrapper js or bash script to load the variable from .env file and pass it to pm2 but it would be better to have a solution without it.
How can I achieve this?
You can create an ecosystem.config.js file and declare your environment variables under the “env:” attribute, in your case the NODE_APP_INSTANCE can be used to set the number of instances:
module.exports = {
apps : [{
name: "MyApp",
script: "./myapp.js",
env: {
NODE_ENV: "development",
NODE_APP_INSTANCE: "max"
},
env_production: {
NODE_ENV: "production",
}
}]
}
Then call pm2 start or pm2 start /path/to/ecosystem.config.js to load an ecosystem from an other folder.
A better pattern here is to remove dotenv from your code and "require" it on the command line. This makes your code nicely transportable between any environment (including cloud-based) - which is one of the main features of environment variables.
a) code up your .env file alongside your script (e.g. app.js)
b) to run your script without pm2:
node -r dotenv/config app.js
c) in pm2.config.js:
module.exports = {
apps : [{
name : 'My Application',
script : 'app.js',
node_args : '-r dotenv/config',
...
}],
}
and then
pm2 start pm2.config.js
Note: the use of dotenv/config on the command line is one of the best practices recommended by dotenv themselves

Vue.js: Defining computed environment variables in vue.config.js (vue cli 3)

The documentation for Vue CLI 3 says here https://cli.vuejs.org/guide/mode-and-env.html#using-env-variables-in-client-side-code:
You can have computed env vars in your vue.config.js file. They still need to be prefixed with VUE_APP_. This is useful for version info process.env.VUE_APP_VERSION = require('./package.json').version
This is exactly what I want to do. But I couldn't find out how to actually define the env var there in vue.config.js. I tried:
module.exports = {
process.env.VUE_APP_VERSION: require("../package.json").version,
...
}
But it just produces an error:
ERROR SyntaxError: Unexpected token .
/Users/lhermann/htdocs/langify/frontend/vue.config.js:2
process.env.VUE_APP_VERSION: require("../package.json").version,
^
Does anyone know?
The environment variables are not part of the config export, you just set them in the vue.config.js file, eg
process.env.VUE_APP_VERSION = require('./package.json').version
module.exports = {
// other config, eg configureWebpack
}
I've raised a feature-request to get an example added to the docs ~ https://github.com/vuejs/vue-cli/issues/2864
Common Environment Variables:
According to Environment Variables and Modes documentation, you can specify env variables by placing .env files in your project root.
The variables will automatically be accessible under process.env.variableName in your project. Loaded variables are also available to all vue-cli-service commands, plugins and dependencies.
.env # loaded in all cases
.env.local # loaded in all cases, ignored by git
.env.[mode] # only loaded in specified mode
.env.[mode].local # only loaded in specified mode, ignored by git
Your .env file(s) should look like this:
VUE_APP_MY_ENV_VARIABLE=value
VUE_APP_ANOTHER_VARIABLE=value
Note that only variables that start with VUE_APP_ will be statically embedded into the client bundle with webpack.DefinePlugin.
Computed Environment Variables:
If you want variables that need pre-processing, you can use chainWebpack property of vue.config.js to inject anything you want:
// vue.config.js
module.exports = {
// ...,
chainWebpack: config => {
config.plugin('define').tap(args => {
args[0]['process.env'].APP_VERSION = `"${require("../package.json").version}"`
return args
})
}
// ...
}
Using this method, you can inject anything, with any names you want; you are not bound by the VUE_APP_ limitation.

Undefined process.env variable with dotenv and nodejs

I have a problem with the dotenv package.
My application folder:
|_app_folder
|_app.js
|_password.env
|_package.json
I've of course install dotenv, but when i tried to log a process.env variables, the result is always undefined, please can you help me ?
password.env :
//password.env
CLIENT_ID=xxxxxxxx
app.js :
//app.js
const express = require('express');
const app = express();
const Twig = require("twig");
//Require dotenv
require('dotenv').config();
// Setting the Twig options
app.set("twig options", {
allow_async: true,
strict_variables: false
});
app.get('/', function (req, res) {
//Trying to log it
console.log(process.env.CLIENT_ID);
//
res.render('index.twig', {
date : new Date().toString()
});
});
app.get('/instagram',function(req,res){
// Building the URL
let url = 'https://api.instagram.com/oauth/authorize/?client_id=';
// Redirect to instagram for oauth
res.redirect(url);
})
app.listen(3000, function () {
console.log('Running');
})
Thank you for your time.
By default the dotenv package does only load a file named .env if you want to load another file you need to specify the path
require("dotenv").config({ path: "path/to/file" })
Resources:
https://www.npmjs.com/package/dotenv
I was having somewhat the same problem for a while turns out you just have to put the .env file in the root of the directory (top-most level).
I know this post is old but I just want to make sure no one struggles with such a simple task again.
When using import instead of require. -
You can use -r (require) to preload dotenv. You do not need to require and load dotenv in your application code.
$ node -r dotenv/config app.js
Even though I put the .env file in the root folder, still console.log(process.env.myKey) is undefined. The fix worked for me is I put the path to the env file in the require config itself like below. (It's in the root of the file - so "./.env)
require("dotenv").config({path:"./.env"})
Another important note:
Place your .env file in the root folder, not in /src

npm global packages: Reference content files from package

I'm in the process of building an npm package which will be installed globally. Is it possible to have non-code files installed alongside code files that can be referenced from code files?
For example, if my package includes someTextFile.txt and a module.js file (and my package.json includes "bin": {"someCommand":"./module.js"}) can I read the contents of someTextFile.txt into memory in module.js? How would I do that?
The following is an example of a module that loads the contents of a file (string) into the global scope.
core.js : the main module file (entry point of package.json)
//:Understanding: module.exports
module.exports = {
reload:(cb)=>{ console.log("[>] Magick reloading to memory"); ReadSpellBook(cb)}
}
//:Understanding: global object
//the following function is only accesible by the magick module
const ReadSpellBook=(cb)=>{
require('fs').readFile(__dirname+"/spellBook.txt","utf8",(e,theSpells)=>{
if(e){ console.log("[!] The Spell Book is MISSING!\n"); cb(e)}
else{
console.log("[*] Reading Spell Book")
//since we want to make the contents of .txt accesible :
global.SpellBook = theSpells // global.SpellBook is now shared accross all the code (global scope)
cb()//callBack
}
})
}
//·: Initialize :.
console.log("[+] Time for some Magick!")
ReadSpellBook((e)=>e?console.log(e):console.log(SpellBook))
spellBook.txt
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ
ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ
ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ
ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ
ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ
If you require it from another piece of code, you will see how it prints to the console and initializes by itself.
If you want to achieve a manual initalization, simply remove the 3 last lines (·: Initialize :.) and use reload() :
const magick = require("core.js")
magick.reload((error)=>{ if(error){throw error}else{
//now you know the SpellBook is loaded
console.log(SpellBook.length)
})
I have built some CLIs which were distributed privately, so I believe I can illuminate a bit here.
Let's say your global modules are installed at a directory called $PATH. When your package will be installed on any machine, it will essentially be extracted at that directory.
When you'll fire up someCommand from any terminal, the module.js will be invoked which was kept at $PATH. If you initially kept the template file in the same directory as your package, then it will be present at that location which is local to module.js.
Assuming you edit the template as a string and then want to write it locally to where the user wished / pwd, you just have to use process.cwd() to get the path to that directory. This totally depends on how you code it out.
In case you want to explicitly include the files only in the npm package, then use files attribute of package.json.
As to particularly answer "how can my code file in the npm package locate the path to the globally installed npm folder in which it is located in a way that is guaranteed to work across OSes and is future proof?", that is very very different from the template thingy you were trying to achieve. Anyway, what you're simply asking here is the global path of npm modules. As a fail safe option, use the path returned by require.main.filename within your code to keep that as a reference.
When you npm publish, it packages everything in the folder, excluding things noted in .npmignore. (If you don't have an .npmignore file, it'll dig into .gitignore. See https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package) So in short, yes, you can package the text file into your module. Installing the module (locally or globally) will get the text file into place in a way you expect.
How do you find the text file once it's installed? __dirname gives you the path of the current file ... if you ask early enough. See https://nodejs.org/docs/latest/api/globals.html#globals_dirname (If you use __dirname inside a closure, it may be the path of the enclosing function.) For the near-term of "future", this doesn't look like it'll change, and will work as expected in all conditions -- whether the module is installed locally or globally, and whether others depend on the module or it's a direct install.
So let's assume the text file is in the same directory as the currently running script:
var fs = require('fs');
var path = require('path');
var dir = __dirname;
function runIt(cb) {
var fullPath = path.combine(__dirname, 'myfile.txt');
fs.readFile(fullPath, 'utf8' , function (e,content) {
if (e) {
return cb(e);
}
// content now has the contents of the file
cb(content);
}
}
module.exports = runIt;
Sweet!

How to use in node properties for deployment and local usage

I've created node application which I can run locally and in the cloud
Now I want that it be done somehow smoother and cleaner ,so I try to put some property in config.json file to check if I want to deploy the app or use it locally but I need to update manually this property before I change the propose , there is a better way to do it with node ?
let runnerServer = `http://localhost:8060/service/runner/${server.address().port}`;
if (cfg.isHosted) {
blogServer = `http://${serverName}/service/runner/${server.address().port}`;
}
and in the conig.json I've the field isHosted which I change manually(true/false) if I want to deploy or not...
update
maybe I can use process.env.PORT but this is just one example that I need to use in my code , currently I've several of fork that need to konw if Im in deployment or running locally ..
One option is to use use node's in built object called process.env (https://nodejs.org/api/process.html) and use two config files per se. This approach is somewhat similar to what you are doing but may be cleaner
config.localhost.json
config.production.json
then by setting properties on this object based on environment such as process.env.NODE_ENV = 'localhost' or process.env.NODE_ENV = 'production', you could read the corresponding file to import the configurations.
var config = require('./config.production.json');
if(process.env.NODE_ENV === 'localhost')
{
config = require('./config.localhost.json');
}
So to set this environment variable when running locally on your dev box , if
OSX - then on terminal export NODE_ENV=localhost
WINDOWS - then on cmd line set NODE_ENV=localhost
An easy way to solve this, if every environment configuration can be in the repo:
config.json:
production: {
// prod config
},
staging: {
// staging config
},
devel: {
// devel config
}
config.js:
const environment = process.env['ENV'] || 'devel';
module.exports = require('./config.json')[environment];
then in your package.json you could add the following scripts:
package.json
// npm stuff
scripts {
prod: "ENV=production node index.js",
stage: "ENV=staging node index.js",
dev: "ENV=devel node index.js"
}
and with this setup, you can run each configuration with the following commands:
production: npm run prod
staging: npm run stage
devel: npm run dev

Categories