I was trying to implement my app's architecture based on: https://github.com/vitaly-t/pg-promise-demo
// server.js
import express from "express";
import cors from "cors";
import db from "./db/connection/db.js";
import testConnection from "./db/connection/testConnection.js";
const app = express();
await testConnection(db);
app.use(express.json( {limit: '10mb'} ));
app.use(cors());
app.get("/", (_req, res) => {
// db.one(`
// CREATE TABLE IF NOT EXISTS questions (
// id SERIAL PRIMARY KEY,
// question TEXT NOT NULL,
// possible_answers TEXT[] NOT NULL,
// answer TEXT NOT NULL,
// category TEXT NOT NULL,
// difficulty INTEGER NOT NULL
// );
// `)
db.question.create()
.then(res => {
console.log(res);
})
.catch(err => {
console.error(err)
})
});
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
// questions.js
import queries from "../sql/sqlQueries.js";
class QuestionsRepository {
constructor(db, pgp) {
this.db = db;
this.pgp = pgp;
}
create() {
return this.db.none(queries.questions.create);
}
findAll() {
return this.db.any(queries.questions.findAll);
}
}
export default QuestionsRepository;
// sqlQueries.js
import QueryFile from "pg-promise";
// Helper for linking to external query files
function sql(file) {
const fullPath = new URL(file, import.meta.url); // generating full path;
const currQueryFile = new QueryFile(fullPath, {minify: true});
if (currQueryFile.error) {
console.error(currQueryFile.error);
}
return currQueryFile;
}
const queries = {
questions: {
create: sql('questions/create.sql'),
findAll: sql('questions/findAll.sql'),
}
}
export default queries;
// db.js
import pgPromise from 'pg-promise';
import dbConfig from './db-config.js';
import QuestionsRepository from "../repos/questions.js"
const initOptions = {
extend(obj) {
obj.question = new QuestionsRepository(obj, pgp);
}
}
const pgp = pgPromise(initOptions);
const db = pgp(dbConfig); // db - singleton instance of the database connection
export default db;
When I tried running the db.question.create() function created in my repository, I encountered the following error:
/opt/app/node_modules/pg-promise/lib/main.js:243
throw new TypeError(Invalid connection details:
+ npm.utils.toJson(cn));
TypeError: Invalid connection details: undefined
When I test the connection to the database using this function it turns out to be successful:
// testConnection.js
async function testConnection(db) {
try {
const conn = await db.connect(); // try to connect
conn.done(); // success, release connection
console.log(`Connection to database successful, PG server version: ${conn.client.serverVersion}`);
} catch (err) {
console.error(`Error connecting to database: ${err}`);
}
}
export default testConnection;
I also tried to run the same query directly (the commented part in server.js) which successfully created the table.
Because of those two facts, I assume that there's something wrong with how pg-promise is extended by the QuestionsRepository as opposed to the connection issues that the error indicates.
I found out what the issue was. It was in the sqlQueries.js file. I changed it to:
import pgPromise from 'pg-promise';
const { QueryFile } = pgPromise;
// Helper for linking to external query files
function sql(file) {
const fullPath = new URL(file, import.meta.url).pathname; // generating full path;
const currQueryFile = new QueryFile(fullPath, {minify: true});
if (currQueryFile.error) {
console.error(currQueryFile.error);
}
return currQueryFile;
}
const queries = {
questions: {
create: sql('questions/create.sql'),
add: sql('questions/add.sql'),
delete: sql('questions/delete.sql'),
findAll: sql('questions/findAll.sql'),
drop: sql('questions/drop.sql'),
}
};
export default queries;
The error was due to the incorrect import of QueryFile and the incorrect value of the fullPath const.