@ranger1/dx 0.1.57 → 0.1.58

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.
@@ -12,18 +12,24 @@ const TARGET_CONFIGS = {
12
12
  configFile: 'vercel.front.json',
13
13
  projectIdEnvVar: 'VERCEL_PROJECT_ID_FRONT',
14
14
  deployCwd: 'apps/front',
15
+ deployMode: 'prebuilt',
16
+ prebuiltCwd: '.',
15
17
  },
16
18
  admin: {
17
19
  configFile: 'vercel.admin.json',
18
20
  projectIdEnvVar: 'VERCEL_PROJECT_ID_ADMIN',
19
21
  deployCwd: 'apps/admin-front',
22
+ deployMode: 'prebuilt',
20
23
  },
21
24
  'telegram-bot': {
22
25
  configFile: 'vercel.telegram-bot.json',
23
26
  projectIdEnvVar: 'VERCEL_PROJECT_ID_TELEGRAM_BOT',
27
+ deployMode: 'prebuilt',
24
28
  },
25
29
  }
26
30
 
31
+ const ALLOWED_DEPLOY_MODES = ['prebuilt']
32
+
27
33
  const APP_ENV_MAP = {
28
34
  development: 'dev',
29
35
  staging: 'staging',
@@ -53,6 +59,14 @@ function isMissingFilesError(err) {
53
59
  )
54
60
  }
55
61
 
62
+ function isNextPrebuiltMissingPathError(err) {
63
+ const text = collectErrorText(err)
64
+ return (
65
+ text.includes('ENOENT') &&
66
+ (text.includes('next-server.js') || text.includes('/node_modules/.pnpm/'))
67
+ )
68
+ }
69
+
56
70
  function listMissingVarKeys(targetConfigs, token, orgId) {
57
71
  const missing = []
58
72
 
@@ -102,6 +116,20 @@ export function resolveTargetRunCwd(projectRoot, targetConfig) {
102
116
  return join(projectRoot, targetConfig.deployCwd)
103
117
  }
104
118
 
119
+ export function resolveTargetDeployMode(targetConfig) {
120
+ if (!targetConfig?.deployMode) return 'prebuilt'
121
+ return targetConfig.deployMode
122
+ }
123
+
124
+ export function isSupportedDeployMode(mode) {
125
+ return ALLOWED_DEPLOY_MODES.includes(mode)
126
+ }
127
+
128
+ export function resolveTargetPrebuiltCwd(projectRoot, targetConfig, runCwd) {
129
+ if (!targetConfig?.prebuiltCwd) return runCwd
130
+ return join(projectRoot, targetConfig.prebuiltCwd)
131
+ }
132
+
105
133
  function maskIdentifier(value) {
106
134
  const raw = String(value || '').trim()
107
135
  if (raw.length <= 10) return raw || '-'
@@ -302,6 +330,8 @@ export async function deployToVercel(target, options = {}) {
302
330
  const configFile = targetConfig.configFile
303
331
  const configPath = join(projectRoot, configFile)
304
332
  const runCwd = resolveTargetRunCwd(projectRoot, targetConfig)
333
+ const deployMode = resolveTargetDeployMode(targetConfig)
334
+ const prebuiltCwd = resolveTargetPrebuiltCwd(projectRoot, targetConfig, runCwd)
305
335
 
306
336
  if (!existsSync(runCwd)) {
307
337
  logger.error(`部署目录不存在: target=${t} deployCwd=${targetConfig.deployCwd || '.'} resolved=${runCwd}`)
@@ -309,7 +339,22 @@ export async function deployToVercel(target, options = {}) {
309
339
  return
310
340
  }
311
341
 
312
- const linkedContext = readLinkedProjectContext(runCwd)
342
+ if (!isSupportedDeployMode(deployMode)) {
343
+ logger.error(`不支持的部署模式: target=${t} mode=${deployMode}`)
344
+ logger.info(`可用部署模式: ${ALLOWED_DEPLOY_MODES.join(', ')}`)
345
+ process.exitCode = 1
346
+ return
347
+ }
348
+
349
+ if (!existsSync(prebuiltCwd)) {
350
+ logger.error(
351
+ `预构建部署目录不存在: target=${t} prebuiltCwd=${targetConfig.prebuiltCwd || targetConfig.deployCwd || '.'} resolved=${prebuiltCwd}`,
352
+ )
353
+ process.exitCode = 1
354
+ return
355
+ }
356
+
357
+ const linkedContext = readLinkedProjectContext(prebuiltCwd)
313
358
 
314
359
  const linkedMismatch =
315
360
  linkedContext.exists &&
@@ -343,7 +388,7 @@ export async function deployToVercel(target, options = {}) {
343
388
  }
344
389
 
345
390
  logger.info(
346
- `[deploy-context] env=${environment} target=${t} strict=${strictContext ? 1 : 0} org=${maskIdentifier(orgId)} project=${maskIdentifier(projectId)} linked=${linkedContext.exists ? 'yes' : 'no'} token=env`,
391
+ `[deploy-context] env=${environment} target=${t} mode=${deployMode} runCwd=${runCwd} prebuiltCwd=${prebuiltCwd} strict=${strictContext ? 1 : 0} org=${maskIdentifier(orgId)} project=${maskIdentifier(projectId)} linked=${linkedContext.exists ? 'yes' : 'no'} token=env`,
347
392
  )
348
393
 
349
394
  const envVars = {
@@ -374,7 +419,7 @@ export async function deployToVercel(target, options = {}) {
374
419
 
375
420
  try {
376
421
  if (strictContext && process.env.DX_VERCEL_KEEP_LINK !== '1') {
377
- clearLinkedProjectContext(runCwd)
422
+ clearLinkedProjectContext(prebuiltCwd)
378
423
  }
379
424
 
380
425
  // 第一步:本地构建
@@ -394,8 +439,8 @@ export async function deployToVercel(target, options = {}) {
394
439
  await run(buildArgs, { env: envVars, cwd: runCwd })
395
440
  logger.success(`${t} 本地构建成功`)
396
441
 
397
- // 第二步:上传预构建产物
398
442
  logger.step(`部署 ${t} 到 Vercel (${environment})`)
443
+
399
444
  const baseDeployArgs = appendTargetArgs(
400
445
  ['deploy', '--prebuilt', '--local-config', configPath, '--yes'],
401
446
  {
@@ -411,7 +456,7 @@ export async function deployToVercel(target, options = {}) {
411
456
  const deployResult = await deployPrebuiltWithFallback({
412
457
  baseArgs: baseDeployArgs,
413
458
  env: envVars,
414
- cwd: runCwd,
459
+ cwd: prebuiltCwd,
415
460
  run,
416
461
  })
417
462
 
@@ -432,6 +477,11 @@ export async function deployToVercel(target, options = {}) {
432
477
  logger.success(`${t} 部署成功`)
433
478
  }
434
479
  } catch (error) {
480
+ if (deployMode === 'prebuilt' && isNextPrebuiltMissingPathError(error)) {
481
+ logger.error(
482
+ '高优先级提示:检测到 Next.js 预构建产物缺失(next-server.js/node_modules/.pnpm)。请检查 front prebuiltCwd 与构建产物路径是否一致。',
483
+ )
484
+ }
435
485
  const message = error?.message || String(error)
436
486
  logger.error(`${t} 构建或部署失败: ${message}`)
437
487
  process.exitCode = 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ranger1/dx",
3
- "version": "0.1.57",
3
+ "version": "0.1.58",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {