An interactive shell for NestJS which allows you to plug-in your custom commands and use them when the app's running
npm install nestjs-shell
For more examples, go there: https://github.com/bmstefanski/nestjs-shell-example
- [x] π Non-blocking runtime console
- [x] π No dependencies
- [x] π€ Simple and stable API
- [x] π‘οΈ Well tested
- [x] π₯οΈ Modifiable error messages and prompt sign
- [x] π¨οΈ Elastic output printer (you can write own printer or use any logger you want)
- [x] π Optional, required and varargs parameters
- [ ] π Travis or GitHub Actions based CI
``production use
$ yarn add nestjs-shell
Usage
##### Execution and registration
`typescript
import { ShellModule, ShellFacade } from 'nestjs-shell'//
ShellModule is Global, so please put it only in your main module and it will work flawlessly in others.
@Module({ imports: [ShellModule] })
export class YourAppMainModule implements OnApplicationBootstrap {
constructor(private readonly shellFacade: ShellFacade) {} public async onApplicationBootstrap(): Promise {
// You can use it without passing any arguments and use default configuration or configure it in your own way.
await this.shellFacade.bootstrap()
// It does not have to be here, you can register components anywhere you want and as many times as you need.
this.shellFacade.registerComponents(
new SayCommandComponent(),
new AnotherSecondTestCommandComponent(new SomeDependency()),
)
}
}
`##### Simple example with required, optional and varargs parameters
`typescript
import { ShellCommand, ShellComponent } from 'nestjs-shell'/* Please do not put @Injectable() or any other decorator that creates a new instance of a class,
it may cause bugs and it is definitely not going to work the way you want.
*/
export class SayCommandComponent extends ShellComponent {
/* Only
name property is required, so by default you have no prefix, no description and no pattern
and it works fine!
*/
/* Pattern ideology is simple:
if your parameter name is wrapped with < and > then it's required
if your parameter name is wrapped with [ and ] then it's optional
if there is @ sign inside any brackets ([ or <) then it's varargs.
Same as in JavaScript varargs, they can only be placed in the last parameter.
*/
@ShellCommand({
name: 'say',
prefix: '.',
description: 'Sends a message to the console',
pattern: ' [@message]',
})
public async sayCommand(sender: string, message: string): Promise {
return ${sender} says: ${message || 'Nothing'}
} // There is no limit to the amount of commands in one ShellComponent.
@ShellCommand({
name: 'said',
prefix: '/',
description: 'Sends a message to the console that has been said',
pattern: ' <@message>',
})
/* You don't have to keep function's parameters in the same order as pattern ones.
They are applied by name, not order.
*/
public async saidCommand(sender: string, message: string): Promise {
return
${sender} said: ${message}
}
}
`
##### Constructor dependencies
`typescript
import { ShellCommand, ShellComponent } from 'nestjs-shell'export class AnotherSecondTestCommandComponent extends ShellComponent {
constructor(private readonly someDependency: TestDependency) {
super()
}
/* You can use as much prefixes as you want..
if you do not specify any then it uses the default, which is '' (empty string)
*/
@ShellCommand({
name: '.help',
description: 'Displays all commands with description and usage',
})
public async help(): Promise {
// Method's execution context is ALWAYS set to the actual class instance and so
this keyword works as expected.
return [
'Here are all available commands: ',
'-------------------------------------',
...this.someDependency,
...this.shellFacade.getAllCommands().map((command) => {
return -> ${command.name} ${command.pattern} - ${command.description || 'Description not available'}
}),
'-------------------------------------',
].join('\n')
}
}
`
API specification
The library shares its methods through the facade, named ShellFacade. In the table below, you can see a brief description of each method.
`typescript
import { ShellFacade } from 'nestjs-shell'
`
| Method | Description | Arguments |
| :------------------- | :-------------------------------------------------------------------: | :-------------------------------: |
|
bootstrap | Enables terminal | BootstrapOptions |
| registerComponents | Adds command components to the registry | ...components: ShellComponent[] |
| getAllCommands | Returns immutable (or to be more precise: deep copy of a) collection) | naught |`typescript
type BootstrapOptions = {
prompt?: string = 'β€³'
messages?: { notFound?: string; wrongUsage?: string } = {
notFound: 'Say what? I might have heard $input',
wrongUsage: 'Wrong usage: $command $pattern',
}
shellPrinter?: ((value: any) => void) = (value: any) => console.log(value)
}
``> Note: If you want to contribute, please keep in mind that I don't want to support various use cases, it should remain as simple as it is. So if you desire to improve code rather than add features, then I would greatly appreciate it ππ»ππΌππ½ππΎππΏ.
Nestjs-shell is MIT licensed