@ranger1/dx 0.1.86 → 0.1.88

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
@@ -199,11 +199,13 @@ dx deploy front --staging
199
199
  dx deploy backend --prod
200
200
  dx lint
201
201
  dx test e2e backend apps/backend/e2e/auth
202
+ dx test e2e quantify apps/quantify/e2e/health/health.e2e-spec.ts
202
203
  ```
203
204
 
204
205
  命令约束摘要:
205
206
 
206
- - `dx test e2e backend` 必须提供文件或目录路径,禁止无路径全量执行
207
+ - 对声明了 `requiresPath: true` 的 E2E target,`dx test e2e <target>` 必须提供文件或目录路径,禁止无路径或 `all` 全量执行
208
+ - `dx test e2e all` 不受支持,必须显式指定 target 和路径
207
209
  - `dx db migrate` 仅允许在 `--dev` 环境创建迁移;非开发环境请使用 `dx db deploy`
208
210
  - `dx start` 未指定服务时默认是开发套件,仅允许 `--dev`
209
211
  - `dx start` 下的单层目标(如 `stagewise-front`)默认仅支持 `--dev`
@@ -97,6 +97,7 @@ export function resolveBackendDeployConfig({ cli, targetConfig, environment, fla
97
97
  const startupMode = String(startupConfig.mode || 'pm2').trim()
98
98
  const prismaGenerate = runConfig.prismaGenerate !== false
99
99
  const prismaMigrateDeploy = runConfig.prismaMigrateDeploy !== false
100
+ const prismaSeed = runConfig.prismaSeed === true
100
101
 
101
102
  const normalized = {
102
103
  projectRoot: cli.projectRoot,
@@ -153,6 +154,7 @@ export function resolveBackendDeployConfig({ cli, targetConfig, environment, fla
153
154
  ),
154
155
  prismaGenerate,
155
156
  prismaMigrateDeploy,
157
+ prismaSeed,
156
158
  skipMigration: Boolean(flags.skipMigration),
157
159
  },
158
160
  verify: resolveVerifyConfig(verifyConfig),
@@ -168,7 +170,7 @@ export function resolveBackendDeployConfig({ cli, targetConfig, environment, fla
168
170
  requireString(normalized.startup.entry, 'startup.entry')
169
171
  }
170
172
 
171
- if (normalized.deploy.prismaGenerate || normalized.deploy.prismaMigrateDeploy) {
173
+ if (normalized.deploy.prismaGenerate || normalized.deploy.prismaMigrateDeploy || normalized.deploy.prismaSeed) {
172
174
  requireString(normalized.runtime.prismaSchemaDir, 'runtime.prismaSchemaDir')
173
175
  requireString(normalized.runtime.prismaConfig, 'runtime.prismaConfig')
174
176
  }
@@ -30,6 +30,7 @@ export function buildRemoteDeployScript(phaseModel = []) {
30
30
  const keepReleases = Number(deploy.keepReleases || 5)
31
31
  const shouldGenerate = deploy.prismaGenerate !== false
32
32
  const shouldMigrate = deploy.prismaMigrateDeploy !== false && deploy.skipMigration !== true
33
+ const shouldSeed = deploy.prismaSeed === true
33
34
  const healthCheckUrl = healthCheck?.url ? String(healthCheck.url) : ''
34
35
  const healthCheckTimeoutSeconds = Number(healthCheck?.timeoutSeconds || 10)
35
36
  const healthCheckMaxWaitSeconds = Number(healthCheck?.maxWaitSeconds || 24)
@@ -62,6 +63,7 @@ HEALTHCHECK_RETRY_DELAY_SECONDS=${healthCheckRetryIntervalSeconds}
62
63
  KEEP_RELEASES=${keepReleases}
63
64
  SHOULD_GENERATE=${shouldGenerate ? '1' : '0'}
64
65
  SHOULD_MIGRATE=${shouldMigrate ? '1' : '0'}
66
+ SHOULD_SEED=${shouldSeed ? '1' : '0'}
65
67
 
66
68
  LOCK_FILE="$APP_ROOT/.deploy.lock"
67
69
  LOCK_DIR="$APP_ROOT/.deploy.lock.d"
@@ -345,6 +347,17 @@ if [[ "$SHOULD_MIGRATE" == "1" ]]; then
345
347
  MIGRATION_EXECUTED=1
346
348
  fi
347
349
 
350
+ if [[ "$SHOULD_SEED" == "1" ]]; then
351
+ CURRENT_PHASE="prisma-seed"
352
+ echo "DX_REMOTE_PHASE=prisma-seed"
353
+ PRISMA_BIN="$RELEASE_DIR/node_modules/.bin/prisma"
354
+ if [[ ! -x "$PRISMA_BIN" ]]; then
355
+ echo "缺少可执行文件: $PRISMA_BIN" >&2
356
+ exit 1
357
+ fi
358
+ run_with_env "$RELEASE_DIR" "$PRISMA_BIN" db seed --schema="$PRISMA_SCHEMA" --config="$PRISMA_CONFIG"
359
+ fi
360
+
348
361
  CURRENT_PHASE="switch-current"
349
362
  echo "DX_REMOTE_PHASE=switch-current"
350
363
  ln -sfn "$RELEASE_DIR" "$CURRENT_LINK"
@@ -94,22 +94,34 @@ export async function handleTest(cli, args) {
94
94
  cli.flags.test = true
95
95
  }
96
96
 
97
- let testConfig = cli.commands.test[type]?.[target] || cli.commands.test[type]
97
+ const typeConfig = cli.commands.test[type]
98
+ let testConfig = typeConfig?.[target]
99
+ if (!testConfig && typeConfig?.command) {
100
+ testConfig = typeConfig
101
+ }
98
102
 
99
103
  if (!testConfig) {
100
104
  logger.error(`未找到测试配置: ${type}.${target}`)
101
- process.exitCode = 1
105
+ process.exit(1)
102
106
  return
103
107
  }
104
108
 
105
- // 如果提供了测试文件路径,使用专门的单文件测试配置
106
- if (testPath && type === 'e2e' && target === 'backend') {
107
- let command = `npx nx test:e2e backend -- ${testPath}`
109
+ if (type === 'e2e' && testConfig.requiresPath && testPath) {
110
+ if (!testConfig.fileCommand) {
111
+ logger.error(`测试配置错误: test.${type}.${target} 已启用 requiresPath,必须配置 fileCommand`)
112
+ process.exit(1)
113
+ }
114
+
115
+ const fileCommand = String(testConfig.fileCommand)
116
+ if (!fileCommand.includes('{TEST_PATH}')) {
117
+ logger.error(`测试配置错误: test.${type}.${target} 的 fileCommand 必须包含 {TEST_PATH}`)
118
+ process.exit(1)
119
+ }
120
+
121
+ let command = fileCommand.replace('{TEST_PATH}', shellEscape(testPath))
108
122
 
109
- // 如果指定了测试用例名称,添加 -t 参数
110
123
  if (testNamePattern) {
111
- const escapedPattern = String(testNamePattern).replace(/(["`\\$])/g, '\\$1')
112
- command += ` -t "${escapedPattern}"`
124
+ command += ` -t ${shellEscape(testNamePattern)}`
113
125
  }
114
126
 
115
127
  testConfig = {
@@ -132,6 +144,10 @@ export async function handleTest(cli, args) {
132
144
  await cli.executeCommand(testConfig)
133
145
  }
134
146
 
147
+ function shellEscape(value) {
148
+ return `'${String(value).replace(/'/g, `'\\''`)}'`
149
+ }
150
+
135
151
  export async function handleLint(cli, args) {
136
152
  void args
137
153
  const baseConfig = cli.commands.lint
package/lib/cli/dx-cli.js CHANGED
@@ -608,17 +608,27 @@ class DxCli {
608
608
  }
609
609
 
610
610
  validateTestPositionals(positionalArgs) {
611
- if (positionalArgs.length === 0) return
612
-
613
611
  const [type = 'e2e', target = 'all', testPath] = positionalArgs
614
612
 
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 仅允许按文件或目录增量执行')
613
+ if (type !== 'e2e') return
614
+
615
+ if (target === 'all') {
616
+ logger.error('dx test e2e all 不受支持,请指定 target 和测试文件或目录路径')
617
+ process.exit(1)
618
+ }
619
+
620
+ const testConfig = this.commands?.test?.[type]?.[target]
621
+ if (!testConfig) return
622
+ if (!testConfig.requiresPath) return
623
+
624
+ if (!testPath) {
625
+ logger.error(`dx test e2e ${target} 必须提供测试文件或目录路径`)
626
+ logger.info(`示例: ${this.invocation} test e2e ${target} apps/${target}/e2e/health`)
627
+ process.exit(1)
628
+ }
629
+
630
+ if (testPath === 'all') {
631
+ logger.error(`dx test e2e ${target} 不支持 all,必须提供测试文件或目录路径`)
622
632
  process.exit(1)
623
633
  }
624
634
  }
package/lib/cli/help.js CHANGED
@@ -43,10 +43,10 @@ export function showHelp() {
43
43
  '',
44
44
  ' test [type] [target] [path] [-t pattern] 运行测试',
45
45
  ' type: e2e, unit (默认: e2e)',
46
- ' target: backend, all (默认: all)',
47
- ' path: 测试文件或目录路径 (必填,仅支持 e2e backend)',
46
+ ' target: commands.json test.<type>.<target> 决定(e2e 默认会拒绝隐式 all',
47
+ ' path: 测试文件或目录路径 (guarded e2e target 必填,例如 backend/quantify)',
48
48
  ' -t pattern: 指定测试用例名称模式 (可选,需要和 path 一起使用)',
49
- ' 说明: backend E2E 禁止无路径全量执行',
49
+ ' 说明: guarded E2E target 禁止无路径或 all 全量执行,dx test e2e all 也不受支持',
50
50
  '',
51
51
  ' worktree [action] [num...] Git Worktree管理',
52
52
  ' action: make, del, list, clean',
@@ -94,6 +94,8 @@ export function showHelp() {
94
94
  ' dx test e2e backend apps/backend/e2e/auth # 按目录运行后端 E2E',
95
95
  ' dx test e2e backend apps/backend/e2e/activity/activity.admin.e2e-spec.ts # 运行单个E2E测试文件',
96
96
  ' dx test e2e backend apps/backend/e2e/activity/activity.admin.e2e-spec.ts -t "should list all activity definitions" # 运行特定测试用例',
97
+ ' dx test e2e quantify apps/quantify/e2e/health/health.e2e-spec.ts # 运行 Quantify E2E 文件',
98
+ ' dx test e2e all # 不受支持,必须指定 target 和 path',
97
99
  ' dx deploy front --staging # 部署前端到 Vercel(staging)',
98
100
  ' dx deploy backend --prod # 构建 backend 制品并上传/部署到远端主机',
99
101
  ' dx deploy backend --build-only # 仅构建 backend 制品,不执行远端部署',
@@ -255,17 +257,20 @@ test 命令用法:
255
257
 
256
258
  参数说明:
257
259
  type: e2e, unit (默认: e2e)
258
- target: backend, all (默认: all)
259
- path: e2e backend 支持,且必须提供文件或目录路径
260
+ target: commands.json test.<type>.<target> 决定
261
+ path: guarded e2e target 必须提供文件或目录路径
260
262
  -t pattern: 指定测试用例名称模式,需要和 path 一起使用
261
263
 
262
264
  限制说明:
263
- backend E2E 禁止无路径全量执行,缺少 path 时命令会直接报错退出。
265
+ guarded E2E target 禁止无路径全量执行。
266
+ guarded E2E target 也不支持把 path 写成 all。
267
+ dx test e2e all 不受支持,必须显式指定 target 和 path。
264
268
 
265
269
  常见示例:
266
270
  dx test e2e backend apps/backend/e2e/auth
267
271
  dx test e2e backend apps/backend/e2e/auth/auth.login.e2e-spec.ts
268
272
  dx test e2e backend apps/backend/e2e/auth/auth.login.e2e-spec.ts -t "should login"
273
+ dx test e2e quantify apps/quantify/e2e/health/health.e2e-spec.ts
269
274
  dx test unit front
270
275
  dx test unit admin
271
276
  `)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ranger1/dx",
3
- "version": "0.1.86",
3
+ "version": "0.1.88",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {