jmcdo29/nest-commander

Need a way to inject current command (instead of root command)

hungtcs opened this issue · 5 comments

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe it

I noticed that there is a decorator at present named InjectCommander, it can inject the root command object.

But sometimes, some functions requires to get the current command object, command.help() eg. different commands print different content.

Describe the solution you'd like

  • @InjectCurrentCommander()
    or
  • @InjectCommander({ current: true })

Teachability, documentation, adoption, migration strategy

No response

What is the motivation / use case for changing the behavior?

Get current command / sub-command object.

My current solution is

import { Command, CommandRunner, InjectCommander } from 'nest-commander';
import { Command as _Command } from 'commander';

@Command({
  name: 'exec',
  description: '',
})
export class ExecCommand implements CommandRunner {

  constructor(
      @InjectCommander() private readonly commander: _Command) {

  }

  public async run() {
    this.commander.commands.find(command => command.name() === 'exec')?.help();
  }

}

I'll see if I can figure out some sort of way to implement this soon. Thanks for the suggestion

So, generally making the current command injectable is not going to be something that can easily be done. That said, if this is just for getting the help output I can patch in a help method to the class so that this.help() could be called. Though, for that, I think the CommandRunner interface would need to become an abstract class so that the help method does not need to be implemented and it just works. Very ugly kind of solution, but it could be doable. I'll keep thinking if there's a cleaner solution here.

Is the main thing you're wanting to do just to be able to output the help for the command?

@jmcdo29 Yes, for now, I just want to output the help of the current command

I think what I'm going to end up doing is adding a commandInstance property and making CommandRunner an abstract class (breaking change) instead of an intrerface then setting that value from the CommandRunnerService class when creating the command. That way, this.commandInstance now points to the current command. As the commands aren't registered in the DI tree, it won't be possible to do @InjectCommand() or anything like that, but this should be a decent solution instead