Node, Express - Index file not calling files correctly - node.js

Hi in my express project, I have my index file where I require different files to startup my application. These require a database connection file, a file for logging stuff using winston and a file for configuring routes.
I use the require() statement within express to call these files, and when I run the application(using nodemon), I expect some messages to be logged to the terminal verifying that the files have been called, however no messages occur.
Here is my code:
index.js:
const express = require('express')
const app = express()
require('./startup/logging') ()
require('./startup/db') ()
require('./startup/routes') (app)
const port = process.env.PORT || 3000
app.listen(port, () => winston.info(`Listening on port: ${port}`))
db.js:
const mongoose = require('mongoose')
const winston = require('winston')
module.exports = function() {
mongoose.connect('mongodb://localhost/dwg', {useNewUrlParser: true, useUnifiedTopology: true})
.then(() => winston.info('Connected to MongoDB...'))
.catch(err => console.error("Error"))
}
logging.js:
const winston = require('winston');
module.exports = function() {
winston.handleExceptions(
new winston.transports.File({ filename: 'uncaughtExceptions.log' }));
process.on('unhandledRejection', (ex) => {
throw ex;
});
winston.add(winston.transports.File, { filename: 'logfile.log' });
}
routes.js:
const express = require('express');
module.exports = function(app) {
app.use(express.json())
}
No database is created when running the application. I can confirm this by looking at mongodb compass. The message that is meant to be printed by app.listen() is also not printed to the console. Does anybody know the issue? Thank you.

The problem doing it this way is your app starts before it gets a chance to do rest of work like creating db connection etc. You should start the app only when these tasks are done. something like this
const express = require('express')
const app = express()
const logging = require('./startup/logging');
const db = require('./startup/db');
const routes = require('./startup/routes');
const port = process.env.PORT || 3000
app.listen(port, async () => {
await logging();
await db();
await routes();
// assuming you have winston here.
winston.info(`Listening on port: ${port}`)
})
Mongo part is defintely async so need await. Check if routes and logging needs await or not.

Related

Node Express Mongo app goes sleep mode in shared cPanel

I deployed a Node js server with Express Js and MongoDB on NameCheap cPanel. The problem is I have to refresh 2 or 3 times to get the data from the server.Otherwise its gives 404. Then it works fine but after some minutes it acts the same. I have to refresh 2 or 3 times.
`
const express = require("express");
const { MongoClient } = require("mongodb");
const cors = require("cors");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
//Middleware
app.use(cors());
app.use(express.json());
//MongoDB linking
const uri = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}#xyz`;
const client = new MongoClient(uri);
async function run() {
try {
await client.connect();
//DB Folder and Subfolder
const database = client.db("XYZ");
const allUsers = database.collection("All-Users");
app.get("/allusers", async (req, res) => {
const get = allUsers.find({});
const allData = await get.toArray();
res.send(allData);
});
} finally {
//await client.close();
}
}
run().catch(console.dir);
app.get("/", (req, res) => {
res.send(" Server is running just fine");
});
app.listen(port, () => {
console.log(" server running on port :", port);
});
`
I dont have idea what the problem is. Did anyone faced the same issue, and solved the issue?
Thank you.

how to use make express endpoints listen to same server as mongoose (apollo server)

i currently have an apollo server interacting with my mongodb database running on a port (localhost or the port given from the host when deployed). i also have another file (app.js) for web scraping that has routes and uses express, running on a different port.
i want the app.js express logic to run on the same port as the call
server.listen({ port: port}) in index.js. how do i do this, please? essentially something like putting the app.get calls in the mongoose.connect which does not seem possible, but so you can get the idea.
moving all the logic in app.js to index.js so the server listens to mongoose, apollo, and all the express endpoints i have in one place on the same, single port.
//index.js
const { ApolloServer } = require('apollo-server');
const mongoose = require('mongoose');
const express = require("express");
const bodyParser = require('body-parser');
const nodemailer = require('nodemailer');
let port = process.env.port || 5000;
const typeDefs = require('./graphql/typeDefs');
const resolvers = require('./graphql/resolvers');
const { MONGODB } = require('./config.js');
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({ req })
});
mongoose.connect(MONGODB, { useNewUrlParser: true })
.then(() => {
console.log("MongoDB connected");
return server.listen({ port: port})
})
.then((res) => {
console.log(`Server running at ${res.url}`);
})
app.js (snippet) used for endpoints that return web scraping data
const express = require("express");
const cors = require('cors')
const cheerio = require('cheerio');
const axios = require('axios');
const app = express();
const port = 5001;
app.get("/events/", function(req, res) {
// redacted logic
let { zipCode } = req.query;
// Create a new yelpAPI object with your API key
let apiKey =[redacted];
let yelp = new yelpAPI(apiKey);
// Set any parameters, if applicable (see API documentation for allowed params)
let params = [{ location: zipCode }];
// Call the endpoint
yelp.query('events', params)
.then(data => {
// Success
res.send(data);
})
.catch(err => {
// Failure
console.log(err);
});
});
app.listen(port, () => console.log(`CORS-enabled web server listening on port ${port}!`));

404 Not Found when requesting after deploying to Heroku, works locally

I have been working all day on trying to deploy my MERN stack app to Heroku. So far it works perfectly fine if I run it locally. The app gets deployed on Heroku, but when I try to submit/get items from MongoDB Atlas, I get a 404 error.
I tried removing the Proxy in package.json, didn't work. I ran a build command and the file is in the correct place, still doesn't work. I'm really clueless about what could be going on..
Here is the code:
BACKEND:
index.js
const express = require('express');
const app = express();
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
app.use(cors());
app.use(express.static('build'));
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ limit: '50mb' }));
const uri =
'mongodb+srv://db:passwordhere#cluster0.fgryd.mongodb.net/myFirstDatabase?retryWrites=true&w=majority';
mongoose.connect(uri);
const profileSchema = new mongoose.Schema({
..
..
..
});
const Profile = mongoose.model('Profile', profileSchema);
module.exports = mongoose.model('Profile', profileSchema);
profileSchema.set('toJSON', {
transform: (document, returnedObject) => {
returnedObject.id = returnedObject._id.toString();
delete returnedObject._id;
delete returnedObject.__v;
},
});
app.get('/api/profiles', (req, res) => {
Profile.find({}).then(profiles => {
res.json(profiles);
});
});
app.post('/api/profiles', (request, response) => {
const body = request.body;
if (!body) {
return response.status(400).json({
error: 'content missing',
});
}
const profile = new Profile({
...
...
...
});
profile.save().then(savedProfile => {
response.json(savedProfile);
});
});
const PORT = process.env.NODE_ENV || 3001;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
My Frontend:
App.js
function App() {
const [viewProfile, setViewProfile] = useState(false);
const [formState, setFormState] = useState(1);
const [prof, setProf] = useState([]);
const handleProfile = () => {
setViewProfile(!viewProfile);
};
const fetchData = async () => {
await axios.get('/api/profiles').then(res => setProf(res.data));
};
useEffect(() => {
fetchData();
}, []);
const addProfile = async data => {
let img = await ImgToBase64(data.profImg);
await axios.post('/api/profiles', {
...
...
...
});
fetchData();
alert(`success!`);
};
return (
<ChakraProvider>
...
...
...
</ChakraProvider>
);
}
Can I please get some help? I almost tried everything
Heroku offers you a node's container instead of VPS (Virtual Private Server).
Inside their servers, there are more than 10k apps running on a VM. They are mapping your app port with their subdomain. for that, you have to feed port configurations to your application.
In your code, there is process.env.NODE_ENV but in the Heroku environment, they are using process.env.PORT.
const PORT = process.env.PORT || 3001;
Also, you need to add a start script in your package.json.
start: "node index.js"
if your main file is not is the index.js, you can replace your script name with main script name
You can try these two things.
Change your PORT name.
https://devcenter.heroku.com/articles/getting-started-with-nodejs#push-local-changes
Your code:
const PORT = process.env.NODE_ENV || 3001;
After
const PORT = process.env.PORT || 3001;
Make sure you created Procfile with text "web: npm start" in the file.
https://devcenter.heroku.com/articles/getting-started-with-nodejs#define-a-procfile
Procfile

what is the best way to use socket.io with expressjs app?

I want to write a real-time chat application with socket.io and because my server and app file are separate, I kind of have no clue that how should I structure it to use socket.io instance in other parts of my app.
This is my app.js file.
const express = require("express");
const pug = require("pug");
const app = express();
module.exports = app;
and this is my server.js file
const app = require("./app");
const mongoose = require("mongoose");
mongoose
.connect(`mongodb://localhost:27017/${process.env.DATABASE}`)
.then(() => {
app.listen(process.env.PORT);
})
.catch((err) => {
console.error(`connection failed: ${err}`);
});
what is the best way to create an instance of socket.io and start it's connection for use in other parts of app?
You can use http with express app and then connect sockets through that http connection and you can listen and emit the topics inside the io.on('connection')
const app = require("./app");
const mongoose = require("mongoose");
const http = require('http').Server(app);
const io = require('socket.io')(http);
mongoose
.connect(`mongodb://localhost:27017/${process.env.DATABASE}`)
.then(() => {
app.listen(process.env.PORT);
io.on('connection', socket => {
console.log('socket connected',socket);
});
})
.catch((err) => {
console.error(`connection failed: ${err}`);
});
I will prefer this second way:
App.js
const express = require("express");
const pug = require("pug");
const app = express();
module.exports = app;
Server.js
const app = require("./app");
const realtime = require("./realtime");
const mongoose = require("mongoose");
const server = require("http").Server(app);
mongoose
.connect(`mongodb://localhost:27017/${process.env.DATABASE}`)
.then(() => {
app.listen(process.env.PORT);
require("./realtime.js")(server);
})
.catch((err) => {
console.error(`connection failed: ${err}`);
});
Realtime.js
module.exports = (app) => {
const io = require("socket.io")(app);
io.on("connection", (socket) => {
console.log("Socket connected")
})
};

Cannot connect to MongoDB via env variable

I am trying to conceal my connection string, so I installed env2 in my project. Then I made a config.env file that keeps my connection string like this:
export DB_URL='mongodb://user:userPassword#ds241968.mlab.com:41968/heroku_hc9xjmcl'
However when I use that variable as a connection string I cannot connect to Mlab I get the following error:
UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [ds241968.mlab.com:41968] on first connect [MongoError: Authentication failed.]
But when I try to connect only with the string without using env2 I connect perfectly, so why does the ahuthentication fail when I use a env variable and how can I connect with one properly? Here is my server.js:
// Requiring the dependencies
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const PORT = process.env.PORT || 3009;
const itemRoutes = express.Router();
let Comment = require('./comment.model');
const env = require('env2')('../config.env');
console.log(process.env.DB_URL)
app.use(cors());
app.use(bodyParser.json());
const { DB_URL } = process.env;
mongoose.connect( DB_URL , { useNewUrlParser: true } )
const connection = mongoose.connection;
connection.once('open', function() {
console.log('Connection to MongoDB established succesfully!');
});
// Serve static assets
if(process.env.NODE_ENV === 'production') {
app.use(express.static('build'));
}
itemRoutes.route('/').get( async (req, res) => {
let collection = connection.collection("posts");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/comments').get( async (req, res) => {
let collection = connection.collection("comments");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/userComments')
.post((req, res) => {
res.setHeader('Content-Type', 'application/json');
let comment = new Comment(req.body);
comment.save()
.then(comment => {
res.status(200).json({comment})
})
.catch(err => {
res.status(400).send('failed')
})
});
app.use('/', itemRoutes);
app.use('/userComments', itemRoutes);
app.listen(PORT, function() {
console.log('Server is running on' + ' ' + PORT);
})
Looks like you are using Node and Heroku. In that case,
You should set Heroku Config Vars (you can do this either via CLI or your Heroku Dashboard)
Refer to the config var in your node application the same way you are referring to now.
Remove 'env2' related code as you won't need it for this purpose
For example, if you create Heroku config var called "MONGO_URI", refer to it as process.env.MONGO_URI in your node application.
Details can be found here: https://devcenter.heroku.com/articles/config-vars#managing-config-vars

Resources