Maximize your business success with our software outsourcing services.
Elevate efficiency, reduce costs, and accelerate innovation with Your Team in India.
Command-Line Interfaces or also known as CLIs (build in Node.js), gives developers a chance to automate all mundane tasks, and that too while leveraging the humongous Node.js ecosystem. The credit even goes to the package managers like yarn and npm, which helps CLI gets distributed and be used on different platforms seamlessly.
Why Create CLI with Node.js?
One of the most prominent reasons to use Node.js to create CLIs is its rich package ecosystem with more than 1.3 million packages in the npm registry. (Source) Just imagine how gigantic is the ecosystem that developers are stepping into with Node.js.
This article is all about why a software developer would want to write a CLI, use Node.js for it, and distribute it without interruption.
Prerequisites
There are certain prerequisites to create CLI, so make sure you have them before you begin:
- The latest version of Node.JS installed
- A text editor
Recommended Read: How To Build CMS Using NodeJS
Let’s Set Up the Project Now
Here, we will be doing a setup of a basic Node.js project. Follow these steps for the same:
- Open Terminal
- Create a folder for the project
~$mkdir termTranslate
- Navigate to it.
~$cd termTranslate
- Now, initialize a Node.js project in this newly created folder.
~$npm init
- Fill in the prompt, and your project is all set up now.
Now, Let’s Build the Basic CLI
Once the last step is done, and we have actually created the node project, it is time now to move to make the CLI. What you need to do is right here:
- Create a folder named ‘bin’ in the project’s root directory created in the step above.
- Now, inside the bin folder, you need to create an index.js file that will act as the entry point of your new CLI.
- In this step, you will have to open the package. json file to further modify the main part to bin/index.js.
- Lastly, you will have to add another entity manually into the package.json file named bin. Set its key to tran and the value to ./bin/index.js. Here is what it must look like now:
"bin": {
"tran": "./bin/index.js"
}
So, the key, tran that we set in the step above, will act as the keyword for calling the CLI. People will type this keyword in the terminal using the CLI. Besides, you can always choose the name for your choice; however, keeping it simple, short, and semantic is important to type and remember it easily. Also, you can change this name anytime you want.
Know about the Growing Nodejs Development Trends here.
Now, after following all the steps, here is how your package.json file will look like:
{
"name": "termtran",
"version": "1.0.0",
"description": "A CLI to translate between languages in the terminal",
"main": "bin/index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [
"cli"
],
"bin": {
"tran": "./bin/index.js"
},
"author": "Your Name",
"license": "ISC"
}
Now, open the index.js file in the bin folder and use the following code in it:
#! /usr/bin/env node
console.log("Hello World!");
In this code, the #! Is known as the shebang line, which specifies the absolute path to the interpreter, which will help run the code.
After that, we will install the CLI and test it as well. For people to call CLI anywhere, we need to install it globally. Navigate to the root directory and then run the following code:
~$npm install -g
The -g flag will signal npm to install it in the system globally, and CLI can be tested by typing a keyword in the terminal.
~$tran
So, if you have been following everything correctly, you will see a message that we console.logged in the index.js file.
Command Line Arguments Handling
We have prepared our CLI, and we will add other functionalities in the same. Also, the basic task for any CLI is to handle the command-line arguments. So, we will receive the language name in our CLI and the sentence that we need to translate. After that, we will parse it.
We will use an npm package ‘yargs’ which is specially made for CLI creation. It will simplify the entire process of parsing the arguments and will help us manage and organize the command line flags.
- Start by installing yargs
~$npm i yargs
- Include the module in index.js
~$const yargs = require("yargs");
- Now we will create the options object that includes all your command line flags
const usage = "\nUsage: tran <lang_name> sentence to be translated";const options = yargs
.usage(usage)
.option("l", {alias:"languages", describe: "List all supported languages.", type: "boolean",
demandOption
: false })
.help(true)
.argv;
In the code given above, we defined an option -I which will print every supported languages when passed by the API. Yargs helps us with --version and --help flags by default.
Now, We Will Add Utility Functions
~$tran lang_name the sentence to be translated
Now, we will need to parse the arguments. So, here’s what we need to do:
- Create another file named utils.js in bin folder
- Include this file in your index.js
const utils = require('./utils.js')
- Here, we create the function to parse the sentence. We will write the function in util.js before finally exporting it.
module.exports = { parseSentence: parseSentence };function parseSentence(words) { var sentence = "";
for(var i = 1; i < words.length; i++) {
sentence = sentence + words[i] + " ";
}
Now, call it in index.js
var sentence = utils.parseSentence(yargs.argv._);
Read our other post on Nodejs Advantages.
- In this step, we will create a function to help when we don’t pass any argument. The function will be created in utils.js.
module.exports = { showHelp: showHelp, parseSentence: parseSentence };const usage = "\nUsage: tran <lang_name
> sentence to be translated";
function showHelp() {
console.log(usage);
console.log('\nOptions:\r')
console.log('\t--version\t ' + 'Show version number.' + '\t\t' + '[boolean]\r')
console.log(' -l, --languages\t' + ' ' + 'List all languages.' + '\t\t' + '[boolean]\r')
console.log('\t--help\t\t ' + 'Show help.' + '\t\t\t' + '[boolean]\n')
}
Now, call it in index.js
if(yargs.argv._[0] == null){
utils.showHelp();
return;
}
- Once that is done, you will see all supported languages right on the screen.
module.exports = { showAll: showAll, showHelp: showHelp, parseSentence: parseSentence};
function showAll(){
console.log(chalk.magenta.bold("\nLanguage Name\t\tISO-639-1 Code\n"))
for(let [key, value] of languages) {
console.log(key + "\\t\\t" + value + "\\n")
}
}
let languages = new Map();
languages.set('afrikaans', 'af')
languages.set('albanian', 'sq')
languages.set('amharic', 'am')
languages.set('arabic', 'ar')
languages.set('armenian', 'hy')
languages.set('azerbaijani', 'az')
languages.set('basque', 'eu')
languages.set('belarusian', 'be')
languages.set('bengali', 'bn')
languages.set('bosnian', 'bs')
languages.set('bulgarian', 'bg')
languages.set('catalan', 'ca')
languages.set('cebuano', 'ceb')
languages.set('chinese', 'zh')
languages.set('corsican', 'co')
languages.set('croatian', 'hr')
languages.set('czech', 'cs')
languages.set('danish', 'da')
languages.set('dutch', 'nl')
languages.set('english', 'en')
languages.set('esperanto', 'eo')
languages.set('estonian', 'et')
languages.set('finnish', 'fi')
languages.set('french', 'fr')
languages.set('frisian', 'fy')
languages.set('galician', 'gl')
languages.set('georgian', 'ka')
languages.set('german', 'de')
languages.set('greek', 'el')
languages.set('gujarati', 'gu')
languages.set('haitian creole', 'ht')
languages.set('hausa', 'ha')
languages.set('hawaiian', 'haw') // (iso-639-2)
languages.set('hebrew', 'he') //or iw
languages.set('hindi', 'hi')
languages.set('hmong', 'hmn') //(iso-639-2)
languages.set('hungarian', 'hu')
languages.set('icelandic', 'is')
languages.set('igbo', 'ig')
languages.set('indonesian', 'id')
languages.set('irish', 'ga')
languages.set('italian', 'it')
languages.set('japanese', 'ja')
languages.set('javanese', 'jv')
languages.set('kannada', 'kn')
languages.set('kazakh', 'kk')
languages.set('khmer', 'km')
languages.set('kinyarwanda', 'rw')
languages.set('korean', 'ko')
languages.set('kurdish', 'ku')
languages.set('kyrgyz', 'ky')
languages.set('lao', 'lo')
languages.set('latin', 'la')
languages.set('latvian', 'lv')
languages.set('lithuanian', 'lt')
languages.set('luxembourgish', 'lb')
languages.set('macedonian', 'mk')
languages.set('malagasy', 'mg')
languages.set('malay', 'ms')
languages.set('malayalam', 'ml')
languages.set('maltese', 'mt')
languages.set('maori', 'mi')
languages.set('marathi', 'mr')
languages.set('mongolian', 'mn')
languages.set('burmese', 'my')
languages.set('nepali', 'ne')
languages.set('norwegian', 'no')
languages.set('nyanja', 'ny')
languages.set('odia', 'or')
languages.set('pashto', 'ps')
languages.set('persian', 'fa')
languages.set('polish', 'pl')
languages.set('portuguese', 'pt')
languages.set('punjabi', 'pa')
languages.set('romanian', 'ro')
languages.set('russian', 'ru')
languages.set('samoan', 'sm')
languages.set('scots', 'gd')//gd gaelic
languages.set('serbian', 'sr')
languages.set('sesotho', 'st')
languages.set('shona', 'sn')
languages.set('sindhi', 'sd')
languages.set('sinhalese', 'si')
languages.set('slovak', 'sk')
languages.set('slovenian', 'sl')
languages.set('somali', 'so')
languages.set('spanish', 'es')
languages.set('sundanese', 'su')
languages.set('swahili', 'sw')
languages.set('swedish', 'sv')
languages.set('tagalog', 'tl')
languages.set('tajik', 'tg')
languages.set('tamil', 'ta')
languages.set('tatar', 'tt')
languages.set('telugu', 'te')
languages.set('thai', 'th')
languages.set('turkish', 'tr')
languages.set('turkmen', 'tk')
languages.set('ukrainian', 'uk')
languages.set('urdu', 'ur')
languages.set('uyghur', 'ug')
languages.set('uzbek', 'uz')
languages.set('vietnamese', 'vi')
languages.set('welsh', 'cy')
languages.set('xhosa', 'xh')
languages.set('yiddish', 'yi')
languages.set('yoruba', 'yo')
languages.set('zulu', 'zu')
So, right there, we have created a hash map for all the languages to their code. There are two reasons behind doing that - one it will help in displaying all the languages as and when needed. And, secondly, we must know that API only takes language code into consideration, which means it will display the language even if a wrong language name is entered.
Now we will have to call the showAll() function in your index.js file if the languages flag is true.
if(yargs.argv.l == true || yargs.argv.languages == true){
utils.showAll();
return;
}
- Now, we will write the function.
module.exports = { parseLanguage: parseLanguage, showAll: showAll, showHelp: showHelp, parseSentence: parseSent
ence };
function parseLanguage (language) {
if(language.length == 2){
return language;
}
if(languages.has(language)){
return languages.get(language)
}
else {
console.error("Language not supported!")
return; //returning null if the language is unsupported.
}
};
After that, we will convert the language to lower case before calling the function in index.js.
if(yargs.argv._[0])
var language = yargs.argv._[0].toLowerCase(); // stores the language.
//parsing the language specified to the ISO-639-1 code.
language = utils.parseLanguage(language);
- Include the API at top of your index.js and check if sentence is empty. If it not empty then we will send it to the API.
const translate = require('[@vitalets/google-translate-api](http://twitter.com/vitalets/google-translate-api)')
;if(sentence == ""){
console.error("\nThe entered sentence is like John Cena, I can't see it!\n")
console.log("Enter tran --help to get started.\n")
return;
}translate(sentence, {to: language}).then(res => {console.log("\n" + "\n" + res.text + "\n" + "\n";}).catch
(err => {
console.error(err);
});
We have completed the CLI now. Finally, if you want you can also use chalk and boxen to decorate or enhance the errors and output with colors and boxes.
Conclusion
Hope this guide helped you learn how to create CLI in Node.js. This was a fully portable CLI and you can easily prepare it using these steps mentioned above. So, go ahead and try it yourself now! Happy coding!!
Stop Wasting Time and Resources on Slow, Unscalable Applications. Partner with Our Node.js Development company in India and Build High-Performance, Real-Time Web Apps That Can Adapt to Your Growing Needs.