Data read from the db using the endpoint appears as undefined - mysql

I used the second method found at https://stackoverflow.com/a/70799801 and applied it to my source.
The version of sveltekit I am currently using is 1.0.0-next.73.
However, when I printed the data to the console, I could only see undefined.
Below is my source code:
/lib/db/mysql.js
import mysql from 'mysql2/promise';
let mysqlconn = null;
export function mysqlconnFn() {
if (!mysqlconn) {
mysqlconn = mysql.createConnection({
host: 'localhost',
port: 3307,
user: 'dbuser',
password: 'dbpassword',
database: 'dbname'
});
}
return mysqlconn;
}
/routes/index.server.js
import { mysqlconnFn } from '$lib/db/mysql';
export async function get() {
let mysqlconn = await mysqlconnFn();
let results = await mysqlconn.query('SELECT * FROM list_user')
.then(function ([rows, fields]) {
// console.log(rows);
return rows;
})
.catch(() => {
console.log("err")
})
return { results }
}
/routes/index.svelte
<script>
export let data
import { onMount } from "svelte"
onMount(() => {
console.log(data)
});
</script>
I'd be grateful if you could tell me where I went wrong and how to fix it.

Files in routes have to be called:
+page.svelte
+page.js/ts
+page.server.js/ts
+server.js/ts
So not index, also if you want data to load, the function (in +page.server.js/ts) has to be called load.

Related

Why I'm always getting an Internal Server Error (code 500) after making a request to BackEnd

I'm having a little trouble with my site and I can't understand what is happening.
First of all I have to say that I was NOT having this behavior when developing on localhost, but now that my site is close to be completed I think that uploading my code to a hosting service and make some tests there would be a good idea.
The issue is that when I make a request to the database, most of the times the site keeps in an eternal loading state, until the error code 500: Internal Server Error appears (I said "most of the times" because it works nice sometime, but normally it remains in a pending state).
Given the fact that SOME TIMES the request work nice, makes me think that the issue is not on the server.js file (where I defined the endpoints), and also is not on my controllers files (where I have some logic and the requests itself).
I'll leave here some pics as example of what is happening but if you need some extra info just tell me:
A simple login example, I just fill the fields and send the request
And here you can see how the request remain as pending
Until it fails
EDIT: I'm using package Mysql2 to connect to the DB, and I was reading that this behavior may be because a bad use of connections (and I'm reading about "pools", but I'm kinda lost tbh)
Here is the connection file:
require("dotenv").config();
const mysql = require("mysql2");
const db = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
waitForConnections: true,
});
const connection = async () => {
db.connect((err) => {
if (err) throw err;
console.log("Successfully connected");
})
}
exports.db = db;
exports.connection = connection;
The first call to the DB (just to check the connection)
connection().then(() => {
app.listen(port, () => {
console.log(`Server running at ...`);
});
});
And the login logic
app.post("/dev-end/api/login", async (req, res) => {
await singleAccount(db, req.body.email)
.then(async (response) => {
if (response.code) {
res.render("templateLogin");
}
try {
if (await bcrypt.compare(req.body.password, response.password)) {
const user = { id: response._id, name: response.name };
await deleteTokenById(db, user.id.toString());
const accessToken = generateAccessToken(user);
const refreshToken = jwt.sign(
user,
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: "604800s" }
);
createToken(db, {
_id: user.id,
accessToken: accessToken,
refreshToken: refreshToken,
createdAt: new Date().toISOString().slice(0, 19).replace("T", " "),
}).then(
res
.cookie("access_token", accessToken, {
httpOnly: true,
maxAge: 60000 * 60 * 24 * 7,
})
.redirect("/dev-end/dashboard")
);
} else {
res.render("templateLogin");
}
} catch {
res.status(500).send();
}
})
.catch(console.log);
});
=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>
const singleAccount = async (conn, email) => {
return await read(conn).then((res) => {
if (!res.code) {
const result = res.find((e) => e.email.toString() === email);
if (!result) {
return {
code: 404,
msg: "No account was found with the provided id",
};
}
return result;
}
return res;
});
};
=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>
const read = async (conn) => {
const sql = `SELECT * FROM accounts`;
return await conn.promise().query(sql)
.then(([res, fields]) => res);
};

How do I connect mysql with cypress through ssh tunneling?

