Retseptlar4 min read

Nest Commander

standalone application hujjatlariga qo'shimcha ravishda, oddiy Nest ilovasiga o'xshash tuzilma bilan command line ilovalar yozish uchun nest-commander paketi ham mavjud.

standalone application hujjatlariga qo'shimcha ravishda, oddiy Nest ilovasiga o'xshash tuzilma bilan command line ilovalar yozish uchun nest-commander paketi ham mavjud.

Info

nest-commander third-party paket hisoblanadi va NestJS core jamoasi tomonidan to'liq boshqarilmaydi. Kutubxonadagi muammolarni mos repository ga yuboring.

O'rnatish

Boshqa paketlar kabi, undan foydalanishdan oldin uni o'rnatishingiz kerak.

Terminal
1$ npm i nest-commander

Command fayli

nest-commander class'lar uchun @Command() va shu class metodlari uchun @Option() dekoratorlari orqali yangi command-line ilovalar yozishni osonlashtiradi. Har bir command fayli CommandRunner abstract class'ini implement qilishi va @Command() dekoratori bilan belgilanishi kerak.

Har bir command Nest tomonidan @Injectable() sifatida ko'riladi, shuning uchun odatiy Dependency Injection kutilganidek ishlaydi. E'tibor qaratish kerak bo'lgan asosiy narsa - har bir command implement qilishi kerak bo'lgan CommandRunner abstract class'i. CommandRunner barcha command'larda Promise<void> qaytaradigan va string[], Record<string, any> parametrlarini qabul qiladigan run metodi bo'lishini kafolatlaydi. run - barcha asosiy business logic boshlanadigan joy. U option flag'lariga mos tushmagan parametrlarni massiv sifatida qabul qiladi, bu bir nechta parametr bilan ishlamoqchi bo'lgan holatlar uchun foydali. options qismi esa Record<string, any> ko'rinishida bo'ladi; uning xossa nomlari @Option() dekoratorlarida berilgan name qiymatiga, xossa qiymatlari esa option handler qaytargan natijaga teng bo'ladi. Yaxshiroq type safety kerak bo'lsa, options uchun alohida interface yaratishingiz mumkin.

Command'ni ishga tushirish

NestJS ilovasida NestFactory orqali server yaratib, uni listen bilan ishga tushirganimiz kabi, nest-commander paketi ham command ilovasini ishga tushirish uchun sodda API beradi. CommandFactory ni import qiling, uning static run metodidan foydalaning va ilovangizning root module'ini uzating. Bu quyidagicha ko'rinadi:

TypeScript
1import { CommandFactory } from 'nest-commander';
2import { AppModule } from './app.module';
3
4async function bootstrap() {
5  await CommandFactory.run(AppModule);
6}
7
8bootstrap();

Standart holatda CommandFactory ishlatilganda Nest logger'i o'chirilgan bo'ladi. Biroq uni run funksiyasining ikkinchi argumenti sifatida uzatish mumkin. Siz custom NestJS logger yoki saqlab qolmoqchi bo'lgan log level'lar massivini berishingiz mumkin. Masalan, faqat Nest xato loglari chiqishini istasangiz, bu yerda hech bo'lmaganda ['error'] uzatish foydali bo'ladi.

TypeScript
1import { CommandFactory } from 'nest-commander';
2import { AppModule } from './app.module';
3import { LogService } './log.service';
4
5async function bootstrap() {
6  await CommandFactory.run(AppModule, new LogService());
7
8  // or, if you only want to print Nest's warnings and errors
9  await CommandFactory.run(AppModule, ['warn', 'error']);
10}
11
12bootstrap();

Hammasi shu. Ichki qatlamda CommandFactory siz uchun NestFactory ni chaqiradi va kerak bo'lganda app.close() ni ham bajaradi, shuning uchun memory leak haqida alohida qayg'urishingiz shart emas. Agar qo'shimcha error handling kerak bo'lsa, run chaqiruvini try/catch bilan o'rashingiz yoki bootstrap() ga .catch() zanjirlashingiz mumkin.

Testing

Ajoyib command line skript yozib, uni oson test qila olmaslikning foydasi yo'q. Yaxshiyamki, nest-commander NestJS ekotizimiga juda mos tushadigan utilitalarni taqdim etadi. Test rejimida command yaratish uchun CommandFactory o'rniga CommandTestFactory dan foydalanishingiz va metadata uzatishingiz mumkin. Bu @nestjs/testing dagi Test.createTestingModule ga juda o'xshaydi. Hatto ichki qatlamda aynan shu paketdan foydalanadi. compile() ni chaqirishdan oldin overrideProvider metodlarini zanjirlab, test ichida DI qismlarini almashtirishingiz ham mumkin.

Hammasini birlashtirish

Quyidagi class basic subcommand'ini qabul qiladigan yoki bevosita chaqiriladigan CLI command'ga teng bo'ladi. U -n, -s, va -b flag'larini (ularning uzun variantlari bilan birga) qo'llab-quvvatlaydi va har bir option uchun custom parser'ga ega. Odatdagidek --help flag'i ham ishlaydi.

TypeScript
1import { Command, CommandRunner, Option } from 'nest-commander';
2import { LogService } from './log.service';
3
4interface BasicCommandOptions {
5  string?: string;
6  boolean?: boolean;
7  number?: number;
8}
9
10@Command({ name: 'basic', description: 'A parameter parse' })
11export class BasicCommand extends CommandRunner {
12  constructor(private readonly logService: LogService) {
13    super()
14  }
15
16  async run(
17    passedParam: string[],
18    options?: BasicCommandOptions,
19  ): Promise<void> {
20    if (options?.boolean !== undefined && options?.boolean !== null) {
21      this.runWithBoolean(passedParam, options.boolean);
22    } else if (options?.number) {
23      this.runWithNumber(passedParam, options.number);
24    } else if (options?.string) {
25      this.runWithString(passedParam, options.string);
26    } else {
27      this.runWithNone(passedParam);
28    }
29  }
30
31  @Option({
32    flags: '-n, --number [number]',
33    description: 'A basic number parser',
34  })
35  parseNumber(val: string): number {
36    return Number(val);
37  }
38
39  @Option({
40    flags: '-s, --string [string]',
41    description: 'A string return',
42  })
43  parseString(val: string): string {
44    return val;
45  }
46
47  @Option({
48    flags: '-b, --boolean [boolean]',
49    description: 'A boolean parser',
50  })
51  parseBoolean(val: string): boolean {
52    return JSON.parse(val);
53  }
54
55  runWithString(param: string[], option: string): void {
56    this.logService.log({ param, string: option });
57  }
58
59  runWithNumber(param: string[], option: number): void {
60    this.logService.log({ param, number: option });
61  }
62
63  runWithBoolean(param: string[], option: boolean): void {
64    this.logService.log({ param, boolean: option });
65  }
66
67  runWithNone(param: string[]): void {
68    this.logService.log({ param });
69  }
70}

Command class modulga qo'shilganiga ishonch hosil qiling:

TypeScript
1@Module({
2  providers: [LogService, BasicCommand],
3})
4export class AppModule {}

Endi main.ts ichida CLI'ni ishga tushirish uchun quyidagini yozishingiz mumkin:

TypeScript
1async function bootstrap() {
2  await CommandFactory.run(AppModule);
3}
4
5bootstrap();

Shu bilan command line ilovangiz tayyor bo'ladi.

Qo'shimcha ma'lumot

Ko'proq ma'lumot, misollar va API hujjatlari uchun nest-commander docs site ga tashrif buyuring.