Reusing postgresql pool in other node javascript files - javascript

I am creating nodejs backend app with postgresql database. What I want is when once I create connection to database in my db.js file, that I can reuse it in other files to execute queries.
This is my db.js file
const pool = new Pool({
user: 'us',
host: 'localhost',
database: 'db',
password: 'pass',
port: 5432,
})
pool.on('connect', () => {
console.log('connected to the Database');
});
module.exports = () => { return pool; }
And this is how I tried to use it in index.js file
const db = require('./db.js')
app.get('/', (request, response) => {
db().query('SELECT * FROM country'), (error, results) => {
if (error) {
response.send(error)
}
console.log(results)
response.status(201).send(results)
}
})
There aren't any errors, and when I go to this specific page, it's keep loading. Nothing in console also.
But, if I write a function in my db.js file and do something like pool.query(...), export it, and in my index.js I write app.get('/', exportedFunction), everything is working fine.
Is there any way not to write all my (like 50) queries in just one (db.js) file, because I want to organise my project a little bit?

To streamline your project structure entirely, if you're starting from scratch maybe try this :
index.js
const express = require('express');
const app = express();
const PORT = 8080;
const bodyparser = require('body-parser');
const baseRouter = require('../your-router');
app.use(bodyparser.json());
app.use(express.json());
app.use('/', baseRouter);
app.listen(PORT, function () {
console.log('Server is running on PORT:', PORT);
});
your-router.js
const Router = require('express');
const router = Router();
const getCountries = require('../handlers/get');
router.get('/check-live', (req, res) => res.sendStatus(200));
// route for getCountries
router.get('/countries', getCountries);
src/handler/get.js
const YourService = require('./service/your-service');
function getCountries(request, response) {
const yourService = new YourService();
yourService.getCountries(request)
.then((res) => { response.send(res); })
.catch((error) => { response.status(400).send({ message: error.message }) })
}
module.exports = getCountries;
src/service/your-service.js
const connectionPool = require('../util/dbConnect');
class yourService {
getCountries(req) {
return new Promise(((resolve, reject) => {
connectionPool.connect((err, db) => {
if (err) reject(err);
let query = format('SELECT * FROM country'); // get inputs from req
db.query(query, (err, result) => {
if (err) reject(err);
resolve(result);
})
});
}));
}
}
module.exports = yourService;
dbConnect.js
const pgCon = require('pg')
const PGUSER = 'USER'
const PGDATABASE = 'localhost'
let config = {
user: PGUSER,
database: PGDATABASE,
max: 10,
idleTimeoutMillis: 30000
}
let connectionPool = new pgCon.Pool(config);
module.exports = connectionPool;
Please consider this as a basic example, refactor your code to use callbacks/async awaits (in the above example you can just use callbacks not needed to convert into promise), if needed - you can have DB-layer calls from the service layer in order to extract DB methods from the service layer.

Related

Why am I getting ReferenceError: db is not defined

For some reason I cannot get axios to connect to the DB. Its is a MSQL server and when I use app.get in the server file I can get data returned but when using express DB connection just doesn't persist. In postman I can return a result with all my code on server.js receiving the entire table. This is what I want. When moving everything to axios and routing it to have less code on my server nothing returns anymore. nothing is broken except i get ReferenceError: db is not defined in nodemon.
HomePage
const express = require('express')
const app = express()
const mysql = require('mysql')
const morgan = require('morgan')
//middleware
app.use(express.json())
app.use(morgan('dev'))
//Connect to DB
const db = mysql.createConnection({
user : 'root',
password : '******',
database : 'avengers'
})
db.connect((err) => {
if(err){
console.log(err)
}
console.log('MySql Connected...')
})
//Routes
app.use('/avengers', require('./routes/avengerRouter.js'))
//error handling
app.use((err, req, res, next) => {
console.log(err)
return res.send({errMsg: err.message})
})
app.listen(9000, () => {
console.log("The server is running on port 9000")
})
Server.js
import React, {useState, useEffect} from 'react'
import axios from 'axios'
import AvengersTable from './AvengerTable.js'
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
export default function Main(){
const [tableState, setTableState] = useState('')
useEffect(() => {
async function getTableData() {
axios.get('/avengers')
await delay(300)
.then(res => {
// setTableState(res.data)
console.log(res)
})
.catch(err => console.log(err.response.data.errMsg))
} getTableData()
}, [])
return (
<div className="Main">
{/* <AvengersTable tableState={tableState}/> */}
</div>
)
}
avengerRouter.js
const express = require('express');
const avengerRouter = express.Router();
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
avengerRouter
// all data from avengers table http://localhost:9000/avengers
.get('/', (req, res) => {
let sql = 'SELECT * FROM avengers.avengers'
db.query(sql, (err, result) => {
if(err) console.log(err)
console.log(result)
})
})
module.exports = avengerRouter;
Create a file named db.js that includes a DB connection.
const mysql = require('mysql')
const db = mysql.createConnection({
user : 'root',
password : '******',
database : 'avengers'
});
export default db;
Usage of db at top of your HomePage
const db = require('./db.js');
db.connect((err) => {
if(err){
console.log(err)
}
console.log('MySql Connected...')
});
// Other codes goes below
...
And finally usage in your avengerRoute.js
const express = require('express');
const avengerRouter = express.Router();
// Forgotten line here
const db = require('./db.js');
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
avengerRouter
// all data from avengers table http://localhost:9000/avengers
.get('/', (req, res) => {
let sql = 'SELECT * FROM avengers.avengers'
db.query(sql, (err, result) => {
if(err) console.log(err)
console.log(result)
})
})
module.exports = avengerRouter;

