How to Build a Command Line Interface (CLI) Application with Node.JS👨‍🎓🤓.

What is a Command Line Interface (CLI) Application?

CLI tools allow you to run certain tasks or operations right from your terminal or command line prompt. As a developer , chances are you spend most of your time in your terminal, typing in …



What is a Command Line Interface (CLI) Application?

CLI tools allow you to run certain tasks or operations right from your terminal or command line prompt. As a developer , chances are you spend most of your time in your terminal, typing in commands to help you get around some tasks. A good example of commonly used applications include npm , Create React App , Vue CLI etc.
In this tutorial you will create a CLI todo list application by using Node JS.



Setting up the project

First , create a directory that will hold the CLI application:

    mkdir todo-list-cli
    cd todo-list-cli

Next, we will initialize our Node.js project

    npm init -y

This will create a package.json file with defaults. Once that is done you need to install some packages that will help create our CLI application. These are:

  1. commander:This package makes creating the CLI application easier. It provides functions that will allow you to set the commands, options and more

  2. chalk:This package lets us print colored messages to the console. It will help us make our CLI application look nice and pretty

  3. conf:This package allows us to save persistent information on the user’s machine. We will be using it to save the user’s todo list

To install these packages, run:

    npm i commander chalk conf

Once installation is done, you are ready to start the development of the CLI tool.



Creating a CLI Application

Firstly start by creating index.js in the root of the project. This will be the main entry of the application.

Next, to create the basic configurations, and functionalities, we can use commander. First, let’s require program from commander.

const {program} = require('commander')

To declare a command, commander provides the following functions:

  1. command: takes a string that defines the command.
  2. description: describes the command for the user. This is helpful when the user uses the –help option.
  3. option: the options that this command can take, if any.
  4. action: particular action to execute, when command is executed.

If you are wondering what about the commands for the CLI?

You need the following commands:

  1. todo list: this will list the tasks in the user’s to-do list
  2. todo add: this will add a new task to the user’s to-do list
  3. todo mark-done: this will mark specific tasks or all tasks as done in the list



Creating the List Command

The list command will just show the list of tasks that the user has added before. It will not take any options. You should be able to run it by running the following command in your terminal:

    todo list

