Browse Source

refactor: 重构 lint 错误处理机制

- 移除 node:child_process 的 execSync 导入
- 添加 colors 工具导入用于错误信息着色
- 创建统一的 LintError 类处理 lint 失败错误
- 串行和并行执行模式统一使用 LintError 抛出错误
- 并行执行改为等待全部完成后再汇总失败命令
- 移除并行执行中的进程强制终止逻辑
- 在主入口捕获 LintError 并显示友好的错误信息
- 导出 LintError 类供外部使用
main
金毛88 23 hours 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 { defineCheckDepCommand } from './check-dep';
import { defineCodeWorkspaceCommand } from './code-workspace';
import { defineLintCommand } from './lint';
import { defineLintCommand, LintError } from './lint';
import { definePubLintCommand } from './publint';
// 命令描述
@ -57,6 +57,12 @@ async function main(): Promise<void> {
await vsh.runMatchedCommand();
} catch (error) {
// lint 检查失败是预期内的结果(格式/规范不达标),
// 直接展示可操作的错误信息,而非笼统的 "unexpected error"
if (error instanceof LintError) {
consola.error(error.message);
process.exit(1);
}
consola.error(
colors.red('An unexpected error occurred:'),
'\n',

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

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

Loading…
Cancel
Save