Cannot connect local PostgreSQL DB in Nodejs - node.js

I connect my PostgreSQL local database in Node.js server using pg.
All worked fine, but suddenly it stopped to work.
This is my code:
const {Pool} = require('pg')
const connectionString = process.env.DATABASE_URL;
const ssl = process.env.NODE_ENV == 'production' ? '?ssl=true' : '';
const pool = new Pool({
connectionString: connectionString + ssl
});
const db = {
pool: pool,
test: async () => {
try {
console.log('before connection');
let result = await pool.query('SELECT $1::text as status', ['connected']);
console.log('connected')
return result.rows[0].status;
} catch (error) {
console.error('Unable to connect to the database:', error);
return null;
}
}
}
module.exports = db;
Here I call it:
const express = require('express')
const Router = express.Router();
const db = require('./database')
Router.get('/testdb', async (req, res) => {
try {
let result = await db.test();
res.status(200).send(result);
} catch (error) {
res.status(500).send(error);
}
})
It stuck on pool.query. 'before connection' is logged, no error is thrown.
The very same code works fine with my remote db, and I can connect the local db with pgAdmin.

This was an incompatibility issue between pg and the node.js 14 version. See also the following GitHub issues where this was tracked and fixed:
https://github.com/brianc/node-postgres/issues/2180
Pull request: https://github.com/brianc/node-postgres/pull/2171
tl;dr: Upgrade pg to a version larger than 8.0.3 (pg>=8.0.3).

I found my problem in node version - some days ago I updated it to 14.5.0.
revise it to 12.18.2 LTS solve the problem.

Related

sql.Connection is not a constructor [nodejs expressjs and SqlServer] ---

I am trying to write a backend API in node and express JS to connect to SQL Server[with windows authentication] and fetch data. The error message is --
const poolPromise = new sql.Connection(config)
TypeError: sql.Connection is not a constructor
The relevant config file code is dbConfig.js :
const sql = require('msnodesqlv8')
const config = {
database: 'ApiDemoDB',
server: '.\\SQLEXPRESS',
driver: 'msnodesqlv8',
options: {
trustedConnection: true
}
}
const poolPromise = new sql.Connection(config) <-------this line error
.connect()
.then(pool => {
console.log('Connected to MSSQL')
return pool
})
.catch(err => console.log('Database Connection Failed! Bad Config!: ', err))
module.exports = {
sql, poolPromise
}
What is the meaning of this error message? sql.Connection is not supposed to take any parameter[config]? I don't get it, what am I supposed to do differently here? What additional code changes do I have to make in order to get this working? Can you please help me solve this problem so that the API can connect to the mssql database? As you can see, as of now I have very little code. Barebones.
Thanking you in advance.
*********************************** EDIT ***********************************
I have changed the code around quite a bit.
My dbconfig.js file is now as:
const sql = require('mssql');
const msnodesqlv8=require('msnodesqlv8');
var dbconfig = {
server: 'localhost',
database: 'ApiDemoDB',
driver: 'msnodesqlv8',
options: {
enableArithAbort:true,
trustedConnection: true,
instancename:'SQLEXPRESS'
},
port:1433
}
module.exports=dbconfig;
And then a separate dbconnect.js file as:
var sql = require("mssql/msnodesqlv8")
var dbConfig = require("./dbConfig")
var dbConnect = new sql.connect(dbConfig,
function(err)
{
if(err){
console.log("Error while connecting to database: " + err)
}else{
console.log("connected to database: " + dbConfig.server)
}
}
)
module.exports = dbConnect
Now, the error that I have is ->
Error while connecting to database: ConnectionError: Failed to connect to localhost:1433 - Could not connect (sequence)
What does this even mean. It's pointing to the dbconfig file, but what changes to be written there, can you suggest me? Thanks

In nodejs how to connect an existing database in sqlite which has password? I have a password but I don't know how to put it in my code

For all that I researched the sqlite does not have a password, but I am wanting to access a database where I work that they put a password with a library for C# (I have the password). With my code below can I read a database generated by this company program if not put a password in it, but with a password I always give this error:
[Error: SQLITE_NOTADB: file is not a database] {
errno: 26,
code: 'SQLITE_NOTADB'
}
My code:
const express = require("express");
const app = express();
const sqlite3 = require('sqlite3');
const sqlite = require('sqlite');
async function main() {
try {
const db = await sqlite.open({ filename: './LocalData.db', driver: sqlite3.Database });
const rows = await db.all('SELECT * FROM ProductionData');
console.log(rows);
await db.close();
} catch (error) {
console.log(error);
}
}
main();
app.listen(5000, () => {
console.log("Servidor iniciado na porta 5000");
});
How can i put the database password inside this code?

node-media-server: session.reject() not working

