Search code examples
pg-promise

Running extended pg-promise query returns TypeError: Invalid connection details: undefined


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.


Solution

  • 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.