Now in index.js, add the following below the code we added earlier:

    program
          .command('list)
          .description('List all the TODO tasks')
          .action(list)

In this the command function is used to declare the command in CLI application. The argument you pass is a string.The description function is used to describe this command to the user when they run the application with the --help option. Finally, the action is assigned to a function called list, which you will create shortly.

Now, create a new directory called commands. And a file list.js in it, which will hold the function that will run when the user runs todo list in the terminal.

For storing and reading the tasks, you will use the conf package. It has the following functions:

  1. set: this sets the information under a specific key
  2. get: this gets the information that is set under a specific key

Lets start by requiring conf in commands/list.js:

    const conf = new (require('conf'))()

Next, you need to implement and export the function for use in index.js:

    function list(){

    }
    module.exports = list

Now, specify the key todo-list inside the list function under which the data will be set and get using the conf package. todo-list will be an array of objects.

    const todoList = conf.get('todo-list')

Next, if todo data is already in the todo-list, you need to loop over them and display them in the terminal, done tasks will have green color and yellow for the tasks that are not done.

If todo-list is empty, which means user does not have any tasks, you need to show a message in red indicating that they don’t have any tasks.

    const todoList = conf.get('todo-list')

    if (todoList && todoList.length) {
      //user has tasks in todoList
    } else {
      //user does not have tasks in todoList
    }

To show color in our terminal, as mentioned before you will use chalk. Let’s require it in the commands/list.js.

    const conf = new (require('conf'))()
    const chalk = require('chalk')

    //rest of our code

Next, you will use chalk in the else part first. You need to show the user that they don’t have any tasks in the todo list. To display message in red using chalk :

    else {
      //user does not have tasks in todoList
      console.log(
      chalk.red.bold('You don\'t have any tasks yet.')
     )
    }

Now, you need to display a message in green if the user does have tasks. First, you need to show a message that details the color meaning of the tasks.

    if (todoList && todoList.length) {
     console.log(
        chalk.blue.bold('Tasks in green are done. Tasks in yellow are still not done.')
     )
    }

Now, the second step is to loop over the tasks in the todoList and for each task, check if it’s done then display green, if not then yellow.

    todoList.forEach((task, index) => {
         if (task.done) {
             console.log(
                 chalk.greenBright(`${index}. ${task.text}`)
             )
         } else {
             console.log(
                 chalk.yellowBright(`${index}. ${task.text}`)
            )
          }
     })

Now the list function is done and you can use it in index.js.

The full code till now is:

    const conf = new (require('conf'))()
    const chalk = require('chalk')
    function list () {
        const todoList = conf.get('todo-list')
        if (todoList && todoList.length) {
            console.log(
                chalk.blue.bold('Tasks in green are done. Tasks in yellow are still not done.')
            )
            todoList.forEach((task, index) => {
                if (task.done) {
                    console.log(
                        chalk.greenBright(`${index}. ${task.text}`)
                    )
                } else {
                    console.log(
                        chalk.yellowBright(`${index}. ${task.text}`)
                    )
                }
            })
        } else {
            console.log(
                chalk.red.bold('You don\'t have any tasks yet.')
            )
        }
    }
    module.exports = list

Now, in the index.js require the list function.

    const list = require('./commands/list')

Then, at the end of file add the following:

    program.parse()

This is important for commander as the input of the user need to be parsed to figure out which command the user is running and execute it.



Testing the Application

The first step is to add the following in the package.json file.

    "bin":{
        "todo":"index.js"
    }

todo will be used in the terminal when running commands from our todo CLI. You can change it to whatever you want. It is pointing at index.js, as this is your main point of entry.

Now, you have to globally install the package on your machine.

    npm i -g

Once it is done you can run the application right from your terminal.

    todo --help

You will see the following in your terminal:

    Usage: todo [options] [command]

    Options:
      -h, --help           display help for command

    Commands:
      list                 List all the TODO tasks
      help [command]       display help for command

If you run the list command:

    todo list

It will just show the message that you don’t have any task yet.
Let’s implement a new command that is add command.



Add Command

The add command will take one argument, which will be the text/title of the task.The command will look.

    todo add "Make CLI App"

Now, you need to declare add command in index.js under the list command, not after the program.parse(), add the the following:

    program
        .command('add <task>')
        .description('Add a new TODO task')
        .action(add)

The command function has add where is the argument the user need to pass. In commander a required argument is , whereas if it’s optional, you use [ARG_NAME]. Also, the name given to the argument is same as name of the parameter passed to the function in action.

Now, just like the list command you need to implement the add function. Let’s create the file commands/add.js with the following :

    const conf = new (require('conf'))()
    const chalk = require('chalk')

    function add (task) {

    }

    module.exports = add

In the add function, a task parameter is passed, which will be passed by the user.

The add function will store the task in the todo-list array using conf. And a success message in green will be displayed using chalk.

First, you will use the get function to get the todo-list and then push a new task to the todo-list array.

The entire code for the add function is:

    function add (task) {
        //get the current todo-list
        let todosList = conf.get('todo-list')

        if (!todosList) {
            //default value for todos-list
            todosList = []
        }

        //push the new task to the todos-list
        todosList.push({
            text: task,
            done: false
        })

        //set todos-list in conf
        conf.set('todo-list', todosList)

        //display message to user
        console.log(
            chalk.green.bold('Task has been added successfully!')
        )
    }

Now, go back to index.js and require the add function:

    const add = require('./commands/add')

Let’s test this command in the terminal:

    todos add "Make CLI App"

You will get a message “Task has been added successfully!” in green. To check that added task, run in your terminal:

    todo list

Try adding some more tasks to see the list grow.

Now will add the mark-done command which will mark a task as done.



mark-done command

The mark-done command, takes a --tasks option followed by at least one index of the tasks user want to mark as done it mark those as done, but by default will mark all tasks as done if not index is specified.

Example command:

    todo mark-done --tasks 1 2

For the simplicity of the tutorial, the indices of tasks to mark them done are used.But in a real-life use case application, you would probably use unique IDs for the tasks.

Now, declare mark-done command under the add command:

    program
        .command('mark-done')
        .description('Mark commands done')
        .option('-t, --tasks <tasks...>', 'The tasks to mark done. If not specified, all tasks will be marked done.')
        .action(markDone)

In this command the option function. The first parameter is the format of the option -t, --tasks means that the user can use either -t or --tasks to pass this option. means that more than one task can be provided, but as the <> is used which means it is required. The second parameter is the description of the option. This is useful when the user types todo mark-done --help command.

Now, just like previous commands you need to implement the markDone function. Let’s create the file commands/markDone.js with the following :

    const conf = new (require('conf'))()
    const chalk = require('chalk')

    function markDone({tasks}) {

    }
    module.exports = markDone

You can see that the markDone function takes an object that includes a tasks property. If the -t or --tasks option is passed to the command, tasks will be an array of the values passed by the user. If not, it will be undefined.

What we need to do inside the markDone function is to get the todo-list array from conf. If todo-list is not empty, you need to loop over it. And mark only the tasks of the indices the user enters as done. If tasks indices is undefined, then mark all tasks as done.

The complete code for markDone is :

    function markDone({tasks}) {
        let todosList = conf.get('todo-list')

        if (todosList) {
            //loop over the todo list tasks
            todosList = todosList.map((task, index) => {
                //check if the user specified the tasks to mark done
                if (tasks) {
                    //check if this task is one of the tasks the user specified
                    if (tasks.indexOf(index.toString()) !== -1) {
                        //mark only specified tasks by user as done
                        task.done = true
                    }
                } else {
                    //if the user didn't specify tasks, mark all as done
                    task.done = true
                }
                return task
            });

            //set the new todo-list
            conf.set('todo-list', todosList)
        }

        //show the user a message
        console.log(
            chalk.green.bold('Tasks have been marked as done successfully')
        )
    }

First check if the todoList is empty or not, if not loop over todosList inside map function. And then check if tasks is defined, which means if the user has passed any specific tasks to mark as done.

If tasks is defined, then you need to check if the current task item is in the tasks by checking if the index is in the tasks array. Note that index.toString() is used because the tasks array will hold the indices as strings.

If tasks is not defined, then, as mentioned before, mark all items as done. After loop completion you get the the updated list, you need to set todo-list using conf.set to the new array. In the end, show the user a success message.

Finally, go back to index.js and require markDone function:

    const markDone = require('./commands/markDone')

Now, test it out. By running:

    todo mark-done

If everything is correct, you can run todo list and see that all items are in green now.

Next, try to add a few more tasks then mark those done using their indices, an example command to mark a single task as done:

    todo mark-done -t 1

To mark multiple tasks:

    todo mark-done -t 1 3 5

You can now play with the commands then check which are marked done and which aren’t using the todos list command.

Our CLI Application is done! todo-list-cli now allows the user to add tasks, view them, and mark them done.



Conclusion

Congratulations, you learned how to create a CLI Application using Node.JS. The number of possible projects are are endless, so go create something more awesome!


Print Share Comment Cite Upload Translate
APA
Lokesh_Choudhary | Sciencx (2024-03-29T07:18:27+00:00) » How to Build a Command Line Interface (CLI) Application with Node.JS👨‍🎓🤓.. Retrieved from https://www.scien.cx/2021/10/14/how-to-build-a-command-line-interface-cli-application-with-node-js%f0%9f%91%a8%e2%80%8d%f0%9f%8e%93%f0%9f%a4%93/.
MLA
" » How to Build a Command Line Interface (CLI) Application with Node.JS👨‍🎓🤓.." Lokesh_Choudhary | Sciencx - Thursday October 14, 2021, https://www.scien.cx/2021/10/14/how-to-build-a-command-line-interface-cli-application-with-node-js%f0%9f%91%a8%e2%80%8d%f0%9f%8e%93%f0%9f%a4%93/
HARVARD
Lokesh_Choudhary | Sciencx Thursday October 14, 2021 » How to Build a Command Line Interface (CLI) Application with Node.JS👨‍🎓🤓.., viewed 2024-03-29T07:18:27+00:00,<https://www.scien.cx/2021/10/14/how-to-build-a-command-line-interface-cli-application-with-node-js%f0%9f%91%a8%e2%80%8d%f0%9f%8e%93%f0%9f%a4%93/>
VANCOUVER
Lokesh_Choudhary | Sciencx - » How to Build a Command Line Interface (CLI) Application with Node.JS👨‍🎓🤓.. [Internet]. [Accessed 2024-03-29T07:18:27+00:00]. Available from: https://www.scien.cx/2021/10/14/how-to-build-a-command-line-interface-cli-application-with-node-js%f0%9f%91%a8%e2%80%8d%f0%9f%8e%93%f0%9f%a4%93/
CHICAGO
" » How to Build a Command Line Interface (CLI) Application with Node.JS👨‍🎓🤓.." Lokesh_Choudhary | Sciencx - Accessed 2024-03-29T07:18:27+00:00. https://www.scien.cx/2021/10/14/how-to-build-a-command-line-interface-cli-application-with-node-js%f0%9f%91%a8%e2%80%8d%f0%9f%8e%93%f0%9f%a4%93/
IEEE
" » How to Build a Command Line Interface (CLI) Application with Node.JS👨‍🎓🤓.." Lokesh_Choudhary | Sciencx [Online]. Available: https://www.scien.cx/2021/10/14/how-to-build-a-command-line-interface-cli-application-with-node-js%f0%9f%91%a8%e2%80%8d%f0%9f%8e%93%f0%9f%a4%93/. [Accessed: 2024-03-29T07:18:27+00:00]
rf:citation
» How to Build a Command Line Interface (CLI) Application with Node.JS👨‍🎓🤓. | Lokesh_Choudhary | Sciencx | https://www.scien.cx/2021/10/14/how-to-build-a-command-line-interface-cli-application-with-node-js%f0%9f%91%a8%e2%80%8d%f0%9f%8e%93%f0%9f%a4%93/ | 2024-03-29T07:18:27+00:00
https://github.com/addpipe/simple-recorderjs-demo