I am trying to create an RTMP-server with the npm package: http://github.com/illuspas/Node-Media-Server. So the server works fine but I need to implement authentication in it. I am trying to check the authentication on "prePublish" event. I am querying the database and retrieving the user if the user was found then I want to let the user stream otherwise rejected. But the problem is, it doesn't leave it instead disconnects and then the stream automatically reconnected to it then it disconnects again and the loop goes on. How do I fix this problem?
Here is the code for the event:
const NodeMediaServer = require('node-media-server');
const config = require('./config').rtmp_server;
const db = require('./db');
const nms = new NodeMediaServer(config);
const getStreamKeyFromStreamPath = (path) => {
const parts = path.split('/');
return parts[parts.length - 1];
};
nms.on('prePublish', async (id, StreamPath, args) => {
const session = nms.getSession(id);
try {
const streamKey = getStreamKeyFromStreamPath(StreamPath);
const validStream = (
await db.query('SELECT * FROM public."People" WHERE stream_key = $1', [streamKey])
).rows[0];
console.log(validStream);
if (validStream) {
// do stuff
} else {
session.reject((reason) => {
console.log(reason);
});
}
console.log(
'[NodeEvent on prePublish]',
`id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`
);
} catch (err) {
session.reject();
}
});
module.exports = nms;
Here is the code of the entry point of the server:
require("dotenv").config();
const db = require("./db");
const nms = require("./nms");
// database connection
db.connect()
.then(() => {
console.log("Connected to database");
// start the rtmp server
nms.run();
})
.catch((err) => console.log(err.message));
Here is the db file:
const { Pool } = require('pg');
const connectionString = process.env.PG_CONNECTION_STRING;
const poolOptions = {
host: process.env.PG_HOST,
user: process.env.PG_USER,
port: process.env.PG_PORT,
password: process.env.PG_PASSWORD,
database: process.env.PG_DATABASE,
};
const pool = new Pool(process.env.NODE_ENV === 'production' ? connectionString : poolOptions);
module.exports = pool;
My procedures to solve that problem:
Instead of the async function, I tried to handle the database query using a callback but it didn't work.
Before I was calling session.reject() now I am passing a callback there but the behavior is still the same
If you have any solution for that, please let me know.
Thanks in advance

How to properly connect to MongoDB using Cloud functions?

I would like to connect to my Atlas cluster only once per instance running Cloud Functions.
Here is my code for an instance :
const MongoClient = require("mongodb").MongoClient;
const client = new MongoClient("myUrl", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
exports.myHttpMethod = functions.region("europe-west1").runWith({
memory: "128MB",
timeoutSeconds: 20,
}).https.onCall((data, context) => {
console.log("Data is: ", data);
client.connect(() => {
const testCollection = client.db("myDB").collection("test");
testCollection.insertOne(data);
});
});
And i would like to avoid the client.connect() in each function call that seems to be really too much.
I would like to do something like this :
const MongoClient = require("mongodb").MongoClient;
const client = await MongoClient.connect("myUrl", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = client.db("myDB");
exports.myHttpMethod = functions.region("europe-west1").runWith({
memory: "128MB",
timeoutSeconds: 20,
}).https.onCall((data, context) => {
console.log("Data is: ", data);
const testCollection = db.collection("test");
testCollection.insertOne(data);
});
But i can't await like this.
In my AWS Lambda functions (running in python) i have not this issue and i am able to connect only once per instance, so i guess there is an equivalent but i don't know much JS / Node JS.
You can store your database client as a global variable. From the documentation,
Cloud Functions often recycles the execution environment of a previous invocation. If you declare a variable in global scope, its value can be reused in subsequent invocations without having to be recomputed.
Try refactoring the code as shown below:
import * as functions from "firebase-functions";
import { MongoClient } from "mongodb";
let client: MongoClient | null;
const getClient = async () => {
if (!client) {
const mClient = new MongoClient("[MONGODB_URI]", {});
client = await mClient.connect();
functions.logger.log("Connected to MongoDB");
} else {
functions.logger.log("Using existing MongoDB connection");
}
functions.logger.log("Returning client");
return client;
};
export const helloWorld = functions.https.onRequest(
async (request, response) => {
const db = (await getClient()).db("[DATABASE]");
const result = await db.collection("[COLLECTION]").findOne({});
response.send("Hello from Firebase!");
}
);
This should reuse the connection for that instance.

Execute a middleware one-time only at server startup in Koa v2

I created this middleware which executing only once when any route in the website gets the first hit from a visitor:
// pg-promise
const db = require('./db/pgp').db;
const pgp = require('./db/pgp').pgp;
app.use(async (ctx, next) => {
try {
ctx.db = db;
ctx.pgp = pgp;
} catch (err) {
debugErr(`PGP ERROR: ${err.message}` || err);
}
await next();
});
// One-Time middleware
// https://github.com/expressjs/express/issues/2457
const oneTime = (fn) => {
try {
let done = false;
const res = (ctx, next) => {
if (done === false) {
fn(ctx, next);
done = true;
}
next();
};
return res;
} catch (err) {
debugErr(`oneTime ERROR: ${err.message}` || err);
}
};
const oneTimeQuery = async (ctx) => {
const result = await ctx.db.proc('version', [], a => a.version);
debugLog(result);
};
app.use(oneTime(oneTimeQuery));
This code executing on the first-time only when a user visiting the website, resulting:
app:log Listening on port 3000 +13ms
app:req GET / 200 - 24ms +2s
23:07:15 connect(postgres#postgres)
23:07:15 SELECT * FROM version()
23:07:15 disconnect(postgres#postgres)
app:log PostgreSQL 9.6.2, compiled by Visual C++ build 1800, 64-bit +125ms
My problem is that I want to execute it at the server start, when there's no any visit on the site.
The future purpose of this code will be to check the existence of tables in the database.
Solution:
Placing this in ./bin/www before the const server = http.createServer(app.callback()); declaration helped:
const query = async () => {
const db = require('../db/pgp').db;
const pgp = require('../db/pgp').pgp;
const result = await db.proc('version', [], a => a.version);
debugLog(`www: ${result}`);
pgp.end(); // for immediate app exit, closing the connection pool (synchronous)
};
query();
You could start your application using a js script that requires your app and uses node's native http module to fire up the server. Exactly like in koa-generator (click).
This is in your app.js file:
const app = require('koa')();
...
module.exports = app;
And then this is in your script to fire up the server:
const app = require('./app');
const http = require('http');
[this is the place where you should run your code before server starts]
const server = http.createServer(app.callback());
server.listen(port);
Afterwards you start your application with:
node [script_name].js
Of course keep in mind the async nature of node when doing it this way. What I mean by that - run the 'listen' method on 'server' variable in callback/promise.

Resources