nestjs-console-oclif

A NestJS module that integrate oclif to build nice cli


Keywords
nestjs, module, cli, console, oclif
License
MIT
Install
npm install nestjs-console-oclif@1.0.5

Documentation

NestJS + Oclif

pipeline status

nestjs-console-oclif is a NestJS module that provides a CLI with Oclif.

Getting started

Generate your NestJS application

The architecture is based on NestJS architecture. So you can generate your application with nestcli : https://docs.nestjs.com/first-steps

Install from NPM

npm install @oclif/command @oclif/config @oclif/errors @oclif/parser nestjs-console-oclif
# or unig yarn
yarn add @oclif/command @oclif/config @oclif/errors @oclif/parser nestjs-console-oclif

:warning: Don't forget to specify Oclif options in package.json :

{
  // ...
  "scripts": {
    "build": "nest build && oclif-dev manifest"
  },
  // ...
  "devDependencies": {
    // ...
    "@oclif/dev-cli": "^1.22.2",
    // ...
  },
  "bin": {
    "myCli": "./dist/main.js"
  },
  // ...
  "oclif": {
    "commands": "./dist/commands",
    "bin": "myCli",
    "plugins": [
      "@oclif/plugin-help"
    ]
  }
  // ...
}

Override NestJS bootstrap

Replace in file src/main.ts with AppModule as your main NestJS module:

#!/usr/bin/env node

import { bootstrap } from 'nestjs-console-oclif';
import { AppModule } from './app.module';

bootstrap({
  nestModule: AppModule
});

Options :

  • nestModule : The class of the NestJS module
  • singleCommand: The class of the single command
  • enableShutdownHooks: true if you want enable shutdown hooks on the NestJS app. See NestJS lifecycle events

Import OclifModule

Import OclifModule in your main NestJS module (in file src/app.module.ts).

import { Module } from '@nestjs/common';
import { OclifModule } from 'nestjs-console-oclif';

@Module({
  imports: [OclifModule.forRoot()],
  providers: [...],
})
export class AppModule {
}

Define your commands

Multi commands

You define your command in src/commands/myCommand.ts like oclif.

But :

  • Extends your command from BaseCommand
  • You don't need to implement the run function.
import { BaseCommand } from 'nestjs-console-oclif';
import { flags } from '@oclif/command';

export class MyCommand extends BaseCommand {
  static description = 'description of this example command';

  static flags: = {
    myFlag: flags.string({
      char: 'f',
      description: 'My flag',
    })
  };

  static args = [
    {name: 'myArg'}
  ];
}

Single command

Define your command in src/commands/myCommand.ts, but specify the command in bootstrap function :

#!/usr/bin/env node

import { bootstrap } from 'nestjs-console-oclif';
import { AppModule } from './app.module';
import { MyCommand } from './commands/myCommand';

bootstrap({
  nestModule: AppModule,
  singleCommand: MyCommand
});

Register your commands entrypoints

Define the entrypoint of the command defined in MyCommand.

:warning: The entrypoint does not take arguments.

import { Injectable } from '@nestjs/common';
import { OclifCommand } from 'nestjs-console-oclif';

@Injectable()
export class AppService {

  @OclifCommand('myCommand')
  async run(): Promise<void> {
    // Do something
  }
}

Read Args and flags

Load your parameters from NestJS context with the decorators OclifArgs and OclifFlags :

import { OclifFlags, OclifCommand, OclifArgs } from 'nestjs-console-oclif';
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  constructor(
        @OclifFlags('myFlag') protected myFlag: string,
        @OclifArgs('myArg') protected myArg: string) {
  }

  @OclifCommand('myCommand')
  async run(): Promise<void> {
    console.log(`my flag : ${this.myFlag}`);
    console.log(`my arg : ${this.myArg}`);
  }
}