@aniyajs/rotor
Version:
基于webpack5开发的一款专注于打包、运行的工具
164 lines (139 loc) • 4.12 kB
JavaScript
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;