create-bfe-cttq
Version:
CTTQ大前端脚手架项目
140 lines (133 loc) • 5.17 kB
JavaScript
/**
* 项目创造器,负责调度
*/
const EventEmitter = require("events");
const fs = require("fs-extra");
const path = require("path");
const ora = require("ora");
const prompts = require("prompts");
const { red, green, bold } = require("kolorist")
const { logWithSpinner, succeedSpinner, failSpinner } = require("./util/spinner");
const { getAllPlugins } = require("./util/plugins")
const Promptor = require("./Promptor");
const Generator = require("./Generator");
const generateReadme = require("./util/generateReadme")
const generateChangelog = require("./util/generateChangelog")
const writeFileTree = require("./util/writeFileTree")
const Package = require("../../package.json");
const TemplateManager = require("./TemplateManager");
module.exports = class Creator extends EventEmitter {
constructor(context) {
super();
this.context = context;
this.plugins = getAllPlugins();
}
async create() {
// cli问答
const promptor = new Promptor(this.plugins);
await promptor.show();
if (Object.keys(promptor.answers).length <= 0) {
return;
}
// 项目路径创建方式
const lowerCaseName = promptor.answers.name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
let targetDir = path.resolve(this.context, lowerCaseName || ".");
if (path.basename(this.context).toLowerCase() == lowerCaseName) {
const { context } = await prompts(
[{
name: "context",
type: "select",
message: `请选择创建项目的目录:`,
choices: [
{
title: "子目录下",
value: targetDir,
description: targetDir,
},
{
title: "当前目录下",
value: this.context,
description: this.context,
}
],
hint: "- ↑ ↓ 选择. 回车 确认",
}],
{
onCancel: () => {
throw new Error(red("✖") + " 取消创建项目");
},
},
);
targetDir = context;
}
if (targetDir != this.context && fs.existsSync(targetDir)) {
const { action } = await prompts(
[{
name: "action",
type: "select",
message: `已经存在该目录 ${green(targetDir)},请选择一种处理方式:`,
choices: [
{
title: "重写",
value: "overwrite",
description: "删除现有项目所有文件,然后重新创建项目",
},
{
title: "合并",
value: "merge",
description: "保留现有目录,合并项目下文件,存在同名文件,则替换该文件",
},
{
title: "取消",
value: "cancel",
description: "取消创建项目",
selected: true
}
],
hint: "- ↑ ↓ 选择. 回车 确认",
}],
{
onCancel: () => {
throw new Error(red("✖") + " 取消创建项目");
},
},
);
if ("cancel" == action) {
throw new Error(red("✖") + " 取消创建项目");
} else if ("overwrite" == action) {
await fs.remove(targetDir)
}
}
const pkg = {
name: lowerCaseName,
version: "0.0.0",
description: promptor.answers.description,
private: true,
devDependencies: {},
engines: {
cli: Package.version,
template: process.env.CTTQ_TEMPLATE_VERSION,
}
}
logWithSpinner("开始创建项目")
// 生成项目
const generator = new Generator(targetDir, this.plugins, pkg, promptor.answers);
await generator.generate();
for (const cb of generator.createdCallbacks) {
await cb()
}
//写入CHANGELOG
if (!generator.files['CHANGELOG.md']) {
await writeFileTree(targetDir, {
"CHANGELOG.md": generateChangelog(pkg)
});
}
// 写入README
if (!generator.files['README.md']) {
await writeFileTree(targetDir, {
"README.md": generateReadme(pkg)
});
}
succeedSpinner("项目创建成功:"+green(targetDir));
}
}