lizi-wxapp-cli
Version:
微信小程序快速创建cli脚手架
266 lines (243 loc) • 9.27 kB
text/typescript
import autocomplete from '@moyuyc/inquirer-autocomplete-prompt'
import chalk from 'chalk'
import fuzzy from 'fuzzy'
import inquirer, { Answers, ConfirmQuestion, InputQuestion } from 'inquirer'
import jsonFormat from 'json-format'
import ora, { Ora } from 'ora'
import path from 'path'
import { regName } from '../ulits/ulits'
import Base from './base'
interface CreateFs {
init(): Promise<void>
makeProjectDir(): Promise<any>
copyProjectFiles(): void
modifyAppJson(): Promise<void>
create(): Promise<Ora>
}
export default abstract class Create extends Base implements CreateFs {
protected _name: string = ''
protected _isSubpackage: boolean = false
protected _selectSubpackage: string = ''
protected _createMain?: string
protected _isIndependent?: boolean
protected newItemRoot: string = ''
protected newItemJsonRoot: string = ''
protected newItemJsonName: string = ''
protected constructor() {
super()
}
public async init(): Promise<void> {
await this.getAppJson()
// 注册插件
inquirer.registerPrompt('autocomplete', autocomplete)
inquirer.prompt([
this.__checkName(),
this.__isSubPackage(),
this.__modifyName(),
this.__selectSubPackage(),
this.__createSubPackage(),
this.__modifySubPackageChildName(),
this.__isIndependent()
]).then((answers: any) => {
let {name, isSubpackage, selectSubpackage, createMain, isIndependent} = answers
this._name = name
this._isSubpackage = isSubpackage
this._selectSubpackage = selectSubpackage
this._createMain = createMain
this._isIndependent = isIndependent
}).then(() => this.create()).catch((error) => {
console.log(error)
})
}
public async create(): Promise<Ora> {
const loading: Ora = ora(`creating ${this.typeRoot}...`).start()
loading.text = `创建${this.typeName}目录`
await this.makeProjectDir()
loading.text = `正在创建${this.typeName}文件`
await this.copyProjectFiles()
loading.text = '正在修改【app.json】文件'
await this.modifyAppJson()
return Promise.resolve(loading)
}
public async makeProjectDir(): Promise<any> {
// 默认不分包
let newItemRoot = path.join(this.projectRoot, this.typeRoot, this._name)
// 如果分包
if (this._isSubpackage) {
let name: string = this._selectSubpackage === '新增分包' && this._createMain ?
path.join(this.subpackageRoot, this._createMain) :
this._selectSubpackage
newItemRoot = path.join(this.projectRoot, name, this.typeRoot, this._name)
}
this.newItemRoot = newItemRoot
// 判断下文件是否存在
if (!await this.checkFileIsExists(newItemRoot)) this.makeDir(newItemRoot)
}
public copyProjectFiles(): void {
// 读取project.config.json获取配置信息
this.getProjectConfig().then(async () => {
const copyRoot = path.join(this.templateRoot, 'component')
// 复制wxml,json文件
await this.copyFilesArr(copyRoot, this.newItemRoot, ['index.wxml', 'index.json'])
.catch(({result}) => this.fileIsRepeat(result))
// 复制脚本文件
this._copyTypeFiles(copyRoot, this.projectMode)
// 复制样式文件
this._copyTypeFiles(copyRoot, this.projectCss)
})
}
public async modifyAppJson(): Promise<void> {
// 是否分包
let newItemJson: string = path.join(this.typeRoot, this._name, 'index').split(path.sep).join('/')
let newItemName: string = this._name
if (this._isSubpackage) {
if (this._selectSubpackage === '新增分包' && this._createMain) {
this.AppJson.subpackages.push({
root: path.join(this.subpackageRoot, this._createMain),
pages: this.typeRoot === 'pages' ? [newItemJson] : [],
components: this.typeRoot === 'components' ? [newItemJson] : [],
isIndependent: this._isIndependent
})
newItemName = path.join(this._createMain, this._name)
newItemJson = path.join(this.subpackageRoot, this._createMain, newItemJson)
} else {
let index: number = this.subRoots.findIndex(v => v === this._selectSubpackage)
this.AppJson.subpackages[index][this.typeRoot].push(newItemJson)
newItemName = path.join(this._selectSubpackage.replace(this.subpackageRoot + '/', ''), this._name)
newItemJson = path.join(this._selectSubpackage, newItemJson)
}
} else {
this.AppJson[this.typeRoot].push(newItemJson)
}
this.newItemJsonRoot = newItemJson.split(path.sep).join('/')
this.newItemJsonName = newItemName.split(path.sep).join('/')
await this.writeFile(this.projectRoot, 'app.json', jsonFormat(this.AppJson))
}
private async _copyTypeFiles(copyRoot, type): Promise<void> {
const root: string = path.join(copyRoot, type)
const files: string[] = await this.readDirs(root)
await this.copyFilesArr(root, this.newItemRoot, files)
.catch(({result}) => this.fileIsRepeat(result))
}
// 验证名称
private __checkName(): InputQuestion<Answers> {
return {
type: 'input',
name: 'name',
message: `请输入${this.typeName}名:`,
validate: (input: string): Promise<boolean | string> => {
return new Promise<boolean | string>((resolve) => {
// 验证名是否正确
if (!regName.test(input)) resolve(chalk.red(`输入的${this.typeName}名不正确!`))
resolve(true)
})
}
}
}
// 是否分包
private __isSubPackage(): ConfirmQuestion<Answers> {
return {
type: 'confirm',
name: 'isSubpackage',
message: `当前${this.typeName}是否分包:`,
default: false
}
}
// 如果不分包,判断是否重复
private __modifyName(): InputQuestion<Answers> {
return {
type: 'input',
name: 'name',
message: answer => `【${this.typeRoot}】中已存在【${answer.name}】${this.typeName},请重新输入${this.typeName}名:`,
when: answer => {
return !answer.isSubpackage &&
this.mainRoots.find(v => v === answer.name) !== undefined
},
validate: (input: string): Promise<boolean | string> => {
return new Promise<boolean | string>(resolve => {
if (this.mainRoots.find(v => v === input)) resolve(chalk.red(`${this.typeName}名重复,请更换!`))
resolve(true)
})
}
}
}
// 选择分包
private __selectSubPackage(): object {
return {
type: 'autocomplete',
name: 'selectSubpackage',
message: `选择${this.typeName}所属分包:`,
choices: [],
suggestOnly: false,
source: (_answers, input: string) => {
return Promise.resolve(fuzzy.filter(input, ['新增分包', ...this.subRoots]).map(e => e.original))
},
when: (answer) => {
return answer.isSubpackage &&
this.subRoots.length >= 0
}
}
}
// 创建分包
private __createSubPackage(): InputQuestion<Answers> {
return {
type: 'input',
name: 'createMain',
message: '创建新的分包:',
when: (answer) => {
return answer.isSubpackage &&
this.subRoots.length <= 0 ||
answer.selectSubpackage === '新增分包'
},
validate: (input: string): Promise<boolean | string> => {
return new Promise<boolean | string>(resolve => {
// 验证名是否正确
if (!regName.test(input)) {
resolve(chalk.red('输入的分包名不正确!'))
}// 检查分包名是否重复
else if (this.subRoots.find(v => v === input)) resolve(chalk.red('该分包已存在,请换个分包名!'))
resolve(true)
})
}
}
}
// 分包下的子包如果重复则需要修改子包名
private __modifySubPackageChildName(): InputQuestion<Answers> {
return {
type: 'input',
name: 'name',
message: answer => `【${answer.selectSubpackage}】分包已存在【${answer.name}】${this.typeName},请更换${this.typeName}名:`,
when: answer => {
return answer.isSubpackage &&
answer.selectSubpackage !== '新增分包' &&
this.subChild[answer.selectSubpackage].find(v => v === answer.name) !== undefined
},
validate: (input: string, answers: any): Promise<boolean | string> => {
return new Promise<boolean | string>(resolve => {
// 验证名是否正确
if (!regName.test(input)) {
resolve(chalk.red(`输入的${this.typeName}名不正确!`))
}// 验证是否重复
else if (this.subChild[answers.selectSubpackage].find(v => v === input)) {
resolve(chalk.red(`${this.typeName}名重复,请更换${this.typeName}名!`))
}
resolve(true)
})
}
}
}
// 新增分包是否为独立分包
private __isIndependent(): ConfirmQuestion<Answers> {
return {
type: 'confirm',
name: 'isIndependent',
message: '是否设置独立分包:',
default: false,
when: (answers) => {
return answers.isSubpackage &&
answers.selectSubpackage === '新增分包' &&
answers.createMain
}
}
}
}