Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
nestjs-console
Advanced tools
nestjs-console is a module that provide a cli. A ready to use service class for your modules that exposes methods to register commands and sub commands using the npm package commander
The nestjs framework is missing a cli to access the application context.
Common use case : Headless application, cront task, export data, etc...
nestjs-console provide a way to bind cli command and subcommands to providers's methods.
The console service works as a standalone process, like the classic entry point, and will initialize a NestApplicationContext (headless) instead a NestApplication. The console service will be accessible inside the container.
npm install commander nestjs-console
# or unig yarn
yarn add commander nestjs-console
Create a file at root next to your entry point named console.ts
Import your app module or any module you want to be loaded. Usually this is your main nestjs module.
// console.ts - example of entrypoint
import { BootstrapConsole } from 'nestjs-console';
import { MyModule } from './module';
const bootstrap = new BootstrapConsole({
module: MyModule,
useDecorators: true
});
bootstrap.init().then(async app => {
try {
// init your app
await app.init();
// boot the cli
await bootstrap.boot();
process.exit(0);
} catch (e) {
process.exit(1);
}
});
// module.ts - your module
import { Module } from '@nestjs/common';
import { ConsoleModule } from 'nestjs-console';
import { MyService } from './service';
@Module({
imports: [
ConsoleModule // import the ConsoleModule
],
providers: [MyService]
exports: [MyService]
})
export class MyModule {}
You can now inject the ConsoleService inside any nestjs providers, controllers...
There are 2 ways of registering providers methods to the console.
Using @decorators or using the ConsoleService.
Example of cli stack
Cli -> Command_A -> [
Command_A1 -> execution,
Command_A2 -> execution
]
-> Command_B -> [
Command_B1 -> execution,
Command_B2 -> [
Command_B2_a -> execution
Command_B2_b -> [... more sub commands ...]
]
]
-> Command_C -> execution
As a simple example, we will define a cli with 2 commands (new and list), one of the command (new) will have 2 sub commands (directory and file)
Cli -> list -> -> execution,
-> new -> [
directory -> execution,
file -> execution
]
Registering methods using class decorators is very easy. Nestjs providers that are decorated with @Console will be scanned and each member method that is decorated with @Command will be registered on the cli.
// service.ts - a nestjs provider using console decorators
import { Console, Command, createSpinner } from 'nestjs-console';
@Console()
export class MyService {
@Command({
command: 'list <directory>',
description: 'List content of a directory'
})
async listContent(directory: string): Promise<void> {
// See Ora npm package for details about spinner
const spin = createSpinner();
spin.start(`Listing files in directory ${directory}`);
// simulate a long task of 1 seconds
const files = await new Promise(done =>
setTimeout(() => done(['fileA', 'fileB']), 1000)
);
spin.succeed('Listing done');
// send the response to the cli
// you could also use process.stdout.write()
console.log(JSON.stringify(files));
}
}
By default, the @Console will tell the module to register all decorated methods at root of the cli.
Example of Usage: [options] [command]
You can name your provider to be registered in a group command container. This is useful when you have a lot of commands and you want to group them as sub command. (git style)
To achieve this, you have to group your methods into class. You have to pass options to the @Console decorator to configure the name of the parent cli. Decorated methods of the providers will be registered as a sub command instead of being registered at root.
// service.new.ts - a nestjs provider using console decorators (sub commands)
@Console({
name: 'new',
description: 'A command to create an item'
})
export class MyNewService {
@Command({
command: 'file <name>',
description: 'Create a file'
})
async createFile(name: string): void | Promise<void> {
console.log(`Creating a file named ${name}`);
// your code...
}
@Command({
command: 'directory <name>',
description: 'Create a directory'
})
async createDirectory(name: string): void | Promise<void> {
console.log(`Creating a directory named ${name}`);
// your code...
}
}
If you need to register other sub commands from other Class to the same cli container, you have to decorate your class using the @Console decorator with the same name.
@Console({
name: 'new' // here the name is the same as the one from MyNewService, grouping all commands
})
export class MyOtherService {...}
Example of Usage: new [options] [command]
Registering methods using the ConsoleService is more flexible than decorators.
When you use the ConsoleService, you simply bind your methods to the cli manually.
This is useful if you need to create the cli or a part of the cli at runtime.
This way you can also create multiple commands ans sub commands from the same context.
// service.ts - a nestjs provider
import { Injectable } from '@nestjs/common';
import { ConsoleService } from 'nestjs-console';
@Injectable()
export class MyService {
constructor(private readonly consoleService: ConsoleService) {
// get the root cli
const cli = this.consoleService.getCli();
// create a single command (See [npm commander arguments/options for more details])
this.consoleService.createCommand(
{
command: 'list <directory>',
description: 'description'
},
this.listContent,
cli // attach the command to the cli
);
// create a parent command container
const groupCommand = this.consoleService.createGroupCommand(
{
name: 'new',
description: 'A command to create an item'
},
cli // attach the command to the root cli
);
// create command
this.consoleService.createCommand(
{
command: 'file <name>',
description: 'Create a file'
},
this.createFile,
groupCommand // attach the command to the group
);
// create an other sub command
this.consoleService.createCommand(
{
command: 'directory <name>',
description: 'Create a directory'
},
this.createDirectory,
groupCommand // attach the command to the group
);
}
listContent = async (directory: string): void | Promise<void> => {
console.log(`Listing files in directory ${directory}`);
// your code...
};
createFile = async (name: string): void | Promise<void> => {
console.log(`Creating a file named ${name}`);
// your code...
};
createDirectory = async (name: string): void | Promise<void> => {
console.log(`Creating a directory named ${name}`);
// your code...
};
}
Add scripts in your package.json (if you want to use them)
{
"scripts": {
// from sources
"console:dev": "ts-node -r tsconfig-paths/register src/console.ts",
// from build (we suppose your app was built in the lib folder)
"console": "node lib/console.js"
}
}
Call the cli (production)
# using node
node lib/console.js --help
# using npm
npm run console -- --help
# using yarn
yarn console --help
Call the cli from sources (dev)
# using ts-node
ts-node -r tsconfig-paths/register src/console.ts --help
# using npm
npm run console:dev -- --help
# using yarn
yarn console:dev --help
Usage: console [options] [command]
Options:
-h, --help output usage information
Commands:
list <directory> List content of a directory
new A command to create an item
[2.1.0] - 2020-02-03
FAQs
A NestJS module that provide a cli
The npm package nestjs-console receives a total of 25,286 weekly downloads. As such, nestjs-console popularity was classified as popular.
We found that nestjs-console demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.