Browse Source

refactor: 重构 lint 错误处理机制

- 移除 node:child_process 的 execSync 导入
- 添加 colors 工具导入用于错误信息着色
- 创建统一的 LintError 类处理 lint 失败错误
- 串行和并行执行模式统一使用 LintError 抛出错误
- 并行执行改为等待全部完成后再汇总失败命令
- 移除并行执行中的进程强制终止逻辑
- 在主入口捕获 LintError 并显示友好的错误信息
- 导出 LintError 类供外部使用
main
金毛88 1 day ago
parent
commit
9bfebc17cb
  1. 8
      scripts/vsh/src/index.ts
  2. 56
      scripts/vsh/src/lint/index.ts

8
scripts/vsh/src/index.ts

@ -6,7 +6,7 @@ import { version } from '../package.json';
import { defineCheckCircularCommand } from './check-circular'; import { defineCheckCircularCommand } from './check-circular';
import { defineCheckDepCommand } from './check-dep'; import { defineCheckDepCommand } from './check-dep';
import { defineCodeWorkspaceCommand } from './code-workspace'; import { defineCodeWorkspaceCommand } from './code-workspace';
import { defineLintCommand } from './lint'; import { defineLintCommand, LintError } from './lint';
import { definePubLintCommand } from './publint'; import { definePubLintCommand } from './publint';
// 命令描述 // 命令描述
@ -57,6 +57,12 @@ async function main(): Promise<void> {
await vsh.runMatchedCommand(); await vsh.runMatchedCommand();
} catch (error) { } catch (error) {
// lint 检查失败是预期内的结果(格式/规范不达标),
// 直接展示可操作的错误信息,而非笼统的 "unexpected error"
if (error instanceof LintError) {
consola.error(error.message);
process.exit(1);
}
consola.error( consola.error(
colors.red('An unexpected error occurred:'), colors.red('An unexpected error occurred:'),
'\n', '\n',

56
scripts/vsh/src/lint/index.ts

@ -1,9 +1,8 @@
import type { CAC } from 'cac'; import type { CAC } from 'cac';
import { execSync } from 'node:child_process';
import { availableParallelism, freemem } from 'node:os'; import { availableParallelism, freemem } from 'node:os';
import { execa } from '@vben/node-utils'; import { colors, execa } from '@vben/node-utils';
interface LintCommandOptions { interface LintCommandOptions {
/** /**
@ -48,6 +47,21 @@ function formatCommand([file, args]: Command) {
return [file, ...args].join(' '); return [file, ...args].join(' ');
} }
/**
* lint
* execa
*/
class LintError extends Error {
constructor(failed: Command[]) {
super(
`Lint failed:\n${failed
.map((command) => ` - ${formatCommand(command)}`)
.join('\n')}\n\n运行 ${colors.cyan('vsh lint --format')} `,
);
this.name = 'LintError';
}
}
/** /**
* *
* *
@ -64,39 +78,29 @@ async function runSerial(commands: Command[]) {
} }
if (failed.length > 0) { if (failed.length > 0) {
throw new Error( throw new LintError(failed);
`Lint failed:\n${failed
.map((command) => ` - ${formatCommand(command)}`)
.join('\n')}`,
);
} }
} }
/** /**
* *
* *
*/ */
async function runParallel(commands: Command[]) { async function runParallel(commands: Command[]) {
const subprocesses = commands.map((command) => runCommand(command)); const subprocesses = commands.map((command) => runCommand(command));
try { const results = await Promise.allSettled(subprocesses);
await Promise.all(subprocesses);
} catch (error) { // 汇总所有失败的命令,与串行模式保持一致的错误输出
for (const subprocess of subprocesses) { const failed: Command[] = [];
try { results.forEach((result, index) => {
if (process.platform === 'win32' && subprocess.pid) { if (result.status === 'rejected') {
execSync(`taskkill /F /T /PID ${subprocess.pid}`, { failed.push(commands[index]);
stdio: 'ignore',
});
} else {
subprocess.kill('SIGKILL');
}
} catch {
// process may have already exited
}
} }
await Promise.allSettled(subprocesses); });
throw error;
if (failed.length > 0) {
throw new LintError(failed);
} }
} }
@ -143,4 +147,4 @@ function defineLintCommand(cac: CAC) {
.action(runLint); .action(runLint);
} }
export { defineLintCommand }; export { defineLintCommand, LintError };

Loading…
Cancel
Save