jmcdo29 / nest-commander

A module for using NestJS to build up CLI applications
https://nest-commander.jaymcdoniel.dev/
MIT License
428 stars 53 forks source link

Command not working with nestjs v9 #602

Closed Sotatek-TyPham closed 1 year ago

Sotatek-TyPham commented 1 year ago

Is there an existing issue for this?

Current behavior

Command "crun create-admin" not working

Minimum reproduction code

CommandModule

import { Module } from '@nestjs/common';
import { TypeOrmModule } from "@nestjs/typeorm";
import { CreateAdminCommand } from './create-admin.command';
import { CreateAdminQuestions } from './questions/create-admin.questions';
import { User } from '../entities/user.entity';

@Module({
  imports: [
    TypeOrmModule.forRoot(),
    TypeOrmModule.forFeature([
      User,
    ]),
  ],
  providers: [
    CreateAdminCommand,
    CreateAdminQuestions,
  ],
  exports: [],
})
export class CommandModule {
}

CreateAdminCommand

import { Command, CommandRunner, Inquirer, InquirerService, Option } from 'nest-commander';
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import bcrypt from 'bcrypt';
import { userType } from '../constants/enum';
import { User } from '../entities/user.entity';

@Command({
  name: 'create-admin',
  description: 'Create a system admin',
  arguments: '[email] [password] [userName]'
})
export class CreateAdminCommand extends CommandRunner {
  constructor(
    private readonly inquirer: InquirerService,
    @InjectRepository(User) private userRepo: Repository<User>,
  ) {
    super()
  }

  async run(
    passedParam: string[],
    options: { isDefault: true }
  ): Promise<void> {
    const answers = await this.inquirer.prompt<{ email: string, password: string, userName: string}>(
      'create-admin-questions',
      undefined
    )
    const email = answers.email;
    const pass = answers.password;
    const userName = answers.userName;

    // Password hashing
    const salt = await bcrypt.genSalt();
    const passwordHash = await bcrypt.hash(pass, salt);
    try {
      await this.userRepo.save({
        email: email,
        password: passwordHash,
        userName: userName,
        loginType: userType.ADMIN,
        isActive: true,
        emailVerified: true,
      })

      console.log('\nCreate admin successfully.');
    } catch (err) {
      console.log('\nFailed to create admin.');
    }
  }

  @Option({
    flags: '-s, --shell <shell>',
  })
  parseShell(val: string) {
    return val;
  }
}

CreateAdminQuestions

import { Question, QuestionSet } from "nest-commander";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import Validator from 'validatorjs';
import { User } from '../../entities/user.entity';

@QuestionSet({ name: 'create-admin-questions' })
export class CreateAdminQuestions {
  constructor(
    @InjectRepository(User) private userRepos: Repository<User>,
  ) {}

  @Question({
    type: 'input',
    message: 'Please enter your email:',
    name: 'email',
    validate: async function (email: string) {
      let rules = {
        email: 'required|string|email',
      };
      let validation = new Validator({email: email}, rules);
      if (validation.fails()) {
        const firstErrors = validation.errors.first('email');
        console.log(`\n${firstErrors}`);

        return false;
      }
      const hasAccount = await this.loginRepos.findOne({
        where:{email: email.trim()}
      });
      if (hasAccount) {
        console.log('\nAccount already exist.');

        return false;
      }

      return true;
    }
  })
  parseEmail(email: string) {
    return email;
  }

  @Question({
    type: 'input',
    message: 'Please enter your username:',
    name: 'userName',
    validate: function (userName: string) {
      let rules = {
        userName: 'required|string|max:64',
      };

      let validation = new Validator({userName: userName}, rules);
      if (validation.fails()) {
        const firstErrors = validation.errors.first('userName');
        console.log(`\n${firstErrors}`);
        return false;
      }

      return true;
    }
  })
  parseFn(userName: string) {
    return userName;
  }

  @Question({
    type: 'password',
    message: 'Please enter your password:',
    name: 'password',
    validate: function (password: string) {
      Validator.register('checkPassword', function(value, requirement, attribute) {
        return value.match(/((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z]).*$/);
      }, 'Password too weak.');
      let rules = {
        password: 'required|string|min:8|max:64|checkPassword',
      };

      let validation = new Validator({password: password}, rules);
      if (validation.fails()) {
        const firstErrors = validation.errors.first('password');
        console.log(`\n${firstErrors}`);
        return false;
      }

      return true;
    }
  })
  parsePw(password: string) {
    return password;
  }
}

cli.js

#!/usr/bin/env node
import { CommandFactory } from "nest-commander";
import { CommandModule } from './commands/command.module';

async function bootstrap() {
  await CommandFactory.run(CommandModule);
}
bootstrap();

package.json

"bin": {
    "crun": "dist/src/cli.js"
  },

Then run: "crun create-admin" and nothing happen.

Expected behavior

That command runs exactly.

Package

Package version

3.1.0

Node.js version

16.18.0

In which operating systems have you tested?

Other

NestJs v9

