Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nestjs-console

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nestjs-console - npm Package Compare versions

Comparing version 2.0.0-rc3 to 2.0.0

28

CHANGELOG.md

@@ -7,2 +7,25 @@ # Changelog

## [2.0.0] - 2020-01-15
### Changed
- BootstrapConsole method are not any more static. You must create an instance to boot.
- ConsoleService new methods `createCommand` and `createGroupCommand`
- Update dependencies versions
- Update to support commander ^4.0.1
### Added
- Possiblity to register multi dimensions commands and sub commands using decorators. (@Console({name: 'cliName'})). If two or more Console decorators with the same name are found, they will be grouped.
- Fix Command lifecycle to be able to resolve command's return or to catch errors
- BootstrapConsole.boot() return a promise resolving the command's return or throwing an error. This is usefull for testing.
## [1.2.1] - 2020-01-03
### Fixed
- Fix a type error during the bootstrap scan for decorators [#61](https://github.com/Pop-Code/nestjs-console/pull/61)
- Remove implicit lodash dependency [#59](https://github.com/Pop-Code/nestjs-console/issues/59)
- Update to support commander@^4 [#58](https://github.com/Pop-Code/nestjs-console/issues/58)
## [1.2.0] - 2019-08-09

@@ -49,3 +72,3 @@

- A decorator `InjectCommander` to inject commander instance (patched for sub commands) as nestjs provider
- A decorator `InjectCli` to inject commander instance (patched for sub commands) as nestjs provider
- A new methods `subCommands() => Command` in the class `ConsoleService` to get sub commands from a non patched commander instance.

@@ -81,3 +104,4 @@ - Tests

[unreleased]: https://github.com/Pop-Code/nestjs-console/compare/v1.2.0...HEAD
[unreleased]: https://github.com/Pop-Code/nestjs-console/compare/v1.2.1...HEAD
[1.2.1]: https://github.com/Pop-Code/nestjs-console/compare/v1.2.0...v1.2.1
[1.2.0]: https://github.com/Pop-Code/nestjs-console/compare/v1.1.4...v1.2.0

@@ -84,0 +108,0 @@ [1.1.4]: https://github.com/Pop-Code/nestjs-console/compare/v1.0.2...v1.1.4

3

lib/bootstrap/abstract.d.ts

@@ -7,2 +7,3 @@ import { INestApplicationContext } from '@nestjs/common';

useDecorators?: boolean;
includeModules?: any[];
contextOptions?: any;

@@ -18,4 +19,4 @@ }

getService(): ConsoleService;
boot(argv?: string[]): import("commander").CommanderStatic.Command;
boot(argv?: string[], displayErrors?: boolean): Promise<any>;
abstract create(): Promise<A>;
}

@@ -25,3 +25,3 @@ "use strict";

const consoleModule = this.container.get(module_1.ConsoleModule);
consoleModule.scan(this.container, [this.options.module]);
consoleModule.scan(this.container, this.options.includeModules);
return this;

@@ -32,5 +32,4 @@ }

this.container = yield this.create();
yield this.container.init();
this.service = this.container.get(service_1.ConsoleService);
if (this.options.withContainer &&
if ((this.options.withContainer || this.options.useDecorators) &&
typeof this.service.setContainer === 'function') {

@@ -48,5 +47,5 @@ this.service.setContainer(this.container);

}
boot(argv) {
boot(argv, displayErrors = true) {
const args = argv || process.argv;
return this.service.init(args);
return this.service.init(args, displayErrors);
}

@@ -53,0 +52,0 @@ }

import ora = require('ora');
import { Options as PrettierOptions } from 'prettier';
export declare function createSpinner(opts?: ora.Options): ora.Ora;
export declare function concatenateHelp(message: string): (help: string) => string;
export declare function formatResponse(data: string | Error, options?: PrettierOptions): string;

@@ -9,6 +9,2 @@ "use strict";

exports.createSpinner = createSpinner;
function concatenateHelp(message) {
return (help) => `${message}\n${help}`;
}
exports.concatenateHelp = concatenateHelp;
function formatResponse(data, options) {

@@ -15,0 +11,0 @@ if (data instanceof Error) {

@@ -13,3 +13,2 @@ "use strict";

const common_1 = require("@nestjs/common");
const commander_1 = require("./commander");
const constants_1 = require("./constants");

@@ -21,3 +20,3 @@ const scanner_1 = require("./scanner");

useFactory: () => {
return commander_1.createCli();
return service_1.ConsoleService.create();
}

@@ -38,19 +37,7 @@ };

if (!parent) {
parent = this.service.createSubCommand(metadata, cli);
parent = this.service.createGroupCommand(metadata, cli);
}
}
for (const method of methods) {
const command = parent.command(method.metadata.command);
if (method.metadata.description) {
command.description(method.metadata.description);
}
if (method.metadata.alias) {
command.alias(method.metadata.alias);
}
if (Symbol.iterator in Object(method.metadata.options)) {
for (const opt of method.metadata.options) {
command.option(opt.flags, opt.description, opt.fn, opt.defaultValue);
}
}
command.action(instance[method.name].bind(instance));
this.service.createCommand(method.metadata, instance[method.name].bind(instance), parent);
}

@@ -57,0 +44,0 @@ });

@@ -0,4 +1,6 @@

/// <reference types="node" />
import { INestApplicationContext } from '@nestjs/common';
import { Command } from 'commander';
import { IConsoleOptions } from './decorators';
import { EventEmitter } from 'events';
import { ICommandDecoratorOptions, IConsoleOptions } from './decorators';
export declare class ConsoleService {

@@ -8,11 +10,14 @@ protected cli: Command;

protected commands: Map<string, Command>;
protected eventManager: EventEmitter;
constructor(cli: Command);
static create(): import("commander").Command;
resetCli(): void;
displayErrorWithHelp(command: Command, error: Error): never;
displayFatalError(command: Command, error: Error): boolean;
logError(error: Error): void;
getCli(name?: string): Command;
setContainer(container: INestApplicationContext): ConsoleService;
getContainer(): INestApplicationContext;
init(argv: string[]): Command;
createSubCommand(options: IConsoleOptions, parent: Command): Command;
createHandler(action: (...args: any[]) => any): (...args: any[]) => Promise<void>;
init(argv: string[], displayErrors: boolean): Promise<any>;
createCommand(options: ICommandDecoratorOptions, handler: (...args: any[]) => any, parent: Command): import("commander").Command;
createGroupCommand(options: IConsoleOptions, parent: Command): Command;
}

@@ -14,23 +14,37 @@ "use strict";

};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var ConsoleService_1;
Object.defineProperty(exports, "__esModule", { value: true });
const common_1 = require("@nestjs/common");
const commander_1 = require("commander");
const commander_2 = require("./commander");
const events_1 = require("events");
const decorators_1 = require("./decorators");
const helpers_1 = require("./helpers");
let ConsoleService = class ConsoleService {
let ConsoleService = ConsoleService_1 = class ConsoleService {
constructor(cli) {
this.cli = cli;
this.commands = new Map();
this.eventManager = new events_1.EventEmitter();
}
static create() {
const cli = new commander_1.Command();
cli.on('command:*', (args, unknown) => {
throw new Error(`"${args[0]}" command not found`);
});
return cli;
}
resetCli() {
this.cli = commander_2.createCli();
this.cli = ConsoleService_1.create();
}
displayErrorWithHelp(command, error) {
return command.help((h) => `${helpers_1.formatResponse(error)}\n${h}`);
logError(error) {
return console.error(helpers_1.formatResponse(error));
}
displayFatalError(command, error) {
command.exitOverride();
return process.stdout.write(helpers_1.formatResponse(error));
}
getCli(name) {

@@ -46,24 +60,77 @@ return name ? this.commands.get(name) : this.cli;

}
init(argv) {
const cli = this.getCli();
try {
if (cli.commands.length === 0) {
this.displayFatalError(cli, new commander_2.CommandError(`The cli does not contains subcommand`, cli));
return process.exit(1);
createHandler(action) {
return (...args) => __awaiter(this, void 0, void 0, function* () {
try {
let response = yield action(...args);
if (response instanceof Promise) {
response = yield response;
}
this.eventManager.emit('data', response);
}
const command = cli.parse(argv);
command.help();
return command;
}
catch (e) {
if (e instanceof commander_2.CommandError) {
this.displayErrorWithHelp(e.command, e);
return process.exit(1);
catch (e) {
this.eventManager.emit('error', e);
}
else {
});
}
init(argv, displayErrors) {
return __awaiter(this, void 0, void 0, function* () {
const cli = this.getCli();
try {
if (cli.commands.length === 0) {
throw new commander_1.CommanderError(1, 'empty', `The cli does not contain sub command`);
}
const response = yield new Promise((ok, fail) => {
this.eventManager.once('data', data => {
ok(data);
});
this.eventManager.once('error', e => {
fail(e);
});
cli.exitOverride(e => {
throw e;
});
cli.parse(argv);
if (argv.length === 2) {
cli.help();
}
});
return response;
}
catch (e) {
if (e instanceof commander_1.CommanderError) {
if (/(helpDisplayed|commander\.help)/.test(e.code)) {
return;
}
if (/missingArgument/.test(e.code)) {
throw e;
}
if (displayErrors && e.exitCode === 1) {
this.logError(e);
}
}
else if (displayErrors) {
this.logError(e);
}
throw e;
}
});
}
createCommand(options, handler, parent) {
const command = parent
.command(options.command)
.exitOverride((...args) => parent._exitCallback(...args));
if (options.description) {
command.description(options.description);
}
if (options.alias) {
command.alias(options.alias);
}
if (Symbol.iterator in Object(options.options)) {
for (const opt of options.options) {
command.option(opt.flags, opt.description, opt.fn, opt.defaultValue);
}
}
return command.action(this.createHandler(handler));
}
createSubCommand(options, parent) {
createGroupCommand(options, parent) {
if (parent._args.length > 0) {

@@ -74,7 +141,17 @@ throw new Error('Sub commands cannot be applied to command with explicit args');

.command(options.name)
.description(options.description)
.alias(options.alias);
.exitOverride((...args) => parent._exitCallback(...args));
if (options.description) {
command.description(options.description);
}
if (options.alias) {
command.alias(options.alias);
}
const name = command.name();
const _onSubCommand = (args, unknown) => {
commander_2.onSubCommand(command, args, unknown);
const commandArgs = command.parseOptions(args.concat(unknown));
command.parseArgs(commandArgs.args, commandArgs.unknown);
if (commandArgs.unknown.length === 0 &&
commandArgs.args.length === 0) {
command.help();
}
};

@@ -86,3 +163,3 @@ parent.on('command:' + name, _onSubCommand);

command.on('command:*', (args) => {
throw new commander_2.CommandError(`"${args[0]}" command not found`, command);
throw new Error(`"${args[0]}" command not found`);
});

@@ -93,3 +170,3 @@ this.commands.set(name, command);

};
ConsoleService = __decorate([
ConsoleService = ConsoleService_1 = __decorate([
common_1.Injectable(),

@@ -96,0 +173,0 @@ __param(0, decorators_1.InjectCommander()),

{
"name": "nestjs-console",
"version": "2.0.0-rc3",
"version": "2.0.0",
"description": "A NestJS module that provide a cli",

@@ -5,0 +5,0 @@ "keywords": [

@@ -0,7 +1,11 @@

<div align="center">
[![nestjs-console](https://raw.githubusercontent.com/Pop-Code/nestjs-console/master/resources/logo-frame.png)][npm]
[![CircleCI](https://circleci.com/gh/Pop-Code/nestjs-console.svg?style=shield)][ci]
[![codecov](https://codecov.io/gh/Pop-Code/nestjs-console/branch/master/graph/badge.svg)][codecov]
[![Actions Status](https://github.com/Pop-Code/nestjs-acl/workflows/CI/badge.svg)](https://github.com/Pop-Code/nestjs-acl/actions)
[![codecov](https://codecov.io/gh/Pop-Code/nestjs-console/branch/v2/graph/badge.svg)][codecov]
[![NPM Downloads](https://img.shields.io/npm/dm/nestjs-console.svg?style=flat)][npmchart]
[![npm](https://img.shields.io/node/v/carbon.svg?style=flat)][npm]
</div>
[nestjs-console][npm] 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][commander]

@@ -21,3 +25,3 @@

1. Bootstrap (entry point e.g console.ts) is invoked by cli.
2. Init a headless nest app
2. Create a headless nest app
- Any module inside the app can create command and subcommands using nestjs-console with [commander][commander]

@@ -47,7 +51,17 @@ 3. nestjs-console invoke commander

BootstrapConsole.init({ module: MyModule }).then(({ app, boot }) => {
// do something with your app container if you need (app)
// boot the cli
boot(/*process.argv*/);
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);
}
});
```

@@ -76,3 +90,3 @@

There are 2 ways of registering providers methods to the console.
Using @decorators (>=v1.1 and >=v2 for multi dimensions) or using the _ConsoleService_.
Using @decorators or using the _ConsoleService_.

@@ -123,3 +137,3 @@ Example of cli stack

})
async listContent(directory: string): void | Promise<void> {
async listContent(directory: string): Promise<void> {
// See Ora npm package for details about spinner

@@ -139,4 +153,2 @@ const spin = createSpinner();

console.log(JSON.stringify(files));
process.exit(0);
}

@@ -151,8 +163,8 @@ }

You can name your provider to use it as a parent command container.
You can name your provider to be registered in a group command container.
This is usefull 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 your provider as a parent command.
Decorated methods of the providers will be registered as a sub command instead of beeing registered at root.
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.

@@ -188,2 +200,11 @@ ```ts

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.
```ts
@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]`

@@ -196,3 +217,3 @@

This is usefull if you need to create the cli or a part of the cli at runtime.
This way you can also create mutliple commands ans sub commands from the same class.
This way you can also create mutliple commands ans sub commands from the same context.

@@ -210,25 +231,41 @@ ```ts

// create a single command (See [npm commander for more details])
cli.command('list <directory>')
.description('List content of a directory')
.action(this.listContent);
// create a single command (See [npm commander arguments/options for more details])
this.consoleService.createCommand(
{
command: 'list <directory>',
description: 'description',
options: [{ flags: '-o, --optional [value]' }]
},
this.listContent,
cli // attach the command to the cli
);
// create a parent command container
const parentCommand = this.consoleService.subCommands(
cli,
'new',
'A command to create an item'
const groupCommand = this.consoleService.createGroupCommand(
{
name: 'new',
description: 'A command to create an item'
},
cli // attach the command to the root cli
);
// create sub command
parentCommand
.command('file <name>')
.description('Create a file')
.action(this.createFile);
// 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
parentCommand
.command('directory <name>')
.description('Create a directory')
.action(this.createDirectory);
this.consoleService.createCommand(
{
command: 'directory <name>',
description: 'Create a directory'
},
this.createDirectory,
groupCommand // attach the command to the group
);
}

@@ -235,0 +272,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc