@conecli/cone-cli
Version:
松果编辑器命令行工具
250 lines (230 loc) • 5.79 kB
JavaScript
const shell = require('shelljs')
const ora = require('ora')
const os = require('os')
const path = require('path')
const fs = require('fs-extra')
const rm = require('rimraf').sync
const spawn = require('child_process').spawn
const logger = require('./logger')
const chalk = require('chalk')
const semver = require('semver')
/**
* 递归查找存在.cone文件的目录
* @returns 返回路径
*/
exports.getWorkspacePath = () => {
let currentPath = process.cwd()
const findCone = (p) => {
if (
shell.test('-f', `${p}${path.sep}.cone`) ||
'' === p ||
path.sep === p
) {
return p
}
return findCone(p.substring(0, p.lastIndexOf(path.sep)))
}
return findCone(currentPath)
}
/**
* 基于配置下载模板
* @param {*} name
* @param {*} config
* @param dest 下载模板存放位置
* @returns
*/
exports.downloadRepoByConfig = (name, config, dest) => {
const gitUrl = config['url']
const gitBranch = config['branch']
return exports.downloadRepo(gitUrl, gitBranch, dest, name)
}
/**
* clone一个git仓库
* @param {*} url
* @param {*} branch
* @param {*} dest
*/
exports.downloadGit = (url, branch, dest) => {
return new Promise((resolve, reject) => {
if (url && dest) {
const cmd = `git clone -b ${branch} ${url} "${dest}"`
const output = shell.exec(cmd, { silent: true })
const gitPath = path.resolve(dest, '.git')
fs.removeSync(gitPath)
if (output.code == 0) {
resolve()
} else {
reject({ message: output.stderr })
}
} else {
reject({ message: `url or dest is empty` })
}
})
}
/**
* 下载仓库
* @param url
* @param branch
* @param tmp
* @param callback
*/
exports.downloadRepo = (url, branch, tmp, name = '') => {
return new Promise((resolve, reject) => {
const spinner = ora(`downloading template ${name}`)
spinner.start()
// Remove if local template exists
if (fs.existsSync(tmp)) {
rm(tmp)
}
exports
.downloadGit(url, branch, tmp)
.then(() => {
spinner.stop()
resolve(true)
})
.catch((err2) => {
spinner.stop()
reject({
code: -1,
message:
'Failed to download template ' +
url +
': ' +
err2.message.trim(),
})
})
})
}
exports.copySync = (dest, target) => {
if (fs.existsSync(dest)) {
fs.copySync(dest, target)
} else {
logger.fatal(`Could not locate supplied dir: ${chalk.green(dest)}`)
}
}
/**
* Spawns a child process and runs the specified command
* By default, runs in the CWD and inherits stdio
* Options are the same as node's child_process.spawn
* @param {string} cmd
* @param {array<string>} args
* @param {object} options
*/
exports.runCommand = (cmd, args, options) => {
return new Promise((resolve, reject) => {
const spwan = spawn(
cmd,
args,
Object.assign(
{
cwd: process.cwd(),
stdio: 'inherit',
shell: true,
},
options
)
)
spwan.on('exit', () => {
resolve()
})
})
}
/**
* Runs `npm install` in the project directory
* @param {string} cwd Path of the created project directory
* @param {object} data Data
*/
exports.installDependencies = (cwd, executable = 'npm', color) => {
console.log(`\n\n# ${color('Installing project dependencies ...')}`)
console.log('# -----------------------\n')
return exports.runCommand(executable, ['install'], {
cwd,
})
}
/**
* Prints the final message with instructions of necessary next steps.
* @param {Object} data Data from questionnaire.
*/
exports.printMessage = (data, { green, yellow, blue }) => {
const message = `
# ${green('Project initialization finished!')}
# -----------------------
To get started:
${yellow(`${data.inPlace ? '' : `cd ${data.destDirName}\n `}yarn start`)}
${blue('Create Project is Done!')}
`
console.log(message)
}
exports.readFile = (path) => {
let result = ''
try {
result = fs.readFileSync(path, 'utf8')
} catch (err) {}
return result
}
exports.writeFile = (path, txt) => {
try {
fs.writeFileSync(path, txt)
} catch (err) {
console.log(err)
}
}
/**
* 初始化git仓库并初始化提交
* @param {*} commitMsg
*/
exports.initGit = (commitMsg = 'InitCommit') => {
console.log(`Initializing git repository...`)
const output = shell.exec('git init -b master')
if (output.code != 0) {
console.log(output.stderr)
} else {
if (shell.exec('git add .', { silent: true }).code == 0) {
shell.exec(`git commit -m '${commitMsg}'`, { silent: true })
}
}
}
function extractVersion(str) {
if (!str) {
return null
}
const versionPattern = /v\d+\.\d+\.\d+/
const match = str.match(versionPattern)
return match ? match[0] : null
}
function checkNeedInstallCaddy() {
console.log('正在检查Caddy安装情况')
const output = shell.exec('caddy version', { silent: true })
if (output.code == 0) {
const version = extractVersion(output.stdout)
if (version && semver.gte(version, '2.0.0')) {
console.log('当前Caddy版本为:', version)
return false
}
} else {
console.log(output.stderr)
}
return true
}
exports.initCaddy = () => {
// 只在Mac系统上安装Caddy
if (os.platform() !== 'darwin') {
return
}
if (checkNeedInstallCaddy()) {
console.log(
'Caddy未安装或者版本不满足要求,正在安装Caddy,执行命令为:brew install caddy'
)
const output = shell.exec('brew install caddy', { silent: true })
if (output.code !== 0) {
console.log(output.stderr)
}
if (checkNeedInstallCaddy()) {
logger.fatal(
`安装Caddy失败,请手动安装:\n安装前建议先执行:brew update 更新brew;然后再执行:brew install caddy 安装caddy,如果是M2芯片的Mac电脑并且执行 brew install caddy 安装失败可以尝试执行:arch -arm64 brew install caddy 安装`
)
} else {
logger.success(`安装Caddy成功`)
}
}
}