create-arena-project
Version:
神奇代码岛<->VSCode,从这里开始,创建一个神岛代码项目的脚手架。
236 lines (207 loc) • 6.9 kB
JavaScript
/**
* @fileoverview 错误处理工具模块
* 提供统一的错误处理、日志记录和错误信息美化功能
*/
import { default as chalk } from "chalk";
import { promises as fs } from "fs";
import { join } from "path";
/**
* 错误类型枚举
*/
const ErrorType = {
FILE_SYSTEM: "文件系统错误",
DEPENDENCY: "依赖安装错误",
CONFIGURATION: "配置错误",
NETWORK: "网络错误",
BUILD: "构建错误",
UNKNOWN: "未知错误",
};
/**
* 日志级别枚举
*/
const LogLevel = {
INFO: "info",
WARN: "warn",
ERROR: "error",
DEBUG: "debug",
};
/**
* 错误处理类
*/
class ErrorHandler {
constructor(options = {}) {
this.logFilePath = options.logFilePath || "arena-project-errors.log";
this.debug = options.debug || false;
this.exitOnError =
options.exitOnError !== undefined ? options.exitOnError : true;
this.showStackTrace = options.showStackTrace || false;
this.hasErrors = false; // 追踪是否有错误发生
}
/**
* 格式化时间戳
* @returns {string} 格式化的时间戳
*/
getTimestamp() {
const now = new Date();
return now.toISOString();
}
/**
* 将日志写入文件
* @param {string} message - 日志消息
* @param {string} level - 日志级别
*/
async writeToLog(message, level = LogLevel.ERROR) {
// 只有错误级别的日志或者在debug模式下才写入文件
if (
level === LogLevel.ERROR ||
level === LogLevel.WARN ||
(this.debug && level === LogLevel.DEBUG)
) {
try {
const logEntry = `[${this.getTimestamp()}] [${level.toUpperCase()}] ${message}\n`;
await fs.appendFile(this.logFilePath, logEntry);
// 标记有错误发生
if (level === LogLevel.ERROR) {
this.hasErrors = true;
}
} catch (err) {
console.error(chalk.red("无法写入日志文件:"), err.message);
}
}
}
/**
* 处理错误
* @param {Error} error - 错误对象
* @param {string} type - 错误类型
* @param {string} context - 错误上下文
* @param {Function} callback - 回调函数
*/
async handleError(
error,
type = ErrorType.UNKNOWN,
context = "",
callback = null
) {
const errorType = ErrorType[type] || ErrorType.UNKNOWN;
const errorMessage = error instanceof Error ? error.message : String(error);
const stackTrace = error instanceof Error ? error.stack : "";
// 构建错误信息
const formattedError = `错误类型: ${errorType}\n上下文: ${context}\n详情: ${errorMessage}`;
// 输出到控制台
console.error(chalk.red("\n✖ 错误发生:"));
console.error(chalk.red(formattedError));
if (this.showStackTrace && stackTrace) {
console.error(chalk.gray("\n堆栈跟踪:"));
console.error(chalk.gray(stackTrace));
}
// 提供修复建议
const suggestion = this.getSuggestion(type, errorMessage);
if (suggestion) {
console.error(chalk.yellow("\n可能的解决方案:"));
console.error(chalk.yellow(suggestion));
}
// 写入日志
await this.writeToLog(
`${formattedError}${stackTrace ? `\n堆栈跟踪: ${stackTrace}` : ""}`
);
// 执行回调
if (typeof callback === "function") {
callback(error);
}
// 根据配置退出进程
if (this.exitOnError) {
console.error(
chalk.red("\n由于错误,进程将退出。详细日志已写入 " + this.logFilePath)
);
process.exit(1);
}
return formattedError;
}
/**
* 根据错误类型和消息提供修复建议
* @param {string} type - 错误类型
* @param {string} message - 错误消息
* @returns {string} 修复建议
*/
getSuggestion(type, message) {
switch (type) {
case "FILE_SYSTEM":
if (message.includes("ENOENT")) {
return "文件或目录不存在。请检查路径是否正确,并确保有适当的读写权限。";
} else if (message.includes("EACCES")) {
return "权限被拒绝。请检查文件权限,或使用管理员权限运行命令。";
}
return "请检查文件路径和权限,确保目标路径可写入。";
case "DEPENDENCY":
if (message.includes("ENOENT")) {
return "命令未找到。请确保 'yarn', 'npm', 或 'pnpm' 已正确安装并配置在系统的 PATH 环境变量中。";
}
if (
message.includes("npm ERR") ||
message.includes("yarn ERR") ||
message.includes("pnpm ERR")
) {
return "依赖安装失败。尝试以下步骤:\n1. 检查网络连接\n2. 尝试使用 'npm cache clean --force'\n3. 检查package.json格式是否正确\n4. 尝试使用其他NPM镜像: 'npm config set registry https://registry.npmmirror.com/'";
}
return "依赖安装失败。请检查网络连接,确保NPM配置正确。";
case "CONFIGURATION":
return "配置错误。请检查配置文件格式是否正确,所有必需字段是否存在。";
case "NETWORK":
return "网络错误。请检查网络连接,确保能够访问相关服务器。如果使用代理,请检查代理设置。";
case "BUILD":
return "构建失败。请检查源代码是否有语法错误,确保所有依赖都已正确安装。";
default:
return "请尝试重新运行命令,或查看文档了解更多信息。";
}
}
/**
* 记录信息日志
* @param {string} message - 日志消息
* @param {string} context - 日志上下文
*/
async logInfo(message, context = "") {
console.log(
chalk.blue(`[信息] ${context ? `[${context}] ` : ""}${message}`)
);
// 只在调试模式下记录信息日志
if (this.debug) {
await this.writeToLog(
`${context ? `[${context}] ` : ""}${message}`,
LogLevel.INFO
);
}
}
/**
* 记录警告日志
* @param {string} message - 日志消息
* @param {string} context - 日志上下文
*/
async logWarning(message, context = "") {
console.warn(
chalk.yellow(`[警告] ${context ? `[${context}] ` : ""}${message}`)
);
await this.writeToLog(
`${context ? `[${context}] ` : ""}${message}`,
LogLevel.WARN
);
}
/**
* 记录调试日志
* @param {string} message - 日志消息
* @param {string} context - 日志上下文
*/
async logDebug(message, context = "") {
if (this.debug) {
console.debug(
chalk.gray(`[调试] ${context ? `[${context}] ` : ""}${message}`)
);
await this.writeToLog(
`${context ? `[${context}] ` : ""}${message}`,
LogLevel.DEBUG
);
}
}
}
// 导出默认错误处理实例
const errorHandler = new ErrorHandler();
export { errorHandler, ErrorHandler, ErrorType, LogLevel };