MongoDB Returns Empty Error Object when Making POST Request

I'm currently learning about APIs. I'm using Dev Ed's video on a RESTful MERN API. I set up my routes and I could successfully connect to my MongoDB database. However, when attempting to call save() on a post to the DB, I was returned my error message, a JSON object with a message containing the err, but my err object was completely empty.
posts.js:
const express = require('express');
const router = express.Router();
const Post = require('../models/Post');
router.get('/', (req, res) => {
res.send('We are on /posts!');
});
router.post('/', (req, res) => {
const post = new Post({
title: req.body.title,
desc: req.body.desc,
});
post.save()
.then(data => {
res.json(data);
})
.catch(err => {
res.json({ message: err });
});
});
module.exports = router;
app.js:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
require('dotenv/config');
const app = express();
const PORT = 8080;
app.use(bodyParser.json());
// Import Routes ------------------------
const postsRoute = require('./routes/posts');
app.use('/posts', postsRoute);
// ROUTES --------------------------------
app.get('/', (req, res) => {
res.send('We are home!');
});
mongoose.connect(
process.env.DB_CONN,
{ useNewUrlParser: true },
() => {
console.log('Succesfully connected to DB!')
});
app.listen(PORT);
Post.js (schema):
const mongoose = require('mongoose');
const PostSchema = mongoose.Schema({
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now,
}
});
module.exports = mongoose.model('Posts', PostSchema);
My POST request and response (Postman):
In my code, I am attempting to send the new Post to my DB, but instead I get an error, an empty one. I either need to figure out how to view my error correctly (so that's it's not empty) or the larger problem: why my POST request is failing.
Again, I am learning about APIs, this is my very first time writing one. If there's anything I missed (like other code that you would need) or if there's something I should be doing differently, please, let me know! Thank you in advance!
use status when you want to use res like this:
for success result
res.status(200).json(data);
for .catch
res.status(500).json({ message: err });
but I prefer use async/await with try/cacth like this:
router.post('/', async(req, res) => {
const post = new Post({
title: req.body.title,
desc: req.body.desc,
});
try {
let data = await post.save()
res.status(200).json(data)
} catch (error) {
res.status(500).json({ message: error});
}
});
check the documentation of promises in mongnoos
check the connection of mongoose like this:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
require('dotenv/config');
const app = express();
const PORT = 8080;
app.use(bodyParser.json());
// Import Routes ------------------------
const postsRoute = require('./routes/posts');
app.use('/posts', postsRoute);
// ROUTES --------------------------------
app.get('/', (req, res) => {
res.send('We are home!');
});
runMongoose()
app.listen(PORT);
async function runMongoose(){
try {
await mongoose.connect(
process.env.DB_CONN,
{ useNewUrlParser: true }
);
console.log("mongodb is OK");
} catch (error) {
console.log("mongodb Warning", error);
}
}
if Succesfully connected to DB! printed mongoose connection is OK
the problem is that you added
{ useNewUrlParser: true }
remove that and it's gonna work fine ;)

App keeps crashing when requiring helper methods from a different module

