UNPKG

@aniyajs/rotor

Version:

基于webpack5开发的一款专注于打包、运行的工具

164 lines (139 loc) 4.12 kB
const path = require("path"); const paths = require("./paths"); const fs = require("fs-extra"); const memFs = require("mem-fs"); const editor = require("mem-fs-editor"); const ejs = require("ejs"); const { aRecursive } = require("./common"); class PluginGenerator { constructor(args) { this.describeParams = {}; // 插件包node_modules中入口地址 this.pluginIndex = args.pluginIndex; // app config配置 this.configition = args.memoConfig; this.resolve = path.resolve; this.join = path.join; this.relative = path.relative; this.basename = path.basename; this.editorFs = null; } initialize() { // 清空一次插件生成的缓存文件 this.clearAllTemp(); const store = memFs.create(); const editorFs = editor.create(store); this.editorFs = editorFs; } use(plugin) { plugin(this); } /** * 描述插件 */ describe(params) { this.describeParams = { config: { default: undefined, ...(params.config ? params.config : {}), }, ...params, }; } /** * 文件操作 */ generate(onGenerateHandle) { const parentDirPath = path.dirname(this.pluginIndex); const parentFileName = path.basename(parentDirPath); const pluginTempPath = path.join(paths.appTempPath, parentFileName); onGenerateHandle({ pluginTempPath, // 插件生成的缓存目录地址 ...paths, }); } /** * 异步读取指定目录下的文件绝对路径 * * @param {string} rootPath 目录 * @param {boolean} withSuffix 是否携带后缀 * @param {function} filterHandle 过滤函数 * * @returns {Promise<string[] | []>} 文件绝对路径数组 */ async readFilterdir({ rootPath, withSuffix, filterHandle }) { const files = await aRecursive(rootPath); const specifyFiles = files.filter(filterHandle).map((filePath) => { // 为true时获取文件后缀 if (withSuffix) { return filePath; } // 解析文件路径 const parsedPath = path.parse(filePath); // 获取不带文件后缀的路径 const directoryPath = parsedPath.dir; const fileName = parsedPath.name; const pathWithoutExtension = path.join(directoryPath, fileName); return pathWithoutExtension; }); return specifyFiles; } /** * 同步复制模板 * * @param {string} from 源文件 * @param {string} to 目标文件 * @param {object} define 模版定义 */ copyTpl(from, to, define) { // 自定义 ejs 模版文件后缀名 ejs.extname = path.extname(from); if (fs.existsSync(to)) { fs.removeSync(to); } this.editorFs.copyTpl(from, to, define); this.editorFs.commit((err) => { if (err) { console.error('copyTpl commit error:', err); } }); // mem-fs-editor commit 是异步的,确保文件已写入 // 使用 fs-extra 做一次同步验证 if (!fs.existsSync(to)) { // 回退:直接用 fs-extra 写入 const content = ejs.render(fs.readFileSync(from, 'utf-8'), define); fs.ensureFileSync(to); fs.writeFileSync(to, content, 'utf-8'); } } /** * 同步写入文件 * * @param {string} file * @param {string} content */ writeFile({ file, content }) { if (fs.existsSync(file)) { fs.removeSync(file); } // 直接使用 fs-extra 同步写入,避免 mem-fs-editor commit 的异步问题 fs.ensureFileSync(file); fs.writeFileSync(file, content, 'utf-8'); } // 清除所有缓存文件 clearAllTemp() { const files = fs.readdirSync(paths.appTempPath); files.forEach((file) => { if (file.startsWith("plugin-")) { fs.removeSync(path.join(paths.appTempPath, file)); } }); } // 修改最终配置 modifyConfig(callFn) { return callFn(this.configition); } // 结束 ending() {} } module.exports = PluginGenerator;