I have a MERN application that runs fine on a Windows machine, but when trying to deploy it to a colleague's macOS machine we're getting the below error. Console logging process.env.DATABASE reveals it is undefined on the macOS machine. We tried setting the variable by running export NODE_ENV=development in the console but still get the same error.
index.js
const express = require('express');
const session = require('express-session');
const mongoose = require('mongoose');
const MongoStore = require('connect-mongo');
const db = require('./database');
const router = require('./routes');
const app = express();
require('dotenv').config({ path: 'variables.env' });
app.use(session({
secret: process.env.SECRET,
key: process.env.KEY,
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongoUrl: process.env.DATABASE })
}));
app.use('/api', router);
app.set('port', process.env.PORT || 8000);
const server = app.listen(app.get('port'), () => {
console.log(`Express running on port ${server.address().port}`);
});
variables.env
NODE_ENV=development
DATABASE=database path
error in console:
> server#1.0.0 start
> node ./index.js
Assertion failed: You must provide either mongoUrl|clientPromise|client in options
/Users/user/Documents/ATT-main/server/node_modules/connect-mongo/build/main/lib/MongoStore.js:119
throw new Error('Cannot init client. Please provide correct options');
^
Error: Cannot init client. Please provide correct options
at new MongoStore (/Users/user/Documents/ATT-main/server/node_modules/connect-mongo/build/main/lib/MongoStore.js:119:19)
at Object.<anonymous> (/Users/user/Documents/ATT-main/server/index.js:32:10)
What am I missing?
Related
I receive the following error when using my browser to make a GET request for all entries in a database table:
Error: connect ECONNREFUSED 127.0.0.1:5432
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1187:16)
Error in GET /products
The relevant folder structure looks like:
server/
db/
index.js
routes/
products.js
index.js
The files involved are:
server/index.js
const express = require("express");
const cors = require("cors");
const app = express();
const PORT = process.env.port || 3001;
app.use(cors());
app.use(express.json());
// const usersRouter = require('./routes/users')
// app.use('/users', usersRouter)
// const authRouter = require('./routes/auth')
// app.use(['/login', '/register'], authRouter)
const productsRouter = require('./routes/products')
app.use('/products', productsRouter)
// const cartsRouter = require('./routes/carts')
// app.use('/carts', cartsRouter)
// const ordersRouter = require('./routes/orders')
// app.use('/orders', ordersRouter)
app.listen(PORT, () => {
console.log(`Listening on ${PORT}`);
});
Initializes the server on port 3001 and creates productsRouter.
server/db/index.js
const { Pool, Client } = require("pg");
const pool = new Pool({
user: "postgres",
host: "localhost",
database: "ecommerce",
password: "postgres",
port: "5432",
});
module.exports = {
query: (text, params, callback) => {
return pool.query(text, params, callback)
},
}
Provides the function for making queries.
server/routes/products.js
const express = require("express");
const products = express.Router();
const db = require("../db/index");
products.get("/", async (req, res) => {
try {
const products = await db.query("SELECT * FROM products");
return res.status(201).send(products.rows);
} catch (err) {
console.log(err.stack);
console.log("Error in GET /products");
res.status(500).send("Server Error Occurred");
}
});
Provides Node.js logic for making requests using db.query calls.
Steps to produce error:
Launch/connect Postbird on port 5432 on localhost.
Run ‘node index.js’ on server/index.js to start Node.js server
listening on port 3001.
Navigate browser to localhost:3001/products to initiate GET request.
Self-taught programmer here. So it turns out that when Codecademy told me to install Windows Subsystem for Linux (WSL), I didn't realize it was truly, essentially a mostly separate system from my main OS. I was using WSL's terminal in VS Code and when I ran 'node index.js', index.js was running on WSL. Therefore, it was unaware of the perfectly good, perfectly accessible instance of Postgresql running on port 5432 of my main OS.
Basically, it was refusing to connect to port 5432 on WSL because there wasn't any Postgres instance listening on that port of WSL; in fact, it wasn't even installed on WSL.
I switched to my Bash terminal, ran 'node index.js', navigated my browser to the URL that calls the GET request which returns the results of a SELECT on all tables in my database, and voila! It worked.
I tried to connect my mongo cluster with my local server but this error keeps on showing up. I am following a tutorial and it seems to work fine for the tutor but this error comes for me. I have provided the error screenshot below.
Error which comes up
The src has been provided
const express = require('express');
const env = require('dotenv');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
//routes
const userRoutes = require('./routes/user');
//constants
env.config();
//mongodb connect
//mongodb+srv://root:<password>#cluster0.9ylhh.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
mongoose.connect(
`mongodb+srv://${process.env.MONGO_DB_USER}:${process.env.MONGO_DB_PASSWORD}#cluster0.9ylhh.mongodb.net/${process.env.MONGO_DB_DATABASE}?retryWrites=true&w=majority`,
{
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
}
).then(() => {
console.log('Database connected');
});
//middleware
app.use(express.urlencoded({ extended: true}));
app.use(express.json());
app.listen(process.env.PORT, () => {
console.log(`server is running on port ${process.env.PORT}`);
});
I also did create a .env file with the credentials details and stuff
I tried to make a comment instead of an answer, but I don't have enough reputation.
If the error is authentication, maybe you have a problem with your credentials.
Does your username or password have any of these chars? : / ? # [ ] #
If they do, you'll have to URI encode them like so:
${encodeURIComponent(process.env.MONGO_DB_USER)}
${encodeURIComponent(process.env.MONGO_DB_PASSWORD)}
More info here: https://docs.mongodb.com/manual/reference/connection-string/#examples
BTW: You forgot the env part on your ${process.MONGO_DB_PASSWORD}.
I am very new to learning and using the MERN stack. Currently, I am having a problem where when I try to run "nodemon server", the port opens on instead of despite specifying in server.js that I want it to start on 5000. I am having trouble sending POST requests to using Insomnia with the current server.js code below (I get a 404 error) and think that this might be causing the POST command to fail. Moreover, it also doesn't run console.log('Server is running on port: ${port}'); into the terminal I am running the server from. Any feedback is appreciated.
server.js
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex: true });
const connection = mongoose.connection;
connection.once("open", () => {
console.log("MongoDB database connection established successfully");
});
const courseRouter = require("./routes/course");
const termRouter = require("./routes/term");
const userRouter = require("./routes/user");
app.use("/course", courseRouter);
app.use("/term", termRouter);
app.use("/user", userRouter);
app.listen(port, () => {
console.log(`Server is running on port: ${port}`);
});
I'm trying to push my application to Heroku, but I'm running into some issues:
Error: ENOENT: no such file or directory, open '.env'
2019-04-10T01:38:23.050188+00:00 app[web.1]: 1 at
Object.openSync (fs.js:438:3) 2019-04-10T01:38:23.050190+00:00
app[web.1]: 1 at Object.readFileSync (fs.js:343:35)
2019-04-10T01:38:23.050192+00:00 app[web.1]: 1 at
Object. (/app/config/database.js:4:39)
It seems that the error is the variable envConfig, but i need it for database to work.
As of now, I'm getting
Here is my config/database.js:
if (!process.env.PG_DB) {
const fs = require('fs')
const dotenv = require('dotenv')
// dotenv, but i need this make the database work
const envConfig = dotenv.parse(fs.readFileSync('.env'))
for (var k in envConfig) {
process.env[k] = envConfig[k]
}
console.log('[api][sequelize] Loaded database ENV vars from .env file')
}
module.exports = {
development: {
username: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DB,
host: process.env.POSTGRES_HOST,
dialect: 'postgres',
migrationStorageTableName: 'sequelize_meta'
},
production: {
username: "root",
password: null,
database: "*********some postgress url",
host: "127.0.0.1",
dialect: "postgres"
}
And my app.js:
var express = require('express');
var app = express();
var userRoute = require('./routes/users');
var postRoute = require('./routes/posts');
var bodyParser = require('body-parser');
var logger = require('morgan');
var session = require('express-session');
var cookieParser = require('cookie-parser') ;
var dotenv = require('dotenv');
var env = dotenv.config();
var cors = require('cors');
var models = require('./models/');
const port = process.env.PORT || 8000;
const passport = require('passport');
const path = require('path');
// const allowOrigin = process.env.ALLOW_ORIGIN || '*'
// CORS Middleware
if (!process.env.PORT) {
require('dotenv').config()
}
if (!process.env.PORT) {
console.log('[api][port] 8000 set as default')
console.log('[api][header] Access-Control-Allow-Origin: * set as default')
} else {
console.log('[api][node] Loaded ENV vars from .env file')
console.log(`[api][port] ${process.env.PORT}`)
console.log(`[api][header] Access-Control-Allow-Origin: ${process.env.ALLOW_ORIGIN}`)
}
require('./config/passport-github');
require('./config/passport');
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser());
app.use(session({
secret : process.env.JWT_SECRET,
saveUninitialized: false,
maxAge: 1000 * 60 * 60 * 84,
resave: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended:false}));
const isAuthenticated = function(req, res, next){
if(req.isAuthenticated()){
next();
console.log('this works');
}else{
res.redirect('http://127.0.0.1:8001/signIn');
}
}
// app.use(function(req, res, next) {
// res.header('Access-Control-Allow-Origin', '*');
// // res.header('Access-Control-Allow-Credentials', true);
// res.header("preflightContinue", false)
// // res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
// res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// next();
// });
app.use(cors({
'allowedHeaders': ['Content-Type'], // headers that React is sending to the API
'exposedHeaders': ['Content-Type'], // headers that you are sending back to React
'origin': '*',
'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
'preflightContinue': false
}));
app.use('/api/users', userRoute );
app.use('/api/posts', isAuthenticated, postRoute );
app.use(function(req, res, next) {
res.locals.user = req.user; // This is the important line
// req.session.user = user
console.log(res.locals.user);
next();
});
models.sequelize.sync().then(() => {
const server = app.listen(port, () => {
console.log(`Server is up and running on port ${port}`);
});
});
Before you do anything else, if those are your real credentials you should invalidate them immediately. They are forever
compromised, and you need to generate new ones. Editing them out of your question is not enough.
You can change
const envConfig = dotenv.parse(fs.readFileSync('.env'))
to
const envConfig = dotenv.config({silent: true})
You don't need to manually read the file here, and skipping it lets you gracefully handle the case when it doesn't exist. There's also no need to manually set values in process.env:
for (var k in envConfig) {
process.env[k] = envConfig[k]
}
This can be entirely skipped. Dotenv takes care of this itself. Therefore, you don't need envConfig either, reducing all of that to just
dotenv.config({silent: true})
If .env exists, its contents will be added to what's already in process.env. In development, this gives you a convenient way to set your database connection information.
In production, .env shouldn't exist, and your database connection information definitely shouldn't be hard-coded. Instead, your database connection information should come from one or more Heroku config vars (these are environment variables that should already be available via process.env). Your database addon has probably already set the DATABASE_URL variable for you.
For things in your .env that you've set yourself, set a Heroku config var for its production value. You can do that through the Heroku web dashboard or via the Heroku CLI:
heroku config:set SOME_VARIABLE=foo
I'm doing an application with Node.js, Express, MongoDB (mongoose), I'm trying to make the database connection in a separate file from server.js, but I'm having a hard time with connect-mongo.
First in my server.js I had this:
/* jshint esversion: 6 */
'use strict';
let express = require('express');
const db = require('./app/config/db');
const routes = require('./app/routes/routes');
const users = require('./app/routes/users');
let app = express();
const conn = db.connect();
app.set('views', path.join(__dirname, 'app/views'));
app.set('view engine', 'hbs');
...
app.use('/', routes);
app.use('/users', users);
app.listen(3000);
module.exports = app;
This only handle the application routes, and the application server, then I had the next folder structure for my project:
myApp
|___app
|___bin
|___config
|___credentials.js
|___db.js
|___controllers
|___routes
|___views
|___node_modules
|___package.json
|___server.js
Welll insidde config folder I had two javascripts that handle the connection to the database, in the credentials.js literally only had the credentials for the access of the database.
Then my problem is inside the db.js, next I show you the file:
/* jshint esversion: 6 */
'use strict';
let mongoose = require('mongoose'),
async = require('async'),
express = require('express');
const credentials = require('./credentials');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
let db = mongoose.connection,
app = express();
exports.connect = function(done){
const connection = mongoose.connect(credentials.host, credentials.database, credentials.port, credentials.db);
db.on('error', (error =>{
console.log("Error estableciendo la conexion");
process.exit(1);
}));
db.on('open', (argv)=>{
db.db.listCollections().toArray((err, collections)=>{
collections.forEach(x => console.log(x));
});
});
/* Define sessions in MongoDB */
app.use(session({
secret: credentials.sessionSecret,
store: new MongoStore({ dbPromise: db })
}));
}
I got the next error:
Error with nodemon server.js
Do you know how to initiate connect-mongo using this project structure?
By the way, in the credentials.js file I setup Bluebird as my promise library.
In advance thank you!
The problem was, like #MananVaghasiya said, that my variable db was not a Promise, this is a bug inside the mongoose project, so I changed the connection type to a basic uri connection with mongoose and then after the query of login I set the session.
The code it's looking like this at this time, so thank you for your time.
module.exports.login = (req, res)=>{
const mail = req.body.mail.replace(/^\s\s*/, '').replace(/\s\s*$/, ''),
password = req.body.password;
user.findOne({$and:[{'mail' : mail}, {'password': password}]}, (err, user)=>{
if(err){
res.send(err);
} else {
/* Define sessions in MongoDB */
app.use(session({
secret: credentials.sessionSecret,
store: new MongoStore({ mongooseConnection: db }),
saveUnitialized: true,
resave: false,
cookie:{
path: "/"
},
name: user.role
}));
return user;
}
});
};