vilicvane / clime

⌨ The command-line interface framework for TypeScript.
252 stars 10 forks source link

Allow passing commands directly when creating a CLI #43

Open MartinJohns opened 6 years ago

MartinJohns commented 6 years ago

Hey ho,

I like your library, but something I'd like over the file-structured based hierarchy is if I could define the architecture myself when creating an instance of CLI. This would also be a workaround for #41 as there's no need for a pre-compiled file.

I'd propose an overload for CLI or a new type like InMemoryCLI that accepts the following data structure as the second argument:

interface CommandMap { readonly [commandName: string]: CommandClass | CommandMap; }

To give an example, here's your structure from the "subcommands" section in the README:

command

command foo
command foo biu
command foo yo

command bar
command bar bia
command bar pia

//

- commands
  - default.ts
  - foo.ts
  - foo
    - biu.ts
    - yo.ts
  - bar
    - default.ts
    - bia.ts
    - pia.ts

And with my proposed functionality:

import { DefaultCommand } from './commands/default';
import { FooDefaultCommand } from './commands/foo/default';
import { FooBiuCommand } from './commands/foo/biu';
import { FooYoCommand } from './commands/foo/yo';
import { BarDefaultCommand } from './commands/bar/default';
import { BarBiaCommand } from './commands/bar/bia';
import { BarPiaCommand } from './commands/bar/pia';

const cli = new CLI(
    'name',
    {
        default: DefaultCommand,
        foo: {
            default: FooDefaultCommand,
            biu: FooBiuCommand,
            yo: FooYoCommand
        },
        bar: {
            default: BarDefaultCommand,
            bia: BarBiaCommand,
            pia: BarPiaCommand
        }
    });

Or alternatively, you could create an index.ts in ever sub-commands folder, e.g. for commands/foo/index.ts:

import { DefaultCommand } from './default';
import { BiuCommand } from './biu';
import { YoCommand } from './yo';

export default {
    default: DefaultCommand,
    biu: BiuCommand,
    yo: YoCommand
};

And when importing:

import FooCommands from './commands/foo';

new CLI('name', { foo: FooCommands });
vilicvane commented 6 years ago

Hi, thanks for this suggestion. There is some performance concern over large command bundle, but I think there would be easy fixes like dynamic import.

dejitaiza commented 6 years ago

Hey, I am interested to implement this feature, as I am needing it myself. Would a PR be welcome @vilic ?

vilicvane commented 6 years ago

@dejitaiza Hi, absolutely yes. But please also add related tests.