So I'm trying to make it so I don't have to have multiple connections to my database when I can just put my connection and runQuery function in a file and just require it in another file. Here is what I have in my "mysql.js" file.
const mysql = require('mysql');
module.exports = function () {
let connection = mysql.createConnection({
host: '------',
user: 'voltclou_site',
password: '----',
database: process.env.database
})
connection.connect(function(err) {
if (err) {
console.error('[DATABASE] Error connecting: ' + err.stack);
return;
}
console.log('[DATABASE] Connected as id ' + connection.threadId);
});
async function runQuery(query, values) {
return new Promise((resolve, reject) => {
connection.query(query, values, function (error, results) {
if (error) return reject(error)
return resolve(results)
})
})
}
}
Here is how I would like to require it in my files:
const { connection, runQuery } = require('./functions/mysql')
Am I doing this correctly? I'm new to this whole module thing. I've been trying to split my files up because one index.js with 3000+ lines is insane. Thanks for any help.
No you didnt do it correclty. What you have done you have exported it as an default but you want to export named functions. You can do it like:
const mysql = require("mysql");
let connection = mysql.createConnection({
host: "81.19.215.6",
user: "voltclou_site",
password: "yogO{6,F#8WS",
database: process.env.database
});
connection.connect(function(err) {
if (err) {
console.error("[DATABASE] Error connecting: " + err.stack);
return;
}
console.log("[DATABASE] Connected as id " + connection.threadId);
});
async function runQuery(query, values) {
return new Promise((resolve, reject) => {
connection.query(query, values, function(error, results) {
if (error) return reject(error);
return resolve(results);
});
});
}
module.exports = {
connection,
runQuery
};
The value you've described, { connection, runQuery }, should be the value assigned to module.exports:
const mysql = require('mysql');
let connection = mysql.createConnection({ ... });
connection.connect(...);
let runQuery = async (query, values) => { ... };
module.exports = { connection, runQuery };
You may not even need to export connection, if all you need elsewhere is runQuery!
Related
I need to create a mysql connection in nodejs , but the credentials for the mysql comes from a third party credential manager service. Can somebody suggest me a way to achieve this?
database.js - i am using connection from this file in all other database operations
const mysql = require("mysql");
const {env} = require('./globals')
const connection = mysql.createConnection({
host: env.DATABASE.HOST,
user: env.DATABASE.USER,
password: env.DATABASE.PASSWORD,
database: env.DATABASE.NAME,
multipleStatements: true
});
connection.connect(function (err) {
if (err) {
console.log("Error in DB connection");
console.log("err", err);
} else console.log("Connected!");
});
module.exports = connection
globals.js
const {getSecret} = require('../src/service')
require("dotenv").config();
async function getCredentials() {
const result = await getSecret()
return JSON.parse(result?.SecretString || {})
}
const credentials = getCredentials() // not working, and i can't use await here
const env = {
DATABASE: {
HOST: credentials.ip_address,
PASSWORD: credentials.password,
NAME: credentials.dbname,
USER: credentials.username,
},
SKU: process.env.SKU
}
module.exports.env = env
Your 2 main options are:
Don't export connection but export an async function that returns a connection.
Write an init() function that sets up your database connection, and ensure it's one of the first things your application calls before anything else.
Well first, you need to fix up that globals.js file. Logic that depends on an async function must be async itself. You can just move everything into the async function like so:
const {getSecret} = require('../src/service')
require("dotenv").config();
async function getCredentials() {
const result = await getSecret()
const credentials = JSON.parse(result?.SecretString || {})
return {
DATABASE: {
HOST: credentials.ip_address,
PASSWORD: credentials.password,
NAME: credentials.dbname,
USER: credentials.username,
},
SKU: process.env.SKU
}
}
module.exports = { getCredentials }
And since even your database connection in database.js depends on this async function, it will have to be async as well:
const mysql = require("mysql");
const {getCredentials} = require('./globals')
const getConnection = getSecret().then(function (env) {
const connection = mysql.createConnection({
host: env.DATABASE.HOST,
user: env.DATABASE.USER,
password: env.DATABASE.PASSWORD,
database: env.DATABASE.NAME,
multipleStatements: true
});
connection.connect(function (err) {
if (err) {
console.log("Error in DB connection");
console.log("err", err);
} else console.log("Connected!");
});
return connection;
})
module.exports = getConnection
I am changing my backend (switching over from Mongo to MySql). I know the error is getting thrown because a return statement is being executed before my SQL query has finished and then when my sql query finishes, it tires to send another res.send, hence why I am trying to use mysql2 with Promise wrappers to use await on queries in my async function.
I have a separate file that creates the DB connection so I can access the connection throughout my Nodejs backend:
const mysql = require('mysql2');
async function pool(){
const pool = await mysql.createPool({
host: "ip",
user: "username",
password: "password",
database: "db"
});
return pool
}
exports.getConnection = async function(callback) {
const currentPool = await pool();
currentPool.getConnection(function(err, conn) {
if(err) return callback(err);
callback(err,conn)
});
};
Then, to create a query that follows async/await:
sql.getConnection(async function(err, client){
client.query(`select email from users where email = "${email}"`, function (error, result){
if(error) return res.status(500).send('an internal db error occurred');
// carry on with code ...
});
});
I've tried using await on the query too:
await sql.getConnection(async function(err, client){
client.query(`select email from users where email = "${email}"`, function (error, result){
if(error) return res.status(500).send('an internal db error occurred');
// carry on with code ...
});
});
What am I missing? I haven't tired to use the normal mysql NPM library and make my own promise wrapper yet...
NEW CODE:
I've updated my function:
const mysql = require('mysql2');
const pool = mysql.createPool({
host: "ip",
user: "user",
password: "pass",
database: "db"
});
exports.db = (sql) => {
new Promise((resolve, reject) => {
pool.getConnection((err, conn) => {
if(err) return reject(err);
conn.query(sql, (err, results, fields) => {
conn.release()
if(err) return reject(err)
console.log(results)
resolve(results);
});
});
});
}
Then I call it via:
try{
const emailExisit = await sql.db(`SELECT email FROM users WHERE email = "${email}"`);
console.log(emailExisit);
if(emailExisit.length > 0) return res.status(422).send({"data": "", "code": "105", "message": "An account with given email already exists"});
}catch (err) {
console.log(err)
return res.status(500).send({"data": "", "code": "108", "message": `There seems to be an error contacting the database. Try again later <br> ${err}`});
}
However, my code still continues, leaving my emailExists variable undefined (yes, it is inside an async function)
This is my configuration to use MySQL with Node.js. I hope it works with you.
/config/mysql.js
const mysql = require('mysql2');
const pool = mysql.createPool({
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
port: process.env.MYSQL_PORT,
database: process.env.MYSQL_DB_NAME,
});
const query = (query, args = []) =>
new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
return reject(err);
}
connection.query(query, args, (err, results) => {
connection.release();
if (err) {
return reject(err);
}
resolve(results);
});
});
});
module.exports = { query };
/index.js
const { query } = require('./mysql');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.get('/api/v1/sum', (req, res) => {
query('SELECT 1 + 1 as sum')
.then(results => {
res.json({ sum: results[0].sum });
})
.catch(err => {
console.error(err);
res.status(500).json({ error: 'error msg' });
});
});
// anther example with async
app.get('/api/v1/sum', async (req, res) => {
try {
const results = await query('SELECT 1 + 1 as sum');
res.json({ sum: results[0].sum });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'error msg' });
}
});
app.listen(3000);
I am creating a discord bot that has integration with mysql. To make it easier, I created a central file for the mysql database (configs/mysql.js) and, when the command needs it, it will send the query request to that file and finally, it will return the processed value. But when I try to do this, the return is undefined in the console (of the command), but in the mysql.js console, it shows the correct value.
MYSQL.js Code
const mysql = require("mysql");
const connection = mysql.createConnection({
host: config.URL,
user: config.dbUser,
password: config.dbPassword,
database: config.database
});
connection.connect(function(err) {
if (err) {
console.error("[MYSQL] Error on Connection: " + err.stack);
return;
}
console.log("[MYSQL] Connected with ID " + connection.threadId + "!");
});
function query(sql) {
connection.query(sql, function(error, result, fields) {
if (error) return error;
const analise = JSON.stringify(result[0]);
console.log(analise) //it's return the value correct
return analise
});
}
exports.connection = connection;
exports.query = query;
The Request
const status1 = await mysql.query("SELECT `status` FROM `server_status`");
console.log(status1); //it's return undefined
Can anyone help me?
Use promise for mysql you can`t use return in callback function.
const mysql = require('mysql');
const connection = mysql.createConnection({
host: config.URL,
user: config.dbUser,
password: config.dbPassword,
database: config.database,
});
connection.connect(function(err) {
if (err) {
console.error('[MYSQL] Error on Connection: ' + err.stack);
return;
}
console.log('[MYSQL] Connected with ID ' + connection.threadId + '!');
});
function query(sql) {
return new Promise(resolve => {
connection.query(sql, function(error, result, fields) {
if (error) return error;
const analise = JSON.stringify(result[0]);
console.log(analise); //it's return the value correct
resolve(analise);
});
});
}
exports.connection = connection;
exports.query = query;
const status1 = await mysql.query("SELECT `status` FROM `server_status`");
This is in a mysql.js file:
const mysql = require('mysql');
const config = require('./config.json');
const con = mysql.createConnection({
host: config.dbhost,
user: config.dbuser,
password: config.dbpass,
database: config.dbname,
});
module.exports = {
findUser: function(email) {
const sql = 'SELECT * FROM users WHERE email = ' + mysql.escape(email);
con.connect(function(err) {
if (err) throw err;
console.log('Connected!');
con.query(sql, function(err, result) {
if (err) throw err;
return result[0].id;
});
});
},
};
then within my index.js file there is this:
const mysql = require('./mysql.js');
console.log(mysql.findUser('example#example.test'));
When the code is running, it outputs "undefined" and then "Connected!" after the db connection is made. Even though if I do a console.log on result[0].id it outputs 1, which is the correct id...
Question: How can I load the mysql.js file first before the function is called?
You need to wait for response cause its an asynchronous function.
Try using callback or promises.
Callback example:
mysql.findUser('example#example.test', function(res)){ console.log(res)});
module.exports = {
findUser: function(email, callback) {
const sql = 'SELECT * FROM users WHERE email = ' + mysql.escape(email);
con.connect(function(err) {
if (err) throw err;
console.log('Connected!');
con.query(sql, function(err, result) {
if (err) throw err;
callback(result[0].id);
});
});
},
Trying to call database query from other javascript file in NodeJS.
Sample database file:
function addUser(user) {
connection.connect(function (err) {
if (err) {
console.error('Error connecting: ' + err);
}
console.log('Connected as id ' + connection.threadId);
});
var sql = "INSERT INTO `mobile`.`main` (`userId`) VALUES (?);"
var inserts = [user];
connection.query(sql, inserts, function (error, results) {
console.log('query');
if (error) {
return error;
} else {
console.log('Success Query');
return results;
}
});
connection.end(function (err) {
if (err) {
console.error('Error connecting: ' + err);
}
console.log('Connection closed!');
});
}
module.exports = addUser;
Sample main.js file:
app.get('/api/mysql/:user', function (req, res) {
var user = req.params.user;
addUsers(user)
res.json({
SQLResp: 'Query succes',
result: addUsers.result
});
});
How to get the result from the first file and use it as a response in the main js?
Welcome to stack overflow.
this is missing from your database file, How did you got connection there?
Here's a sample example over How to export database connection and use this to make calls from other files.
Also do read about callbacks-functions, Promises, async-await and Asynchronous functions of JavaScript. These are basics of JavaScript and also do go through NodeJS docs.
DB.js:
const MYSQL = require('mysql');
const connection = MYSQL.createConnection({
host: 'localhost', // url of db
user: 'root',
password: 'root',
database: 'dbName'
});
module.exports = connection;
Now will use this connection from other file to call database.
app.js:
const db = require('./DB'); // Path of your db connection file. I named it DB.js on same level as of app.js
function addUser(user) {
// Since database calls are async in NodeJS thus using promises.
return new Promise ( (resolve, reject) => {
db.connect(function (err) {
if (err) {
console.error('Error connecting: ' + err);
return reject(err);
}
console.log('Connected as id ' + connection.threadId);
});
var sql = "INSERT INTO `mobile`.`main` (`userId`) VALUES (?);"
var inserts = [user];
db.query(sql, inserts, function (error, results) {
console.log('query');
if (error) {
return reject(err);
} else {
console.log('Success Query');
return resolve(results);
}
});
db.end(function (err) {
if (err) {
console.error('Error connecting: ' + err);
}
console.log('Connection closed!');
});
});
}
app.get('/api/mysql/:user', function (req, res) {
var user = req.params.user;
addUsers(user)
.then (result => { // When addUsers will resolve promise will be in then.
res.json({
SQLResp: 'Query succes',
result: result
});
})
.catch(err => { // If promise is rejected then on catch
res.json({
SQLResp: 'Query err',
result: err
});
});
});
You need to pass a callback into your addUser function, and call it inside your connection.query with the results.
Currently, when you return, you're returning inside another callback, which means the data is more or less being thrown away.
That will also let you handle all of the error cases in a way you can tell the user about.