npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@anchan828/nest-commands

v0.2.41

Published

> TODO: description

Downloads

448

Readme

@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