Currently cypress supports mysql connection without using ssh as seen in the link below
https://docs.cypress.io/api/commands/task#Allows-a-single-argument-only
But I am trying to connect cypress to mysql through an ssh tunneling.
I am using the npm package mysql-ssh to establish the connection.
I am able to achieve this directly using node.js but I am facing issues while implementing through cypress. Here's the snippet I tried in node.js.
const mysqlssh = require('mysql-ssh');
const fs = require('fs');
mysqlssh.connect(
{
host: 'x.x.x.x',
user: 'xyz',
privateKey: fs.readFileSync('filePath') //this is the ssh filePath
},
{
host: 'HOST_NAME',
user: 'USER_NAME',
password: 'xxxx',
database: 'DB_NAME'
}
)
.then(client => {
client.query('select * from TABLE_NAME', function (err, results, fields) {
if (err)
{
console.log(err)
}
console.log(results);
mysqlssh.close()
})
})
.catch(err => {
console.log(err)
})
I want to do this either through the cypress/plugins/index.js file or directly in cypress/integration. Is there a simple way to do this?
I have found the solution. Here is my code for cypress/plugins/index.js file:
const dotenvPlugin = require('cypress-dotenv');
const mysqlssh = require('mysql-ssh');
const fs = require('fs');
module.exports = (on, config) => {
// `config` is the resolved Cypress config
config = dotenvPlugin(config);
on('task', {
executeSql (sql, ...args) {
return new Promise(async (resolve, reject) => {
try {
let connection = await mysqlssh.connect( {
host: process.env.SSH_HOST,
user: process.env.SSH_USER,
privateKey: fs.readFileSync(process.env.HOME + '/.ssh/id_rsa_old')
},
{
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DB
});
let result = await connection.promise().query(sql, args);
mysqlssh.close();
resolve(result[0][0]);
} catch (err) {
reject(err);
}
});
}
})
return config
}
So this connection has to be established in this file b/c cypress does not communicate with node process supplied by the host. So we need to use cypress tasks to run a Node code. see docs here - https://docs.cypress.io/api/commands/task#Examples
And in a test file example, I used it like so:
describe('Db Test', () => {
it('Query Test', () => {
cy.task('executeSql', 'SELECT count(id) as cnt FROM table_name').then(result => {
expect(result.cnt, 'Does not equal to 8').to.equal(2000);
})
})
})
P.S. Additional cypress-dotenv package is just used to load env vars from .env file.

Async/Await in NodeJs and MySql connection

I've two problems.
Async/Await in queries
Env variables in pool config
I use TypeScript with Node.js and Express and I install promise-mysql but I would not refuse the use of myslq or mysql2. Currently this is my code:
database.ts
import mysql, { PoolConfig } from 'promise-mysql';
import keys from './keys';
const pool = startConnection();
export default pool;
// Functions
function startConnection() {
const pool = mysql.createPool(dbOptions(true));
pool.get('getConnection').then(async () => {
await (await pool).releaseConnection;
console.log('DB is connected.');
});
return pool;
}
function dbOptions(dev: boolean): PoolConfig {
var dbInfo: PoolConfig;
if (dev) {
dbInfo = {
database: process.env.DB || keys.DB.DB,
host: process.env.DB_HOST || keys.DB.DB_HOST,
user: process.env.DB_USER || keys.DB.DB_USER,
password: process.env.DB_U_PASS || keys.DB.DB_U_PASS
};
} else {
dbInfo = {
database: process.env.DB,
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_U_PASS
};
}
return dbInfo;
}
And a query looks like this:
import pool from 'database';
const books: Book[] = await (await pool).query('SELECT * FROM book WHERE pages => ?', [minPages]);
So, i don't want the second await when i use the pool (if it's possible), and the dbOptions() don't works because the startConnection() function starts before the dotenv.config() in index.ts then the procces.env.something returns undefined each time, so how can i fixed that?.
Thanks for help! 😁
So, I cannot view all your code to help with dotenv issue, but you can pass await pool as a paramter for a callback function that starts your app. Anyway, I would implement your code by using mysql2:
database.ts:
import { createPool, Pool, PoolOptions } from "mysql2";
import keys from "./keys";
function startConnection(): Pool {
const options: PoolOptions = dbOptions({ isDev: true });
const pool: Pool = createPool(options);
return pool;
}
function dbOptions({ isDev }: {
isDev: boolean;
}): PoolOptions {
let dbConfig: PoolOptions = {
database: process.env.DB ?? (isDev &&= keys.DB.DB),
host: process.env.DB_HOST ?? (isDev &&= keys.DB.DB_HOST),
user: process.env.DB_USER ?? (isDev &&= keys.DB.DB_USER),
password: process.env.DB_U_PASS ?? (isDev &&= keys.DB.DB_U_PASS),
};
return dbConfig;
}
export const connectionPool = startConnection();
query.ts
import { connectionPool } from "database";
const books: Book[] = await connectionPool.query("SELECT * FROM book WHERE pages => ?", [minPages]);

MySQL query in Supertest returning {sql, bindings} instead of results

I'm running supertest + jest against a route that queries a mysql db, run locally. Testing through insomnia returns the correct information, but none of my db queries return correct values when using supertest.
// test.js
import request from 'supertest';
import db from '../database';
import app from './app';
describe('/', () => {
test('should return db results', async () => {
const mock = jest.spyOn(db, 'query');
const response = await request(app).get(`/`)
console.log(response.error);
expect(dbMock).toBeCalled();
expect(response.status).toBe(200);
});
});
// route (excerpt from app.js)
import returnUserInfo from './returnUserInfo';
app.get(
'/',
returnUserInfo
);
// returnUserInfo.js
import db from '../database';
export default async function returnUserInfo(req, res, next) {
const sql = 'select `userInfo` from `users` where `email` = ?';
const bindings = ['test'];
try {
const data = await db.query(sql, bindings);
if (data.length !== 1) {
throw new Error(`Invalid ${Object.keys(data)}`);
}
return res.json(data[0]);
} catch (err) {
return next(err);
}
}
// database.js
import { PoolConnection } from 'mysql';
const db = new PoolConnection(
{
host: 'localhost',
user: 'root',
password: 'foobar',
database: 'db',
connectionLimit: 100,
},
false,
);
export default db;
As mentioned before, testing with postman/insomnia returns the correct result...
When testing with supertest and logging the error:
Error: Invalid sql,bindings
It appears there had been a node_module manual mock for the mysql db which was overriding all calls to the database and simply returning
{ sql, bindings }
Note to self: when things don't make sense...check that they're supposed to be making sense.

Serverless with nodejs and mysql => Process exited before completing request

I'm developing some functions with serverless with the nodejs template. I have a service that connects to a mysql database and retrieves some data. Everything is fine when I make the first call, but when I repeat it I receive a "Process exited before completing request" error message.
If I try that same call again, I receive data. So the service is doing right on the odd calls and it's returning the error on the even calls (funny right?). This is the code of the handler function:
module.exports.getAll = (event, context, done) => {
deviceRepository.getAllDevices().then((response) => {
done(null, { response });
}).catch((error) => {
done(error);
});
};
and this is the code of the repository function:
const mysql = require('mysql');
const when = require('when');
const config = require('./config');
const conn = mysql.createConnection({
host: config.RDSHOST,
user: config.RDSUSER,
password: config.RDSPASS,
database: config.RDSDB,
port: config.RDSPORT
});
module.exports.getAllDevices = () => {
const deferred = when.defer();
conn.connect();
conn.query('SELECT * FROM device', (err, rows) => {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(rows);
}
conn.end();
});
return deferred.promise;
};
As you can see I use promises with the 'when' library. I call the 'done' callback in the handler, and there should be a response from the promise in every possible situation.
I can't see what is wrong with this and why is making the odd requests wrong. Anyone can help?
Thanks in advance!
Solved by myself...
The problem is that I was making the createConnection outside of the handler (when I declared the conn constant).
Moving the createConnection declaration inside the handler function works as expected in every call.
const mysql = require('mysql');
const when = require('when');
const config = require('./config');
module.exports.getAllDevices = () => {
const conn = mysql.createConnection({
host: config.RDSHOST,
user: config.RDSUSER,
password: config.RDSPASS,
database: config.RDSDB,
port: config.RDSPORT
});
const deferred = when.defer();
conn.connect();
conn.query('SELECT * FROM device', (err, rows) => {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(rows);
}
conn.end();
});
return deferred.promise;
};
Hope this helps. Thanks!