UNPKG

nsgm-cli

Version:

A CLI tool to run Next/Style-components and Graphql/Mysql fullstack project

234 lines (233 loc) 11.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.deleteFiles = void 0; const path_1 = __importDefault(require("path")); const shelljs_1 = __importDefault(require("shelljs")); const constants_1 = require("./constants"); const utils_1 = require("./utils"); // 常量定义 const CLEANUP_TIMEOUT = 1000; // 辅助函数 const generateDeletePaths = (controller, action, dictionary) => { const basePath = dictionary || process.cwd(); return { destPagesController: path_1.default.join(basePath, "pages", controller), destClientReduxController: path_1.default.join(basePath, "client", "redux", controller), destClientServiceController: path_1.default.join(basePath, "client", "service", controller), destClientStyledController: path_1.default.join(basePath, "client", "styled", controller), destServerModulesController: path_1.default.join(basePath, "server", "modules", controller), destServerApisController: path_1.default.join(basePath, "server", "apis", `${controller}.js`), destServerSqlController: path_1.default.join(basePath, "server", "sql", `${controller}.sql`), // 配置文件路径 destClientReduxReducersAllPath: path_1.default.join(basePath, "client", "redux", "reducers.ts"), destClientUtilsMenuPath: path_1.default.join(basePath, "client", "utils", "menu.tsx"), destServerRestPath: path_1.default.join(basePath, "server", "rest.js"), // 多语言文件路径 destI18nZhCN: path_1.default.join(basePath, "public", "locales", "zh-CN", `${controller}.json`), destI18nEnUS: path_1.default.join(basePath, "public", "locales", "en-US", `${controller}.json`), destI18nJaJP: path_1.default.join(basePath, "public", "locales", "ja-JP", `${controller}.json`), ...(action && { destPagesAction: path_1.default.join(basePath, "pages", controller, `${action}.tsx`), destClientReduxControllerAction: path_1.default.join(basePath, "client", "redux", controller, action), destClientAction: path_1.default.join(basePath, "client", "components", controller, action), destClientStyledAction: path_1.default.join(basePath, "client", "styled", controller, `${action}.js`), }), }; }; const deleteAllControllerFiles = (paths) => { const directoriesToDelete = [ paths.destPagesController, paths.destClientReduxController, paths.destClientServiceController, paths.destClientStyledController, paths.destServerModulesController, ]; const filesToDelete = [paths.destServerApisController, paths.destServerSqlController]; directoriesToDelete.forEach((dir) => (0, utils_1.rmdirSync)(dir)); filesToDelete.forEach((file) => (0, utils_1.rmFileSync)(file)); }; const deleteSpecificActionFiles = (paths) => { if (paths.destPagesAction) { (0, utils_1.rmFileSync)(paths.destPagesAction); } if (paths.destClientReduxControllerAction) { (0, utils_1.rmdirSync)(paths.destClientReduxControllerAction); } if (paths.destClientAction) { (0, utils_1.rmFileSync)(paths.destClientAction); } if (paths.destClientStyledAction) { (0, utils_1.rmFileSync)(paths.destClientStyledAction); } }; const deleteI18nFiles = (paths) => { console.log("Deleting i18n files..."); const i18nFilesToDelete = [paths.destI18nZhCN, paths.destI18nEnUS, paths.destI18nJaJP]; i18nFilesToDelete.forEach((filePath) => { (0, utils_1.rmFileSync)(filePath); console.log(`✅ 删除多语言文件: ${filePath}`); }); }; const cleanupConfigurationFiles = (controller, action, paths) => { if (action === "all") { // 清理所有控制器相关的配置 // 1. 删除 import 语句 shelljs_1.default.sed("-i", new RegExp(`^.*import.*${controller}.*Reducer.*from.*$`, "gm"), "", paths.destClientReduxReducersAllPath); // 2. 删除 export 对象中的属性行 shelljs_1.default.sed("-i", new RegExp(`^\\s*${controller}[^:]*:\\s*${controller}.*Reducer,?\\s*$`, "gm"), "", paths.destClientReduxReducersAllPath); // 3. 修复可能出现的语法问题 // 移除空行 shelljs_1.default.sed("-i", /^\s*$/g, "", paths.destClientReduxReducersAllPath); shelljs_1.default.sed("-i", /\n\n\n/g, "\n\n", paths.destClientReduxReducersAllPath); // 4. 修复对象末尾的逗号问题 // 如果对象只剩一个属性,移除末尾逗号 shelljs_1.default.sed("-i", /,(\s*\n\s*\})/, "$1", paths.destClientReduxReducersAllPath); // 5. 清理服务器端配置 shelljs_1.default.sed("-i", new RegExp(`.*${controller}.*`, "g"), "", paths.destServerRestPath); } else { // 清理特定动作的配置 shelljs_1.default.sed("-i", new RegExp(`^.*import.*${controller}${(0, utils_1.firstUpperCase)(action)}Reducer.*from.*$`, "gm"), "", paths.destClientReduxReducersAllPath); shelljs_1.default.sed("-i", new RegExp(`^\\s*${controller}${(0, utils_1.firstUpperCase)(action)}[^:]*:\\s*${controller}${(0, utils_1.firstUpperCase)(action)}.*Reducer,?\\s*$`, "gm"), "", paths.destClientReduxReducersAllPath); // 修复语法问题 shelljs_1.default.sed("-i", /^\s*$/g, "", paths.destClientReduxReducersAllPath); shelljs_1.default.sed("-i", /,(\s*\n\s*\})/, "$1", paths.destClientReduxReducersAllPath); } }; const performDatabaseCleanup = (controller, paths) => { try { shelljs_1.default.sed("-i", new RegExp(`${constants_1.mysqlDatabase};`, "g"), `${constants_1.mysqlDatabase};\nDROP TABLE \`${controller}\`;\n/*`, paths.destServerSqlController); shelljs_1.default.sed("-i", /utf8mb4;/g, "utf8mb4;\n*/", paths.destServerSqlController); const mysqlCommand = `mysql -u${constants_1.mysqlUser} -p${constants_1.mysqlPassword} -h${constants_1.mysqlHost} -P${constants_1.mysqlPort} < ${paths.destServerSqlController}`; shelljs_1.default.exec(mysqlCommand); console.log("Database cleanup completed"); } catch (error) { console.error("Failed to execute database cleanup:", error); } }; const performAdvancedCleanup = (controller, action, paths) => { const cleanupRules = [ // 标准化空行 { from: /\n\s*\n\s*\n/g, to: "\n\n", files: [paths.destClientReduxReducersAllPath], }, // 修复 reducers.ts 中可能的语法问题 { from: /(\w+Reducer),?\s*\n\s*\}/g, to: "$1,\n}", files: [paths.destClientReduxReducersAllPath], }, ]; if (action === "all") { cleanupRules.push( // 服务器端 REST 文件清理 { from: /'(.\/apis\/template.*?)'\)\s*\n/, to: "'./apis/template')\n\n", files: [paths.destServerRestPath], }, { from: /template\)\s*\n/, to: "template)\n\n", files: [paths.destServerRestPath], }, // 菜单清理 - 改进版本,保持正确的缩进和逗号 { from: new RegExp(`,?\\s*\\{\\s*//\\s*${controller}_.*_start[\\s\\S]*?//\\s*${controller}_.*_end\\s*\\}\\s*,?`, "gm"), to: ",", // 保留逗号,确保数组语法正确 files: [paths.destClientUtilsMenuPath], }); } setTimeout(() => { (0, utils_1.replaceInFileAll)(cleanupRules, 0, () => { console.log("Advanced cleanup completed"); // 执行额外的清理步骤 performFinalCleanup(paths); // 如果是删除整个控制器,还需要清理菜单缩进 if (action === "all") { cleanupMenuIndentation(paths); } }); }, CLEANUP_TIMEOUT); }; // 新增:智能菜单清理函数 const cleanupMenuIndentation = (paths) => { // 读取菜单文件内容 const menuFile = paths.destClientUtilsMenuPath; // 使用更智能的方式处理菜单清理,保持正确的缩进 setTimeout(() => { // 清理可能出现的缩进问题,确保注释代码块有正确的缩进 shelljs_1.default.sed("-i", /^[ ]{0,2}\/\*\{/gm, " /*{", menuFile); shelljs_1.default.sed("-i", /^[ ]{0,4}key:/gm, " key:", menuFile); shelljs_1.default.sed("-i", /^[ ]{0,4}text:/gm, " text:", menuFile); shelljs_1.default.sed("-i", /^[ ]{0,4}url:/gm, " url:", menuFile); shelljs_1.default.sed("-i", /^[ ]{0,4}icon:/gm, " icon:", menuFile); shelljs_1.default.sed("-i", /^[ ]{0,4}subMenus:/gm, " subMenus:", menuFile); shelljs_1.default.sed("-i", /^[ ]{0,2}\}\*\//gm, " }*/", menuFile); // 修复可能出现的连续逗号问题 shelljs_1.default.sed("-i", /,,+/g, ",", menuFile); // 修复数组末尾多余的逗号(在注释前) shelljs_1.default.sed("-i", /,(\s*\/\*)/g, "$1", menuFile); // 确保数组项之间有正确的逗号 shelljs_1.default.sed("-i", /(\})(\s*\/\*)/g, "$1,$2", menuFile); console.log("Menu indentation cleanup completed"); }, 1500); }; // 新增:最终清理函数 const performFinalCleanup = (paths) => { // 修复 reducers.ts 的最终格式 setTimeout(() => { // 确保最后一个属性有逗号(如果不是空对象) shelljs_1.default.sed("-i", /(\w+Reducer)(\s*\n\s*\})/, "$1,$2", paths.destClientReduxReducersAllPath); // 移除空对象中的逗号 shelljs_1.default.sed("-i", /\{\s*,\s*\}/, "{}", paths.destClientReduxReducersAllPath); // 标准化缩进 shelljs_1.default.sed("-i", /^[ ]{2}/gm, " ", paths.destClientReduxReducersAllPath); console.log("Final cleanup completed"); }, 500); }; /** * 删除控制器相关的文件 * @param controller 控制器名称 * @param action 动作名称,传入 'all' 删除整个控制器 * @param deleteDBFlag 是否删除数据库表 * @param dictionary 目标目录路径(可选,默认为当前目录) */ const deleteFiles = (controller, action, deleteDBFlag = false, dictionary) => { console.log("deleteFiles", constants_1.sourceFolder, constants_1.destFolder, constants_1.isLocal, controller, action, deleteDBFlag, dictionary); try { // 1. 生成删除路径 const paths = generateDeletePaths(controller, action, dictionary); // 2. 删除文件和目录 if (action === "all") { console.log("Deleting all controller files..."); deleteAllControllerFiles(paths); // 删除多语言文件 deleteI18nFiles(paths); } else { console.log(`Deleting specific action files for ${action}...`); deleteSpecificActionFiles(paths); } // 3. 清理配置文件 cleanupConfigurationFiles(controller, action, paths); console.log("Configuration files cleaned up"); // 4. 处理数据库清理(仅在删除整个控制器且设置了标志时) if (action === "all" && deleteDBFlag) { performDatabaseCleanup(controller, paths); } // 5. 执行高级清理 performAdvancedCleanup(controller, action, paths); console.log("deleteFiles completed successfully"); } catch (error) { console.error("Failed to delete files:", error); throw error; } }; exports.deleteFiles = deleteFiles;