0.2.41 • Published 2 years ago

@anchan828/nest-commands v0.2.41

Weekly downloads
245
License
MIT
Repository
github
Last release
2 years ago

@anchan828/nest-commands

Make command line tools based on yargs.

$ nest-commands-example --help
nest-commands-example <command>

Commands:
  nest-commands-example author  Show author information
  nest-commands-example file    Show file information

Options:
  --help     Show help                           [boolean]
  --version  Show version number                 [boolean]

Install

$ npm i @anchan828/nest-commands
$ npm i --save-dev @types/yargs

Usage

cli.ts

import { Commander, Command, CommandModule, CommandService } from "@anchan828/nest-commands";

@Commander()
class TestCommander {
  @Command({ name: "basic" })
  public basic() {
    console.log("hello!");
  }
}

@Module({
  imports: [CommandModule.register()],
  providers: [TestCommander],
})
class TestAppModule {}

(async () => {
  const app = await NestFactory.createApplicationContext(TestAppModule, { logger: false });
  app.get(CommandService).exec();
})();
$ ts-node cli.ts basic
hello!

CommandModule.register

You can set some options

CommandModule.register({
   /**
   * Set to yargs.scriptName
   *
   * @type {string}
   * @memberof CommandModuleOptions
   */
  scriptName?: string;

  /**
   * Set to yargs.usage
   *
   * @type {string}
   * @memberof CommandModuleOptions
   */
  usage?: string;

  /**
   * Set to yargs.locale
   *
   * @type {string}
   * @memberof CommandModuleOptions
   */
  locale?: string;
})

Nested command

If you want to use nested command, add name to commander.

@Commander({ name: "nested" })
class TestCommander {
  @Command({ name: "command1" })
  public command1(): void {
    console.log("Run nested command1");
  }

  @Command({ name: "command2" })
  public command2(): void {
    console.log("Run nested command2");
  }
}

Global options

You can set options to top level. Use @CommanderOption and no set commander name

@Commander()
class GlobalOptions {
  @CommanderOption({
    description: "Output as json",
    name: "json",
    type: "boolean",
  })
  public json!: boolean;
}

positional and option

@Commander()
class TestCommander {
  // See: https://github.com/yargs/yargs#complex-example
  @Command({ describe: "start the server", name: "serve" })
  public serve(
    @CommandPositional({
      default: 5000,
      describe: "port to bind on",
      name: "port",
    })
    port: number,
    @CommandOption({
      alias: "v",
      default: false,
      description: "Run with verbose logging",
      name: "verbose",
      type: "boolean",
    })
    verbose: boolean,
  ): void {
    console.log(`port is ${port}`);
    console.log(`verbose is ${verbose}`);
  }
}

Array positional

If you want to array positional, add .. at the end.

@Commander()
class TestCommander {
  @Command({ describe: "array positional", name: "list" })
  public serve(
    @CommandPositional({
      describe: "show files",
      name: "files..",
    })
    files: string[],
  ): void {
    console.log("Run array positional command");
    console.log(files);
  }
}

Pipe

@Injectable()
class StringPipe implements PipeTransform<string, string> {
  transform(value: string): string {
    return `updated ${value}`;
  }
}

@Commander()
class TestCommander {
  @Command({ describe: "start the server", name: "serve" })
  public serve(): void {
    // token is 'updated token'
    console.log(`token is '${this.token}'`);
  }

  @CommanderOption({ demandOption: true, name: "token", type: "string" }, StringPipe)
  public token!: string;
}

Load config file (cosmiconfig)

You can load config file from user project.

If you want to load config, set configName. Then CLI will search and load them

  • A {configName} property in a package.json file.
  • A .{configName}rc file with JSON or YAML syntax.
  • A .{configName}rc.json file.
  • A .{configName}rc.yaml, .{configName}rc.yml, or .{configName}rc.js file.
  • A {configName}.config.js JS file exporting the object.

Please see cosmiconfig about more details

Also, You can add custom config filename

@Module({
  imports: [
    CommandModule.register({
      configName: "nest-commands",
      searchPlaces: ["custom-config-name.json"],
    }),
  ],
  providers: [TestCommander],
})
class TestAppModule {}

Customize config object

You can customize config after loading it.

@Module({
  imports: [
    CommandModule.register({
      config: {
        name: "nest-commands",
        processor: async (config: TestConfig): Promise<TestConfig> => {
          if (config.date === "today") {
            config.date = new Date().toDateString();
          }
          return config;
        },
      },
    }),
  ],
  providers: [TestCommander],
})
class TestAppModule {}

Also, you can use decorators!

@GlobalConfig({ name: "nest-commands", searchPlaces: ["custom-config-name.json"] })
class TestGlobalConfig {
  @GlobalConfigProcessor()
  public async processor(config: TestConfig): Promise<TestConfig> {
    if (config.date === "today") {
      config.date = new Date().toDateString();
    }
    return config;
  }
}

@Module({
  imports: [CommandModule.register()],
  providers: [TestCommander, TestGlobalConfig],
})
class TestAppModule {}

Example

You can try to run command!