Please see Edit 2
I have a utils.js module that contains helper methods. Whenever other modules require it, it causes the whole app to crash. For instance, in my server.js, I have
const express = require("express");
const app = express();
const path = require("path");
const connectDb = require("./config/db");
app.use(express.json({ extended: false }));
// Define routes
app.use("/api/auth", require("./routes/api/posts"));
// connect to db
connectDb();
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
My posts.js is:
const express = require("express");
const router = express.Router();
// model
const Post = require("../../models/Post");
const { COMMENT_SAVE_ERROR, STRING } = require("../../constants/constants");
const { sendNotification, addNotificationToDb } = require("./utils/utils");
// #route GET api/posts/test
// #desc Test route
// #access Public
router.get("/test", async (req, res) => {
console.log('reached')
});
And my connectDb method is:
const connectDb = async () => {
try {
console.log('connecting to mongodb');
await mongoose.connect(db, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true
});
console.log("Mongo DB connected");
} catch (err) {
console.log('unable to connect to mongodb');
console.log('err===> ', err);
console.log(err.message);
//exit if failure
process.exit(1);
}
};
As it is now, when I run the app, I get an error:
getaddrinfo ENOTFOUND pilled-shard-00-01-xxghh.mongodb.net
This is such a weird error, because if I get rid of this from posts.js,
const { sendNotification, addNotificationToDb } = require("./utils/utils");
It connects with no problem. What am I doing wrong here? It throws the same error if I do,
const {} = require("./utils/utils");
Is this even related to MongoDB? Am I not allowed to import functions like this?
utils.js exports the methods as,
module.exports = {
sendNotification,
addNotificationToDb
};
Edit:
const addNotificationToDb = (userId, postId, type) => {
try {
const newNotification = new Notification({
userId,
postId,
typeOfNotification: type
});
newNotification.save();
} catch (err) {
console.log("Error saving notification", err);
}
};
Edit 2:
I've figured out the culprit. api/utils.js requires models, several of which /utils/utils.js requires. So when server.js does app.use('/api/utils), those models are required twice (at least I think that's the culprit). I figured this out by commenting out the model requires in utils/utils.js. How can I circumvent this? Is my only option to require the models in api/utils and just pass them individually to the methods that are imported from utils/utils.js?

What is causing MySQL Database to refuse connection?

I am trying to use MySQL for a local database in my Electron app to store settings and user data but am getting the following error:
Error: connect ECONNREFUSED 127.0.0.1:3306
I can't seem to figure out what is causing this and think I have it properly set up. Here is the code for my setup:
// main.js (Electron's main file)
const path = require('path');
require(path.resolve(`${__dirname}/assets/server/server`));
// server.js
const express = require('express');
const apiRouter = require('./routes/index');
const app = express();
app.use(express.json());
app.use('/api', apiRouter);
app.listen('3000', error => {
if (error) {
return console.error(error);
}
console.log('Server started on Port: 3000');
});
// routes - index.js
const express = require('express');
const db = require('../db/index');
const router = express.Router();
router.get('/', async (request, response, next) => {
try {
response.json(await db.all());
} catch (error) {
console.error(error);
response.sendStatus(500);
}
});
module.exports = router;
// db - index.js
const mysql = require('mysql');
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: null,
database: 'storage',
connectionLimit: 10,
port: 3306
});
function all () {
return new Promise((resolve, reject) => {
pool.query('SELECT * FROM Products', (error, results) => {
if (error) {
return reject(error);
}
resolve(results);
});
}).catch((error) => {
console.error(error);
});
}
module.exports = { all };

Returning undefined object when doing a query

I'm building an application on Node.js that works with MongoDB through mongoose. The connection is perfect, I can add new documents, the problem is definitely not in the connection.
I'm building all the functions that work with mongoose in a separate .js file, which I called from dbconfig.js.
dbconfig.js
const mongoose = require('mongoose');
// Models
const User = require('./models/User');
const Category = require('./models/Category');
var database_name = "htm";
mongoose.Promise = global.Promise;
// Connection with database_name
var connect = () => {
mongoose.connect("mongodb://localhost/"+database_name, {useNewUrlParser: true}).then(() =>{
console.log("Conectado ao database: " + database_name);
}).catch((erro) => {
console.log("Erro ao se conectar ao database: " + database_name +" - "+ erro);
});
mongoose.model('users', User);
mongoose.model('categories', Category);
}
var getCategory = () => {
const Ref = mongoose.model('categories');
Ref.find().then((categories) => {
return categories;
})
}
module.exports = {
connect: connect,
getCategory: getCategory
}
The problem is in the getCategory () function, when I call it in my app.js (my main file of this project node.js), it returns only undefined. And I know that the variable categories are filled out because I inserted a console.log (categories); and got the following result:
[ { _id: 5c7ea6fb91526418ec3ba2fd,
name: 'UNHAS',
slug: 'unhas',
__v: 0 } ]
app.js
const express = require('express');
const app = express();
const categoriesRouter = require('./routes/categories');
const handlebars = require('express-handlebars');
const path = require('path');
const configDB = require('./dbconfig')
// Config
// Template Engine
app.engine('handlebars', handlebars({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
// Start Database Connection
configDB.connect();
// Public
app.use(express.static(path.join(__dirname, "public")));
// Routes
app.use('/categorias', categoriesRouter);
app.get('/', (req, res) => {
var categories = configDB.getCategory();
res.render('home', categories);
});
app.listen(3001, () =>{
console.log("Servidor iniciado na porta 3001");
});
Whenever the variable categories is received in my app.js it arrives as undefined.
Can someone help me?
You are not properly using the Promise object returned from getCategory() in your express router:
app.get('/', (req, res) => {
var categories = configDB.getCategory(); <-- this is a Promise, not a synchronous value
res.render('home', categories);
});
Instead, you can use async/await to help bridge the gap between your currently synchronous code and the asynchronous Promise-based database interface you have:
app.get('/', async (req, res) => {
var categories = await configDB.getCategory();
res.render('home', categories);
});
Inspired by a response given by #jakemingolla who suggested async-await, I started using callback to return the 'categories' object and everything worked perfectly.
function in my file dbconfig.js
const getCategoryList = (callback) => {
CategoryRef.find().then((categories) => {
callback(categories);
})
}
calling the function in my app.js file
app.get('/', (req, res) => {
database.getCategoryHomeList((categories) => {
res.render('home', {categories: categories});
})
});

Categories

Resources