bia
Version:
a tool for download git repository
536 lines (503 loc) • 17.9 kB
JavaScript
/*
* @Author: hzxulin@yeah.net
* @Date: 2018-11-19 18:15:59
* @Last Modified by: hzxulin@yeah.net
* @Last Modified time: 2019-12-18 15:34:39
*/
const path = require('path')
const execa = require('execa')
const ora = require('ora')
const fse = require('fs-extra')
const figlet = require('figlet')
const colors = require('colors')
const request = require('request')
const BASE_CONFIG = require('../../config/base.json')
/**
* 获取当前时间
*/
const getNowDate = () => {
let _dateObj = new Date()
let _year = _dateObj.getFullYear()
let _month = _dateObj.getMonth() + 1
let _date = _dateObj.getDate()
_month = _month < 10 ? `0${_month}` : _month
_date = _date < 10 ? `0${_date}` : _date
return `${_year}-${_month}-${_date}`
}
/**
* clone远程git项目,去除.git文件
* @param {string} repo git的源地址
* @param {string} branch 分支名称
* @param {string} text 提示文案
*/
const cloneGit = (repo, branch, text) => {
text = text || '项目初始化中...'
return new Promise((resolve, reject) => {
const spinner = ora(`== ${text} ==`)
const tplTemp = path.resolve(process.env.HOME, '.web-init-templates', repo.replace(/\/|:/g, '-'))
spinner.start()
fse.emptyDirSync(tplTemp)
let cmd = `git clone ${branch ? `-b ${branch}` : ''} ${repo} ${tplTemp}`
execa.shell(cmd).then(() => {
fse.removeSync(path.resolve(tplTemp, '.git'))
spinner.stop()
resolve(tplTemp)
}).catch(err => {
spinner.stop()
console.log(colors.red('== 初始化异常,停止进程 =='))
reject(err)
})
})
}
/**
* 移动文件
* @param {string} file 文件名称
* @param {string} src 源路径
* @param {string} dist 目标路径
*/
const moveFiles = (file, src, dist) => {
return new Promise((resolve, reject) => {
const srcFolder = file ? path.resolve(src, file) : src
const distFolder = file ? path.resolve(dist, file) : dist
try {
fse.copySync(srcFolder, distFolder)
resolve()
} catch (err) {
reject(err)
}
})
}
/**
* 渲染文件,用于pageInfo文件
* @param {object} answer 配置信息
* @param {string} src 源文件地址
* @param {string} dist 目标地址
*/
const renderPageInfo = (answer, src, dist) => {
return new Promise((resolve, reject) => {
fse.readFile(src, 'utf-8', (_err, _data) => {
if (_err) {
reject(_err)
} else {
let _deployPC = true
let _deployH5 = true
let _combinePC = 'pc'
let _combineH5 = 'h5'
switch (+answer.platform) {
case 0: {
break
}
case 1: {
_deployH5 = false
_combineH5 = 'pc'
break
}
case 2: {
_deployPC = false
_combinePC = 'h5'
break
}
}
let _newData = String(_data).replace(/\$\{projectId\}/, (answer.projectId && answer.projectId.length) ? `"${answer.projectId}"` : '0')
.replace(/\$\{title\}/, answer.title)
.replace(/\$\{startTime\}/, `${answer.startTime} 00:00:00`)
.replace(/\$\{endTime\}/, `${answer.endTime} 00:00:00`)
.replace(/\$\{category\}/, answer.category)
.replace(/\$\{deployPC\}/, _deployPC)
.replace(/\$\{deployH5\}/, _deployH5)
.replace(/\$\{combinePC\}/, _combinePC)
.replace(/\$\{combineH5\}/, _combineH5)
try {
fse.outputFileSync(dist, _newData)
resolve()
} catch (err) {
reject(err)
}
}
})
})
}
/**
* 渲染文件,用于pageInfo json文件
* @param {object} answer 配置信息
* @param {string} src 源文件地址
* @param {string} dist 目标地址
*/
const renderPageInfoJson = (answer, src, dist) => {
return new Promise((resolve, reject) => {
fse.readFile(src, 'utf-8', (_err, _data) => {
if (_err) {
reject(_err)
} else {
let _newData = String(_data)
.replace(/\$\{title\}/ig, answer.title)
.replace(/\$\{startTime\}/ig, `${answer.startTime} 00:00:00`)
.replace(/\$\{endTime\}/ig, `${answer.endTime} 00:00:00`)
.replace(/\$\{businessId\}/ig, answer.businessId)
.replace(/\$\{cateList\}/ig, answer.cateList)
try {
fse.removeSync(src)
fse.outputFileSync(dist, _newData)
resolve()
} catch (err) {
reject(err)
}
}
})
})
}
/**
* 删除指定的文件或目录
* @param {string} dist 文件或目录
*/
const removeDist = (dist) => {
return new Promise((resolve, reject) => {
try {
fse.removeSync(dist)
resolve()
} catch (err) {
reject(err)
}
})
}
/**
* 渲染模板
* @param {number} platform pc或者h5,或其他
* @param {*} src 源地址
* @param {*} dist 目标地址
*/
const renderTpl = (platform, src, dist) => {
return new Promise((resolve, reject) => {
try {
fse.removeSync(dist)
switch (+platform) {
case 1: {
fse.copySync(path.resolve(src, 'pc'), path.resolve(dist, 'pc'))
break
}
case 2: {
fse.copySync(path.resolve(src, 'h5'), path.resolve(dist, 'h5'))
break
}
case 0:
default: {
fse.copySync(path.resolve(src, 'pc'), path.resolve(dist, 'pc'))
fse.copySync(path.resolve(src, 'h5'), path.resolve(dist, 'h5'))
break
}
}
resolve()
} catch(err) {
reject(err)
}
})
}
/**
* 成功打印logo
* @param {function} cb 回调函数cb
* @param {boolean} exitFlag 结束标志
*/
const showSuccess = (cb, exitFlag) => {
figlet('^ Bia >>>', (err, data) => {
if (err) throw err
console.log(colors.green(`\n${data}`))
if (Object.prototype.toString.call(cb) === '[object Function]') {
cb()
} else {
console.log(colors.green('== Bia success. =='))
}
if (exitFlag) process.exit()
})
}
/**
* 查询活动计划
*/
const getProjectPlan = () => {
return new Promise((resolve, reject) => {
request('http://pub.mail.163.com/pscpub/captain/api/project/getSimpleUnOffList.do?sign=178b95ad88feec0b9c1f04e641fe3317', (_err, _res, _body) => {
if (_res.statusCode == 200) {
let _result = []
try {
_result = JSON.parse(_body).result
} catch (e) {
_result = _body.result
}
resolve(_result)
} else {
reject('Failed to get the list of plan.')
}
})
})
}
/**
* 获取页面搭建系统的cate列表
*/
const getCateList = () => {
return new Promise((resolve, reject) => {
const cateList = BASE_CONFIG.cateList
resolve(cateList)
})
}
/**
* 渲染文件,用于floor json文件
* @param {object} answer 配置信息
* @param {string} src 源文件地址
* @param {string} dist 目标地址
*/
const renderFloorListJson = (answer, src, dist) => {
return new Promise((resolve, reject) => {
fse.readFile(src, 'utf-8', (_err, _data) => {
if (_err) {
reject(_err)
} else {
try {
let _newData = JSON.parse(String(_data))
switch (+answer.platform) {
case 0: {
_newData = {
"pc": _newData,
"h5": _newData,
}
break
}
case 1: {
_newData = {
"pc": _newData,
}
break
}
case 2: {
_newData = {
"h5": _newData,
}
break
}
}
fse.removeSync(src)
fse.outputFileSync(dist, JSON.stringify(_newData, null, 4))
resolve()
} catch (err) {
reject(err)
}
}
})
})
}
/**
* 更新taro组件开发的文件信息
* @param {string} dist 目标路径
* @param {object} info
*/
const formatComponentFile = (dist, info) => {
return new Promise((resolve, reject) => {
fse.readFile(dist, 'utf-8', (_err, _data) => {
if (_err) {
reject(_err)
} else {
try {
const _newData = String(_data)
.replace(/\$componentName\$/ig, info.name || '')
.replace(/\$componentVersion\$/ig, info.version || '')
.replace(/\$componentDesc\$/ig, info.desc || '')
fse.outputFileSync(dist, _newData)
resolve()
} catch (err) {
reject(err)
}
}
})
})
}
/**
* 获取目标路径下所有的文件
* @param {string} dir 目标路径
*/
const getAllFiles = (dir) => {
return new Promise((resolve, reject) => {
try {
let res = []
const findAllFiles = (subDir) => {
let files = fse.readdirSync(subDir)
files.forEach((item) => {
let fPath = path.resolve(subDir, item)
let stat = fse.statSync(fPath)
if(stat.isDirectory()) {
res.push({
type: 'directory',
value: fPath,
})
findAllFiles(fPath)
}
if (stat.isFile()) {
res.push({
type: 'file',
value: fPath,
})
}
})
}
findAllFiles(dir)
resolve(res)
} catch (err) {
reject(err)
}
})
}
/**
* 更新component框架下的开发src路径下的内容
* @param {object} info
*/
const updateComponentSrc = (info) => {
return new Promise((resolve, reject) => {
try {
const srcFolder = path.resolve(process.cwd(), 'src/components/$componentName$')
const distFolder = srcFolder.replace(/\$componentName\$/ig, info.name || '')
fse.copySync(srcFolder, distFolder)
removeDist(srcFolder).then(() => {
return getAllFiles(path.resolve(process.cwd(), `src`))
}).then((res) => {
console.log(res)
return Promise.all(res.filter(item => (item.type == 'file')).map(item => {
return formatComponentFile(item.value, info)
}))
}).then(() => {
resolve()
}).catch((err) => {
reject(err)
})
} catch (err) {
reject(err)
}
})
}
/**
* 更新taro组件开发的框架
* @param {object} info
*/
const updateComponentFramework = (info) => {
return new Promise((resolve, reject) => {
return formatComponentFile(path.resolve(process.cwd(), 'package.json'), info).then(() => {
return updateComponentSrc(info)
}).then(() => {
resolve(info)
}).catch(err => {
reject(err)
})
})
}
/**
* 获取老活动框架的pageInfo
*/
const getOldPageInfo = () => {
return new Promise((resolve, reject) => {
const oriPageInfo = path.resolve(process.cwd(), 'pageInfo/pageInfo.yml')
fse.readFile(oriPageInfo, 'utf-8', (_err, _data) => {
if (_err) {
reject(_err)
} else {
try {
const title = String(_data).match(/title:\s*\"(.*)\"/)[1]
const startTime = String(_data).match(/startTime:\s*\"(.*)\"/)[1]
const endTime = String(_data).match(/endTime:\s*\"(.*)\"/)[1]
resolve({
title,
startTime,
endTime,
})
} catch (err) {
reject(err)
}
}
})
})
}
/**
* 输出新的pageInfo
* @param {object} pageInfo 页面pageInfo
*/
const outputNewPageInfo = (pageInfo) => {
return new Promise((resolve, reject) => {
const oriPageInfo = path.resolve(process.cwd(), 'pageInfo/pageInfo.yml')
const newPageInfo = path.resolve(process.cwd(), 'pageInfo/pageInfo.json')
fse.readFile(newPageInfo, 'utf-8', (_err, _data) => {
if (_err) {
reject(_err)
} else {
try {
const _newData = String(_data)
.replace(/\$\$pageName\$\$/ig, pageInfo.title || '')
.replace(/\$\$startTime\$\$/ig, pageInfo.startTime || '')
.replace(/\$\$endTime\$\$/ig, pageInfo.endTime || '')
fse.removeSync(oriPageInfo)
fse.outputFileSync(newPageInfo, _newData)
resolve()
} catch (err) {
reject(err)
}
}
})
})
}
/**
* 输出新的package文件
*/
const outputPackage = () => {
return new Promise((resolve, reject) => {
const oriPackage = path.resolve(process.cwd(), 'package.json')
const newPackage = path.resolve(process.cwd(), 'package.temp.json')
fse.readFile(oriPackage, 'utf-8', (_err, _data) => {
if (_err) {
reject(_err)
} else {
fse.readFile(newPackage, 'utf-8', (_err2, _data2) => {
if (_err2) {
reject(_err2)
} else {
let oriPackageJson = JSON.parse(String(_data))
let newPackageJson = JSON.parse(String(_data2))
const oldPackageDep = ["art-template", "art-template-loader", "autoprefixer", "babel-core", "babel-eslint", "babel-loader", "babel-plugin-add-module-exports", "babel-plugin-lodash", "babel-plugin-transform-runtime", "babel-preset-env", "babel-preset-stage-2", "chalk", "css-loader", "cssnano", "es3ify-loader", "es5-shim", "eslint", "eslint-config-standard", "eslint-friendly-formatter", "eslint-loader", "eslint-plugin-bia", "eslint-plugin-html", "eslint-plugin-import", "eslint-plugin-node", "eslint-plugin-promise", "eslint-plugin-standard", "execa", "express", "extract-text-webpack-plugin", "file-loader", "friendly-errors-webpack-plugin", "fs-extra", "html-loader", "html-string-replace-webpack-plugin", "html-webpack-inline-source-plugin", "html-webpack-plugin", "htmlhint-bia-loader", "html-modulemarket-plugin", "http-proxy-middleware", "ip", "json-server", "node-sass", "opn", "ora", "portfinder", "postcss-bialint", "postcss-import", "postcss-loader", "request", "rimraf", "sass-loader", "script-loader", "string-replace-webpack-plugin", "style-loader", "url-loader", "vconsole-webpack-plugin", "webpack", "webpack-dev-middleware", "webpack-hot-middleware", "webpack-merge", "yargs"]
let tempDep = oriPackageJson.devDependencies
Object.keys(tempDep).forEach((item) => {
if (oldPackageDep.indexOf(item) > -1) {
delete tempDep[item]
}
})
const resPackageJson = Object.assign({}, newPackageJson, {
devDependencies: Object.assign({}, newPackageJson.devDependencies, tempDep),
dependencies: Object.assign({}, newPackageJson.dependencies, oriPackageJson.dependencies),
})
fse.removeSync(newPackage)
fse.outputFileSync(oriPackage, JSON.stringify(resPackageJson, null, 4))
resolve()
}
})
}
})
})
}
/**
* 活动框架更新
*/
const updateAct = () => {
return getOldPageInfo().then((pageInfo) => {
return outputNewPageInfo(pageInfo)
}).then(() => {
return outputPackage()
})
}
module.exports = {
getNowDate,
cloneGit,
moveFiles,
renderPageInfo,
renderPageInfoJson,
removeDist,
renderTpl,
showSuccess,
getProjectPlan,
getCateList,
renderFloorListJson,
updateComponentFramework,
updateAct,
updateComponentSrc,
}