Recently while working on my website I made a command line tool in Node.js. The tool took in an HTML file and tokenized its contents into a JSON file. Writing command line tools with Node.js sounds complicated at first but is actually incredibly simple! This discovery post introduces a simple command line tool for generating random numbers - written in Node.js.
One of the great things about the Node.js and the npm ecosystem is all the community built npm modules. For command line tools there are many different modules to choose from. In this discovery post I use commander.js. I chose this module over all the others because it has no dependencies! Less dependencies generally means more reliable code and less unused code.
The first step for building the application is initializing the projects package.json file and setting up a
bin is an object of key value pairs. The key is the name of a command and the value is the file that executes when the command is called. Npm takes the key value pairs in
bin and adds the executable files (the values) to the systems
PATH variable1. In Unix systems
PATH declares a list of directories for executable programs2. In order to install this executable globally the following command is run:
Now the executable is referenced globally throughout the filesystem by running
Commander.js introduces a really nice API for building command line apps. The API uses chained methods to declare the applications functionality. Let's go through the Node.js application piece by piece before displaying the entire application in full.
The first line of the script must be a shebang line, otherwise the command line application won't work.
A shebang line is written to determine which interpreter is used on an executable file3. The syntax consists of the
#! symbols followed by a path to an interpreter script. The shebang line is used on Unix operating systems, but in different OS environments other methods are used. For example, on Windows the interpreter is simply implied by the file name extension.
Shebang lines are commonly used with the format
#!/usr/bin/env followed by the interpreter name. This sequence uses the Unix
env command to look for the interpreter name in the systems
I also used the
--harmony flag when specifying the
node interpreter. This flag enables the use of ES6+ features.
Now comes the main body of the application. I import the commander.js module and declare the command line program:
The application is broken down into pieces - each piece being a chained method call. The first method call is to
version(), which specifies a version number that is displayed when using the
random --version command.
The seconds method call is to
arguments(), which specifies mandatory arguments users must enter when writing a command. Two arguments are specified here -
<end>. Remember that the command line app is for generating random numbers. The
start argument specifies a lower bound the random number, and
end specifies an upper bound. Later in the method chain I accessed these two arguments with the
end variables respectively.
arguments() which specifies mandatory parameters,
option() specifies optional flags for the command. Optional flags provides additional functionality for an application. The code above specifies a flag declared with either
--type followed by a
<type> argument. Its used to specify whether the random number is an integer or a floating point number.
Optional flags are also accessed as variables in the
action() method. The
<type> argument is stored in the
program.type variable. I will go over
action() in just a bit.
parse() specify text to display when calling
random --help and to explicitly bind the programs arguments to the command line arguments (
action() contains logic to perform based on the command line arguments. This is the meat of the application.
The code here is straightforward. Return a random integer or floating point number within the bounds specified in the command line arguments. That is all!
The program is executed like so:
Easy! The command line application I built for my website has a bit more complexity, but even that is simple and easy to understand. You can check out the code for my app on GitHub.