penn-cli
Version:
快速生成cli项目的脚手架
264 lines (246 loc) • 12.3 kB
JavaScript
/*eslint-disable*/
// https://gitee.com/jipengju/dashboard/projects
const program = require(`commander`) // 命令行中参数的处理
const inquirer = require(`inquirer`) // 命令行中的select 选择器
const downloadRepo = require(`download-git-repo`) // 仓库下载
const ora = require(`ora`) // Loading
const figlet = require(`figlet`) // 生成好看的标识颜色
const Printer = require('@darkobits/lolcatjs') // 生成随机颜色
const chalk = require(`chalk`)//给提示文案着色 *注:5版本是esm,如果在ts中或者构建工具中使用,目前建议使用4版本
const myUtil = require(`./utils/myUtil`) // 私有工具集
const clear = require('clear') // 清屏
// 常量
const packageJson = require(`./package.json`)
const cliName = packageJson.projectName // cli名称
const repoCurrentVersion = packageJson.version // 当前的版本
const repolatestVersionObj = myUtil.checkUpdateVersion(packageJson.name, repoCurrentVersion, packageJson.repository.npmUrl) // 获取最新的版本
const repoLastVersion = repolatestVersionObj.lastVersion // 上一次版本
const repolatestVersion = repolatestVersionObj.latest // 最新的版本
const repoNodeVersion = packageJson.engines.node // 获取工程依赖node版本
const nodeVersion = process.version // 系统node版本
const Log = console.log // 日志
// Log(repolatestVersionObj)
// 全局变量
let Loading = null // 创建加载器
// 系统色彩变量
const repoColor = {
warning: `#f40` // 警告
}
// cli 图标
const repoLogo = figlet.textSync(`${cliName}`, {
font: `epic`,
horizontalLayout: `Smush (U)`,
verticalLayout: `Smush (U)`
})
// 检测node版本
if (!myUtil.checkNodeVersion(nodeVersion, repoNodeVersion))
return
// CLI对象
const myCli = {
/*
* 执行回调
* projectName 项目名
* option 对应上面的指令选项
* */
// 检测是否存在重名项目
checkIsHasProject(projectName) {
return new Promise((resolve, reject) => {
if (myUtil.hasFileName(projectName)) {
inquirer.prompt([
{
type: 'list',
name: 'DeleteAndUpdate',
message: `检测到本地已存在名字为${projectName}的工程目录/文件,是否需要自动删除并创建?`,
choices: [
{
name: `自动删除并创建${chalk.hex(repoColor.warning)(`[该项会自动删除重名目录,请谨慎操作]`)}`, value: 1
},
{
name: '手动删除',
value: 0
}
]
}
]).then((answer) => {
if (!answer.DeleteAndUpdate) {
resolve(answer.DeleteAndUpdate)
return
}
myUtil.deleteDir(ora, projectName).then(t => {
resolve(answer.DeleteAndUpdate)
})
})
} else {
resolve(true)
}
})
},
// 拉取项目
cloneProject(url, name) {
Loading = ora({
text: chalk.greenBright(`正在拉取脚手架...`)
}).start() // 开始状态 => 加载状态
downloadRepo(
`direct:${url}`,
name,
{ clone: true },
err => {
if (err) return Loading.warn(chalk.redBright(`=====| 脚手架已存在或仓库资源错误 |=====`)) // 加载状态 => 成功状态
Loading.succeed(chalk.greenBright(`=========| 脚手架创建成功 |=========`)) // 加载状态 => 成功状态
Loading.succeed(chalk.greenBright(`------------------------------------`)) // 加载状态 => 成功状态
Loading.succeed(chalk.greenBright(`------------------------------------`)) // 加载状态 => 成功状态
Loading.succeed(chalk.greenBright(`------------------------------------`)) // 加载状态 => 成功状态
Loading.succeed(chalk.greenBright(`============| 运行指南 |============`)) // 加载状态 => 成功状态
Loading.succeed(chalk.greenBright(`====| ${Printer.fromString(`npm install`)} [拉取依赖] |====`)) // 加载状态 => 成功状态
Loading.succeed(chalk.greenBright(`====| ${Printer.fromString(`npm run serve`)} [项目启动] |====`)) // 加载状态 => 成功状态
}
)
},
// cli 初始化
_init(projectName, option) {
clear()
// welcome
Log(chalk.blueBright(repoLogo))
Log(chalk.blueBright(`Hello, Welcome to ${cliName}!`))
// cli init
const projectType = Object.keys(option).length ? Object.keys(option)[0].toLowerCase() : null
// 类型判断
if (projectType) { // 默认指令
Log(chalk.green(`去生成一个web-${projectType}...`))
myCli.checkIsHasProject(projectName).then(isHas => {
if (!isHas) {
Log(chalk.hex(repoColor.warning)(`请自行删除本地的${projectName}工程目录/文件!`))
return
}
myCli.cloneProject(packageJson.repository[`${projectType}Url`], projectName)
})
} else { // 自定义
Log(chalk.hex(repoColor.warning)(`你好,欢迎使用${cliName}!`))
//筛选问题
const questions = [
{
type: 'input',
name: 'customProjectName',
message: '请输入项目名称:',
validate: function (val) {
if (val.match(/^[A-Za-z0-9\( \)\-\#]+$/g)) {
return true
}
return '请输入规范的项目名称'
},
when: (answer) => {
if (!answer.customProjectName) {
return true
}
return false
}
},
{
type: `list`,
name: `framework`,
message: `请选择需要的脚手架:`,
default: `pc-|cut|-${packageJson.repository.pcUrl}`,
choices: [
{
name: 'pc端脚手架',
value: `pc-|cut|-${packageJson.repository.pcUrl}`
}, {
name: '移动端脚手架',
value: `h5-|cut|-${packageJson.repository.h5Url}`
}
],
when: (answer) => {
if (answer.customProjectName) {
Log(chalk.red(`\n\nVue CLI v4.5.13`))
if (repolatestVersion > repoCurrentVersion) {
Log(`
┌───────────────────────────────────────────┐
│ │
│ Hello, I'm Penn Ji. │
│ the author of Penn-CLI. │
│ ${Printer.fromString(`Welcome to `)}${Printer.fromString(`use it.`)} │
│ │
│ Your current version is ${chalk.red(`${repoCurrentVersion}`)} │
│ New version available ${chalk.hex(repoColor.warning)(`${repoLastVersion}`)} → ${chalk.hex(repoColor.warning)(`${repolatestVersion}`)} │
│ Run ${chalk.hex(repoColor.warning)(`npm i -g penn-cli`)} to update! │
│ │
└───────────────────────────────────────────┘
`)
} else {
Log(`
┌───────────────────────────────────────────┐
│ │
│ Hello, I'm Penn Ji. │
│ the author of Penn-CLI. │
│ ${Printer.fromString(`Welcome to `)}${Printer.fromString(`use it.`)} │
│ │
│ Your current version is ${chalk.red(`${repoCurrentVersion}`)} │
│ You're the ${chalk.greenBright(`latest version`)}! │
│ │
└───────────────────────────────────────────┘
`)
}
}
return true
}
}
]
// 自定义默认项
const answers = {
customProjectName: projectName
}
// Log(`answers==>${JSON.stringify(answers)}`)
inquirer.prompt(questions, answers)
.then((answer) => {
if (answer.framework) {
const frameworkArr = answer.framework.split(`-|cut|-`)
answer.frameworkObj = {
name: frameworkArr[0],
url: frameworkArr[1]
}
Log(JSON.stringify(answer))
Log(chalk.green(`去生成一个web-${answer.frameworkObj.name}...`))
const _projectName = answer.customProjectName
myCli.checkIsHasProject(_projectName).then(isHas => {
if (!isHas) {
Log(chalk.hex(repoColor.warning)(`请自行删除本地的${_projectName}工程目录/文件!`))
return
}
myCli.cloneProject(packageJson.repository[`${answer.frameworkObj.name}Url`], _projectName)
})
} else {
return
}
})
}
},
// 构建
_build() {
// 开始构建
program
.version(
// 彩虹色logo
Printer.fromString(
` \n Penn-CLI v${repoCurrentVersion}\n ${repoLogo}\n Hello, Welcome to ${cliName}!`
)
) // 获取版本 以package.json 版本信息为准
.description(`欢迎使用${cliName}脚手架~`) // 脚手架描述
.option(`-F, --framework`, `指定创建的脚手架,目前支持web-pc和web-h5`) // 指定构建的脚手架
.configureOutput({
// 此处使输出变得容易区分
writeOut: (str) => process.stdout.write(`[OUT] ${str}`),
writeErr: (str) => process.stdout.write(`[ERR] ${str}`),
// 将错误高亮显示
// outputError: (str, write) => write(chalk.hex(repoColor.warning)(str))
outputError: (str, write) => write(chalk.red(str))
})
.command(`create [projectName]`)
.description(`创建脚手架`)
.option(`-pc`, `生成一个用于web-pc的项目脚手架`)
.option(`-h5`, `生成一个用于web-h5的项目脚手架`)
.action((projectName, option, command) => (myCli._init(projectName, option)))
program.parse(process.argv) // 解析指令
}
}
myCli._build()