{"id":18351666,"url":"https://github.com/bmstefanski/nestjs-shell","last_synced_at":"2025-05-12T16:13:31.983Z","repository":{"id":43866542,"uuid":"267318659","full_name":"bmstefanski/nestjs-shell","owner":"bmstefanski","description":"🐚 An interactive shell for NestJS which allows you to plug-in your custom commands and use them when the app's running","archived":false,"fork":false,"pushed_at":"2023-07-18T22:26:29.000Z","size":1565,"stargazers_count":50,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-06T00:11:51.520Z","etag":null,"topics":["console","javascript","nest","nestjs","nestjs-library","nestjs-module","nodejs","shell","terminal","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bmstefanski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-27T12:52:00.000Z","updated_at":"2025-01-30T04:18:30.000Z","dependencies_parsed_at":"2024-11-05T21:35:55.367Z","dependency_job_id":null,"html_url":"https://github.com/bmstefanski/nestjs-shell","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmstefanski%2Fnestjs-shell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmstefanski%2Fnestjs-shell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmstefanski%2Fnestjs-shell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bmstefanski%2Fnestjs-shell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bmstefanski","download_url":"https://codeload.github.com/bmstefanski/nestjs-shell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253774581,"owners_count":21962199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["console","javascript","nest","nestjs","nestjs-library","nestjs-module","nodejs","shell","terminal","typescript"],"created_at":"2024-11-05T21:32:10.728Z","updated_at":"2025-05-12T16:13:31.966Z","avatar_url":"https://github.com/bmstefanski.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eNestJS Shell\u003c/h1\u003e\n  \u003cimg width=\"700\" src=\"https://raw.githubusercontent.com/bmstefanski/nestjs-shell/master/shell-example.gif\" let=\"Example GIF of interactive shell\"\u003e\n  \u003cbr /\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://travis-ci.org/github/bmstefanski/nestjs-shell\"\u003e\u003cimg alt=\"travis build badge\" src=\"https://travis-ci.org/bmstefanski/nestjs-shell.svg?branch=master\"\u003e\u003c/a\u003e  \n  \u003ca href=\"https://www.npmjs.com/package/nestjs-shell\"\u003e\u003cimg alt=\"npm version badge\" src=\"https://img.shields.io/npm/v/nestjs-shell\"\u003e\u003c/a\u003e  \n  \u003cimg alt=\"npm bundle size\" src=\"https://img.shields.io/bundlephobia/min/nestjs-shell\"\u003e\n  \u003cimg alt=\"license badge\" src=\"https://img.shields.io/npm/l/nestjs-shell\"\u003e\n  \u003ca href='https://coveralls.io/github/bmstefanski/nestjs-shell?branch=master'\u003e\u003cimg src='https://coveralls.io/repos/github/bmstefanski/nestjs-shell/badge.svg?branch=master' alt='Coverage Status' /\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n## Description\nI 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).\nCurrently, 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.   \nSo I decided to give you full control of where and when shell's instance should start and a way to execute commands in runtime.\n\nFor more examples, go there: https://github.com/bmstefanski/nestjs-shell-example\n\n\n## Features\n\n\u003cimg align=\"right\" src=\"https://raw.githubusercontent.com/bmstefanski/nestjs-shell/master/code-sample.png\" alt=\"Code sample with command that prints specified parameters to the console\" width=\"600\"\u003e   \n     \n- [x] 🙉 Non-blocking runtime console \n- [x] 🚚 No dependencies\n- [x] 🤠 Simple and stable API\n- [x] 🛡️ Well tested\n- [x] 🖥️ Modifiable error messages and prompt sign\n- [x] 🖨️ Elastic output printer (you can write own printer or use any logger you want)\n- [x] 📔 Optional, required and varargs parameters\n- [ ] 📗 Travis or GitHub Actions based CI\n\n\n## Installation\n\n```\n# production use\n$ yarn add nestjs-shell\n\n# development use\n$ yarn add -D nestjs-shell\n```\n\n\n## Usage\n\n##### Execution and registration\n```typescript\nimport { ShellModule, ShellFacade } from 'nestjs-shell'\n\n// `ShellModule` is Global, so please put it only in your main module and it will work flawlessly in others. \n@Module({ imports: [ShellModule] })\nexport class YourAppMainModule implements OnApplicationBootstrap {\n  constructor(private readonly shellFacade: ShellFacade) {}\n\n  public async onApplicationBootstrap(): Promise\u003cvoid\u003e {\n    // You can use it without passing any arguments and use default configuration or configure it in your own way.\n    await this.shellFacade.bootstrap()\n\n    // It does not have to be here, you can register components anywhere you want and as many times as you need. \n    this.shellFacade.registerComponents(\n      new SayCommandComponent(), \n      new AnotherSecondTestCommandComponent(new SomeDependency()),\n    )\n  }\n}\n```\n\n##### Simple example with required, optional and varargs parameters\n```typescript\nimport { ShellCommand, ShellComponent } from 'nestjs-shell'\n\n/* Please do not put @Injectable() or any other decorator that creates a new instance of a class, \n  it may cause bugs and it is definitely not going to work the way you want. \n*/\nexport class SayCommandComponent extends ShellComponent {\n\n  /* Only `name` property is required, so by default you have no prefix, no description and no pattern\n    and it works fine!\n  */\n  /* Pattern ideology is simple:\n      if your parameter name is wrapped with `\u003c` and `\u003e` then it's required\n      if your parameter name is wrapped with `[` and `]` then it's optional\n      if there is `@` sign inside any brackets (`[` or `\u003c`) then it's varargs. \n      Same as in JavaScript varargs, they can only be placed in the last parameter.\n  */\n  @ShellCommand({\n    name: 'say',\n    prefix: '.',\n    description: 'Sends a message to the console',\n    pattern: '\u003csender\u003e [@message]',\n  })\n  public async sayCommand(sender: string, message: string): Promise\u003cstring\u003e {\n    return `${sender} says: ${message || 'Nothing'}`\n  }\n\n  // There is no limit to the amount of commands in one ShellComponent.\n  @ShellCommand({\n    name: 'said',\n    prefix: '/',\n    description: 'Sends a message to the console that has been said',\n    pattern: '\u003csender\u003e \u003c@message\u003e',\n  })\n  /* You don't have to keep function's parameters in the same order as pattern ones. \n    They are applied by name, not order.\n  */\n   public async saidCommand(sender: string, message: string): Promise\u003cstring\u003e {\n    return `${sender} said: ${message}`\n  }\n}\n```\n\n\n##### Constructor dependencies \n```typescript\nimport { ShellCommand, ShellComponent } from 'nestjs-shell'\n\nexport class AnotherSecondTestCommandComponent extends ShellComponent {\n  constructor(private readonly someDependency: TestDependency) {\n    super()\n  }\n\n  /* You can use as much prefixes as you want.. \n    if you do not specify any then it uses the default, which is '' (empty string)\n  */\n  @ShellCommand({\n    name: '.help',\n    description: 'Displays all commands with description and usage',\n  })\n  public async help(): Promise\u003cstring\u003e {\n    // Method's execution context is ALWAYS set to the actual class instance and so `this` keyword works as expected.\n    return [\n      'Here are all available commands: ',\n      '-------------------------------------',\n      ...this.someDependency,\n      ...this.shellFacade.getAllCommands().map((command) =\u003e {\n        return `-\u003e ${command.name} ${command.pattern} - ${command.description || 'Description not available'}`\n      }),\n      '-------------------------------------',\n    ].join('\\n')\n  }\n}\n```\n\n\n## API specification\nThe library shares its methods through the facade, named `ShellFacade`. In the table below, you can see a brief description of each method.\n```typescript\nimport { ShellFacade } from 'nestjs-shell'\n```\n\n\n| Method               |                              Description                              |             Arguments             |\n| :------------------- | :-------------------------------------------------------------------: | :-------------------------------: |\n| `bootstrap`          |                           Enables terminal                            |        `BootstrapOptions`         |\n| `registerComponents` |                Adds command components to the registry                | `...components: ShellComponent[]` |\n| `getAllCommands`     | Returns immutable (or to be more precise: deep copy of a) collection) |              naught               |\n\n```typescript\ntype BootstrapOptions = {\n  prompt?: string = '⤳'\n  messages?: { notFound?: string; wrongUsage?: string } = { \n    notFound: 'Say what? I might have heard $input',\n    wrongUsage: 'Wrong usage: $command $pattern',\n  }\n  shellPrinter?: ((value: any) =\u003e void) = (value: any) =\u003e console.log(value)\n}\n```\n\n\n## Contributions and license\n\n\u003e **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 🙏🏻🙏🏼🙏🏽🙏🏾🙏🏿.\n\nNestjs-shell is [MIT licensed](LICENSE)\n\n","funding_links":[],"categories":["Packages"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbmstefanski%2Fnestjs-shell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbmstefanski%2Fnestjs-shell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbmstefanski%2Fnestjs-shell/lists"}