# 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: 2/11/2022, 7:27:21 PM
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