Skip to content

Question: proper way for cloning a command #2370

@mdrozdovz

Description

@mdrozdovz

Hello, it's a bit unusual request since lib is intended for one-shot execution.
However, I have some functionality where I'd like to re-use existing commands during app lifetime. Basically, exposing a remote code execution interface for internal use.

In order to avoid duplication, here's the snippet I use for cloning recursively:

const cloneCommand = (cmd) => {
    const clone = new Command()
        .copyInheritedSettings(cmd)
        .name(cmd.name())

    if (cmd.description()) clone.description(cmd.description())
    if (cmd.version()) clone.version(cmd.version())
    if (cmd.alias()) clone.alias(cmd.alias())

    cmd.registeredArguments.forEach(clone.addArgument.bind(clone))
    cmd.options.filter(o => !['version'].includes(o.name())).forEach(clone.addOption.bind(clone))
    cmd.commands.forEach(c => clone.addCommand(cloneCommand(c)))

    clone._actionHandler = cmd._actionHandler
    clone._optionValueSources = cmd._optionValueSources

    return clone
}

and a bit of cleaning up after cloning:

const executable = cloneCommand(program)
        .showHelpAfterError(true)
        .showSuggestionAfterError(true)
executable._lifeCycleHooks = {}

Usage:

executable.exitOverride(err => { ... })
executable.configureOutput({ ... })
await executable.parseAsync(args, { from: 'user' })

This however, doesn't parse options properly and they remain set to default values (or undefined). Works good for arguments though.

So the question is: what am I doing wrong during cloning or what am I missing? Any better way or plans to add cloning support out-of-the-box?

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions