Command-line interfaces (CLI) are powerful tools that can significantly enhance the usability and automation capabilities of your application. By adding a CLI to your TypeScript project, you can provide users with a simple and efficient way to interact with your application through the terminal. In this article, I will guide you through the process of adding a CLI to an existing TypeScript project using the popular commander
library. This article assumes that you have already set up a TypeScript project with testing using Jest.
If you run into EACCES permission errors I recommend reading this article about how to solve it.
Table of Contents
- Introduction to Commander
- Installing Commander
- Creating the CLI Entry Point
- Defining Commands and Options
- Building and Distributing Your CLI
- Conclusion
Introduction to Commander
Commander.js is a lightweight, expressive, and versatile library for building command-line interfaces in Node.js. It provides a comprehensive set of features, including:
- Command and option parsing
- Automated help generation
- Nested subcommands
- Customizable error handling
By leveraging Commander, you can quickly develop a robust and user-friendly CLI for your TypeScript project.
Installing Commander
To get started, you need to install Commander. Open your terminal and navigate to your project directory, then run the following command:
# Use 'sudo' keyword if necessary
npm install commander
Creating the CLI Entry Point
In your src
folder, create a new file called cli.ts
. This file will serve as the entry point for your CLI. Here is a basic example:
#!/usr/bin/env node
import { program } from 'commander';
program
.description('My TypeScript CLI');
program.parse(process.argv);
This script sets up the basic structure of your CLI, including a description. The #!/usr/bin/env node
shebang line at the top allows the script to be executed as a standalone executable.
Defining Commands and Options
Next, you will define the commands and options for your CLI. Since this CLI was created for an existing TypeScript project let’s import your functions. In the below example I’m importing addNewItem and throttle. Complete example is shared in my GitHub:
import { program } from 'commander';
import { addNewItem, throttle } from './script';
program
.command('add <item>')
.description('Add item')
.action((item: string) => {
// Initialize array
let array: string[] = [];
//Define throttle function
const throttledAddNewItem = throttle(() => {addNewItem(array, item); console.log(array);}, 1000);
// Simulate rapid calls
throttledAddNewItem();
throttledAddNewItem();
throttledAddNewItem();
});
program.parse(process.argv);
Building and Distributing Your CLI
To make your CLI executable, you need to compile your TypeScript code to JavaScript. If necessary update your tsconfig.json
to include the src directory where your cli.ts lives:
{
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"module": "commonjs",
"target": "es6",
"strict": true
},
"include": [
"src/**/*",
],
"exclude": [
"node_modules",
"dist"
]
}
Then, add a build script to your package.json
:
"scripts": {
"cli": "node dist/cli.js"
}
Compile your code with TypeScript compiler:
tsc src/cli.ts --outDir dist
Then, link your package globally:
npm link
You can now run your CLI commands from anywhere using the npm run cli
command.
Conclusion
Adding a CLI to your existing TypeScript project using Commander is a straightforward process that can significantly enhance the usability of your application. By following the steps outlined in this article, you can create a robust and user-friendly CLI that allows users to interact with your application through the terminal. Remember to write tests to ensure the reliability of your CLI commands and consider distributing your CLI as a global npm package for broader accessibility. Happy coding!