geeks-cli
Version:
simple vue cli
144 lines (120 loc) • 4.84 kB
JavaScript
// lib/Generator.js
const { getRepoList, getTagList } = require('./http')
const ora = require('ora')
const inquirer = require('inquirer')
const util = require('util')
const downloadGitRepo = require('download-git-repo') // 不支持 Promise
const chalk = require('chalk')
const path = require('path');
const fs = require("fs-extra");
const jsoncParser = require('jsonc-parser');
// 添加加载动画
async function wrapLoading(fn, message, ...args) {
const spinner = ora(message).start();
try {
const result = await fn(...args);
spinner.succeed();
return result;
} catch (error) {
spinner.fail('Request failed, refetch ...');
throw error; // 重新抛出异常
}
}
// 获取JSON文件并修改其属性
async function operationJSon(name, filePath) {
const fullPath = `./${name}/${filePath}.json`;
let data = await fs.readFile(fullPath, 'utf8');
const edits = jsoncParser.modify(data, ['name'], name, {
formattingOptions: {
insertSpaces: true,
tabSize: 4
}
});
const modifiedData = jsoncParser.applyEdits(data, edits);
await fs.ensureDir(path.dirname(fullPath)); // 确保路径存在
await fs.writeFile(fullPath, modifiedData); // 使用 Promise 版本
console.log('File written successfully');
}
class Generator {
constructor(name, targetDir) {
// 目录名称
this.name = name;
// 创建位置
this.targetDir = targetDir;
// 对 download-git-repo 进行 promise 化改造
this.downloadGitRepo = util.promisify(downloadGitRepo);
}
// 获取用户选择的模板
// 1)从远程拉取模板数据
// 2)用户选择自己新下载的模板名称
// 3)return 用户选择的名称
async getRepo() {
// 1)从远程拉取模板数据
const repoList = await wrapLoading(getRepoList, 'waiting fetch template');
if (!repoList) return;
// 过滤我们需要的模板名称
const repos = repoList.map(item => item.name);
// 2)用户选择自己新下载的模板名称
const { repo } = await inquirer.prompt({
name: 'repo',
type: 'list',
choices: repos,
message: 'Please choose a template to create project'
})
// 3)return 用户选择的名称
return repo;
}
// 获取用户选择的版本
// 1)基于 repo 结果,远程拉取对应的 tag 列表
// 2)自动选择最新版的 tag
async getTag(repo) {
// 1)基于 repo 结果,远程拉取对应的 tag 列表
const tags = await wrapLoading(getTagList, 'waiting fetch tag', repo);
if (!tags) return;
// 过滤我们需要的 tag 名称
const tagsList = tags.map(item => item.name);
// 2)return 用户选择的 tag
return tagsList[0]
}
// 下载远程模板
// 1)拼接下载地址
// 2)调用下载方法
async download(repo, tag) {
// 1)拼接下载地址
const requestUrl = `geek-cli/${repo}${tag ? '#' + tag : ''}`;
// 2)调用下载方法
await wrapLoading(
this.downloadGitRepo, // 远程下载方法
'waiting download template', // 加载提示信息
requestUrl, // 参数1: 下载地址
await path.resolve(process.cwd(), this.targetDir) // 参数2: 创建位置
)
console.log('create success')
}
// 核心创建逻辑
// 1)获取模板名称
// 2)获取 tag 名称
// 3)下载模板到模板目录
// 4) 对uniapp模板中部分文件进行读写
// 5) 模板使用提示
async create() {
// 1)获取模板名称
const repo = await this.getRepo()
// 2) 获取 tag 名称
const tag = await this.getTag(repo)
// 3)下载模板到模板目录
await this.download(repo, tag);
// 4) 对uniapp模板中部分文件进行读写
await operationJSon(this.name, 'src/manifest')
await operationJSon(this.name, 'package-lock')
await operationJSon(this.name, 'package')
// 修改README.md 文件
const md = await fs.readFile(`./${this.name}/README.md`, "utf8");
await fs.writeFile(`./${this.name}/README.md`, `# ${this.name}\n` + md, 'utf8');
// 5)模板使用提示
console.log(`\r\nSuccessfully created project ${chalk.cyan(this.name)}`)
console.log(`\r\n cd ${chalk.cyan(this.name)}`)
console.log(`\r\n 启动前请务必阅读 ${chalk.cyan("README.md")} 文件`)
}
}
module.exports = Generator;