@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 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` 配置驱动,不再依赖硬编码服务列表。
@@ -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 = '''
@@ -2,6 +2,8 @@ model = "gpt-5.3-codex"
2
2
  model_reasoning_effort = "low"
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 = '''
@@ -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 = '''
@@ -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/model_reasoning_effort/config_file`
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; fixer_reasoning_written=0; fixer_cfg_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 = \"bug fixer\"";
256
- if (!fixer_reasoning_written) print "model_reasoning_effort = \"medium\"";
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 = \"orchestrator\"";
262
- if (!orch_cfg_written) print "config_file = \"~/.codex/agents/orchestrator.toml\"";
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 = \"reviewer\"";
267
- if (!reviewer_cfg_written) print "config_file = \"~/.codex/agents/reviewer.toml\"";
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 = \"spark\"";
272
- if (!spark_cfg_written) print "config_file = \"~/.codex/agents/spark.toml\"";
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 = \"bug fixer\""; fixer_desc_written=1; }
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 = \"~/.codex/agents/fixer.toml\""; fixer_cfg_written=1; }
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 = \"orchestrator\""; orch_desc_written=1; }
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 = \"~/.codex/agents/orchestrator.toml\""; orch_cfg_written=1; }
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 = \"reviewer\""; reviewer_desc_written=1; }
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 = \"~/.codex/agents/reviewer.toml\""; reviewer_cfg_written=1; }
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 = \"spark\""; spark_desc_written=1; }
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 = \"~/.codex/agents/spark.toml\""; spark_cfg_written=1; }
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 = \"bug fixer\"";
393
- print "model_reasoning_effort = \"medium\"";
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 = \"orchestrator\"";
400
- print "config_file = \"~/.codex/agents/orchestrator.toml\"";
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 = \"reviewer\"";
406
- print "config_file = \"~/.codex/agents/reviewer.toml\"";
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 = \"spark\"";
412
- print "config_file = \"~/.codex/agents/spark.toml\"";
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; ok_fixer_reason=0; ok_fixer_cfg=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:]]*"bug fixer"$/) ok_fixer_desc=1;
446
- if (in_fixer && line ~ /^model_reasoning_effort[[:space:]]*=[[:space:]]*"medium"$/) ok_fixer_reason=1;
447
- if (in_fixer && line ~ /^config_file[[:space:]]*=[[:space:]]*"~\/\.codex\/agents\/fixer\.toml"$/) ok_fixer_cfg=1;
448
- if (in_orch && line ~ /^description[[:space:]]*=[[:space:]]*"orchestrator"$/) ok_orch_desc=1;
449
- if (in_orch && line ~ /^config_file[[:space:]]*=[[:space:]]*"~\/\.codex\/agents\/orchestrator\.toml"$/) ok_orch_cfg=1;
450
- if (in_reviewer && line ~ /^description[[:space:]]*=[[:space:]]*"reviewer"$/) ok_reviewer_desc=1;
451
- if (in_reviewer && line ~ /^config_file[[:space:]]*=[[:space:]]*"~\/\.codex\/agents\/reviewer\.toml"$/) ok_reviewer_cfg=1;
452
- if (in_spark && line ~ /^description[[:space:]]*=[[:space:]]*"spark"$/) ok_spark_desc=1;
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 && ok_fixer_reason && ok_fixer_cfg &&
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;
@@ -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 = `pnpm --filter ./apps/backend run test:e2e:file ${testPath}`
107
+ let command = `npx nx test:e2e backend -- ${testPath}`
85
108
 
86
109
  // 如果指定了测试用例名称,添加 -t 参数
87
110
  if (testNamePattern) {
@@ -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
- // 兼容旧用法:非 dev 环境使用 migrate 时给出明确提示,推荐改用 deploy
24
+ // 创建迁移只允许在开发环境进行,避免 AI/用户在非开发环境误执行
25
25
  if (action === 'migrate' && envKey && envKey !== 'dev') {
26
26
  const envFlag = cli.getEnvironmentFlagExample(envKey) || `--${envKey}`
27
- logger.warn(`检测到在非开发环境执行 migrate: ${environment || envKey}`)
28
- logger.info('建议仅在开发环境使用 `dx db migrate --dev --name <migration-name>` 创建迁移。')
29
- logger.info(`如需在当前环境应用已有迁移,请使用: ${cli.invocation} db deploy ${envFlag}`)
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: 测试文件路径 (可选,仅支持e2e backend)',
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 # 运行后端E2E测试',
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ranger1/dx",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {