UNPKG

create-arena-project

Version:

神奇代码岛<->VSCode,从这里开始,创建一个神岛代码项目的脚手架。

236 lines (207 loc) 6.9 kB
/** * @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 };