jmcdo29 commented 1 year ago

Do you get an error?

Please provide a minimum reproduction repository (Git repository/StackBlitz/CodeSandbox project).

why reproductions are required

Sotatek-TyPham commented 1 year ago

@jmcdo29 No any error, please try https://github.com/typv/nest-commander

jmcdo29 commented 1 year ago

@jmcdo29 No any error, please try typv/nest-commander

This isn't a minimum reproduction. I shouldn't have to set up a database for this, right? Your reproduction currently requires me to. Please follow the instructions in the link I provided about what a minimum reproduction is.

Sotatek-TyPham commented 1 year ago

@jmcdo29 This is a test repository and I have provided you the docker-compose.yml.

jmcdo29 commented 1 year ago

After adding in a Logger to debug

pnpm build

> nest-typescript-starter@1.0.0 build /home/jay/Documents/code/help/nest-commander
> nest build

nest-commander at   on  master [  ] via  v16.18.0 with  took 4s
❯ node dist/src/cli.js create-admin
[Nest] 38796  - 10/24/2022, 9:52:49 PM     LOG [NestFactory] Starting Nest application...
[Nest] 38796  - 10/24/2022, 9:52:49 PM   ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)...
MissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-mysql", "aurora-postgres", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mong
    at DriverFactory.create (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/typeorm@0.3.10_xfe65cbtrj7nyogdydel56wvce/node_modules/typeorm/driver/DriverFactory.js:72:23)
    at new DataSource (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/typeorm@0.3.10_xfe65cbtrj7nyogdydel56wvce/node_modules/typeorm/data-source/DataSource.js:49:59)
    at createTypeormDataSource (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.
    at Function.<anonymous> (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.mod
    at Generator.next (<anonymous>)
    at /home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:20:71
    at new Promise (<anonymous>)
    at __awaiter (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:16:1
    at /home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:174:76
    at Observable._subscribe (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/rxjs@7.5.7/node_modules/rxjs/dist/cjs/internal/observable/defer.js:8:31)
[Nest] 38796  - 10/24/2022, 9:52:49 PM     LOG [InstanceLoader] CommandRootModule dependencies initialized +3ms
[Nest] 38796  - 10/24/2022, 9:52:49 PM     LOG [InstanceLoader] TypeOrmModule dependencies initialized +0ms
[Nest] 38796  - 10/24/2022, 9:52:49 PM     LOG [InstanceLoader] DiscoveryModule dependencies initialized +0ms
[Nest] 38796  - 10/24/2022, 9:52:49 PM     LOG [InstanceLoader] CommandRunnerModule dependencies initialized +1ms
[Nest] 38796  - 10/24/2022, 9:52:52 PM   ERROR [TypeOrmModule] Unable to connect to the database. Retrying (2)...
MissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-mysql", "aurora-postgres", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mong
    at DriverFactory.create (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/typeorm@0.3.10_xfe65cbtrj7nyogdydel56wvce/node_modules/typeorm/driver/DriverFactory.js:72:23)
    at new DataSource (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/typeorm@0.3.10_xfe65cbtrj7nyogdydel56wvce/node_modules/typeorm/data-source/DataSource.js:49:59)
    at createTypeormDataSource (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.
    at Function.<anonymous> (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.mod
    at Generator.next (<anonymous>)
    at /home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:20:71
    at new Promise (<anonymous>)
    at __awaiter (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:16:12)
    at /home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:174:76
    at Observable._subscribe (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/rxjs@7.5.7/node_modules/rxjs/dist/cjs/internal/observable/defer.js:8:31)
[Nest] 38796  - 10/24/2022, 9:53:01 PM   ERROR [TypeOrmModule] Unable to connect to the database. Retrying (5)...
MissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-mysql", "aurora-postgres", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "nativescript", "oracle", "postgres", "react-native", "sap", "sqlite", "sqljs", "spanner".
    at DriverFactory.create (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/typeorm@0.3.10_xfe65cbtrj7nyogdydel56wvce/node_modules/typeorm/driver/DriverFactory.js:72:23)
    at new DataSource (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/typeorm@0.3.10_xfe65cbtrj7nyogdydel56wvce/node_modules/typeorm/data-source/DataSource.js:49:59)
    at createTypeormDataSource (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:172:23)
    at Function.<anonymous> (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:176:46)
    at Generator.next (<anonymous>)
    at /home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:20:71
    at new Promise (<anonymous>)
    at __awaiter (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:16:12)
    at /home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/@nestjs+typeorm@9.0.1_v5sk3sol6y4pjqg44yrie3mozm/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:174:76
    at Observable._subscribe (/home/jay/Documents/code/help/nest-commander/node_modules/.pnpm/rxjs@7.5.7/node_modules/rxjs/dist/cjs/internal/observable/defer.js:8:31)

I can't just run the reproduction. So please, make it so that I can.

Sotatek-TyPham commented 1 year ago

@jmcdo29 I found the error of import Typeorm to CommandModule, it not related to nest-commander. Sorry for that and thanks for your support.