CLI Tool
This explains how the CLI tool was built and the concepts on which it is based. Our focus was on making the tool user-friendly.
We used
and
to develop the tool.
We chose these languages because we have already learned them, and other CLI tools are built with them as well.
These ecosystems also have a lot of support. We didn't want to figure it out on our own because that would have taken a lot of time. We wanted to use that time to develop a tool.
Dependencies
In this section, we will show you the dependencies we used to build our CLI.
Commander
We used a library called "Commander" to build the CLI tool. This library provides all the features we need. We can configure commands, use TypeScript, and much more.
Inquirer
We used "Inquirer" for an interactive command-line interface (CLI). For example, we built an interact command helper for when a user misspells a command.
For instance, if you misspell "check" and write "ceck" instead:
Chalk
"Chalk" is a widely used library for working with colors in the terminal. It is easy to use. In the image above, we used Chalk to highlight the misspelled command in yellow.
It natively combines with other tools, like Inquirer, and is easy to use. You can use Chalk literally anywhere in the CLI.
Ora
"ora" is a library used for loaders and spinners. It gives the CLI a special touch and also helps improve the user experience.
Figlet
We used "Figlet" for the NDM banner in the ndm info command. It's much easier to use this library than to build it yourself.
ConfigStore
"configstore" is a library used for configuration. We use it to manage and store the configuration for the server address.
Folder structure
We use an easy-to-understand folder structure for the CLI tool. The following graph shows where the most important files are located:
.github/
src/
├─ commands/
│ ├─ check.ts
│ ├─ info.ts
│ ├─ analyze.ts
│ └─ ...
├─ utils/
│ ├─ banner.ts
│ ├─ config.ts
│ └─ checks/
│ ├─ calcHealthScore.ts
│ ├─ calculateRiskScore.ts
│ └─ ...
└─ index.ts
test/
├─ example.test.ts
└─ utils/
├─ checks.test.ts
├─ checks2.test.ts
└─ ...
We saved all the commands in the commands folder. We imported them into the index.ts file for better organization.
import { Command } from "commander";
import { infoCommand } from "./commands/info";
...
async function main() {
const program = new Command();
program
.name("ndm")
.description(
"NDM CLI Tool – Node Dependency Monitor -understand how packages work.",
)
.version("0.1.0");
//Register of Commands:
program.addCommand(infoCommand); // It is so easy to add a command
...
}
main();
We saved all the larger sub-functions of the actual commands in the utils folder. For example, there is a file called askForPackageName.ts because we ask for the package name in both check and analyze.
UX
For the user experience, we used colors so that you can easily read the text and extract the important information. We also used bars to show the health and risk scores.
...
Overall Risk Score:
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/100 // in the ClI in red
...
Overall Health Score:
██████████████████████████░░░░ 85/100 // in the ClI in green
We used loaders to show users that NDM is loading. The "check" command also tells the user what NDM is currently working on while loading.
Development Tools
To keep the NDM codebase clean, maintainable, and consistent across all contributors, we use several development tools that automatically enforce coding standards and quality checks.
Additionally, GitHub Actions are used to validate every pull request targeting the main branch.
This ensures that all code follows the project's formatting and quality requirements before it can be merged.
Linter
We use Oxlint as our linter. It is part of the Oxc ecosystem and was chosen because of its exceptional performance and modern TypeScript support. Since Oxlint is written in Rust, it is significantly faster than many traditional JavaScript-based linters while still providing high quality diagnostics.
A linter helps us identify potential problems before they reach production, including:
- Possible programming mistakes
- Suspicious or error-prone code patterns
- Unused variables and imports
- Violations of project coding standards
- Maintainability and readability issues
Every pull request is automatically checked with Oxlint through GitHub Actions. A pull request cannot be merged if linting errors are detected.
Developers can run the linter with:
pnpm lint
Formatter
We use Prettier as our code formatter. It is one of the most widely adopted formatting tools in the JavaScript and TypeScript ecosystem and provides a consistent code style with almost no configuration.
The main benefits of using Prettier are:
- Consistent formatting across the entire project
- Improved code readability
- Reduced discussions about code style
- Easier code reviews
- Better collaboration between contributors
Every pull request is automatically checked with Prettier through GitHub Actions. A pull request cannot be merged if formatting errors are detected.
Developers can format the entire project locally using:
pnpm format