@ranger1/dx 0.1.78 → 0.1.80
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/README.md +10 -2
- package/codex/agents/fixer.toml +2 -0
- package/codex/agents/orchestrator.toml +2 -0
- package/codex/agents/reviewer.toml +2 -0
- package/codex/agents/spark.toml +2 -1
- package/codex/skills/doctor/SKILL.md +1 -1
- package/codex/skills/doctor/scripts/doctor.sh +35 -42
- package/lib/cli/commands/core.js +24 -1
- package/lib/cli/commands/db.js +6 -4
- package/lib/cli/dx-cli.js +74 -0
- package/lib/cli/help.js +38 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -188,7 +188,7 @@ dx 的命令由 `dx/config/commands.json` 驱动,并且内置了一些 interna
|
|
|
188
188
|
|
|
189
189
|
```bash
|
|
190
190
|
dx start backend --dev
|
|
191
|
-
dx start all
|
|
191
|
+
dx start all --dev
|
|
192
192
|
dx build backend --prod
|
|
193
193
|
dx build sdk --dev
|
|
194
194
|
dx db generate
|
|
@@ -196,9 +196,17 @@ dx db migrate --dev --name init
|
|
|
196
196
|
dx db deploy --prod -Y
|
|
197
197
|
dx deploy front --staging
|
|
198
198
|
dx lint
|
|
199
|
-
dx test e2e backend
|
|
199
|
+
dx test e2e backend apps/backend/e2e/auth
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
+
命令约束摘要:
|
|
203
|
+
|
|
204
|
+
- `dx test e2e backend` 必须提供文件或目录路径,禁止无路径全量执行
|
|
205
|
+
- `dx db migrate` 仅允许在 `--dev` 环境创建迁移;非开发环境请使用 `dx db deploy`
|
|
206
|
+
- `dx start` 未指定服务时默认是开发套件,仅允许 `--dev`
|
|
207
|
+
- `dx start` 下的单层目标(如 `stagewise-front`)默认仅支持 `--dev`
|
|
208
|
+
- `dx build` 显式传入环境标志时,必须是该 target 实际支持的环境
|
|
209
|
+
|
|
202
210
|
### `dx start stack` 配置详解(PM2 交互式服务栈)
|
|
203
211
|
|
|
204
212
|
从 `0.1.78` 起,`dx start stack` 推荐完全由 `dx/config/commands.json` 配置驱动,不再依赖硬编码服务列表。
|
package/codex/agents/fixer.toml
CHANGED
package/codex/agents/spark.toml
CHANGED
|
@@ -2,6 +2,8 @@ model = "gpt-5.3-codex"
|
|
|
2
2
|
model_reasoning_effort = "medium"
|
|
3
3
|
approval_policy = "never"
|
|
4
4
|
sandbox_mode = "workspace-write"
|
|
5
|
+
|
|
6
|
+
[sandbox_workspace_write]
|
|
5
7
|
network_access = true
|
|
6
8
|
|
|
7
9
|
developer_instructions = '''
|
|
@@ -18,4 +20,3 @@ prompt是一个文件路径并不存在时,必须返回结构化错误:{"err
|
|
|
18
20
|
|
|
19
21
|
'''
|
|
20
22
|
|
|
21
|
-
|
|
@@ -57,7 +57,7 @@ bash "$CODEX_HOME/skills/doctor/scripts/doctor.sh" --max-rounds 3
|
|
|
57
57
|
- 自动修复:确保 `~/.codex/config.toml` 含以下目标值(缺失补齐、值不符覆盖):
|
|
58
58
|
- `[features] multi_agent = true`
|
|
59
59
|
- `[agents] max_threads = 15`
|
|
60
|
-
- `[agents.fixer] description/
|
|
60
|
+
- `[agents.fixer] description/config_file`
|
|
61
61
|
- `[agents.orchestrator] description/config_file`
|
|
62
62
|
- `[agents.reviewer] description/config_file`
|
|
63
63
|
- `[agents.spark] description/config_file`
|
|
@@ -233,7 +233,7 @@ ensure_codex_config() {
|
|
|
233
233
|
in_features=0; in_agents=0; in_fixer=0; in_orch=0; in_reviewer=0; in_spark=0;
|
|
234
234
|
features_emitted=0; agents_emitted=0; fixer_emitted=0; orch_emitted=0; reviewer_emitted=0; spark_emitted=0;
|
|
235
235
|
features_multi_written=0; agents_max_threads_written=0;
|
|
236
|
-
fixer_desc_written=0;
|
|
236
|
+
fixer_desc_written=0; fixer_cfg_written=0;
|
|
237
237
|
orch_desc_written=0; orch_cfg_written=0;
|
|
238
238
|
reviewer_desc_written=0; reviewer_cfg_written=0;
|
|
239
239
|
spark_desc_written=0; spark_cfg_written=0;
|
|
@@ -252,24 +252,23 @@ ensure_codex_config() {
|
|
|
252
252
|
}
|
|
253
253
|
function flush_fixer() {
|
|
254
254
|
if (!fixer_emitted) return;
|
|
255
|
-
if (!fixer_desc_written) print "description = \"
|
|
256
|
-
if (!
|
|
257
|
-
if (!fixer_cfg_written) print "config_file = \"~/.codex/agents/fixer.toml\"";
|
|
255
|
+
if (!fixer_desc_written) print "description = \"bugfix 代理\"";
|
|
256
|
+
if (!fixer_cfg_written) print "config_file = \"agents/fixer.toml\"";
|
|
258
257
|
}
|
|
259
258
|
function flush_orch() {
|
|
260
259
|
if (!orch_emitted) return;
|
|
261
|
-
if (!orch_desc_written) print "description = \"
|
|
262
|
-
if (!orch_cfg_written) print "config_file = \"
|
|
260
|
+
if (!orch_desc_written) print "description = \"pr 修复流程编排代理\"";
|
|
261
|
+
if (!orch_cfg_written) print "config_file = \"agents/orchestrator.toml\"";
|
|
263
262
|
}
|
|
264
263
|
function flush_reviewer() {
|
|
265
264
|
if (!reviewer_emitted) return;
|
|
266
|
-
if (!reviewer_desc_written) print "description = \"
|
|
267
|
-
if (!reviewer_cfg_written) print "config_file = \"
|
|
265
|
+
if (!reviewer_desc_written) print "description = \"代码评审代理\"";
|
|
266
|
+
if (!reviewer_cfg_written) print "config_file = \"agents/reviewer.toml\"";
|
|
268
267
|
}
|
|
269
268
|
function flush_spark() {
|
|
270
269
|
if (!spark_emitted) return;
|
|
271
|
-
if (!spark_desc_written) print "description = \"
|
|
272
|
-
if (!spark_cfg_written) print "config_file = \"
|
|
270
|
+
if (!spark_desc_written) print "description = \"通用执行代理\"";
|
|
271
|
+
if (!spark_cfg_written) print "config_file = \"agents/spark.toml\"";
|
|
273
272
|
}
|
|
274
273
|
function flush_active_section() {
|
|
275
274
|
if (in_features) flush_features();
|
|
@@ -332,42 +331,38 @@ ensure_codex_config() {
|
|
|
332
331
|
}
|
|
333
332
|
|
|
334
333
|
if (in_fixer && match(t, /^description[[:space:]]*=/)) {
|
|
335
|
-
if (!fixer_desc_written) { print "description = \"
|
|
336
|
-
next;
|
|
337
|
-
}
|
|
338
|
-
if (in_fixer && match(t, /^model_reasoning_effort[[:space:]]*=/)) {
|
|
339
|
-
if (!fixer_reasoning_written) { print "model_reasoning_effort = \"medium\""; fixer_reasoning_written=1; }
|
|
334
|
+
if (!fixer_desc_written) { print "description = \"bugfix 代理\""; fixer_desc_written=1; }
|
|
340
335
|
next;
|
|
341
336
|
}
|
|
342
337
|
if (in_fixer && match(t, /^config_file[[:space:]]*=/)) {
|
|
343
|
-
if (!fixer_cfg_written) { print "config_file = \"
|
|
338
|
+
if (!fixer_cfg_written) { print "config_file = \"agents/fixer.toml\""; fixer_cfg_written=1; }
|
|
344
339
|
next;
|
|
345
340
|
}
|
|
346
341
|
|
|
347
342
|
if (in_orch && match(t, /^description[[:space:]]*=/)) {
|
|
348
|
-
if (!orch_desc_written) { print "description = \"
|
|
343
|
+
if (!orch_desc_written) { print "description = \"pr 修复流程编排代理\""; orch_desc_written=1; }
|
|
349
344
|
next;
|
|
350
345
|
}
|
|
351
346
|
if (in_orch && match(t, /^config_file[[:space:]]*=/)) {
|
|
352
|
-
if (!orch_cfg_written) { print "config_file = \"
|
|
347
|
+
if (!orch_cfg_written) { print "config_file = \"agents/orchestrator.toml\""; orch_cfg_written=1; }
|
|
353
348
|
next;
|
|
354
349
|
}
|
|
355
350
|
|
|
356
351
|
if (in_reviewer && match(t, /^description[[:space:]]*=/)) {
|
|
357
|
-
if (!reviewer_desc_written) { print "description = \"
|
|
352
|
+
if (!reviewer_desc_written) { print "description = \"代码评审代理\""; reviewer_desc_written=1; }
|
|
358
353
|
next;
|
|
359
354
|
}
|
|
360
355
|
if (in_reviewer && match(t, /^config_file[[:space:]]*=/)) {
|
|
361
|
-
if (!reviewer_cfg_written) { print "config_file = \"
|
|
356
|
+
if (!reviewer_cfg_written) { print "config_file = \"agents/reviewer.toml\""; reviewer_cfg_written=1; }
|
|
362
357
|
next;
|
|
363
358
|
}
|
|
364
359
|
|
|
365
360
|
if (in_spark && match(t, /^description[[:space:]]*=/)) {
|
|
366
|
-
if (!spark_desc_written) { print "description = \"
|
|
361
|
+
if (!spark_desc_written) { print "description = \"通用执行代理\""; spark_desc_written=1; }
|
|
367
362
|
next;
|
|
368
363
|
}
|
|
369
364
|
if (in_spark && match(t, /^config_file[[:space:]]*=/)) {
|
|
370
|
-
if (!spark_cfg_written) { print "config_file = \"
|
|
365
|
+
if (!spark_cfg_written) { print "config_file = \"agents/spark.toml\""; spark_cfg_written=1; }
|
|
371
366
|
next;
|
|
372
367
|
}
|
|
373
368
|
|
|
@@ -389,27 +384,26 @@ ensure_codex_config() {
|
|
|
389
384
|
if (!fixer_emitted) {
|
|
390
385
|
print "";
|
|
391
386
|
print "[agents.fixer]";
|
|
392
|
-
print "description = \"
|
|
393
|
-
print "
|
|
394
|
-
print "config_file = \"~/.codex/agents/fixer.toml\"";
|
|
387
|
+
print "description = \"bugfix 代理\"";
|
|
388
|
+
print "config_file = \"agents/fixer.toml\"";
|
|
395
389
|
}
|
|
396
390
|
if (!orch_emitted) {
|
|
397
391
|
print "";
|
|
398
392
|
print "[agents.orchestrator]";
|
|
399
|
-
print "description = \"
|
|
400
|
-
print "config_file = \"
|
|
393
|
+
print "description = \"pr 修复流程编排代理\"";
|
|
394
|
+
print "config_file = \"agents/orchestrator.toml\"";
|
|
401
395
|
}
|
|
402
396
|
if (!reviewer_emitted) {
|
|
403
397
|
print "";
|
|
404
398
|
print "[agents.reviewer]";
|
|
405
|
-
print "description = \"
|
|
406
|
-
print "config_file = \"
|
|
399
|
+
print "description = \"代码评审代理\"";
|
|
400
|
+
print "config_file = \"agents/reviewer.toml\"";
|
|
407
401
|
}
|
|
408
402
|
if (!spark_emitted) {
|
|
409
403
|
print "";
|
|
410
404
|
print "[agents.spark]";
|
|
411
|
-
print "description = \"
|
|
412
|
-
print "config_file = \"
|
|
405
|
+
print "description = \"通用执行代理\"";
|
|
406
|
+
print "config_file = \"agents/spark.toml\"";
|
|
413
407
|
}
|
|
414
408
|
}' "$cfg_file" >"$tmp_file"
|
|
415
409
|
|
|
@@ -424,7 +418,7 @@ check_codex_config() {
|
|
|
424
418
|
awk '
|
|
425
419
|
BEGIN {
|
|
426
420
|
in_features=0; in_agents=0; in_fixer=0; in_orch=0; in_reviewer=0; in_spark=0;
|
|
427
|
-
ok_features=0; ok_threads=0; ok_fixer_desc=0;
|
|
421
|
+
ok_features=0; ok_threads=0; ok_fixer_desc=0; ok_fixer_cfg=0;
|
|
428
422
|
ok_orch_desc=0; ok_orch_cfg=0; ok_reviewer_desc=0; ok_reviewer_cfg=0; ok_spark_desc=0; ok_spark_cfg=0;
|
|
429
423
|
}
|
|
430
424
|
function trim(s) { gsub(/^[[:space:]]+|[[:space:]]+$/, "", s); return s }
|
|
@@ -442,19 +436,18 @@ check_codex_config() {
|
|
|
442
436
|
}
|
|
443
437
|
if (in_features && line ~ /^multi_agent[[:space:]]*=[[:space:]]*true$/) ok_features=1;
|
|
444
438
|
if (in_agents && line ~ /^max_threads[[:space:]]*=[[:space:]]*15$/) ok_threads=1;
|
|
445
|
-
if (in_fixer && line ~ /^description[[:space:]]*=[[:space:]]*"
|
|
446
|
-
if (in_fixer && line ~ /^
|
|
447
|
-
if (
|
|
448
|
-
if (in_orch && line ~ /^
|
|
449
|
-
if (
|
|
450
|
-
if (in_reviewer && line ~ /^
|
|
451
|
-
if (
|
|
452
|
-
if (in_spark && line ~ /^
|
|
453
|
-
if (in_spark && line ~ /^config_file[[:space:]]*=[[:space:]]*"~\/\.codex\/agents\/spark\.toml"$/) ok_spark_cfg=1;
|
|
439
|
+
if (in_fixer && line ~ /^description[[:space:]]*=[[:space:]]*"bugfix 代理"$/) ok_fixer_desc=1;
|
|
440
|
+
if (in_fixer && line ~ /^config_file[[:space:]]*=[[:space:]]*"agents\/fixer\.toml"$/) ok_fixer_cfg=1;
|
|
441
|
+
if (in_orch && line ~ /^description[[:space:]]*=[[:space:]]*"pr 修复流程编排代理"$/) ok_orch_desc=1;
|
|
442
|
+
if (in_orch && line ~ /^config_file[[:space:]]*=[[:space:]]*"agents\/orchestrator\.toml"$/) ok_orch_cfg=1;
|
|
443
|
+
if (in_reviewer && line ~ /^description[[:space:]]*=[[:space:]]*"代码评审代理"$/) ok_reviewer_desc=1;
|
|
444
|
+
if (in_reviewer && line ~ /^config_file[[:space:]]*=[[:space:]]*"agents\/reviewer\.toml"$/) ok_reviewer_cfg=1;
|
|
445
|
+
if (in_spark && line ~ /^description[[:space:]]*=[[:space:]]*"通用执行代理"$/) ok_spark_desc=1;
|
|
446
|
+
if (in_spark && line ~ /^config_file[[:space:]]*=[[:space:]]*"agents\/spark\.toml"$/) ok_spark_cfg=1;
|
|
454
447
|
}
|
|
455
448
|
END {
|
|
456
449
|
ok = ok_features && ok_threads &&
|
|
457
|
-
ok_fixer_desc &&
|
|
450
|
+
ok_fixer_desc && ok_fixer_cfg &&
|
|
458
451
|
ok_orch_desc && ok_orch_cfg &&
|
|
459
452
|
ok_reviewer_desc && ok_reviewer_cfg &&
|
|
460
453
|
ok_spark_desc && ok_spark_cfg;
|
package/lib/cli/commands/core.js
CHANGED
|
@@ -17,6 +17,8 @@ export async function handleBuild(cli, args) {
|
|
|
17
17
|
const target = args[0] || 'all'
|
|
18
18
|
const environment = cli.determineEnvironment()
|
|
19
19
|
const envKey = cli.normalizeEnvKey(environment)
|
|
20
|
+
const explicitEnv =
|
|
21
|
+
Boolean(cli.flags.dev || cli.flags.prod || cli.flags.staging || cli.flags.test || cli.flags.e2e)
|
|
20
22
|
|
|
21
23
|
const buildConfig = cli.commands.build[target]
|
|
22
24
|
if (!buildConfig) {
|
|
@@ -36,6 +38,27 @@ export async function handleBuild(cli, args) {
|
|
|
36
38
|
// 处理嵌套配置
|
|
37
39
|
let config = buildConfig
|
|
38
40
|
if (typeof config === 'object' && !config.command) {
|
|
41
|
+
const supportsCurrentEnv = Boolean(
|
|
42
|
+
config[envKey] || (envKey === 'staging' && config.prod),
|
|
43
|
+
)
|
|
44
|
+
if (explicitEnv && !supportsCurrentEnv) {
|
|
45
|
+
const envFlag = cli.getEnvironmentFlagExample(envKey) || `--${envKey}`
|
|
46
|
+
logger.error(`构建目标 ${target} 不支持 ${envFlag} 环境`)
|
|
47
|
+
logger.info('显式传入环境标志时,必须是该 target 实际支持的环境。')
|
|
48
|
+
const available = ['dev', 'staging', 'prod', 'test', 'e2e']
|
|
49
|
+
.filter(key => key in config)
|
|
50
|
+
.map(key => cli.getEnvironmentFlagExample(key) || `--${key}`)
|
|
51
|
+
if (available.length > 0) {
|
|
52
|
+
logger.info(`支持的环境: ${available.join(', ')}`)
|
|
53
|
+
logger.info(`示例: ${cli.invocation} build ${target} ${available[0]}`)
|
|
54
|
+
if (available.length > 1) {
|
|
55
|
+
logger.info(`示例: ${cli.invocation} build ${target} ${available[1]}`)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
process.exitCode = 1
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
39
62
|
// 如果是嵌套配置,尝试获取环境特定的配置(兼容 dev/prod 与 development/production 命名)
|
|
40
63
|
if (config[envKey]) config = config[envKey]
|
|
41
64
|
else if (envKey === 'staging' && config.prod) config = config.prod
|
|
@@ -81,7 +104,7 @@ export async function handleTest(cli, args) {
|
|
|
81
104
|
|
|
82
105
|
// 如果提供了测试文件路径,使用专门的单文件测试配置
|
|
83
106
|
if (testPath && type === 'e2e' && target === 'backend') {
|
|
84
|
-
let command = `
|
|
107
|
+
let command = `npx nx test:e2e backend -- ${testPath}`
|
|
85
108
|
|
|
86
109
|
// 如果指定了测试用例名称,添加 -t 参数
|
|
87
110
|
if (testNamePattern) {
|
package/lib/cli/commands/db.js
CHANGED
|
@@ -21,12 +21,14 @@ export async function handleDatabase(cli, args) {
|
|
|
21
21
|
const environment = cli.determineEnvironment()
|
|
22
22
|
const envKey = cli.normalizeEnvKey(environment)
|
|
23
23
|
|
|
24
|
-
//
|
|
24
|
+
// 创建迁移只允许在开发环境进行,避免 AI/用户在非开发环境误执行
|
|
25
25
|
if (action === 'migrate' && envKey && envKey !== 'dev') {
|
|
26
26
|
const envFlag = cli.getEnvironmentFlagExample(envKey) || `--${envKey}`
|
|
27
|
-
logger.
|
|
28
|
-
logger.info('
|
|
29
|
-
logger.info(
|
|
27
|
+
logger.error('dx db migrate 仅允许在 --dev 环境下创建迁移')
|
|
28
|
+
logger.info('请使用 `dx db migrate --dev --name <migration-name>` 创建新迁移。')
|
|
29
|
+
logger.info(`非开发环境请改用: ${cli.invocation} db deploy ${envFlag}`)
|
|
30
|
+
process.exitCode = 1
|
|
31
|
+
return
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
// 处理 script 子命令
|
package/lib/cli/dx-cli.js
CHANGED
|
@@ -456,6 +456,7 @@ class DxCli {
|
|
|
456
456
|
ensureMax(1)
|
|
457
457
|
break
|
|
458
458
|
case 'build': {
|
|
459
|
+
this.validateBuildPositionals(positionalArgs)
|
|
459
460
|
if (positionalArgs.length >= 2 && this.isEnvironmentToken(positionalArgs[1])) {
|
|
460
461
|
this.reportEnvironmentFlagRequired(command, positionalArgs[1], positionalArgs)
|
|
461
462
|
}
|
|
@@ -497,6 +498,7 @@ class DxCli {
|
|
|
497
498
|
break
|
|
498
499
|
}
|
|
499
500
|
case 'test':
|
|
501
|
+
this.validateTestPositionals(positionalArgs)
|
|
500
502
|
ensureMax(3)
|
|
501
503
|
break
|
|
502
504
|
case 'worktree': {
|
|
@@ -516,6 +518,7 @@ class DxCli {
|
|
|
516
518
|
break
|
|
517
519
|
}
|
|
518
520
|
case 'start': {
|
|
521
|
+
this.validateStartPositionals(positionalArgs)
|
|
519
522
|
const extras = positionalArgs.slice(1)
|
|
520
523
|
const envToken = extras.find(token => this.isEnvironmentToken(token))
|
|
521
524
|
if (envToken) {
|
|
@@ -604,6 +607,77 @@ class DxCli {
|
|
|
604
607
|
return parts.concat(rest).join(' ')
|
|
605
608
|
}
|
|
606
609
|
|
|
610
|
+
validateTestPositionals(positionalArgs) {
|
|
611
|
+
if (positionalArgs.length === 0) return
|
|
612
|
+
|
|
613
|
+
const [type = 'e2e', target = 'all', testPath] = positionalArgs
|
|
614
|
+
|
|
615
|
+
if (type === 'e2e' && target === 'backend' && !testPath) {
|
|
616
|
+
logger.error('dx test e2e backend 必须提供测试文件或目录路径')
|
|
617
|
+
logger.info(`示例: ${this.invocation} test e2e backend apps/backend/e2e/auth`)
|
|
618
|
+
logger.info(
|
|
619
|
+
`示例: ${this.invocation} test e2e backend apps/backend/e2e/auth/auth.login.e2e-spec.ts -t "should login"`,
|
|
620
|
+
)
|
|
621
|
+
logger.info('说明: 为避免误触发全量 E2E,backend E2E 仅允许按文件或目录增量执行')
|
|
622
|
+
process.exit(1)
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
validateStartPositionals(positionalArgs) {
|
|
627
|
+
const service = positionalArgs[0] || 'dev'
|
|
628
|
+
const environment = this.determineEnvironment()
|
|
629
|
+
const envKey = this.normalizeEnvKey(environment)
|
|
630
|
+
|
|
631
|
+
if (service === 'dev' && envKey !== 'dev') {
|
|
632
|
+
logger.error('dx start 在未指定服务时仅允许使用开发环境')
|
|
633
|
+
logger.info(`示例: ${this.invocation} start all --dev`)
|
|
634
|
+
logger.info(`示例: ${this.invocation} start backend --prod`)
|
|
635
|
+
process.exit(1)
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const startConfig = this.commands?.start?.[service]
|
|
639
|
+
if (!startConfig) return
|
|
640
|
+
|
|
641
|
+
// 对 start 下的单层 command 配置,默认视为开发态目标,仅允许 --dev。
|
|
642
|
+
if (startConfig.command && envKey !== 'dev') {
|
|
643
|
+
logger.error(`启动目标 ${service} 仅支持开发环境`)
|
|
644
|
+
logger.info(`示例: ${this.invocation} start ${service} --dev`)
|
|
645
|
+
process.exit(1)
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
validateBuildPositionals(positionalArgs) {
|
|
650
|
+
const target = positionalArgs[0] || 'all'
|
|
651
|
+
const environment = this.determineEnvironment()
|
|
652
|
+
const envKey = this.normalizeEnvKey(environment)
|
|
653
|
+
const explicitEnv = Boolean(
|
|
654
|
+
this.flags.dev || this.flags.prod || this.flags.staging || this.flags.test || this.flags.e2e,
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
if (!explicitEnv) return
|
|
658
|
+
|
|
659
|
+
const buildConfig = this.commands?.build?.[target]
|
|
660
|
+
if (!buildConfig || buildConfig.command) return
|
|
661
|
+
|
|
662
|
+
const supportsCurrentEnv = Boolean(buildConfig[envKey] || (envKey === 'staging' && buildConfig.prod))
|
|
663
|
+
if (supportsCurrentEnv) return
|
|
664
|
+
|
|
665
|
+
const envFlag = this.getEnvironmentFlagExample(envKey) || `--${envKey}`
|
|
666
|
+
logger.error(`构建目标 ${target} 不支持 ${envFlag} 环境`)
|
|
667
|
+
logger.info('显式传入环境标志时,必须是该 target 实际支持的环境。')
|
|
668
|
+
const available = ['dev', 'staging', 'prod', 'test', 'e2e']
|
|
669
|
+
.filter(key => key in buildConfig)
|
|
670
|
+
.map(key => this.getEnvironmentFlagExample(key) || `--${key}`)
|
|
671
|
+
if (available.length > 0) {
|
|
672
|
+
logger.info(`支持的环境: ${available.join(', ')}`)
|
|
673
|
+
logger.info(`示例: ${this.invocation} build ${target} ${available[0]}`)
|
|
674
|
+
if (available.length > 1) {
|
|
675
|
+
logger.info(`示例: ${this.invocation} build ${target} ${available[1]}`)
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
process.exit(1)
|
|
679
|
+
}
|
|
680
|
+
|
|
607
681
|
reportDevCommandRemoved(args) {
|
|
608
682
|
const target = args?.[0]
|
|
609
683
|
logger.error('`dx dev` 命令已移除,统一使用 `dx start`。')
|
package/lib/cli/help.js
CHANGED
|
@@ -44,8 +44,9 @@ export function showHelp() {
|
|
|
44
44
|
' test [type] [target] [path] [-t pattern] 运行测试',
|
|
45
45
|
' type: e2e, unit (默认: e2e)',
|
|
46
46
|
' target: backend, all (默认: all)',
|
|
47
|
-
' path:
|
|
48
|
-
' -t pattern: 指定测试用例名称模式 (可选,需要和path一起使用)',
|
|
47
|
+
' path: 测试文件或目录路径 (必填,仅支持 e2e backend)',
|
|
48
|
+
' -t pattern: 指定测试用例名称模式 (可选,需要和 path 一起使用)',
|
|
49
|
+
' 说明: backend E2E 禁止无路径全量执行',
|
|
49
50
|
'',
|
|
50
51
|
' worktree [action] [num...] Git Worktree管理',
|
|
51
52
|
' action: make, del, list, clean',
|
|
@@ -90,9 +91,9 @@ export function showHelp() {
|
|
|
90
91
|
' dx build all --prod # 构建所有应用(生产环境)',
|
|
91
92
|
' dx db deploy --dev # 应用开发环境数据库迁移',
|
|
92
93
|
' dx db reset --prod -Y # 重置生产数据库(跳过确认)',
|
|
93
|
-
' dx test e2e backend
|
|
94
|
-
' dx test e2e backend e2e/activity/activity.admin.e2e-spec.ts # 运行单个E2E测试文件',
|
|
95
|
-
' dx test e2e backend e2e/activity/activity.admin.e2e-spec.ts -t "should list all activity definitions" # 运行特定测试用例',
|
|
94
|
+
' dx test e2e backend apps/backend/e2e/auth # 按目录运行后端 E2E',
|
|
95
|
+
' dx test e2e backend apps/backend/e2e/activity/activity.admin.e2e-spec.ts # 运行单个E2E测试文件',
|
|
96
|
+
' dx test e2e backend apps/backend/e2e/activity/activity.admin.e2e-spec.ts -t "should list all activity definitions" # 运行特定测试用例',
|
|
96
97
|
' dx deploy front --staging # 部署前端到 Vercel(staging)',
|
|
97
98
|
' dx worktree make 88 # 为issue #88创建worktree',
|
|
98
99
|
' dx worktree del 88 # 删除issue #88的worktree',
|
|
@@ -131,6 +132,9 @@ build 命令用法:
|
|
|
131
132
|
target: backend, front, admin, shared, mobile, sdk, all, affected
|
|
132
133
|
环境标志: --dev、--staging、--prod、--test、--e2e(默认 --dev)
|
|
133
134
|
|
|
135
|
+
限制说明:
|
|
136
|
+
显式传入环境标志时,必须是该 target 实际支持的环境;不支持时会直接报错
|
|
137
|
+
|
|
134
138
|
常见示例:
|
|
135
139
|
dx build backend --staging # 使用 staging 环境变量构建后端 (prod 流程)
|
|
136
140
|
dx build front --prod # 强制以生产配置构建前端
|
|
@@ -159,6 +163,8 @@ db 命令用法:
|
|
|
159
163
|
|
|
160
164
|
帮助提示:
|
|
161
165
|
- 未提供迁移名称时命令会直接报错退出,避免 Prisma 进入交互式输入
|
|
166
|
+
- 仅允许在开发环境使用 \`dx db migrate --dev --name <migration-name>\` 创建迁移
|
|
167
|
+
- 非开发环境请使用 dx db deploy
|
|
162
168
|
- 使用模式示例: dx db migrate --dev --name init-user-table
|
|
163
169
|
- 如需仅执行已有迁移(本地/CI/生产),请使用 dx db deploy(无需 --name)
|
|
164
170
|
|
|
@@ -220,11 +226,38 @@ start 命令用法:
|
|
|
220
226
|
环境说明:
|
|
221
227
|
支持 --dev、--staging、--prod、--test、--e2e。--staging 会注入 .env.staging*. 层并复用 prod 启动流程
|
|
222
228
|
|
|
229
|
+
限制说明:
|
|
230
|
+
未指定 service 时默认使用 dev 套件,仅允许 --dev
|
|
231
|
+
stagewise 等单层 start 目标默认视为开发态目标,仅允许 --dev
|
|
232
|
+
|
|
223
233
|
常见示例:
|
|
224
234
|
dx start backend --staging # 使用 staging 配置启动后端 (生产模式流程)
|
|
225
235
|
dx start stagewise-front # Stagewise 桥接用户前端,端口 3001 -> 3002
|
|
226
236
|
|
|
227
237
|
提示: service 省略时默认启动 dev 套件,可结合 --dev/--staging/--prod 标志使用。
|
|
238
|
+
`)
|
|
239
|
+
return
|
|
240
|
+
|
|
241
|
+
case 'test':
|
|
242
|
+
console.log(`
|
|
243
|
+
test 命令用法:
|
|
244
|
+
dx test [type] [target] [path] [-t pattern]
|
|
245
|
+
|
|
246
|
+
参数说明:
|
|
247
|
+
type: e2e, unit (默认: e2e)
|
|
248
|
+
target: backend, all (默认: all)
|
|
249
|
+
path: 仅 e2e backend 支持,且必须提供文件或目录路径
|
|
250
|
+
-t pattern: 指定测试用例名称模式,需要和 path 一起使用
|
|
251
|
+
|
|
252
|
+
限制说明:
|
|
253
|
+
backend E2E 禁止无路径全量执行,缺少 path 时命令会直接报错退出。
|
|
254
|
+
|
|
255
|
+
常见示例:
|
|
256
|
+
dx test e2e backend apps/backend/e2e/auth
|
|
257
|
+
dx test e2e backend apps/backend/e2e/auth/auth.login.e2e-spec.ts
|
|
258
|
+
dx test e2e backend apps/backend/e2e/auth/auth.login.e2e-spec.ts -t "should login"
|
|
259
|
+
dx test unit front
|
|
260
|
+
dx test unit admin
|
|
228
261
|
`)
|
|
229
262
|
return
|
|
230
263
|
|