命令标志
本指南介绍在自定义命令中定义命令标志。你将了解以下主题:
- 定义布尔、字符串、数字和数组标志
- 自定义标志名称和描述
- 为简写用法创建标志别名
- 为标志设置默认值
- 转换和校验标志值
- 访问所有提供的标志
概述
标志提供了一种接受可选或具名参数的方式,而无需特定顺序。它们使用两个连字符(--)表示全名,或使用单个连字符(-)表示别名。
在下面的命令中,--resource 和 --singular 都是标志。
node ace make:controller users --resource --singular
与位置参数不同,标志可以出现在命令中的任何位置,如果它们是可选的,还可以完全省略。这使得标志非常适合用于自定义命令行为的选项,例如启用功能、指定输出格式或提供配置值。
Ace 支持多种标志类型,包括用于开/关选项的布尔标志、用于文本值的字符串标志、用于数字输入的数字标志,以及用于多个值的数组标志。
定义布尔标志
布尔标志表示开/关或是/否选项。它们是最简单的标志类型,不需要值——只需提及该标志就会将其设置为 true。
使用 @flags.boolean 装饰器定义布尔标志。
import { BaseCommand, flags } from '@adonisjs/core/ace'
export default class MakeControllerCommand extends BaseCommand {
static commandName = 'make:controller'
/**
* 启用资源型控制器生成
*/
@flags.boolean()
declare resource: boolean
/**
* 创建一个单一的资源型控制器
*/
@flags.boolean()
declare singular: boolean
async run() {
if (this.resource) {
this.logger.info('Creating a resource controller')
}
}
}
当用户提及该标志时,其值变为 true。如果他们省略该标志,则其值为 undefined。
node ace make:controller users --resource
# this.resource === true
node ace make:controller users
# this.resource === undefined
否定布尔标志
布尔标志支持使用 --no- 前缀进行否定,允许用户显式地将标志设置为 false。当某个标志的默认值为 true 且用户需要禁用它时,这会很有用。
node ace make:controller users --no-resource
# this.resource === false
默认情况下,否定变体不会显示在帮助界面中,以保持输出简洁。你可以使用 showNegatedVariantInHelp 选项显示它。
@flags.boolean({
showNegatedVariantInHelp: true,
})
declare resource: boolean
定义字符串标志
字符串标志接受用户在标志名称之后提供的文本值。使用 @flags.string 装饰器定义字符串标志。
import { BaseCommand, flags } from '@adonisjs/core/ace'
export default class MakeControllerCommand extends BaseCommand {
static commandName = 'make:controller'
/**
* 要与控制器关联的模型名称
*/
@flags.string()
declare model: string
async run() {
if (this.model) {
this.logger.info(`Creating controller for ${this.model} model`)
}
}
}
用户在标志名称之后提供值,用空格或等号分隔。
node ace make:controller users --model user
# this.model = 'user'
node ace make:controller users --model=user
# this.model = 'user'
如果标志值包含空格或特殊字符,用户必须用引号将其包裹。
node ace make:controller posts --model blog user
# this.model = 'blog'
# (只取第一个单词)
node ace make:controller posts --model "blog user"
# this.model = 'blog user'
# (捕获整个短语)
Ace 会显示错误,如果用户提及了标志但没有提供值,即使该标志是可选的。
node ace make:controller users
# 正常 - 可选的 flag 未被提及
node ace make:controller users --model
# 错误:Missing value for flag --model
定义数字标志
数字标志与字符串标志类似,但 Ace 会校验提供的值是否为有效的数字。这确保你的命令接收的是数值输入,而非任意文本。
使用 @flags.number 装饰器定义数字标志。
import { BaseCommand, flags } from '@adonisjs/core/ace'
export default class CreateUserCommand extends BaseCommand {
static commandName = 'create:user'
/**
* 新用户的初始分数
*/
@flags.number()
declare score: number
async run() {
this.logger.info(`Creating user with score: ${this.score}`)
}
}
用户必须提供有效的数值。
node ace create:user --score 100
# this.score = 100
node ace create:user --score abc
# 错误:Flag --score must be a valid number
定义数组标志
数组标志允许用户多次指定相同的标志,将所有值收集到一个数组中。当命令需要接受同一类型的多个项(如文件路径、标签或权限组)时,这会很有用。
使用 @flags.array 装饰器定义数组标志。
import { BaseCommand, flags } from '@adonisjs/core/ace'
export default class CreateUserCommand extends BaseCommand {
static commandName = 'create:user'
/**
* 要分配给用户的组
*/
@flags.array()
declare groups: string[]
async run() {
this.logger.info(`Assigning user to groups: ${this.groups.join(', ')}`)
}
}
用户可以多次指定该标志以构建数组。
node ace create:user --groups=admin --groups=moderators --groups=creators
# this.groups = ['admin', 'moderators', 'creators']
自定义标志名称和描述
默认情况下,Ace 将你的属性名转换为短横线形式(dashed-case)作为标志名称。例如,名为 startServer 的属性会变成 --start-server。你可以使用 flagName 选项自定义它。
@flags.boolean({
flagName: 'server'
})
declare startServer: boolean
添加描述有助于用户理解标志的用途。描述会在用户使用 --help 标志运行命令时出现在帮助界面中。
@flags.boolean({
flagName: 'server',
description: 'Start the application server after the build'
})
declare startServer: boolean
创建标志别名
标志别名提供了标志的简写名称,使常用选项的命令输入更快。别名使用单个连字符(-),且必须是单个字符。
@flags.boolean({
alias: 'r',
description: 'Generate a resource controller'
})
declare resource: boolean
@flags.boolean({
alias: 's',
description: 'Create a singular resource controller'
})
declare singular: boolean
用户可以使用全名或别名。
node ace make:controller users --resource --singular
# 等同于
node ace make:controller users -r -s
多个单字符别名可以在单个连字符后组合。
node ace make:controller users -rs
# 等同于 --resource --singular
设置默认值
你可以使用 default 选项为标志指定默认值。当用户不提供标志时,Ace 会使用默认值代替 undefined。
@flags.boolean({
default: true,
description: 'Start the application server after build'
})
declare startServer: boolean
@flags.string({
default: 'sqlite',
description: 'Database connection to use'
})
declare connection: string
默认值确保你的命令始终有一个值可用,即使用户没有指定标志。
node ace build
# this.startServer = true(默认)
# this.connection = 'sqlite'(默认)
node ace build --no-start-server --connection=mysql
# this.startServer = false(显式设置)
# this.connection = 'mysql'(显式设置)
转换标志值
parse 方法允许你在将标志值赋给你的类属性之前对其进行转换或校验。这对于规范化输入、查找配置值或执行校验很有用。
parse 方法接收原始字符串值,并且必须返回转换后的值。
@flags.string({
description: 'Database connection to use',
parse(value) {
/**
* 将短名称映射为完整的连接字符串
*/
const connections = {
pg: 'postgresql://localhost/myapp',
mysql: 'mysql://localhost/myapp',
sqlite: 'sqlite://./database.sqlite'
}
return value ? connections[value] || value : value
}
})
declare connection: string
现在用户可以提供短连接名称,它们会被展开为完整的连接字符串。
node ace migrate --connection=pg
# this.connection = 'postgresql://localhost/myapp'
你也可以使用 parse 方法来校验输入,并为无效值抛出错误。
@flags.string({
description: 'Deployment environment',
parse(value) {
const validEnvironments = ['development', 'staging', 'production']
if (value && !validEnvironments.includes(value)) {
throw new Error(`Environment must be one of: ${validEnvironments.join(', ')}`)
}
return value
}
})
declare environment: string
访问所有标志
你可以使用 this.parsed.flags 属性访问用户提供的所有标志。这会返回一个包含所有标志值作为键值对的对象。
import { BaseCommand, flags } from '@adonisjs/core/ace'
export default class MakeControllerCommand extends BaseCommand {
static commandName = 'make:controller'
@flags.boolean()
declare resource: boolean
@flags.boolean()
declare singular: boolean
async run() {
/**
* 访问所有已定义的标志
*/
console.log(this.parsed.flags)
// 输出:{ resource: true, singular: false }
/**
* 访问被提及但未定义的标志
* (仅在 allowUnknownFlags 为 true 时可用)
*/
console.log(this.parsed.unknownFlags)
// 输出:['--some-unknown-flag']
}
}
当你在命令选项中启用了 allowUnknownFlags,并且需要处理或透传命令未显式定义的标志时,unknownFlags 属性特别有用。