@vin_coder/pg-cli
Version:
pg-cli 构建项目工具
292 lines (237 loc) • 7.48 kB
JavaScript
const chalk = require("chalk");
const execa = require("execa");
const inquirer = require("inquirer");
const path = require("path");
const cloneDeep = require("lodash.clonedeep");
const writeFileTree = require("./utils/writeFileTree");
const { hasYarn } = require("./utils/env");
const PackageManager = require("./utils/packageManager");
const sortObject = require("./utils/sortObject");
const Generator = require("./utils/Generator");
const { loadModules } = require("./utils/module");
const generateReadme = require("./utils/generateReadme");
const { defaults, loadOptions, defaultFrame } = require("./options");
module.exports = class Initiator {
constructor(name, context) {
this.name = name;
this.ctx = process.env.PG_CLI_RESOURCE = context;
this.frameCtx = "";
const { framePrompt } = this.resolveFramePrompts();
const { projectPrompt } = this.resolveProjectPrompts();
this.framePrompt = framePrompt;
this.projectPrompt = projectPrompt;
this.run = this.run.bind(this);
}
async initiate(options) {
let { name, ctx, run } = this;
// 初始化 前端项目 package.json
const plugs = {};
let frameName = "";
let projectName = "";
let f;
let p;
if ((f = options.frame)) {
if (!defaultFrame.includes(f.toLowerCase())) {
console.log(chalk.red(`暂不支持 框架${f}, vue, react 可任选其一`));
return;
} else {
frameName = f;
}
} else {
// 提示
let answer = await inquirer.prompt([this.framePrompt]);
frameName = answer.frame;
}
if ((p = options.project)) {
projectName = p;
} else {
// 提示用户是否现在创建项目,是则 提示用户输入项目名称,否则提示用户可以通过 pg add project <projectName> 来手动添加项目
let answer = await inquirer.prompt(this.projectPrompt);
if (!answer.addProject) {
console.log(
"提示:你可以后续通过 pg add project <projectName> 来添加项目"
);
} else {
if ((p = answer.projectName)) {
projectName = p;
}
console.log(JSON.stringify(answer, null, " "));
}
}
this.frameCtx = path.join(ctx, frameName);
plugs["@vin_coder/pg-cli-service"] = Object.assign({
projectName: name,
});
plugs["@vin_coder/pg-cli-plugin-service"] = {};
plugs[`@vin_coder/pg-cli-template-frame-${frameName}`] = {};
if (projectName) {
plugs[`@vin_coder/pg-cli-template-project-${frameName}`] = {};
}
const packageManager =
loadOptions().packageManager || (hasYarn() ? "yarn" : "npm");
const pm = new PackageManager({
ctx: this.frameCtx,
forcePackageManager: packageManager,
});
console.log();
console.log(
chalk.green(
`✨ 项目${chalk.bgBlack(`${name}`)}正在 目录 ${chalk.bgBlack(
`${this.frameCtx}`
)} 生成中...`
)
);
console.log();
const pkg = {
name,
version: "0.1.0",
private: true,
devDependencies: {},
};
const deps = Object.keys(plugs);
deps.forEach((dep) => {
pkg.devDependencies[dep] = plugs[dep].version || "latest";
});
//写入package.json
await writeFileTree(this.frameCtx, {
"package.json": JSON.stringify(pkg, null, 2),
});
// return;
// 初始化git仓库
console.log();
console.log(chalk.green(`🗃 初始化git 仓库...`));
console.log();
await run("git init");
// 安装cli 插件
console.log();
console.log(chalk.green(`⚙ 安装命令行工具所需插件,可能需要等一会儿...`));
console.log();
await pm.install();
// 执行插件中的generator
console.log();
console.log(chalk.green(`🚀 执行生成器...`));
console.log();
const plugins = await this.resolvePlugins(plugs);
const generator = new Generator(this.frameCtx, {
pkg,
plugins,
currentProjectName: projectName,
});
await generator.generate();
// 安装条件依赖
console.log();
console.log(chalk.green(`📦 安装插件所需依赖...`));
console.log();
await pm.install();
//生成 read.me
console.log();
console.log(chalk.green(`📄 生成READ.ME 文件...`));
console.log();
await writeFileTree(this.frameCtx, {
"README.md": generateReadme(pkg, packageManager),
});
await run("git add -A");
try {
await run("git", ["commit", "-m", "初始化git提交"]);
} catch (e) {
console.log(
chalk.yellow(`😈 项目 ${name} 初始化提交失败 ,请尝试手动提交`)
);
}
// 提示成功
console.log();
console.log(chalk.green(`🎉 成功创建项目仓库 ${name}.`));
console.log();
}
resolveProjectPrompts() {
const frames = defaultFrame;
const projectPrompt = [
{
type: "confirm",
name: "addProject",
message: "想要现在添加项目吗?",
},
{
type: "input",
name: "projectName",
message: "请输入所要添加的项目名称",
when: function (answers) {
return answers.addProject;
},
validate: function (val) {
if (!val || frames.includes(val.toLowerCase())) {
return "项目名称不可为空或不可以和依赖框架同名";
}
return true;
},
},
];
return { projectPrompt };
}
// 返回 框架选择 prompt
resolveFramePrompts() {
const frames = defaultFrame;
const frameChoices = frames.map((name) => ({
name,
value: name,
}));
const framePrompt = {
name: "frame",
type: "list",
message: "请选择一个依赖的前端框架:",
choices: frameChoices,
};
return { framePrompt };
}
getPresets() {
const savedOptions = loadOptions();
return Object.assign({}, savedOptions.presets, defaults.presets);
}
async promptAndResolvePreset(answers = null) {
if (!answers) {
answers = await inquirer.prompt([this.presetPrompt]);
}
let preset;
if (answers.preset) {
preset = await this.resolvePreset(answers.preset);
}
return preset;
}
async resolvePreset(name) {
let preset;
const savedPresets = loadOptions().presets;
if (name in savedPresets) {
preset = savedPresets[name];
}
if (name === "default" && !preset) {
preset = defaults.presets.default;
}
if (!preset) {
console.log(chalk.yellow("preset 没有找到"));
const presets = Object.keys(savedPresets);
if (presets.length > 0) {
console.log(chalk.green(`可能的preset 如下: ${presets.join("\n")}`));
} else {
console.log(chalk.red("没有perset ,手动配置一下吧"));
}
process.exit(1);
}
return preset;
}
async resolvePlugins(rawPlugins) {
rawPlugins = sortObject(rawPlugins, ["@vin_coder/pg-cli-service"], true);
const plugins = [];
for (const id of Object.keys(rawPlugins)) {
let apply = loadModules(`${id}/generator`, this.frameCtx) || (() => {});
let options = rawPlugins[id] || {};
plugins.push({ id, apply, options });
}
return plugins;
}
run(cmd, args) {
if (!args) {
[cmd, ...args] = cmd.split(/\s+/);
}
return execa(cmd, args, { cwd: process.env.PG_CLI_ROOT });
}
};