my .env variables wont return for database login in node.js - node.js

Having a problem with .env variables in node.js, am using dotenv to handle the variables.
straight forward
require('dotenv').load()
and then checked console log to see if I can access then variables like so
console.log("database Name: "+process.env.DB_NAME);
console.log("database Username: "+process.env.DB_USER);
etc and all return fine.
the part of the code that calls the db is the following-
var Sequelize = require('sequelize');
module.exports = new Sequelize('dbname, 'username', 'password', {
host: 'hostname',
dialect: 'mssql',
dialectOptions: {
instanceName: 'namehere'
}
});
I replace the dbname with process.env.DB_NAME and all is fine, nothing falls over but the moment I try and use DB_USER in there then it fails to connect and shows user as ' ' in the log.
module.exports = new Sequelize(process.env.DB_NAME, process.env.USER_DB, 'password', { etc
the .env file itself is very straight forward and nothing out of the ordinary. structured as
NAME="value"
NAME2="value2"
etc. I though maybe once a value has been console logged it wont be available and turned off the console logs, but no luck. I also tried changing the name of the value encase that was reserved. please advise.

nevermind I was being silly. I presumed it only needed to be required once but not the case.

Related

Using Connection URIs with Read Replication in Sequelize

If I have a connection URI, I can use that normally with Sequelize as such:
const sequelize = new Sequelize('postgres://user:pass#example.com:5432/dbname');
However, if I want to use Read and Write replication (https://sequelize.org/master/manual/read-replication.html), then there doesn't seem an option to use connection URI. Can I pass connection URI strings to read and write in the replication option as in:
const sequelize = new Sequelize(null, null, null, {
dialect: 'postgres',
replication: {
read: [
'postgres://user:pass#reader.example.com:5432/dbname',
'postgres://user:pass#anotherreader.example.com:5432/dbname'
],
write: 'postgres://user:pass#writer.example.com:5432/dbname'
}
})
EDIT:
I have already found a solution to the issue. and that is using an npm library like connection string to parse the connection string as shown below:
const write_uri = new ConnectionString(uri);
const sequelize = new Sequelize(null, null, null, {
dialect: 'postgres',
replication: {
read: [
'postgres://user:pass#reader.example.com:5432/dbname',
'postgres://user:pass#anotherreader.example.com:5432/dbname'
],
write: {
host: write_uri.hosts[0].name,
username: write_uri.user,
password: write_uri.password,
database: write_uri.path[0],
port: write_uri.hosts[0].port
}
}
});
But, that is not what I'm looking for.
As per sequelize source at master, you can't.
According to the sequelize source docs at sequelize.js, The Sequelize Constructor accepts options agrument, like this
constructor(database, username, password, options){
}
Where options.replication should be an object with two properties, read and write. Write should be an object (a single server for handling writes), and read an array of object (several servers to handle reads). Each read/write server can have the following properties: host, port, username, password, database.
you need to pass an array of objects to read:[] with connection values as props instead of passing strings.
You can pass config object to sequelize constructor even if you use uri connection.
Look the example in from the docs:
https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor
// with uri
const sequelize = new Sequelize('mysql://localhost:3306/database', {})
Look at the constructor overloading definition:
Sequelize(uri: string, options?: Sequelize.Options): Sequelize.Sequelize
Just pass the options you need.

Hapi.js Catbox Redis returning "server.cache is not a function"

So I'm like 99% sure I'm just screwing up something dumb here.
I'm trying to set up catbox to cache objects to redis. I have redis up and running and I can hit it with RDM (sql pro like utility for redis) but Hapi is not cooperating.
I register the redis catbox cache like so:
const server = new Hapi.Server({
cache: [
{
name: 'redisCache',
engine: require('catbox-redis'),
host: 'redis',
partition: 'cache',
password: 'devpassword'
}
]
});
I am doing this in server.js After this block of code I go on to register some more plugins and start the server. I also export the server at the end of the file
module.exports = server;
Then in my routes file, I am attempting to set up a testing route like so:
{
method: 'GET',
path: '/cacheSet/{key}/{value}',
config: { auth: false },
handler: function(req, res) {
const testCache = server.cache({
cache: 'redisCache',
expireIn: 1000
});
testCache.set(req.params.key, req.params.value, 1000, function(e) {
console.log(e);
res(Boom.create(e.http_code, e.message));
})
res(req.params.key + " " + req.params.value);
}
},
Note: My routes are in an external file, and are imported into server.js where I register them.
If I comment out all the cache stuff on this route, the route runs fine and returns my params.
If I run this with the cache stuff, at first I got "server not defined". So I then added
const server = require('./../server.js');
to import the server.
Now when I run this, I get "server.cache is not a function" and a 500 error.
I don't understand what I'm doing wrong. My guess is that I'm importing server, but perhaps it's the object without all the configs set so it's unable to use the .cache method. However this seems wrong because .cache should always be a default method with the default memory cache, so even if my cache registration isn't active yet, server.cache should theoretically still be a method.
I know it has to be something basic I'm messing up, but what?
I was correct. I was doing something stupid. It had to do with how I was exporting my server. I modified my structure to pull out the initial server creation and make it more modular. Now I am simply exporting JUST the server like so:
'use strict';
const Hapi = require('hapi');
const server = new Hapi.Server({
cache: [
{
name: 'redisCache',
engine: require('catbox-redis'),
host: 'redis',
partition: 'cache',
password: 'devpassword'
}
]
});
module.exports = server;
I then import that into my main server file (now index.js previously server.js) and everything runs fine. I can also import this into any other file (in this case my routes file) and access the server for appropriate methods.
Redis is happily storing keys and Hapi is happily not giving me errors.
Leaving here in case anyone else runs into a dumb mistake like this.

How exactly does eval work with nodejs?

Let's say I do:
eval(
db_config = {
host: 'localhost',
user: 'root',
database: 'forum',
password: 'test'
}
);
var gamefunctions = require('gamefunctions.js');
I can use db_config anywhere inside gamefunctions.js without having to pass it through a parameter. That's pretty neat. But, is this bad practice?
Reason I ask this is because if I do:
var db_config = {
host: 'localhost',
user: 'root',
database: 'forum',
password: 'test'
}
var gamefunctions = require('gamefunctions.js');
db_config becomes undefined anytime I use it in gamefunctions.js. And I would have to pass it through a parameter on each different function which just seems like evaling it first would save time and code, any downside to this?
Does eval basically just define the variables in a global scope for you, so they can be used in any file in nodejs?
You're doing 2 things wrong and there's much more elegant solution to this.
To explain what you're doing wrong, first is the use of globals. Second is that you're storing sensitive information in your code - your database password! And besides, it won't be very portable. Suppose you want to run it on another machine that has some other database credentials you'll end up changing your code unnecessarily.
You need to store it as environment variables. And if you end up hosting it some environments automatically have those set for you so you could use them in your app. For example openshift would have an $OPENSHIFT_MONGODB_DB_HOST that it tells you to use in your app to connect to its database.
And you need to create a separate file to store your db_config which you can require from other files.
So you might create a db_config.js which would look like this
var config = {};
config.host = process.env.HOST || 'localhost';
config.user = process.env.USER || 'root';
config.password = process.env.password;
module.exports = config;
Then you can safely just pass it the sensitive information like password from console
$ password=pass
$ node index.js
And as for having that information in your gamefunctions.js all you gotta do is require it
var db_config = require('./db_config');

Where do I put database connection information in a Node.js app?

Node.js is my first backend language and I am at the point where I am asking myself "where do I put the database connection information?".
There is a lot of good information regarding this issue. Unfortunately for me all the examples are in PHP. I get the ideas but I am not confident enough to replicate it in Node.js.
In PHP you would put the information in a config file outside the web root, and include it when you need database data.
How would you do this in Node.js? using the Express.js framework.
So far I have this:
var express = require('express'), app = express();
var mysql = require('mysql');
app.get('/', function(req,res) {
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'store'
});
var query = connection.query('SELECT * from customers where email = "deelo42#gmail.com"');
query.on('error', function(err) {
throw err;
});
query.on('fields', function(fields) {
console.log('this is fields');
});
query.on('result', function(row) {
var first = row.first_name;
var last = row.last_name;
res.render('index.jade', {
title: "My first name is " + first,
category: "My last name is " + last
});
});
});
app.listen(80, function() {
console.log('we are logged in');
});
As you can see I have a basic express application with 1 GET route. This route sets off the function to go to the database and pull out information based on an email address.
At the top of the GET route is the database connection information. Where do I put that? How do I call it? How do I keep it out of web root, and include it like PHP ? Can you please show me in a working example. Thanks!
I use the Express Middleware concept for same and that gives me nice flexibility to manage files.
I am writing a detailed answer, which includes how i am use the config params in app.js to connect to DB.
So my app structure looks something this:
How i connect to DB? (I am using MongoDB, mongoose is ORM, npm install mongoose)
var config = require('./config/config');
var mongoose = require("mongoose");
var connect = function(){
var options = {
server: {
socketOptions:{
keepAlive : 1
}
}
};
mongoose.connect(config.db,options);
};
connect();
under the config folder i also have 'env' folder, which stores the environment related configurations in separate files such as development.js, test.js, production.js
Now as the name suggests, development.js stores the configuration params related to my development environment and same applies to the case of test and production. Now if you wish you can have some more configuration setting such as 'staging' etc.
project-name/config/config.js
var path = require("path");
var extend = require("util")._extend;
var development = require("./env/development");
var test = require("./env/test");
var production = require("./env/production");
var defaults = {
root: path.normalize(__dirname + '/..')
};
module.exports = {
development: extend(development,defaults),
test: extend(test,defaults),
production: extend(production,defaults)
}[process.env.NODE_ENV || "development"]
project-name/config/env/test.js
module.exports = {
db: 'mongodb://localhost/mongoExpress_test'
};
Now you can make it even more descriptive by breaking the URL's into, username, password, port, database, hostname.
For For more details have a look at my repo, where you can find this implementation, in fact now in all of my projects i use the same configuration.
If you are more interested then have a look at Mean.js and Mean.io, they have some better ways to manage all such things. If you are beginner i would recommend to keep it simple and get things going, once you are comfortable, you can perform magic on your own. Cheers
I recommend the 12-factor app style http://12factor.net which keeps all of this in env vars. You never should have this kind of information hard-coded or in the app source-code / repo, so you can reuse it in different environments or even share it publicly without breaking security.
However, since there are lots of environment vars, I tend to keep them together in a single env.js like the previous responder wrote - although it is not in the source code repo - and then source it with https://www.npmjs.org/package/dotenv
An alternative is to do it manually and keep it in, e.g. ./env/dev.json and just require() the file.
Any of these works, the important point is to keep all configuration information separate from code.
I agree with the commenter, put it in a config file. There is no ultimate way, but nconf is also one of my favourites.
The important best practise is that you keep the config separate if you have a semi-public project, so your config file will not overwrite other developers.
config-sample.json (has to be renamed and is tracked with for example git)
config.json (not tracked / ignored by git)

Node Express Session Count

I have an application where I need to limit the number of active connections, and the most logical way of doing this to me, would be to simply count the number of active sessions.
I have searched for "node express session count" but did not find anything useful.
Is it possible to get the number of open sessions in node express ?
The alternative would be to save the IP address of each connected client, but the problem with this method is that the ip address would need to be manually removed from the datastore.
I guess if I use redis as the data store, I could use expire to achieve something similar.
set ip.192.168.42.1 true
expire ip.192.168.42.1 60
ttl ip.192.168.42.1
etc etc
Or is there a better way ?
EDIT
I have tried the suggestion of using MemoryStore but I can't seem to figure out how to use it ??
var express = require("express");
var MemoryStore = express.session.MemoryStore;
MemoryStore.prototype.length = function(fn) {
fn(null, Object.keys(this.sessions).length);
};
MemoryStore.length(function(len) {
console.log('sessions:'+len);
});
Use the Store.length(fn) method. In the default Connect memory storage, it's written like this:
MemoryStore.prototype.length = function(fn) {
fn(null, Object.keys(this.sessions).length);
};
So you would call it like this:
store.length(function(len) {
// we have len number of sessions
});
I am well aware of how old this post is but I thought I would share my way, as this comes up as the top result as I was trying to figure it out.
This what I did and it seems to be working.
So if you are using MySQLStore & Express Session you can approach it like this,
Add activeUsers to your options(app/index.js):
var options = {
host: process.env.DB_HOST,
port: 3306,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
activeUsers: 0
};
On your login.js add:
req.sessionStore.options.userCount += 1
And on your logout:
req.sessionStore.options.userCount += 1
Now I am not sure if on session timeout if this will return back to 0 or not, but I would assume that it does. And then just create a app.local that refers to the userSession count

Resources