Create a Code Generating CLI
Today I would like to walk through the procedure to create a code generating CLI. This is not a step by step tutorial, although we will be looking at the concepts involved.
What is a Code generating CLI, you ask? You might have surely used one in your career, some of the examples being create-react-app, express-generator, vue-cli or the amazing ng-cli.
All of these have a CLI interface that create a fully fledged application with the options passed to it. Today, we look to achieve something similar (but smaller) using the Gluegun CLI building toolkit.
Gluegun defines itself as a delightful toolkit for building Node-powered CLIs. If this is your first time, then you can read on features and why you might want to use it from their docs here. It is used in production by awesome tools like AWS Amplify and Ignite CLI.
What we are going to build
Updated my business card š pic.twitter.com/psqZQ9pj4L
ā Tierney Cyren (@bitandbang)
December 19, 2018
Tierney Cyren had tweeted this and things went out of control very soon with lots and lots of people creating their own cards. (Even I have my own, with npx boywithsilverwings) What we are trying to create today is a CLI to create your own npx card, because why the hell not!
I have a ready made CLI here that you can run with:
Tip: npm allows you to skip the
createpart in your package name withnpm init. For eg.npm init react-app
Recap on EJS
Before we start on Gluegun, we need to take a quick recap of ejs that we will be using for templating.
There is a lot more to it than that, but that is what we will be using for this tutorial.
ejs is not just used for templating HTML strings, it can be used in any environment, it being JSON, Javascript or CSS. This is what we will use to generate our code according to the template.
Getting started with Gluegun
Gluegun comes with a CLI (which Surprise! uses the Gluegun package) that helps us bootstrap a project really fast.
What's inside
src contains all the code that we are going to edit. bin contains the cli file that is the root of the application.
Tip: This currently adds
yarn.lockandpackage.lock.jsonto.gitignoreby default, you might want to remove them.
Let's looks inside the src now.
Commands
The commands folder contain the commands you want the cli app to run. In our example, we will only have a single command, that also corresponds to the name of the app.
The run function actually contains the code that will execute when you type in create-card in the console. Inside, you see that print is taken out of something called the toolbox. What all does this toolbox actually have? Well, a lot of things. We will look at some along the way. What print command does is to print whatever text you give it to the console. There are variety of formats for use, like print.info, print.warning, print.error etc. (just like console, you get the idea)
But you can see that writing all the code inside these run functions can get very tricky. This is where extensions helps with.
Extensions
Extensions are how we can create reusable functions and attach them to the toolbox.
You can now invoke an extension from inside a command like:
Not a fan of this technique, but may be it gets better with types.
Templates
Now, fast forward to the topic. How do we create the files that the user interacts with. That is what the templates folder does. Inside this folder you will find the required files that have an extra extension, .ejs This is what helps us inject user provided content into these files.
Now, all these files may not need content injection, for example .gitignore, but we include the extension so we can replace it by just iterating over all the files.
Here is an example of a file that needs injection:
You can see that this files requires us to fill in the name with props.name where props is supposed to be passed into this function. This is same as the name that the user has already entered with create command. How do we pass this in?
Once this is complete, you will have all the files copied to the directory of preference and ready.
bin/card.js contains the javascript that will be suppled to the user. It uses boxen to draw a box and chalk to output text in colors for the console. It reads user details from config.json and creates console output.
You can find the complete application here for reference.
Feel free to ping me at @agneymenon if you get stuck.