skip to Main Content

I recently came across the error popping up in terminal or command prompt mentioned in the question above.

Exact error shown is:

const taskCollection = db.collection('tasks');
                              ^

TypeError: Cannot read properties of undefined (reading 'collection')
    at Command.<anonymous> (C:AbcxyzTask-Manager-CLI-Projectindex.js:50:31)
    at Command.listener [as _actionHandler] (C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:494:17)
    at C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:1296:65
    at Command._chainOrCall (C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:1193:12)
    at Command._parseCommand (C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:1296:27)
    at C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:1082:27
    at Command._chainOrCall (C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:1193:12)
    at Command._dispatchSubcommand (C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:1078:25)
    at Command._parseCommand (C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:1264:19)
    at Command.parse (C:AbcxyzTask-Manager-CLI-Projectnode_modulescommanderlibcommand.js:910:10)

This is a simple task manager CLI project. I have connected mongoDB with my project, still it shows the same error and I am not getting where the error is? How do I solve it
Here are my 2 code files:

db.js

const { MongoClient } = require('mongodb');
const uri = 'mongodb://localhost:27017';

//we have used MongoDB Node.js driver to connect js to MongoDB database.

const client = new MongoClient(uri)

let db;

async function connect(){
    try{
        await client.connect();
        db = client.db('task_manager_db'); 
        
        // it is selecting the database named 'taskmanager'. If the specified database does not exist, MongoDB will create it when you first write data to it.
        //now variable db holds the reference to 'taskmanager' database
        
        console.log('Connected to the database');
    } catch(err){
        console.log('Error connecting to the database...', err);
    }
}

function getDB(){
    return db;
}

module.exports = {connect, getDB};

index.js

//using commander.js library for the project
//commander.js library provides functions that can run the project on CLI mode.
//Which is the ultimate aim and learning behind the project: To create and run a project using CLI.

const program = require('commander');

//importing the functions from db.js
const {connect, getDB} = require('./db');

program
.version('1.0.0')
.description('Task Manager CLI')
//connecting MongoDB database (i.e. to the uri to be specific)
.action(connect());

//general structure of defining commands for CLI using commander.js library
// program
// .command('')
// .description('')
// .action(//function inside() => { });

//command to list all tasks --> list
program
.command('list')
.description('list of commands')
.action(async() => {
    //extract database from function
    const db = getDB();
    //refer to the collection in db
    const taskCollection = db.collection('tasks');

    try{
        const tasks = await taskCollection.find().toArray();
        console.log("Listing all the tasks:");
        tasks.forEach((task_) => {
            console.log(`- ${tasks.task_}`);
        });
    }catch(err){
        console.log("Error displaying tasks...");
    }

});

//command to add a task --> add <taskname>
program
.command('add <taskname>')
.description('Add a new task')
.action(async() => {
    const db = getDB();
    const taskCollection = db.collection('tasks');

    try{
        const result = await taskCollection.insertOne({ taskname });
        console.log(`New Task added: ${task} TaskID: ${result.insertedId}`);
    }catch(err){
        console.log("Error adding task...", err);
    }
});

//command to delete task --> delete <TaskId>
program
.command("delete <TaskId>")
.description("Delete a task")
.action(async() => {
    const db = getDB();
    const taskCollection = await db.collection('tasks');

    try{
        const result = await tasksCollection.deleteOne({ _id: new ObjectId(TaskId) });
        console.log(`Deleted Task (ID: ${TaskId}`);
    }catch(err){
        console.log("Error deleting a task...", err);
    }
});

program.parse(process.argv);
  1. I tried changing the URI from my MongoDB compass, even renamed it from "New Connection" TO "Project1" then copied the URI to db.js file. Didn’t work.

  2. I tried changing the URI from mongodb://localhost:27017 to mongodb://localhost:27018
    OR from mongodb://localhost:27017 to mongodb://localhost:27017/Project1 still didn’t work. The error still pops.

Expected output is the commands list, add , delete should run on command prompt and show the coded console.log() outputs or error handling outputs. Instead it says the collection tasks of my database task_manager_db is undefined and hence cannot read its properties.

2

Answers


  1. Since connect() is an asynchronous function, you should return db within that function itself and use await in your index.js file like this:

    db.js

    const { MongoClient } = require('mongodb');
    const uri = 'mongodb://localhost:27017';
    const client = new MongoClient(uri)
    
    let db;
    
    async function connect(){
        try{
            await client.connect();
            db = client.db('task_manager_db'); 
            return db;
        } catch(err){
            console.log('Error connecting to the database...', err);
        }
    }
    
    module.exports = {connect};
    

    index.js

    const program = require('commander');
    const {connect} = require('./db');
    
    program
    .version('1.0.0')
    .description('Task Manager CLI');
    
    program
    .command('list')
    .description('list of commands')
    .action(async() => {
        const db = await connect();
        const taskCollection = db.collection('tasks');
    
        try{
            const tasks = await taskCollection.find().toArray();
            console.log("Listing all the tasks:");
            tasks.forEach((task_) => {
                console.log(`- ${tasks.task_}`);
            });
        }catch(err){
            console.log("Error displaying tasks...");
        }
    
    });
    
    program
    .command('add <taskname>')
    .description('Add a new task')
    .action(async() => {
        const db = await connect();
        const taskCollection = db.collection('tasks');
    
        try{
            const result = await taskCollection.insertOne({ taskname });
            console.log(`New Task added: ${task} TaskID: ${result.insertedId}`);
        }catch(err){
            console.log("Error adding task...", err);
        }
    });
    
    program
    .command("delete <TaskId>")
    .description("Delete a task")
    .action(async() => {
        const db = await connect();
        const taskCollection = await db.collection('tasks');
    
        try{
            const result = await tasksCollection.deleteOne({ _id: new ObjectId(TaskId) });
            console.log(`Deleted Task (ID: ${TaskId}`);
        }catch(err){
            console.log("Error deleting a task...", err);
        }
    });
    
    program.parse(process.argv);
    
    Login or Signup to reply.
  2. The issue is with your connection to MongoDB. The connection to MongoDB is async. Wait for the connection to complete using the async function on your commander action. In your case, the index.js, the snipet to connect to mongo should look like this:

    program
    .version('1.0.0')
    .description('Task Manager CLI')
    //connecting MongoDB database 
    .action(async ()=>{
       await connect());
    }
    

    This should ensure your connection is complete before you can run any commands.

    async actions in commander.js

    MongoDB reason behind Cannot read properties of undefined (reading ‘collection’)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search