In my previous post about Making CLI Application in Node.js (I am going to call it the previous blog), which you can find it below.

In this article, I talked about basic steps to make a global module which can be accessed from anywhere on the system using terminal window or command line tool.

Today, we are extending functionality of that application to access wide variety of command arguments and making our app simpler to use for end users. There are two great npm modules available to achieve that. Commander.js (https://github.com/tj/commander.js) is node module which will help us parse process.argv in much easy and better way while Inquirer.js (https://github.com/SBoudrias/Inquirer.js) will help us design interactive CLI application. This is going to be very simple tutorial to showcase how a simple example would work combining these two modules, but you should explore more functionality of these modules from their documentation.

I advice you to read my previous blog first so that you can understand how to create a npm global app that works with CLI.

Let’s talk little bit about what we are going to develop. We are making a CLI application for coffee shop. Using this app, people can either view coffee menu or order a coffee of their choice. A user has choice to select coffee type, sugar level, regular or decaf, served hot or cold, served in mug, cup or takeaway package, stirrer included or not etc.

CLI commands a person can use are like

coffee-shop list

coffee-shop order [type] -d --sugar-level low ...

We are going to explore more about command arguments to incorporate all choices a person can use to customize his/her coffee. But at this point, let’s get all our project dependencies installed. I hope you have read by previous blog, so I am not going to explain everything about setting up the project.

Let’s initialize package.json and install few modules.

mkdir coffee-shop-app && cd coffee-shop-app

npm init -y

npm install --save commander inquirer colors

We have created coffee-shop-app folder and installed Commander.js and Inquirer.js npm modules along with colors module to add some colors to console output. Now we need to edit package.json to incorporate few changes in bin field. Since, we want people to use coffee-shop command, we should have this keyword as key with value pointing to bin/index.js file. Hence with knowledge from previous blog, we can speculate that our package.json file should look like

{

"name": "coffee-shop-app",

"version": "1.0.0",

"preferGlobal": true,

"bin": {

"coffee-shop": "./bin/index.js"

},

"dependencies": {

"colors": "^1.2.1",

"commander": "^2.15.1",

"inquirer": "^5.2.0"

}

}

In lib folder, we will have two files viz. list.js and order.js which will take responsibility of listing menu and ordering coffee individually. From index.js , we need to route user request to one of these files depending on sub-commands (list or order). We will also have values.js file inside lib folder to export things like coffee types, sugar levels etc.

We are first going to develop app only with Commander.js and then simplify user input using Inquierer.js, which will help you understand why Inquirer.js is awesome. But since this isn’t a tutorial about Commander or Inquirer, I am going to explain their specs in brief.

Let’s first export values in values.js like below

(values.js)

Then inside list.js , we are going to export a function which prints list of coffee drinks as shop menu, like below

(list.js)

Above code imports types from values.js and exports a function which prints coffee menu of the shop. We also have used some colors to print this menu, which is nice :).

We can test, if list.js exported function is working properly, by implementing inside index.js .

// ./bin/index.js const program = require('commander'); // import function to list coffeee menu

const list = require('../lib/list'); // print menu

list();

Above output is impressively good. As we know that command coffee-shop will use bin/index.js along with whatever arguments passed to it, hence coffee-shop sub-command --arguments command is just like bin/index.js sub-command --arguments command.

Let’s implement our first sub-command which is coffee-shop list which should output above result shown in gif. Which means bin/index.js list command should output that same result. This is where Commander.js comes into play.

Commander parses process.argv and gives very easy interface to work with. If you check documentation here at https://github.com/tj/commander.js, there are many flavors using which you can construct a CLI command. For our use case, we are using Command-specific options (https://github.com/tj/commander.js/#command-specific-options) flavor.

(index.js)

In above program, we are creating a sub-command list for main command coffee-shop so that user can use coffee-shop list command to print coffee menu. User can also use alias ls like coffee-shop ls which also does the same thing. description will help user understand use of this command when they use coffee-shop --help command as help argument is provided by Commander by default. In action method, we are executing list function which prints the coffee menu. action method will execute only when user uses list sub-command. We need to pass process.argv to Commander to parse user input from which is last line of the program.

It’s time to install our app globally from local source code. Don’t forget to add shebang line as the first line in index.js , like done in above program.

npm install -g ./

After installation is completed, we can use command coffee-shop list or coffee-shop ls which should print coffee menu like below.

Command coffee-shop will not do anything as no sub-command was used with it. But you can figure out a way to throw error when no sub-command is used.

(CLI)

Hurey. We have successfully created our first list sub-command. Let’s now move to order sub-command.

(index.js)

Above is a sample code to show how order sub-command will be implemented. The new option method is used to define arguments used with command like below.

(CLI)

Please read Commander documentation for more help regarding command arguments and how to use them.

Since we don’t want to present above output to the user because it’s not neat and we want order.js file to handle output related functionality. But there is another User Experience related problem.

A user needs to know all command arguments to be able to use this app. But nobody is going to read manual before using this app, trust me. Hence we need to figure out how to present choices to the user to choose their preferences from. This is where Inquirer comes into play. Inquirer will eliminate implementation of all command arguments from Commander and take responsibility on its own by asking user inputs in interactive questions.

Let’s create a simple Inquirer program to see how it works. Basically, Inquirer accepts a list of questions. A question has name (variable name), description or message to present while asking question, type of question (yes/no or list choice or other) and other data. Let’s modify index.js to implement a simple example.

(index.js)

In above example, we have written simple Inquirer program to test how it works. inquirer.prompt takes question list and returns a Promise . Promise is resolved when user answers all the question. Promise returns answers to all the questions in JavaScript Object. Since index.js is executed with coffee-shop command, we can try above program like below

(output)

As you can see from above output, Inquirer makes CLI application interactive. We got rid of command line arguments completely to get same user input data. Since this was just an example, we need to implement this code inside lib/order.js and print order in neat format. We are going to use pad npm module to add some padding to console output.

First of all, let’s modify index.js to implement order sub-command along with previous list sub-command.

(index.js)

In order.js , we have to export a function which will print order information. It is better if we implement Inquirer code inside order.js file to make this module locally available as well.

(order.js)

We are done with our program. Now let’s see entire application in action.

(CLI)

Now you can choose to publish your package or keep to yourself. Commander and Inquirer combination made coffee-shop application more interactive and fun. There are lot of other fun stuff you can do with these modules, hence I urge you to check out their documentation.

There is another CLI application builder module name vorpal (https://github.com/dthree/vorpal) which provide functionality of Commander and Inquirer combined, more or less.

To make this module available locally without CLI interface, we can create index.js in root directory of the module and export list and order functions.

// ./index.js

exports.list = require('./lib/list');

exports.order = require('./lib/order');

I guess that’s it guys. Let me know your thoughts on this one. You can find source code of this blog at https://github.com/thatisuday/npm-interactive-cli-module-demo.