Trouble with Node.js constants - javascript

I'm currently learning Node.js and I'm having trouble integrating constants into my service. I have created a constants file and am referencing those values from other files. Unfortunately, I don't seem to be doing it correctly as things start to fail when I reference constants rather than just place literals into all of my function calls.
constants.js
exports.DB_HOST = 'localhost';
exports.DB_PORT = 3306;
exports.DB_USER = 'user';
exports.DB_PASSWORD = 'password';
exports.DB_DATABASE = 'database';
When trying to connect to a MySQL database, the connection fails as the server claims that the credentials are incorrect. However, when I replace all of the constants below with literals, everything works correctly (so I'm not using incorrect authentication information).
var constants = require('constants');
...
var connection = mysql.createConnection({
host: constants.DB_HOST,
port: constants.DB_PORT,
user: constants.DB_USER,
password: constants.DB_PASSWORD,
database: constants.DB_DATABASE
});
...
connection.query('SELECT * FROM table',
function(err, rows, fields) {
res.send(err);
});

constants is a built-in node module that provides system-level constants for use with other built-in modules, like fs, crypto, etc. If you want your constants.js, you will need to include the (absolute or relative) path to it. For example:
var constants = require('./constants');

In addition to changing your require() to use your local module rather than a built-in module:
var constants = require('./constants');
There is a misspelling here in your code:
port: constants.DB_POST,
// wrong character ^
should be:
port: constants.DB_PORT,

So, a couple things:
It looks like you're trying to require either an installed node module called constants or a built-in module (which is pretty much a set of constants for us in built-in node modules like fs, http, crypto, etc.). That would be the main reason you can't access it. Node doesn't know to look for your local module b/c no path string has been supplied.
you might be able to clean up your module a bit w/ some optional but (sometimes) helpful refactoring.
I would recommend the following change to how you require your module:
// Bc it's a set of constants, use the es6/2015 `const` if available when requiring your module
const constants = require('./constants');
You could clean up your module a little bit w/ module.exports; makes it really clear what the object you're exposing is:
module.exports = {
DB_HOST : 'localhost',
DB_PORT : 3306,
DB_USER : 'user',
DB_PASSWORD : 'password',
DB_DATABASE : 'database',
}
Another consideration: in most apps, you really want to keep configuration as internally-stateless as possible. That means your app shouldn't really have any configurational values hard-coded into it. Generally, if you avoid doing so you will have a much more flexible setup externally. In other words, you'd be able to spin up as many different instances as you want with as many different databases to connect to. When you change databases, you'd only have to change the environment, not the app itself. And, if you get into the semantics of it all, your app's job is to connect, not to really decide where to connect — the environment should provide that. So, these could be made available from your module as:
const config = {
DB_HOST : process.env.DB_HOST,
DB_PORT : process.env.DB_PORT,
DB_USER : process.env.DB_USER,
DB_PASSWORD : process.env.DB_PASSWORD,
DB_DATABASE : process.env.DB_DATABASE,
};
module.exports = config;
You could just access them from anywhere with process.env.YOUR_VAR, but if you want to consolidate them all in a module that is just as good in many ways and would let you change external config value variable names (i.e. process.env.DB_USERNAME instead of DB_USER) and not have to change it everywhere else (if you don't need the names to be kept in sync).
Hope that helps! :)

Related

Dotenv unable to overwrite key value pair

I am trying to implement environment variables using dotenv on my node server, however I am having trouble loading them in from the .env file which is located in the root. When I run const dotenv = require("dotenv").config({debug: true}); I encounter the following message: "USER" is already defined in process.env and will not be overwritten
Additionally when I try to load the page, it encounter the following error: ER_DBACCESS_DENIED_ERROR: Access denied for user ''#'localhost' to database '_api'
.env:
USER=root
PASS=
From the Variables overwriting/priority.
Environment variables that are already set will not be overwritten, that means that the command line variables have a higher priority over all those defined in env files;
And this What happens to environment variables that were already set?
We will never modify any environment variables that have already been set. In particular, if there is a variable in your .env file which collides with one that already exists in your environment, then that variable will be skipped. This behavior allows you to override all .env configurations with a machine-specific environment, although it is not recommended.
If you want to override process.env you can do something like this:
const fs = require('fs')
const dotenv = require('dotenv')
const envConfig = dotenv.parse(fs.readFileSync('.env.override'))
for (const k in envConfig) {
process.env[k] = envConfig[k]
}
As of version 16.0.1, you can override process.env values with require('dotenv').config({ override: true }).
.env:
access_token=aa
index.js:
require('dotenv').config({ override: true })
process.env.access_token = bb
console.log(process.env.access_token) //bb

Type error: expected parameter accessToken in react Js

Error screenshot:
While running react project by npm start, it shows error related to contentful.js. why does the package shows these types of error? I attached the screenshot with this post. How to solve this issue?
.env file
CONTENTFUL_ACCESS_TOKEN: process.env.REACT_APP_CONTENTFUL_ACCESS_TOKEN,
config file
import SETTINGS from "../env";
const contentfulClient = contentful.createClient({
space: SETTINGS.CONTENTFUL_SPACE,
accessToken: SETTINGS.CONTENTFUL_ACCESS_TOKEN
});
Do i need to enter api token anywhere?
.env
const SETTINGS = {
LANDING_BLOG_POSTS: "",
ICON_TYPE: "svg",
CONTENTFUL_SPACE: process.env.REACT_APP_CONTENTFUL_SPACE,
CONTENTFUL_ACCESS_TOKEN: process.env.REACT_APP_CONTENTFUL_ACCESS_TOKEN,
CLOUDINARY_UNSIGNED_PRESET: process.env.REACT_APP_CLOUDINARY_UNSIGNED_PRESET,
CLOUDINARY_CLOUD_NAME: process.env.REACT_APP_CLOUDINARY_CLOUD_NAME,
SERVER_7CHIP: process.env.REACT_APP_SERVER_7HIP || false,
HARD_CODED_USERNAME: process.env.REACT_APP_TOKEN_USERNAME || "**********",
HARD_CODED_PASSWORD: process.env.REACT_APP_TOKEN_PASSWORD || "************",
FACEBOOK_API_ID: process.env.REACT_APP_FACEBOOK_APP_ID,
FACEBOOK_PAGE_TOKEN: process.env.REACT_APP_FACEBOOK_PAGE_TOKEN,
FACEBOOK_PAGE_ID: process.env.REACT_APP_FACEBOOK_PAGE_ID || "**************",
FACEBOOK_SERVER_CALL: true
};
export default SETTINGS;
Since your code got as far as getting into the createClient function, that tells me your SETTINGS object is loading (otherwise you'd get a TypeError from accessToken: SETTINGS.CONTENTFUL_ACCESS_TOKEN). However the error message says that no accessToken was provided.
Therefore SETTINGS.CONTENTFUL_ACCESS_TOKEN is undefined, null or an empty string. Since that value is set to process.env.REACT_APP_CONTENTFUL_ACCESS_TOKEN this probably means that you have not set your REACT_APP_CONTENTFUL_ACCESS_TOKEN environment variable before running the program.
Try setting that environment variable to your access token value, then running the program.
If that works, you might want to reconsider the approach. You have an "env" file but is getting values from system environment variables. Usually you have an "env" file so that you can hardcode values into it, not rely on them being set externally. If they have to be set externally you might as well not use an "env" file and just use process.env.VARIABLE_NAME directly in your code.
Note that if you hardcode access tokens or other private information in an "env" file, you should add that file to .gitignore so that passwords/keys are not stored in git.
You created .env.development file same location as package.json file.
hope, this will help you.
For me, I had the variables in the .env file in the source directory and just had to source it. I ran . ./.env and that sorted out the error in my case.
In my case environment variables weren't accessible, because I created the .env file when my server was already running. I had to restart the server and everything worked like a charm.

Difference between export SOME_ENV_VAR=KEY and SOMEOTHER_ENV_VAR=KEY in dotenv?

I am relatively new to Node.js. I want to export environment variables from .env file to my javascript files. In order to do that I am using dotenv.
Which method should I use to export the environment variables to my main javascript files ( say- app.js)
export GEOCODER_API_KEY= someKeyXYZ // inside .env file
GEOCODER_API_KEY_1 = someKeyXYZ // inside .env file
One thing to note is that upon console.log(process.env) in the app.js, the GEOCODER_API_KEY_1 shows up as env variable, but not GEOCODER_API_KEY? Why is that. What use is the first one then, since it is not accessible?
A more confusing thing is that:
var options = {
provider: 'google',
httpAdapter: 'https',
apiKey: process.env.GEOCODER_API_KEY,
formatter: null
}; // this works
... // some javascript
console.log(process.env.GEOCODER_API_KEY) //SHOWS UNDEFINED
I basically want to export the API_KEY (unrestricted) safely to my project. Is there a catch that I might be missing?
The correct way of writing portable variable declarations in an .env file is:
FOO=BAR
This is - when you use dotenv implementations like dotenv.
require('dotenv').config();
console.log(process.env);
When using export in .env in a Unix/Bash environment (what you have probably seen in the wild) - sourcing the file will yield differences concerning the scope of the declared variable:
# .env
export GEOCODER_API_KEY=someKeyXYZ
GEOCODER_API_KEY_1=someKeyXYZ
# main.sh
#!/bin/bash
. ./.env
./subprocess.sh
# subprocess.sh
#!/bin/bash
echo "GEOCODER_API_KEY": $GEOCODER_API_KEY
echo "GEOCODER_API_KEY_1": $GEOCODER_API_KEY_1
./main.sh
GEOCODER_API_KEY: someKeyXYZ
GEOCODER_API_KEY_1:

Requiring files in electron without babel

I'm trying to convert a web application into an electron app. I have multiple functions, in different files that I've imported into my main.js using a transpiler.
However, whenever I try do that in my electron app, I run into an issue with a module I'm using to move away from using php to access my database. Instead I'm using the mysql module on npm.
I want to save this function in its own file, and then require it in main.js. When I try to transpile it with babel, I get an error about Net.Connection not working (or something along those lines). As I understand it, this is because of how Node works. I'm happy to work around this, but I'm hoping there's a way to save this function in another file, and import it without having to use babel.
function loadColourFilter(){
var mysql = require('mysql');
let query_result;
var connection = mysql.createConnection({
host : 'xxxxxxxxxxxx',
user : 'xxxxxxxxxxxx',
password : 'xxxxxxxxxxxx',
database : 'xxxxxxxxxxxx'
});
connection.connect();
let query = "xxxxxxxxxxxxxxxx";
connection.query(query, function (error, results, fields) {
});
connection.end();
return (query_result);
}
EDIT: I've removed some parts of the function to keep credentials safe and whatnot. I'm fairly certain their absence won't change anything when trying to solve this.
EDIT:
My project directory is essentially
src
--- js
--- --- main.js
--- functionFile.js // This would be where my loadColourFilter function above would be saved
--- node_modules
--- --- ...
--- index.html // js/main.js is referenced in a script tag here.
--- main.js // Where the electron window is created.
--- package.json
There should be 2 js contexts, one running in the electron app and one running in node. You won't be able to require you scripts directly from your directory if you are in the electron context (which is like a browser js context).
I'm just assuming this is the case since we don't get a lot of information for your problem, and the other answer should have resolved your problem.
Try to include your js file in your index.html and see what's up.
Edit: Since it's a Transpiling error with babel, babel is probably transpiling for node when it should transpile for the browser.
You can easily make a simple local module using NodeJS by creating a source file and then adding a module.exports assignment to export some functionality/variables/etc from the file. In your case something like a file named colourFilter.js with the contents:
function load(){
var mysql = require('mysql');
let query_result;
var connection = mysql.createConnection({
host : 'xxxxxxxxxxxx',
user : 'xxxxxxxxxxxx',
password : 'xxxxxxxxxxxx',
database : 'xxxxxxxxxxxx'
});
connection.connect();
let query = "xxxxxxxxxxxxxxxx";
connection.query(query, function (error, results, fields) {
});
connection.end();
return (query_result);
}
module.exports = load
And then in your code where you'd like to use it include it by doing something like:
loadColourFilter = require('colourFilter.js')
And use the function like
let result = loadColourFilter()
This is a simple way to split up your code into multiple files/classes/modules but still keep one main file/class/module as the important one which is the public-facing portion or entry point. And of course you don't have to use the names I've used above :P
If you would like to make an object-style module you can instead export an object like
module.exports = {
load
}
Or
module.exports = {
load: loadFunctionNameInThisFile
}
And then use it like
const colourFilter = require('colourFilter.js')
let result = colourFilter.load()

Use different file for testing in node js

I am using a particular set of URLs for connecting to services. They are there in the config.js file. Now while testing using mocha, I want to use a different set of urls. Is it possible to over-ride the urls configured in the js file from the test cases.This is how my config.js looks -
var servercfg = {
host: 'localhost',
port: '9010'
};
var enterprisesercfg = {
userserurl: 'http://localhost:9020',
accountserurl: 'http://localhost:9020',
creditcardserurl: 'http://localhost:9020'
};
var oauth2sercfg = {
url: 'http://localhost:9000/api/oauth2/verify'
};
module.exports={
servercfg,
enterprisesercfg,
oauth2sercfg
};
There are already several solutions to manage your configuration; for example this one: https://github.com/lorenwest/node-config
You define different files for your different NODE_ENV.
//development.json
{
"someURL": "http://url.com"
}
//test.json
{
"someURL: "http://url.com"
}
So all you need to do to change the file from which you load the config is set the NODE_ENV variable when starting your app.
There are other modules besides this one, it's just an example on how to solve your problem.

Categories

Resources