Optimizing Nest-Commander: User Inputs
Tags: nestjs, node, devops
Published: 2023-09-26 18:19:03

---
title: Optimizing Nest-Commander: User Inputs
published: true
date: 2023-09-26 14:57:47 UTC
description: Learn how to boost the functionality of your Nest-Commander application by incorporating user inputs effectively.
tags:
  - NestJS
  - NodeJS
  - DevOps
canonical_url: https://thebenforce.com/post/optimizing-nest-commander-user-inputs/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xiy9ctuz6dnje2rq4nik.png
---

In my [previous article](https://dev.to/thebenforce/how-to-make-a-cli-app-with-nestjs-step-by-step-30fm), you created a NestJS CLI application. It was a very basic starting point that printed a cow saying a static message in the console.

But what if your users demand the ability to display custom messages? That's what you're going to add in this article. The new and improved application will display the same message by default, or any string that you pass in with the `--message` argument.

## Adding a Message Option

The easiest way to add an option is to add a parser function for a parameter and add the `@Option` decorator to it.

In the `cow-say.command.ts` file, add the following method to your `CowSayCommand` class.

```typescript
@Option({
  flags: '--message <message>',
  description: 'The message we want to see the cow say',
})
parseMessage(value: string) {
  return value;
}
```

### Decorating It

If you've used the commander library before, this should look familiar. The `<message>` tells commander that if the `--message` option is provided, the user doesn't need to provide a parameter after it. If the value was required it would be `[message]` instead.

The `description` parameter is used when the user displays help for a specific command. The description will be displayed in a column to the right of every available option.

### The Parser

The `@Option` decorator is applied to a parser function, in this case `parseMessage`. The function takes in a string and needs to convert it to whatever type you'll want at runtime. If you had a `--count <count>` parameter, you'd need to convert a string to an integer.

Since the message should be a string, you just need to return it. Nothing fancy here.

### Using the Options

To use the option, you need to accept two parameters in the `run` method. The first is an array of parameters that were passed in, and the second is an options object that includes all of the parsed options. Since you aren't using the parameters you can just ignore it.

```typescript
async run(_passedParams: string[], options: { message?: string }): Promise<void> {
  const message = options.message ?? 'Hello World!';

  console.log(cowsay.say({ text: message }));
}
```

Awesome, now if you run the program with a `--message "Foo Bar"` parameter, the cow will be saying "Foo Bar".

## Using Inquirer

Using parsers like in the previous step works great for smaller commands. It has the advantage of being simple. But what if you would like to gracefully ask the user to enter any parameters they forgot to provide? For that, you can use the `InquirerService`.

The first thing you need to do is define the types of inputs that will be used for each parameter. That's done with a class decorated with `@QuestionSet` and parsing methods decorated with `@Question`.

Create a `cow-say.questions.ts` file and add the following to it.

```typescript
import { Question, QuestionSet } from 'nest-commander';

@QuestionSet({
  name: 'cowSay',
})
export class CowSayQuestions {
  @Question({
    type: 'input',
    name: 'message',
    message: 'What does the cow say?',
  })
  parseMessage(value: string) {
    return value;
  }
}
```

Now add this class as a provider to your module.

```typescript
...
import { CowSayQuestions } from './cow-say.questions';

@Module({
  providers: [CowSayCommand, CowSayQuestions],
})
export class CowSayModule {}
```

Now the `message` parameter needs to be updated to be mandatory in the command.

```typescript
@Option({
    flags: '--message [message]',
    description: 'The message we want to see the cow say',
  })
```

Next, inject the inquirer service into the command.

```typescript
constructor(private readonly inquiererService: InquirerService) {
  super();
}
```

*Finally*, update the `run` method and use the inquirer service to update the options parameter.

```typescript
options = await this.inquiererService.ask('cowSay', options);

console.log(cowsay.say({ text: options.message }));
```

Now, when you run the command if you don't pass in the `--message` option the application will ask you to provide it.

```typescript
❯ npm run start:cli   

> my-cli-project@0.0.1 start:cli
> ts-node src/main.ts

? What does the cow say? Mooooooo
 __________
< Mooooooo >
 ----------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```

## Summary

In this article, you expanded upon the basic NestJS CLI application created in the previous installment. You learned how to add arguments with an option parser function and used the `@Option` decorator. You also learned how to use the `InquirerService` to gracefully prompt users to enter missing parameters and integrated it into your command, enhancing user interaction.