npx ts-node -T ./examples/basic.ts basic --help
npx ts-node -T ./examples/nested-commands.ts nested show --help
npx ts-node -T ./examples/positional-and-option.ts serve --help
npx ts-node -T ./examples/many-modules.ts --help
npx ts-node -T ./examples/many-modules.ts user show
npx ts-node -T ./examples/array-positional.ts list test1 test2
npx ts-node -T ./examples/merge-commanders merge --help
npx ts-node -T ./examples/commander-option.ts --token token serve
npx ts-node -T ./examples/global-options.ts --json test show
npx ts-node -T ./examples/use-pipes.ts --token token serve
npx ts-node -T ./examples/config.ts test
npx ts-node -T ./examples/config.processor.ts test

Tips

You can create single executable file using ncc / pkg / nexe.

See: @anchan828/nest-commands-example

0.2.41

2 years ago

0.2.40

2 years ago

0.2.39

2 years ago

0.2.38

2 years ago

0.2.37

2 years ago

0.2.36

2 years ago

0.2.35

2 years ago

0.2.27

2 years ago

0.2.26

2 years ago

0.2.25

2 years ago

0.2.24

2 years ago

0.2.23

2 years ago

0.2.30

2 years ago

0.2.34

2 years ago

0.2.33

2 years ago

0.2.32

2 years ago

0.2.31

2 years ago

0.2.29

2 years ago

0.2.28

2 years ago

0.2.22

2 years ago

0.2.21

2 years ago

0.2.20

2 years ago

0.2.19

2 years ago

0.2.18

3 years ago

0.2.17

3 years ago

0.2.16

3 years ago

0.2.15

3 years ago

0.2.14

3 years ago

0.2.13

3 years ago

0.2.12

3 years ago

0.2.11

3 years ago

0.2.10

3 years ago

0.2.9

3 years ago

0.2.8

3 years ago

0.2.7

3 years ago

0.2.6

3 years ago

0.2.5

3 years ago

0.2.4

3 years ago

0.2.3

3 years ago

0.2.2

3 years ago

0.2.1

3 years ago

0.2.0

3 years ago

0.1.79

3 years ago

0.1.78

3 years ago

0.1.77

3 years ago

0.1.76

3 years ago

0.1.75

3 years ago

0.1.74

3 years ago

0.1.72

3 years ago

0.1.73

3 years ago

0.1.70

3 years ago

0.1.71

3 years ago

0.1.69

3 years ago

0.1.68

3 years ago

0.1.67

3 years ago

0.1.66

3 years ago

0.1.65

3 years ago

0.1.64

3 years ago

0.1.63

3 years ago

0.1.62

3 years ago

0.1.61

3 years ago

0.1.60

3 years ago

0.1.59

3 years ago

0.1.58

3 years ago

0.1.57

3 years ago

0.1.56

3 years ago

0.1.55

3 years ago

0.1.54

3 years ago

0.1.53

3 years ago

0.1.52

3 years ago

0.1.51

3 years ago

0.1.50

3 years ago

0.1.49

3 years ago

0.1.48

3 years ago

0.1.47

3 years ago

0.1.46

3 years ago

0.1.45

3 years ago

0.1.44

4 years ago

0.1.43

4 years ago

0.1.42

4 years ago

0.1.41

4 years ago

0.1.40

4 years ago

0.1.39

4 years ago

0.1.38

4 years ago

0.1.37

4 years ago

0.1.36

4 years ago

0.1.35

4 years ago

0.1.34

4 years ago

0.1.33

4 years ago

0.1.32

4 years ago

0.1.31

4 years ago

0.1.30

4 years ago

0.1.29

4 years ago

0.1.28

4 years ago

0.1.27

4 years ago

0.1.26

4 years ago

0.1.25

4 years ago

0.1.24

4 years ago

0.1.23

4 years ago

0.1.22

4 years ago

0.1.21

4 years ago

0.1.20

4 years ago

0.1.19

4 years ago

0.1.18

4 years ago

0.1.17

4 years ago

0.1.16

4 years ago

0.1.15

4 years ago

0.1.14

4 years ago

0.1.13

4 years ago

0.1.12

4 years ago

0.1.11

4 years ago

0.1.10

4 years ago

0.1.9

4 years ago

0.1.8

4 years ago

0.1.7

4 years ago

0.1.6

4 years ago

0.1.5

4 years ago

0.1.4

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago

0.0.35

4 years ago

0.0.36

4 years ago

0.0.34

4 years ago

0.0.33

4 years ago

0.0.32

4 years ago

0.0.31

4 years ago

0.0.30

4 years ago

0.0.28

4 years ago

0.0.29

4 years ago

0.0.27

4 years ago

0.0.25

4 years ago

0.0.26

4 years ago

0.0.24

4 years ago

0.0.23

4 years ago

0.0.22

4 years ago

0.0.21

4 years ago

0.0.20

4 years ago

0.0.19

4 years ago

0.0.18

4 years ago

0.0.17

4 years ago

0.0.16

4 years ago

0.0.15

4 years ago

0.0.14

4 years ago

0.0.13

4 years ago

0.0.12

4 years ago

0.0.11

4 years ago

0.0.10

4 years ago

0.0.9

4 years ago

0.0.8

4 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago