jmcdo29 / nest-commander

A module for using NestJS to build up CLI applications

Home Page:https://nest-commander.jaymcdoniel.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to use @RequestModule()

aryagelato opened this issue · comments

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

I was trying to import a service into the command by Dependency Injection but it gives me an error:

ERROR [CommandRunnerService] A service tried to call a property of "undefined" in the EcomProductEventsHandleCommand class. Did you use a request scoped provider without the @RequestModule() decorator?

I have checked your documentation and there is no example of it!

Minimum reproduction code

import { Command, CommandRunner, Option } from 'nest-commander';
import { Logger } from '../../common/logger/logger.service';
import { PriceRmqHandlerService } from '../services/price-rmq-handler.service';

interface CommandOptions {
  data?: string;
}

@Command({ name: 'ecom-product-events-handle', description: 'Handling product events from shared bus' })
export class EcomProductEventsHandleCommand extends CommandRunner {
  constructor(
    private readonly logger: Logger,
    private readonly priceRmqHandlerService: PriceRmqHandlerService,
    ) {
    super()
  }

  async run(inputs: string[], options?: CommandOptions): Promise<void> {
    if (options?.data) {
      this.runWithData(inputs, options?.data);
    } else {
      this.runWithNone()
    }
    process.exit(0)
  }

  @Option({
    flags: '-d, --data json',
    description: 'A JSON data parser',
  })
  parseJson(val: string): Object {
    return JSON.parse(val);
  }

  runWithData(param: string[], option: string): void {
    console.log("Running with data...")
  }

  runWithNone(): void {
    console.log("Running...")
  }
}

Expected behavior

because we are importing the main module in main-cli.ts like this:

async function bootstrap() {
  await CommandFactory.run(AppModule, ['warn', 'error']);
}

should do the DI automatically!

Package

  • nest-commander
  • nest-commander-schematics
  • nest-commander-testing

Package version

3.11.0

Node.js version

16

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

There is documentation for it. And here's the API docs too

More than likely, one of the providers you are injecting is REQUEST scoped, which is what caused the error to trigger. If I had to guess without a reproduction, I would say it's the logger.

There is documentation for it. And here's the API docs too

I created the module for the command and imported it into the AppModule like this:

@RequestModule({
    imports: [SharedModule],
    providers: [
        EcomProductEventsHandleCommand,
        Logger,
        PriceRmqHandlerService
    ],
    requestObject: { headers: { Authorization: 'Bearer token' } }
  })
  export class PriceCommandModule {}

but still, it's giving me the same error

StackBlitz

Sure! Here we go. you can run it like this npm run command-nest:dev ecom-product-events-handle

https://stackblitz.com/edit/nestjs-typescript-starter-cvtmuu

Explicitly setting the scope to Scope.REQUEST messes up the possibility of using the @RequestModule() due to how Nest then treats the provider. What @RequestModule() is doing is creating a local REQUEST provider that is explicitly Scope.DEFAULT so that Nest's automatic resolution of REQUEST goes to the local definition and it becomes default scoped. But if the @Injectable({ scope: Scope.REQUEST }) is set, then that provider will always be REQUEST scoped, even if none of the providers inside of it are, which causes the error to come forth. Remove that setting in your RequestService and everything should work