# Command
@tsed/cli-core is the npm module that provide API to create CLI. It can be to create your own CLI or to run your Ts.ED
application code. Ts.ED cli-core use commander (opens new window) to parse cli
arguments, Inquirer (opens new window)
to display prompt and Listr (opens new window) to run tasks.
The cli-core works as a standalone process, like the classic entry point, and will initialize a container to run your code (Service/Provider/etc...).
- Bootstrap (entry point e.g:
bin/index.ts) is invoked by cli. - Create a headless Ts.ED Application.
- Create command with decorator and inject service from your existing code.
# Installation
npm install @tsed/cli-core
# Or yarn
yarn add @tsed/cli-core
2
3
Note: You have to install the @tsed/cli-core
If you start your project from scratch, you can use Ts.ED cli v3 to bootstrap your project with the Command
feature.
Optional. You can install the @tsed/cli in global to run your custom commands directly from the Ts.ED CLI:
npm install -g @tsed/cli
# Create the CLI entrypoint
Create index.ts file in src/bin. This file will be dedicated to bootstrap the CLI with your own configuration.
#!/usr/bin/env node
import {CliCore} from "@tsed/cli-core";
import {config} from "../config"; // Import your application configuration
import {HelloCommand} from "./HelloCommand";
CliCore.bootstrap({
...config,
// add your custom commands here
commands: [HelloCommand]
}).catch(console.error);
2
3
4
5
6
7
8
9
10
# Create command
Use tsed g command to create a new Command file. Here is a basic Command example:
import {Command, CommandProvider, QuestionOptions} from "@tsed/cli-core";
export interface HelloCommandContext {}
@Command({
name: "hello-command",
description: "Command description",
args: {},
options: {},
allowUnknownOption: false
})
export class HelloCommand implements CommandProvider {
/**
* Ask questions with Inquirer. Return an empty array or don't implement the method to skip this step
*/
async $prompt(initialOptions: Partial<HelloCommandContext>): Promise<QuestionOptions> {
return [];
}
/**
* This method is called after the $prompt to create / map inputs to a proper context for the next step
*/
$mapContext(ctx: Partial<HelloCommandContext>): HelloCommandContext {
return {
...ctx
// map something, based on ctx
};
}
/**
* This step run your tasks with Listr module
*/
async $exec(ctx: HelloCommandContext): Promise<any> {
return [
{
title: "Do something",
task: () => {
console.log("HELLO");
}
}
];
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
The @Command decorator allow you to bind a class to Commander. Here the previous example can be run by executing the
following command:
tsed run hello-command
By default, you have to give the name and description.
# Command Args
Arguments are the values given to your command without a flag option. Example:
tsed run hello-command create user
To bind these arguments with your custom command, you have to declare the arguments as following:
import {Command, CommandProvider, QuestionOptions} from "@tsed/cli-core";
export interface HelloCommandContext {
action: "create";
subAction: "user";
}
@Command({
name: "hello-command",
description: "Command description",
args: {
action: {
type: String,
defaultValue: "create",
description: "My action"
},
subAction: {
type: String,
defaultValue: "user",
description: "My sub action"
}
},
options: {},
allowUnknownOption: false
})
export class HelloCommand implements CommandProvider {
$exec(ctx: HelloCommandContext) {
console.log(ctx);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Command Options
Options are the values given to your command with a specific flag option. Example:
tsed run hello-command -o test
To bind this option with your custom command, you have to declare the option as following:
import {Command, CommandProvider, QuestionOptions} from "@tsed/cli-core";
export interface HelloCommandContext {
option1: string;
}
@Command({
name: "hello-command",
description: "Command description",
args: {},
options: {
"-o, --opt-1 <option1>": {
type: String,
defaultValue: "dev",
description: "My option"
}
},
allowUnknownOption: false
})
export class HelloCommand implements CommandProvider {
$exec(ctx: HelloCommandContext) {
console.log(ctx);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Allow extra options
By default, commander doesn't accept unknown options. You can change this behaviour, by change the allowUnknownOption
to true.
Then you'll be able to get all args and options in the rawArgs property:
import {Command, CommandProvider, QuestionOptions} from "@tsed/cli-core";
export interface HelloCommandContext {
rawArgs: string[];
}
@Command({
name: "hello-command",
description: "Command description",
args: {},
options: {},
allowUnknownOption: true
})
export class HelloCommand implements CommandProvider {
$exec(ctx: HelloCommandContext) {
console.log(ctx);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Inject service
Use the Inject decorator to inject your service in a command:
import {Command, CommandProvider, QuestionOptions} from "@tsed/cli-core";
import {MyService} from "../services/MyService";
export interface HelloCommandContext {
rawArgs: string[];
}
@Command({
name: "hello-command",
description: "Command description",
args: {},
options: {},
allowUnknownOption: false
})
export class HelloCommand implements CommandProvider {
@Inject()
myService: MyService;
async $exec(ctx: HelloCommandContext): Promise<any> {
return [
{
title: "Update something",
task: () => this.myService.update(ctx)
}
];
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Prompt
You can implement the $prompt method to provide a CLI prompt to your consumer. Prompt is based
on Inquirer (opens new window).
import {Command, CommandProvider, QuestionOptions} from "@tsed/cli-core";
import {MyService} from "../services/MyService";
export interface HelloCommandContext {
projectName: string;
}
@Command({
name: "hello-command",
description: "Command description",
args: {},
options: {}
})
export class HelloCommand implements CommandProvider {
@Inject()
myService: MyService;
async $prompt(initialOptions: Partial<HelloCommandContext>): Promise<QuestionOptions> {
return [
{
type: "input",
name: "projectName",
message: "What is your project name",
transformer(input) {
return paramCase(input);
}
}
];
}
async $exec(ctx: HelloCommandContext): Promise<any> {
console.log(ctx);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
See Inquirer (opens new window) for more details to create prompt.
Last Updated: 12/17/2024, 6:59:22 AM
Other topics
- Session & cookies
- Passport.js
- Keycloak
- Prisma
- TypeORM
- MikroORM
- Mongoose
- GraphQL
- Socket.io
- Swagger
- AJV
- Multer
- Serve static files
- Templating
- Serverless HTTP
- Seq
- OIDC
- Stripe
- Agenda
- Terminus
- Serverless
- IORedis
- Controllers
- Providers
- Model
- JsonMapper
- Middlewares
- Pipes
- Interceptors
- Authentication
- Hooks
- Exceptions
- Throw HTTP Exceptions
- Cache
- Command
- Response Filter
- Injection scopes
- Custom providers
- Lazy-loading provider
- Custom endpoint decorator
- Testing
- Customize 404