Nest: Possibility to write "Console Commands"

Created on 25 Sep 2018  路  9Comments  路  Source: nestjs/nest

I'm submitting a...

[ ] Regression <!--(a behavior that used to work and stopped working in a new release)-->
[ ] Bug report
[X] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Background

Coming from the PHP world and working with Symfony and Laravel, I was used to be able to create independent commands that could be run from the command Line. This is useful when you need to perform a single task independently from your normal app behavior.

Example: I would like to be able to write a command that logs all the queries that need to be run to update my database from TypeORM schemas. I would launch the:

npm run execute-command typeorm:schema:log

And it would give me the needed queries to update my schema in output:

ALTER TABLE `scope_group` ADD `name` varchar(255) NOT NULL;
ALTER TABLE `grant` CHANGE `created_at` `created_at` datetime NOT NULL;
ALTER TABLE `grant` CHANGE `updated_at` `updated_at` datetime NOT NULL;
ALTER TABLE `scope` CHANGE `created_at` `created_at` datetime NOT NULL;
ALTER TABLE `scope` CHANGE `updated_at` `updated_at` datetime NOT NULL;

Current behavior

In order to quickly reproduce this behavior, I created a scripts folder where I put my scripts. In fact, those scripts are just copy pasted from the main.ts nest file:

// src/scripts/syncDatabase.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from '../app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const logs = await app.get<AppModule>(AppModule).getConnection().driver.createSchemaBuilder().log();
  logs.upQueries.forEach(query => {
    console.log(query + ';');
  });
  process.exit();
}

bootstrap();

Expected behavior

It would be nice to have an official "nest way" to do it. Like Symfony and Laravel do. Those commands could be injected or at least use some services from what I call the "service container":

// src/commands/syncDatabase.ts
import {Connection} from 'typeorm';
import {Injectable} from '@nestjs/common';
import {NestFactory} from '@nestjs/core';

class LogQueriesCommand extends ContainerAwareCommand {

    async configure () {
        this.setName('typeorm:schema:log')
    }

    async execute (input: InputInterface, output: OutputInterface): number {
        const connection = this.container.get(Connection);

        const logs = await connection.driver.createSchemaBuilder().log();

        logs.upQueries.forEach(query => {
            console.log(query + ';');
        });

        return 0;
    }
}

Commands should then be able to be registered into modules just like controllers are:

@Module({
    ...
    controllers: [AppController],
    commands: [LogQueriesCommand],
})

Final informations

Take a look at the documentation from Symfony and Laravel to better understand the use cases and the API for this implementation...

Idk if this could be useful for anyone else, don't hesitate to close this issue if it's not relevant. But if it's not I would love to hear why :)

Have a very good day!

3rd-party 馃殌 todo 馃挌

Most helpful comment

All 9 comments

It should be pretty easy to implement with Execution Context feature: https://docs.nestjs.com/execution-context

I think that it might be good to provide a similar functionality as a 3rd party package to reduce an amount of boilerplate 馃憤

Django also have a good method to create per module commands that in finally are spited in common commands list

https://docs.djangoproject.com/en/2.1/howto/custom-management-commands/

https://www.npmjs.com/package/nestjs-command not work correctly... It would be nice have a native console commands in nestjs even thought we are using nestjs in prod without console applications :(.
We are using symfony with console very well.

You can also give a try to https://github.com/Pop-Code/nestjs-console, it's using commander

@izquierdogalan What do you mean "not work correctly"? What's the issue with it?

We ported the console from Symfony to TypeScript a few weeks ago, it might not be stable enough, but you can take a look. https://github.com/media-service-dev/console

A little late here, but we just released the support for native console commands in our boilerplate. It uses inquirer, chalkjs and yargs, which makes it very lightweight and fast.

Feel free to pluck the console module out and integrate it with your codebase.

Happy Building!!

Was this page helpful?
0 / 5 - 0 ratings