fontcolor_theme
Deepkit App

参数与标志

命令行中的命令参数就是 execute 方法或函数的常规参数。它们会被自动映射到命令行参数。 如果你将某个参数标记为可选,则不必传入它。如果你为其设置了默认值,也同样不必传入。

根据类型(string、number、联合类型等),传入的值会被自动反序列化并验证。

import { cli } from '@deepkit/app';

// 函数式
new App().command('test', (name: string) => {
    console.log('Hello', name);
});

// 类
@cli.controller('test')
class TestCommand {
    async execute(name: string) {
        console.log('Hello', name);
    }
}

如果现在执行该命令但未指定 name 参数,将会报告错误:

$ ts-node app.ts test
RequiredArgsError: Missing 1 required arg:
name

使用 --help 可以获得关于必需参数的更多信息:

$ ts-node app.ts test --help
USAGE
  $ ts-node-script app.ts test NAME

一旦将 name 作为参数传入,命令会被执行,并且该名称会被正确传递。

$ ts-node app.ts test "beautiful world"
Hello beautiful world

所有原始参数类型,如 string、number、boolean、字符串字面量、它们的联合类型,以及它们的数组,都会自动用作 CLI 参数,并自动进行验证与反序列化。参数的顺序决定了 CLI 参数的顺序。你可以添加任意数量的参数。

一旦定义了复杂对象(接口、类、对象字面量),它就会被视为服务依赖,依赖注入容器会尝试解析它。更多信息参见章节《依赖注入》。

标志(Flags)

标志是向命令传递值的另一种方式。大多数情况下它们是可选的,但也可以是必需的。使用 Flag 类型修饰的参数可以通过 --name value--name=value 传入。

import { Flag } from '@deepkit/app';

// 函数式
new App().command('test', (id: number & Flag) => {
    console.log('id', name);
});

// 类
class TestCommand {
    async execute(id: number & Flag) {
        console.log('id', id);
    }
}
$ ts-node app.ts test --help
USAGE
  $ ts-node app.ts test

OPTIONS
  --id=id  (required)

在帮助信息的“OPTIONS”中,你可以看到需要一个 --id 标志。若正确传入该标志,命令会接收到该值。

$ ts-node app.ts test --id 23
id 23

$ ts-node app.ts test --id=23
id 23

布尔标志

标志的优势在于它也可以作为无值标志使用,例如用于激活某种行为。只要将参数标记为可选的布尔值,就会启用这种行为。

import { Flag } from '@deepkit/app';

// 函数式
new App().command('test', (remove: boolean & Flag = false) => {
    console.log('delete?', remove);
});

// 类
class TestCommand {
    async execute(remove: boolean & Flag = false) {
        console.log('delete?', remove);
    }
}
$ ts-node app.ts test
delete? false

$ ts-node app.ts test --remove
delete? true

多值标志

若要为同一个标志传入多个值,可以将标志标记为数组。

import { Flag } from '@deepkit/app';

// 函数式
new App().command('test', (id: number[] & Flag = []) => {
    console.log('ids', id);
});

// 类
class TestCommand {
    async execute(id: number[] & Flag = []) {
        console.log('ids', id);
    }
}
$ ts-node app.ts test
ids: []

$ ts-node app.ts test --id 12
ids: [12]

$ ts-node app.ts test --id 12 --id 23
ids: [12, 23]

单字符标志

要允许以单个字符传递标志,可以使用 Flag<{char: 'x'}>

import { Flag } from '@deepkit/app';

// 函数式
new App().command('test', (output: string & Flag<{char: 'o'}>) => {
    console.log('output: ', output);
});

// 类
class TestCommand {
    async execute(output: string & Flag<{char: 'o'}>) {
        console.log('output: ', output);
    }
}
$ ts-node app.ts test --help
USAGE
  $ ts-node app.ts test

OPTIONS
  -o, --output=output  (required)


$ ts-node app.ts test --output test.txt
output: test.txt

$ ts-node app.ts test -o test.txt
output: test.txt

可选 / 默认值

方法/函数的签名决定了哪些参数或标志是可选的。如果在类型系统中参数是可选的,用户就不必提供它。

// 函数式
new App().command('test', (name?: string) => {
    console.log('Hello', name || 'nobody');
});

// 类
class TestCommand {
    async execute(name?: string) {
        console.log('Hello', name || 'nobody');
    }
}
$ ts-node app.ts test
Hello nobody

对具有默认值的参数也是如此:

// 函数式
new App().command('test', (name: string = 'body') => {
    console.log('Hello', name);
});

// 类
class TestCommand {
    async execute(name: string = 'body') {
        console.log('Hello', name);
    }
}
$ ts-node app.ts test
Hello nobody

标志也以同样的方式适用。

序列化 / 验证

所有参数与标志都会基于其类型自动反序列化、验证,并且可以附加额外的约束。

因此,虽然命令行界面基于文本(字符串),但在控制器中被定义为 number 的参数总能保证是数字类型。

// 函数式
new App().command('test', (id: number) => {
    console.log('id', id, typeof id);
});

// 类
class TestCommand {
    async execute(id: number) {
        console.log('id', id, typeof id);
    }
}
$ ts-node app.ts test 123
id 123 number

可以使用来自 @deepkit/type 的类型注解定义额外的约束。

import { Positive } from '@deepkit/type';
// 函数式
new App().command('test', (id: number & Positive) => {
    console.log('id', id, typeof id);
});

// 类
class TestCommand {
    async execute(id: number & Positive) {
        console.log('id', id, typeof id);
    }
}

id 中的 Postive 类型表示只允许正数。如果用户现在传入负数,代码将不会被执行,并显示错误信息。

$ ts-node app.ts test -123
Validation error in id: Number needs to be positive [positive]

这种非常容易实现的额外验证,使命令对错误输入更加稳健。更多信息参见章节《验证》。

描述

要描述一个标志或参数,请使用 @description 注释装饰器。

import { Positive } from '@deepkit/type';

class TestCommand {
    async execute(
        /** @description 用户的标识符 */
        id: number & Positive,
        /** @description 删除该用户? */
        remove: boolean = false
    ) {
        console.log('id', id, typeof id);
    }
}

在帮助信息中,这些描述会显示在标志或参数之后:

$ ts-node app.ts test --help
USAGE
  $ ts-node app.ts test ID

ARGUMENTS
  ID  The users identifier

OPTIONS
  --remove  Delete the user?
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)