npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nestjs-shell

v1.4.1

Published

An interactive shell for NestJS which allows you to plug-in your custom commands and use them when the app's running

Downloads

285

Readme

Description

I wanted to create as simple as possible API without redundant use cases. Which allows you to create a simple command in less than a minute (counting installation time). Currently, there are a few libraries that provide something similar to this, but they violate your app's execution file with their code and require you to re-run the app's instance every time you want to execute a command.
So I decided to give you full control of where and when shell's instance should start and a way to execute commands in runtime.

For more examples, go there: https://github.com/bmstefanski/nestjs-shell-example

Features

  • [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

Installation

# production use
$ yarn add nestjs-shell

# development use
$ yarn add -D nestjs-shell

Usage

Execution and registration
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<void> {
    // 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
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: '<sender> [@message]',
  })
  public async sayCommand(sender: string, message: string): Promise<string> {
    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: '<sender> <@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<string> {
    return `${sender} said: ${message}`
  }
}
Constructor dependencies
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<string> {
    // 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.

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 |

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)
}

Contributions and license

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