@ranger1/dx 0.1.96 → 0.1.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cli/commands/core.js +12 -20
- package/lib/cli/commands/db.js +22 -32
- package/lib/cli/commands/export.js +7 -2
- package/lib/cli/commands/start.js +14 -33
- package/lib/cli/commands/worktree.js +0 -4
- package/lib/cli/dx-cli.js +46 -98
- package/lib/cli/flags.js +0 -6
- package/lib/cli/help-model.js +217 -0
- package/lib/cli/help-renderer.js +135 -0
- package/lib/cli/help-schema.js +549 -0
- package/lib/cli/help.js +114 -292
- package/lib/env.js +4 -5
- package/lib/worktree.js +37 -17
- package/package.json +1 -1
package/lib/cli/commands/core.js
CHANGED
|
@@ -6,13 +6,8 @@ import { execManager } from '../../exec.js'
|
|
|
6
6
|
import { showHelp, showCommandHelp } from '../help.js'
|
|
7
7
|
|
|
8
8
|
export function handleHelp(cli, args = []) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
else showHelp()
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function handleDev(cli, args = []) {
|
|
15
|
-
return cli.reportDevCommandRemoved(args)
|
|
9
|
+
if (args[0]) showCommandHelp(args[0], cli)
|
|
10
|
+
else showHelp(cli)
|
|
16
11
|
}
|
|
17
12
|
|
|
18
13
|
export async function handleBuild(cli, args) {
|
|
@@ -24,12 +19,6 @@ export async function handleBuild(cli, args) {
|
|
|
24
19
|
|
|
25
20
|
const buildConfig = cli.commands.build[target]
|
|
26
21
|
if (!buildConfig) {
|
|
27
|
-
// 兼容用户误输入或快捷命令,把 "all./scripts/dx" 这类粘连错误拆分
|
|
28
|
-
const fixed = String(target).split(/\s|\t|\r|\n|\u00A0|\.|\//)[0]
|
|
29
|
-
if (fixed && cli.commands.build[fixed]) {
|
|
30
|
-
logger.warn(`自动修正构建目标: ${target} -> ${fixed}`)
|
|
31
|
-
return await handleBuild(cli, [fixed])
|
|
32
|
-
}
|
|
33
22
|
logger.error(`未找到构建目标: ${target}`)
|
|
34
23
|
process.exitCode = 1
|
|
35
24
|
return
|
|
@@ -40,14 +29,12 @@ export async function handleBuild(cli, args) {
|
|
|
40
29
|
// 处理嵌套配置
|
|
41
30
|
let config = buildConfig
|
|
42
31
|
if (typeof config === 'object' && !config.command) {
|
|
43
|
-
const supportsCurrentEnv = Boolean(
|
|
44
|
-
config[envKey] || (envKey === 'staging' && config.prod),
|
|
45
|
-
)
|
|
32
|
+
const supportsCurrentEnv = Boolean(config[envKey])
|
|
46
33
|
if (explicitEnv && !supportsCurrentEnv) {
|
|
47
34
|
const envFlag = cli.getEnvironmentFlagExample(envKey) || `--${envKey}`
|
|
48
35
|
logger.error(`构建目标 ${target} 不支持 ${envFlag} 环境`)
|
|
49
36
|
logger.info('显式传入环境标志时,必须是该 target 实际支持的环境。')
|
|
50
|
-
const available = ['
|
|
37
|
+
const available = ['development', 'staging', 'production', 'test', 'e2e']
|
|
51
38
|
.filter(key => key in config)
|
|
52
39
|
.map(key => cli.getEnvironmentFlagExample(key) || `--${key}`)
|
|
53
40
|
if (available.length > 0) {
|
|
@@ -61,10 +48,15 @@ export async function handleBuild(cli, args) {
|
|
|
61
48
|
return
|
|
62
49
|
}
|
|
63
50
|
|
|
64
|
-
//
|
|
51
|
+
// 严格按显式环境选择配置,不做环境回退
|
|
65
52
|
if (config[envKey]) config = config[envKey]
|
|
66
|
-
else
|
|
67
|
-
|
|
53
|
+
else config = null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!config) {
|
|
57
|
+
logger.error(`构建目标 ${target} 未提供 ${cli.getEnvironmentFlagExample(envKey) || envKey} 环境配置`)
|
|
58
|
+
process.exitCode = 1
|
|
59
|
+
return
|
|
68
60
|
}
|
|
69
61
|
|
|
70
62
|
if (config.concurrent) {
|
package/lib/cli/commands/db.js
CHANGED
|
@@ -22,7 +22,7 @@ export async function handleDatabase(cli, args) {
|
|
|
22
22
|
const envKey = cli.normalizeEnvKey(environment)
|
|
23
23
|
|
|
24
24
|
// 创建迁移只允许在开发环境进行,避免 AI/用户在非开发环境误执行
|
|
25
|
-
if (action === 'migrate' && envKey && envKey !== '
|
|
25
|
+
if (action === 'migrate' && envKey && envKey !== 'development') {
|
|
26
26
|
const envFlag = cli.getEnvironmentFlagExample(envKey) || `--${envKey}`
|
|
27
27
|
logger.error('dx db migrate 仅允许在 --dev 环境下创建迁移')
|
|
28
28
|
logger.info('请使用 `dx db migrate --dev --name <migration-name>` 创建新迁移。')
|
|
@@ -49,10 +49,15 @@ export async function handleDatabase(cli, args) {
|
|
|
49
49
|
// 处理嵌套配置
|
|
50
50
|
let config = dbConfig
|
|
51
51
|
if (typeof config === 'object' && !config.command) {
|
|
52
|
-
//
|
|
52
|
+
// 严格按显式环境选择配置,不做环境回退
|
|
53
53
|
if (config[envKey]) config = config[envKey]
|
|
54
|
-
else
|
|
55
|
-
|
|
54
|
+
else config = null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!config) {
|
|
58
|
+
logger.error(`数据库操作 ${action} 未提供 ${cli.getEnvironmentFlagExample(envKey) || envKey} 环境配置`)
|
|
59
|
+
process.exitCode = 1
|
|
60
|
+
return
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
// 危险操作确认
|
|
@@ -71,7 +76,7 @@ export async function handleDatabase(cli, args) {
|
|
|
71
76
|
|
|
72
77
|
// 支持为 migrate 传入迁移名:--name/-n
|
|
73
78
|
let command = config.command
|
|
74
|
-
if (action === 'migrate' && envKey === '
|
|
79
|
+
if (action === 'migrate' && envKey === 'development') {
|
|
75
80
|
const allArgs = cli.args
|
|
76
81
|
let migrationName = null
|
|
77
82
|
// 优先解析显式标志 --name/-n
|
|
@@ -123,24 +128,14 @@ export async function handleDatabase(cli, args) {
|
|
|
123
128
|
.join('')
|
|
124
129
|
}
|
|
125
130
|
|
|
126
|
-
if (action === 'reset' && envKey !== '
|
|
131
|
+
if (action === 'reset' && envKey !== 'production') {
|
|
127
132
|
extraEnv.PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION = 'yes'
|
|
128
133
|
logger.info('非生产环境重置数据库,已自动确认危险操作: PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION=yes')
|
|
129
134
|
}
|
|
130
135
|
|
|
131
|
-
const execFlags = { ...cli.flags }
|
|
132
|
-
;['dev', 'development', 'prod', 'production', 'test', 'e2e', 'staging', 'stage'].forEach(
|
|
133
|
-
key => delete execFlags[key],
|
|
134
|
-
)
|
|
135
|
-
if (envKey === 'prod') execFlags.prod = true
|
|
136
|
-
else if (envKey === 'dev') execFlags.dev = true
|
|
137
|
-
else if (envKey === 'test') execFlags.test = true
|
|
138
|
-
else if (envKey === 'e2e') execFlags.e2e = true
|
|
139
|
-
else if (envKey === 'staging') execFlags.staging = true
|
|
140
|
-
|
|
141
136
|
await cli.executeCommand(
|
|
142
137
|
{ ...config, command, env: { ...(config.env || {}), ...extraEnv } },
|
|
143
|
-
|
|
138
|
+
cli.createExecutionFlags(environment),
|
|
144
139
|
)
|
|
145
140
|
}
|
|
146
141
|
|
|
@@ -177,7 +172,7 @@ export async function handleDatabaseScript(cli, scriptName, envKey, dbConfig) {
|
|
|
177
172
|
return
|
|
178
173
|
}
|
|
179
174
|
|
|
180
|
-
const environment = envKey
|
|
175
|
+
const environment = envKey
|
|
181
176
|
logger.step(`执行数据库脚本: ${cleanScriptName} (${environment})`)
|
|
182
177
|
logger.info(`脚本路径: ${scriptPath}`)
|
|
183
178
|
|
|
@@ -185,12 +180,17 @@ export async function handleDatabaseScript(cli, scriptName, envKey, dbConfig) {
|
|
|
185
180
|
let config = dbConfig
|
|
186
181
|
if (typeof config === 'object' && !config.command) {
|
|
187
182
|
if (config[envKey]) config = config[envKey]
|
|
188
|
-
else
|
|
189
|
-
|
|
183
|
+
else config = null
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!config) {
|
|
187
|
+
logger.error(`数据库脚本 ${scriptName} 未提供 ${cli.getEnvironmentFlagExample(envKey) || envKey} 环境配置`)
|
|
188
|
+
process.exitCode = 1
|
|
189
|
+
return
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
// 危险操作确认
|
|
193
|
-
if (config.dangerous && envKey === '
|
|
193
|
+
if (config.dangerous && envKey === 'production') {
|
|
194
194
|
const confirmed = await confirmManager.confirmDatabaseOperation(
|
|
195
195
|
`script: ${cleanScriptName}`,
|
|
196
196
|
envManager.getEnvironmentDescription(environment),
|
|
@@ -224,18 +224,8 @@ export async function handleDatabaseScript(cli, scriptName, envKey, dbConfig) {
|
|
|
224
224
|
const extraEnv = { NX_CACHE: 'false' }
|
|
225
225
|
logger.info('为数据库脚本禁用 Nx 缓存: NX_CACHE=false')
|
|
226
226
|
|
|
227
|
-
const execFlags = { ...cli.flags }
|
|
228
|
-
;['dev', 'development', 'prod', 'production', 'test', 'e2e', 'staging', 'stage'].forEach(
|
|
229
|
-
key => delete execFlags[key],
|
|
230
|
-
)
|
|
231
|
-
if (envKey === 'prod') execFlags.prod = true
|
|
232
|
-
else if (envKey === 'dev') execFlags.dev = true
|
|
233
|
-
else if (envKey === 'test') execFlags.test = true
|
|
234
|
-
else if (envKey === 'e2e') execFlags.e2e = true
|
|
235
|
-
else if (envKey === 'staging') execFlags.staging = true
|
|
236
|
-
|
|
237
227
|
await cli.executeCommand(
|
|
238
228
|
{ ...config, command, env: { ...(config.env || {}), ...extraEnv } },
|
|
239
|
-
|
|
229
|
+
cli.createExecutionFlags(environment),
|
|
240
230
|
)
|
|
241
231
|
}
|
|
@@ -25,8 +25,13 @@ export async function handleExport(cli, args) {
|
|
|
25
25
|
let config = exportConfig
|
|
26
26
|
if (typeof config === 'object' && !config.command) {
|
|
27
27
|
if (config[envKey]) config = config[envKey]
|
|
28
|
-
else
|
|
29
|
-
|
|
28
|
+
else config = null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!config) {
|
|
32
|
+
logger.error(`导出目标 ${target} 未提供 ${cli.getEnvironmentFlagExample(envKey) || envKey} 环境配置`)
|
|
33
|
+
process.exitCode = 1
|
|
34
|
+
return
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
logger.step(`导出 ${target} (${environment})`)
|
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
import { logger } from '../../logger.js'
|
|
2
2
|
|
|
3
3
|
export async function handleStart(cli, args) {
|
|
4
|
-
const service = args[0] || '
|
|
4
|
+
const service = args[0] || 'development'
|
|
5
5
|
|
|
6
6
|
const environment = cli.determineEnvironment()
|
|
7
7
|
const envKey = cli.normalizeEnvKey(environment)
|
|
8
|
-
|
|
9
|
-
let rawConfig = cli.commands.start[service]
|
|
10
|
-
let configNamespace = 'start'
|
|
11
|
-
|
|
12
|
-
if (!rawConfig && cli.commands.dev?.[service]) {
|
|
13
|
-
if (envKey !== 'dev') {
|
|
14
|
-
logger.error(`目标 ${service} 仅支持开发环境启动,请使用 --dev 或省略环境标志。`)
|
|
15
|
-
process.exitCode = 1
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
rawConfig = cli.commands.dev[service]
|
|
19
|
-
configNamespace = 'dev'
|
|
20
|
-
logger.info(`检测到 legacy "dev" 配置,已自动回退至 ${service} 开发脚本。`)
|
|
21
|
-
}
|
|
8
|
+
const rawConfig = cli.commands.start[service]
|
|
22
9
|
|
|
23
10
|
if (!rawConfig) {
|
|
24
11
|
logger.error(`未找到启动配置: ${service}`)
|
|
@@ -27,13 +14,17 @@ export async function handleStart(cli, args) {
|
|
|
27
14
|
}
|
|
28
15
|
|
|
29
16
|
let startConfig = rawConfig
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
const isRunnableConfig =
|
|
18
|
+
rawConfig &&
|
|
19
|
+
typeof rawConfig === 'object' &&
|
|
20
|
+
(rawConfig.command || rawConfig.internal || rawConfig.concurrent || rawConfig.sequential)
|
|
21
|
+
|
|
22
|
+
if (!isRunnableConfig && rawConfig && typeof rawConfig === 'object') {
|
|
23
|
+
startConfig = rawConfig[envKey] || null
|
|
33
24
|
}
|
|
34
25
|
|
|
35
26
|
if (!startConfig) {
|
|
36
|
-
logger.error(`启动目标 ${service} 未提供 ${
|
|
27
|
+
logger.error(`启动目标 ${service} 未提供 ${cli.getEnvironmentFlagExample(envKey) || envKey} 环境配置。`)
|
|
37
28
|
process.exitCode = 1
|
|
38
29
|
return
|
|
39
30
|
}
|
|
@@ -41,7 +32,7 @@ export async function handleStart(cli, args) {
|
|
|
41
32
|
logger.step(`启动 ${service} 服务 (${environment})`)
|
|
42
33
|
|
|
43
34
|
if (startConfig.concurrent && Array.isArray(startConfig.commands)) {
|
|
44
|
-
await cli.handleConcurrentCommands(startConfig.commands,
|
|
35
|
+
await cli.handleConcurrentCommands(startConfig.commands, 'start', envKey)
|
|
45
36
|
return
|
|
46
37
|
}
|
|
47
38
|
|
|
@@ -52,26 +43,16 @@ export async function handleStart(cli, args) {
|
|
|
52
43
|
|
|
53
44
|
const ports = cli.collectStartPorts(service, startConfig, envKey)
|
|
54
45
|
|
|
55
|
-
if (envKey === '
|
|
46
|
+
if (envKey === 'development' && ports.length > 0) {
|
|
56
47
|
logger.info(`开发环境自动清理端口: ${ports.join(', ')}`)
|
|
57
48
|
}
|
|
58
49
|
|
|
59
50
|
const configToExecute = {
|
|
60
51
|
...startConfig,
|
|
61
52
|
...(ports.length > 0 ? { ports } : {}),
|
|
62
|
-
...(envKey === '
|
|
53
|
+
...(envKey === 'development' ? { forcePortCleanup: true } : {}),
|
|
63
54
|
}
|
|
64
55
|
|
|
65
56
|
// 为执行阶段构造环境标志,确保 dotenv 选择正确层
|
|
66
|
-
|
|
67
|
-
;['dev', 'development', 'prod', 'production', 'test', 'e2e', 'staging', 'stage'].forEach(
|
|
68
|
-
key => delete execFlags[key]
|
|
69
|
-
)
|
|
70
|
-
if (envKey === 'prod') execFlags.prod = true
|
|
71
|
-
else if (envKey === 'dev') execFlags.dev = true
|
|
72
|
-
else if (envKey === 'test') execFlags.test = true
|
|
73
|
-
else if (envKey === 'e2e') execFlags.e2e = true
|
|
74
|
-
else if (envKey === 'staging') execFlags.staging = true
|
|
75
|
-
|
|
76
|
-
await cli.executeCommand(configToExecute, execFlags)
|
|
57
|
+
await cli.executeCommand(configToExecute, cli.createExecutionFlags(environment))
|
|
77
58
|
}
|
|
@@ -64,8 +64,6 @@ export async function handleWorktree(cli, args) {
|
|
|
64
64
|
break
|
|
65
65
|
|
|
66
66
|
case 'del':
|
|
67
|
-
case 'delete':
|
|
68
|
-
case 'rm':
|
|
69
67
|
// 互斥校验:--all 不能与 issue 编号同时使用
|
|
70
68
|
// args[0] 是 action,args[1] 开始才是 issue 编号
|
|
71
69
|
if (cli.flags.all && args.length > 1) {
|
|
@@ -131,12 +129,10 @@ export async function handleWorktree(cli, args) {
|
|
|
131
129
|
break
|
|
132
130
|
|
|
133
131
|
case 'list':
|
|
134
|
-
case 'ls':
|
|
135
132
|
await worktreeManager.list()
|
|
136
133
|
break
|
|
137
134
|
|
|
138
135
|
case 'clean':
|
|
139
|
-
case 'prune':
|
|
140
136
|
await worktreeManager.clean()
|
|
141
137
|
break
|
|
142
138
|
|
package/lib/cli/dx-cli.js
CHANGED
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
import { FLAG_DEFINITIONS, parseFlags } from './flags.js'
|
|
14
14
|
import { getCleanArgs, getCleanArgsWithConsumedValues } from './args.js'
|
|
15
15
|
import { showHelp, showCommandHelp } from './help.js'
|
|
16
|
+
import { buildStrictHelpValidationContext, validateHelpConfig } from './help-schema.js'
|
|
16
17
|
import { getPackageVersion } from '../version.js'
|
|
17
18
|
import {
|
|
18
19
|
handleHelp,
|
|
19
|
-
handleDev,
|
|
20
20
|
handleBuild,
|
|
21
21
|
handleTest,
|
|
22
22
|
handleLint,
|
|
@@ -51,7 +51,6 @@ class DxCli {
|
|
|
51
51
|
this.envCache = null
|
|
52
52
|
this.commandHandlers = {
|
|
53
53
|
help: args => handleHelp(this, args),
|
|
54
|
-
dev: args => handleDev(this, args),
|
|
55
54
|
start: args => handleStart(this, args),
|
|
56
55
|
build: args => handleBuild(this, args),
|
|
57
56
|
test: args => handleTest(this, args),
|
|
@@ -70,6 +69,7 @@ class DxCli {
|
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
this.flagDefinitions = FLAG_DEFINITIONS
|
|
72
|
+
this.validateLoadedHelpConfig()
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// 加载命令配置
|
|
@@ -84,6 +84,10 @@ class DxCli {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
validateLoadedHelpConfig() {
|
|
88
|
+
validateHelpConfig(this.commands, buildStrictHelpValidationContext(this))
|
|
89
|
+
}
|
|
90
|
+
|
|
87
91
|
// 检测并安装依赖
|
|
88
92
|
async ensureDependencies() {
|
|
89
93
|
const nodeModulesPath = join(process.cwd(), 'node_modules')
|
|
@@ -172,22 +176,9 @@ class DxCli {
|
|
|
172
176
|
throw new Error('未找到 db.generate 命令配置,请检查 dx/config/commands.json')
|
|
173
177
|
}
|
|
174
178
|
|
|
175
|
-
const envKey = this.normalizeEnvKey(environment)
|
|
176
|
-
const execFlags = { ...this.flags }
|
|
177
|
-
;['dev', 'development', 'prod', 'production', 'test', 'e2e', 'staging', 'stage'].forEach(
|
|
178
|
-
key => {
|
|
179
|
-
delete execFlags[key]
|
|
180
|
-
},
|
|
181
|
-
)
|
|
182
|
-
if (envKey === 'prod') execFlags.prod = true
|
|
183
|
-
else if (envKey === 'dev') execFlags.dev = true
|
|
184
|
-
else if (envKey === 'test') execFlags.test = true
|
|
185
|
-
else if (envKey === 'e2e') execFlags.e2e = true
|
|
186
|
-
else if (envKey === 'staging') execFlags.staging = true
|
|
187
|
-
|
|
188
179
|
await execManager.executeCommand(generateConfig.command, {
|
|
189
180
|
app: generateConfig.app || 'backend',
|
|
190
|
-
flags:
|
|
181
|
+
flags: this.createExecutionFlags(environment),
|
|
191
182
|
// Prisma generate 不应卡在环境变量校验上
|
|
192
183
|
skipEnvValidation: true,
|
|
193
184
|
})
|
|
@@ -286,9 +277,9 @@ class DxCli {
|
|
|
286
277
|
// 显示帮助
|
|
287
278
|
if (this.flags.help || !this.command) {
|
|
288
279
|
if (this.flags.help && this.command && this.command !== 'help') {
|
|
289
|
-
showCommandHelp(this.command)
|
|
280
|
+
showCommandHelp(this.command, this)
|
|
290
281
|
} else {
|
|
291
|
-
showHelp()
|
|
282
|
+
showHelp(this)
|
|
292
283
|
}
|
|
293
284
|
return
|
|
294
285
|
}
|
|
@@ -298,7 +289,7 @@ class DxCli {
|
|
|
298
289
|
// Fail fast for unknown commands before dependency/env startup checks.
|
|
299
290
|
if (this.command && !this.commandHandlers[this.command]) {
|
|
300
291
|
logger.error(`未知命令: ${this.command}`)
|
|
301
|
-
showHelp()
|
|
292
|
+
showHelp(this)
|
|
302
293
|
process.exit(1)
|
|
303
294
|
}
|
|
304
295
|
|
|
@@ -346,7 +337,7 @@ class DxCli {
|
|
|
346
337
|
const [, ...subArgs] = cleanArgs
|
|
347
338
|
|
|
348
339
|
if (!command) {
|
|
349
|
-
showHelp()
|
|
340
|
+
showHelp(this)
|
|
350
341
|
return
|
|
351
342
|
}
|
|
352
343
|
|
|
@@ -504,14 +495,14 @@ class DxCli {
|
|
|
504
495
|
case 'worktree': {
|
|
505
496
|
if (positionalArgs.length === 0) return
|
|
506
497
|
const action = positionalArgs[0]
|
|
507
|
-
if (
|
|
498
|
+
if (action === 'del') {
|
|
508
499
|
return
|
|
509
500
|
}
|
|
510
|
-
if (
|
|
501
|
+
if (action === 'make') {
|
|
511
502
|
ensureMax(3)
|
|
512
503
|
break
|
|
513
504
|
}
|
|
514
|
-
if (
|
|
505
|
+
if (action === 'list' || action === 'clean') {
|
|
515
506
|
ensureMax(1)
|
|
516
507
|
break
|
|
517
508
|
}
|
|
@@ -550,11 +541,8 @@ class DxCli {
|
|
|
550
541
|
const value = String(token).toLowerCase()
|
|
551
542
|
return (
|
|
552
543
|
value === 'dev' ||
|
|
553
|
-
value === 'development' ||
|
|
554
544
|
value === 'prod' ||
|
|
555
|
-
value === 'production' ||
|
|
556
545
|
value === 'staging' ||
|
|
557
|
-
value === 'stage' ||
|
|
558
546
|
value === 'test' ||
|
|
559
547
|
value === 'e2e'
|
|
560
548
|
)
|
|
@@ -570,18 +558,19 @@ class DxCli {
|
|
|
570
558
|
if (suggestion) {
|
|
571
559
|
logger.info(`建议命令: ${suggestion}`)
|
|
572
560
|
} else if (normalizedFlag) {
|
|
573
|
-
|
|
561
|
+
logger.info(`示例: ${this.invocation} ${command} ... ${normalizedFlag}`)
|
|
574
562
|
}
|
|
575
563
|
logger.info('未显式指定环境时将默认使用 --dev。')
|
|
576
564
|
process.exit(1)
|
|
577
565
|
}
|
|
578
566
|
|
|
579
567
|
getEnvironmentFlagExample(token) {
|
|
580
|
-
|
|
581
|
-
switch (key) {
|
|
568
|
+
switch (String(token || '').toLowerCase()) {
|
|
582
569
|
case 'dev':
|
|
570
|
+
case 'development':
|
|
583
571
|
return '--dev'
|
|
584
572
|
case 'prod':
|
|
573
|
+
case 'production':
|
|
585
574
|
return '--prod'
|
|
586
575
|
case 'staging':
|
|
587
576
|
return '--staging'
|
|
@@ -634,13 +623,13 @@ class DxCli {
|
|
|
634
623
|
}
|
|
635
624
|
|
|
636
625
|
validateStartPositionals(positionalArgs) {
|
|
637
|
-
const service = positionalArgs[0] || '
|
|
626
|
+
const service = positionalArgs[0] || 'development'
|
|
638
627
|
const environment = this.determineEnvironment()
|
|
639
628
|
const envKey = this.normalizeEnvKey(environment)
|
|
640
629
|
|
|
641
|
-
if (service === '
|
|
630
|
+
if (service === 'development' && envKey !== 'development') {
|
|
642
631
|
logger.error('dx start 在未指定服务时仅允许使用开发环境')
|
|
643
|
-
logger.info(`示例: ${this.invocation} start
|
|
632
|
+
logger.info(`示例: ${this.invocation} start --dev`)
|
|
644
633
|
logger.info(`示例: ${this.invocation} start backend --prod`)
|
|
645
634
|
process.exit(1)
|
|
646
635
|
}
|
|
@@ -649,7 +638,7 @@ class DxCli {
|
|
|
649
638
|
if (!startConfig) return
|
|
650
639
|
|
|
651
640
|
// 对 start 下的单层 command 配置,默认视为开发态目标,仅允许 --dev。
|
|
652
|
-
if (startConfig.command && envKey !== '
|
|
641
|
+
if (startConfig.command && envKey !== 'development') {
|
|
653
642
|
logger.error(`启动目标 ${service} 仅支持开发环境`)
|
|
654
643
|
logger.info(`示例: ${this.invocation} start ${service} --dev`)
|
|
655
644
|
process.exit(1)
|
|
@@ -669,13 +658,13 @@ class DxCli {
|
|
|
669
658
|
const buildConfig = this.commands?.build?.[target]
|
|
670
659
|
if (!buildConfig || buildConfig.command) return
|
|
671
660
|
|
|
672
|
-
const supportsCurrentEnv = Boolean(buildConfig[envKey]
|
|
661
|
+
const supportsCurrentEnv = Boolean(buildConfig[envKey])
|
|
673
662
|
if (supportsCurrentEnv) return
|
|
674
663
|
|
|
675
664
|
const envFlag = this.getEnvironmentFlagExample(envKey) || `--${envKey}`
|
|
676
665
|
logger.error(`构建目标 ${target} 不支持 ${envFlag} 环境`)
|
|
677
666
|
logger.info('显式传入环境标志时,必须是该 target 实际支持的环境。')
|
|
678
|
-
const available = ['
|
|
667
|
+
const available = ['development', 'staging', 'production', 'test', 'e2e']
|
|
679
668
|
.filter(key => key in buildConfig)
|
|
680
669
|
.map(key => this.getEnvironmentFlagExample(key) || `--${key}`)
|
|
681
670
|
if (available.length > 0) {
|
|
@@ -688,19 +677,6 @@ class DxCli {
|
|
|
688
677
|
process.exit(1)
|
|
689
678
|
}
|
|
690
679
|
|
|
691
|
-
reportDevCommandRemoved(args) {
|
|
692
|
-
const target = args?.[0]
|
|
693
|
-
logger.error('`dx dev` 命令已移除,统一使用 `dx start`。')
|
|
694
|
-
if (target) {
|
|
695
|
-
logger.info(`请执行: ${this.invocation} start ${target} --dev`)
|
|
696
|
-
} else {
|
|
697
|
-
logger.info(`示例: ${this.invocation} start backend --dev`)
|
|
698
|
-
logger.info(` ${this.invocation} start front --dev`)
|
|
699
|
-
logger.info(` ${this.invocation} start admin --dev`)
|
|
700
|
-
}
|
|
701
|
-
process.exit(1)
|
|
702
|
-
}
|
|
703
|
-
|
|
704
680
|
reportExtraPositionals(command, extras) {
|
|
705
681
|
const list = extras.join(', ')
|
|
706
682
|
if (command === '全局') {
|
|
@@ -772,7 +748,7 @@ class DxCli {
|
|
|
772
748
|
continue
|
|
773
749
|
}
|
|
774
750
|
commands.push({
|
|
775
|
-
command:
|
|
751
|
+
command: config.command,
|
|
776
752
|
options: {
|
|
777
753
|
app: config.app,
|
|
778
754
|
ports: config.ports,
|
|
@@ -820,22 +796,11 @@ class DxCli {
|
|
|
820
796
|
if (environment && config) {
|
|
821
797
|
const envKey = this.normalizeEnvKey(environment)
|
|
822
798
|
if (config[envKey]) config = config[envKey]
|
|
823
|
-
else if (envKey === 'staging' && config.prod) config = config.prod
|
|
824
799
|
}
|
|
825
800
|
|
|
826
801
|
return config
|
|
827
802
|
}
|
|
828
803
|
|
|
829
|
-
// SDK 构建命令当前不再暴露 --online/--offline 模式,保留该方法仅为兼容旧调用
|
|
830
|
-
applySdkModeFlags(command) {
|
|
831
|
-
return command
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
// 向后兼容的别名
|
|
835
|
-
applySdkOfflineFlag(command) {
|
|
836
|
-
return command
|
|
837
|
-
}
|
|
838
|
-
|
|
839
804
|
collectStartPorts(service, startConfig, envKey) {
|
|
840
805
|
const portSet = new Set()
|
|
841
806
|
|
|
@@ -845,15 +810,6 @@ class DxCli {
|
|
|
845
810
|
})
|
|
846
811
|
}
|
|
847
812
|
|
|
848
|
-
if (envKey === 'dev') {
|
|
849
|
-
const legacyConfig = this.commands.dev?.[service]
|
|
850
|
-
if (legacyConfig && Array.isArray(legacyConfig.ports)) {
|
|
851
|
-
legacyConfig.ports.forEach(port => {
|
|
852
|
-
this.addPortToSet(portSet, port)
|
|
853
|
-
})
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
|
|
857
813
|
return Array.from(portSet)
|
|
858
814
|
}
|
|
859
815
|
|
|
@@ -936,28 +892,6 @@ class DxCli {
|
|
|
936
892
|
}
|
|
937
893
|
|
|
938
894
|
const rawCommand = String(config.command).trim()
|
|
939
|
-
// backward compat: old commands.json referenced scripts/lib/*.js in the project
|
|
940
|
-
if (rawCommand.startsWith('node scripts/lib/sdk-build.js')) {
|
|
941
|
-
const argsText = rawCommand.replace(/^node\s+scripts\/lib\/sdk-build\.js\s*/g, '')
|
|
942
|
-
const args = argsText ? argsText.split(/\s+/).filter(Boolean) : []
|
|
943
|
-
await withTempEnv(async () => {
|
|
944
|
-
const { runSdkBuild } = await import('../sdk-build.js')
|
|
945
|
-
await runSdkBuild(args)
|
|
946
|
-
})
|
|
947
|
-
return
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
if (rawCommand.startsWith('node scripts/lib/backend-package.js')) {
|
|
951
|
-
const argsText = rawCommand.replace(/^node\s+scripts\/lib\/backend-package\.js\s*/g, '')
|
|
952
|
-
const args = argsText ? argsText.split(/\s+/).filter(Boolean) : []
|
|
953
|
-
await withTempEnv(async () => {
|
|
954
|
-
const { runBackendPackage } = await import('../backend-package.js')
|
|
955
|
-
await runBackendPackage(args)
|
|
956
|
-
})
|
|
957
|
-
return
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
const command = this.applySdkOfflineFlag(rawCommand)
|
|
961
895
|
|
|
962
896
|
const options = {
|
|
963
897
|
app: config.app,
|
|
@@ -969,7 +903,7 @@ class DxCli {
|
|
|
969
903
|
forcePortCleanup: Boolean(config.forcePortCleanup),
|
|
970
904
|
}
|
|
971
905
|
|
|
972
|
-
await execManager.executeCommand(
|
|
906
|
+
await execManager.executeCommand(rawCommand, options)
|
|
973
907
|
}
|
|
974
908
|
|
|
975
909
|
// 确定环境
|
|
@@ -977,17 +911,14 @@ class DxCli {
|
|
|
977
911
|
return envManager.detectEnvironment(this.flags)
|
|
978
912
|
}
|
|
979
913
|
|
|
980
|
-
// 规范化环境键到命令配置使用的命名(
|
|
914
|
+
// 规范化环境键到命令配置使用的命名(development/staging/production/test/e2e)
|
|
981
915
|
normalizeEnvKey(env) {
|
|
982
916
|
switch (String(env || '').toLowerCase()) {
|
|
983
917
|
case 'development':
|
|
984
|
-
|
|
985
|
-
return 'dev'
|
|
918
|
+
return 'development'
|
|
986
919
|
case 'production':
|
|
987
|
-
|
|
988
|
-
return 'prod'
|
|
920
|
+
return 'production'
|
|
989
921
|
case 'staging':
|
|
990
|
-
case 'stage':
|
|
991
922
|
return 'staging'
|
|
992
923
|
case 'test':
|
|
993
924
|
return 'test'
|
|
@@ -998,6 +929,23 @@ class DxCli {
|
|
|
998
929
|
}
|
|
999
930
|
}
|
|
1000
931
|
|
|
932
|
+
createExecutionFlags(environment) {
|
|
933
|
+
const envKey = this.normalizeEnvKey(environment)
|
|
934
|
+
const execFlags = { ...this.flags }
|
|
935
|
+
|
|
936
|
+
;['dev', 'prod', 'staging', 'test', 'e2e'].forEach(key => {
|
|
937
|
+
delete execFlags[key]
|
|
938
|
+
})
|
|
939
|
+
|
|
940
|
+
if (envKey === 'production') execFlags.prod = true
|
|
941
|
+
else if (envKey === 'development') execFlags.dev = true
|
|
942
|
+
else if (envKey === 'test') execFlags.test = true
|
|
943
|
+
else if (envKey === 'e2e') execFlags.e2e = true
|
|
944
|
+
else if (envKey === 'staging') execFlags.staging = true
|
|
945
|
+
|
|
946
|
+
return execFlags
|
|
947
|
+
}
|
|
948
|
+
|
|
1001
949
|
}
|
|
1002
950
|
|
|
1003
951
|
export { DxCli }
|
package/lib/cli/flags.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
export const FLAG_DEFINITIONS = {
|
|
2
2
|
_global: [
|
|
3
3
|
{ flag: '--dev' },
|
|
4
|
-
{ flag: '--development' },
|
|
5
4
|
{ flag: '--prod' },
|
|
6
|
-
{ flag: '--production' },
|
|
7
5
|
{ flag: '--staging' },
|
|
8
|
-
{ flag: '--stage' },
|
|
9
6
|
{ flag: '--test' },
|
|
10
7
|
{ flag: '--e2e' },
|
|
11
8
|
{ flag: '--no-env-check' },
|
|
@@ -59,15 +56,12 @@ export function parseFlags(args = []) {
|
|
|
59
56
|
if (!flag.startsWith('-')) continue
|
|
60
57
|
switch (flag) {
|
|
61
58
|
case '--dev':
|
|
62
|
-
case '--development':
|
|
63
59
|
flags.dev = true
|
|
64
60
|
break
|
|
65
61
|
case '--prod':
|
|
66
|
-
case '--production':
|
|
67
62
|
flags.prod = true
|
|
68
63
|
break
|
|
69
64
|
case '--staging':
|
|
70
|
-
case '--stage':
|
|
71
65
|
flags.staging = true
|
|
72
66
|
break
|
|
73
67
|
case '--test':
|