Create awesome cli tools with Node.js
JavaScript was developed in 1995, primarily as a language for browsers. Though, the language was invented in hurry, It had powerful features from the starting. It became even more powerful after invention of Node.js in 2009. Node.js opened a platform where JS developer could write command line tools(cli) and do server-side scripting. Not only it gave a way, it soon became a powerful tool for developing network applications. Recent stack overflow survey says that JavaScript is used by 71.5% and Node.js by 49.9% of professional developers among the respondent of it's survey. These days, JS developers are in demand as never before. We are going to build a cli with Node.js.
tl;dr
JavaScript is great language, and we will build awesome cli with JavaScript.
What we are going to build
We will create a command line tool which will connect user to their google account, and manage their google events. We will let user view and create google events in this tutorial. We will also:
- Package the command line utility 📦
- Publish it to npm ✨
Initialize your project 🎉
To setup your node project:
$ npm init
It will automatically create a package.json
file which will store all of our dependencies in one manageable place.
Packages we will need
We need to add these dependencies to our package.json
file. googleapis
is official client for google, vorpal
is the framework we will be using to create our command line tool. And, opn
is used to open browser(though opn
can be used to open any other things too, we will only be using it to open browser for this project). Other packages we will be explained later on.
"dependencies": {
"chrono-node": "^1.3.5",
"cli-spinner": "^0.2.8",
"googleapis": "^32.0.0",
"moment": "^2.22.2",
"opn": "^5.3.0",
"vorpal": "^1.12.0"
}
Let's start coding 🖥
Without further due, we will jump into writing our first command. vorpal
provides us easy to use chain-able functions to create commands. Your first command can be easy as below 💪
We will need to know three things from vorpal
to jump start building our cli. First, a command, we will need to specify the command name and arguments that our command will take. In the above example, we set the command name say
and a variadic
argument words
(Please look at vorpal documentation to know different types of argument they support). Second, a description, this function will provide description of the command it's attached to. And, finally, action, this is where your command logic resides. An action function will be provided with two parameters args
and callback
. All the arguments, that an user pass with the command will be provided through args.
For example, words
in above example will be provided as args.words
.
vorpal.command('say [words…]');
// $ say foo bar and so on -> {words: ['foo', 'bar' , 'and', 'so', 'on']}
The callback
function is called when the process for that command is completed.
Let's jump to what we are building 🚀
In this section, we are going to build simple commands to connect google account and authorize it with Google OAuth 2.0. OAuth is a authentication process which will let our command line tool to perform certain action on the user's google calendar.
Authenticating our app with Google OAuth 2.0 will require us to follow below processes:
- We need to resister our app to google and get our CLIENT_ID and CLIENT_SECRET
- Now, as we are making a cli, we will not register any redirect url, instead we will use copy/paste process.
- We need to create a authentication url, where user will give consent that they give access to their calendar to our cli. And, open a browser and redirect user to that url.
- Now, user will paste the code they get from step 3 to our cli and we will get
access_token
andrefresh_token
which will be using to perform action on google calendar later on.
In the index.js
file, we are going to add two commands, namely connect
and authorize
. connect
command will open user's default browser and redirect to the authentication url, where they will get a code that is used in authorize
command. In authorize
command access_token
and refresh_token
is generated.
Let’s save tokens for next use 🔒
Now that we have already implemented authentication we should store the token so that user can use same account later on. We will be simply using a JSON file config.json
to store access_token
, refresh_token
, expiry_date
etc. We will add a utils.js
file to perform read and write operation on JSON file.
We will update our index.js
file in order to check if user is already connected to their google calendar or not. We are also making sure that the client can logout of their account.
List Events 🚀
We have already authenticated user's google account, now it's time to show events that user have in their primary
calendar. For this we will be using calendar
of googleapis
. In order to list google events, we have to:
GET https://www.googleapis.com/calendar/v3/calendars/calendarId/events
With gooleapis
, we can simply list events like below:
We can use many other options with list
, some more will be shown later on. We are also using moment.js
to format time. Altogether, list command will be like below
Let's add some options 🔥
We can add functionalities to our cli with options. Here, we are adding from
and to
dates to filter out the events between that date range. Also, results
option tells how many results to list.
In vorpal
, we can add options by chaining a option
function. We can simply provide alternative
commands by separating them with a comma.
We have also added chorno-node
to parse the natural language date provided by the user.
Create an Event 🚀
To create an event in calendar, we will need start time, end time, a short summary and location of the event. location
is an optional field.
We will now add a validate method, which validates if the start time and end time is present on the command. You can also validate that start time is always less than end time.
Let's make our cli interactive 🚀
We have http requests to list and create google events. We were just showing a blank screen until http request completes. We will add a spinner to make it more interactive, and to show that http request is processing instead of a blank screen. We will use a package called cli-spinner
.
We can use cli-spinner
as below.
With spinner, list
command looks like below. You can think of other places where you can add spinner.
Package your command line tool 📦
We will first need to add a line as shown below to our index.js
file, this tells the system that node interpreter should be used to run the code.
#!/usr/bin/env node
Now, we will add a bin
section in our package.json
. bin
has a key and a value; which are name of the cli tool and file pointing to source code of cli tool respectively. For us, key is g-event
and value is index.js
.
"bin": {
"ggl-event": "./index.js"
}
To test we can,
- Link it from command line
$ npm link
- Open your cli
$ ggl-event
Publish your cli to npm ✨
To publish your package in npm,
- Create an account in www.npm.org
- Add publishing user,
$ npm adduser
- Publish your package,
$ npm publish
Anybody can easily download your cli 👏
$ npm install -g ggl-event
The completed code lives at https://github.com/Tolsee/gevent
The package is also published to https://www.npmjs.com/package/ggl-event