UNPKG

lizi-wxapp-cli

Version:

微信小程序快速创建cli脚手架

212 lines (195 loc) 6.84 kB
import chalk from 'chalk' import process, { ChildProcessWithoutNullStreams } from 'child_process' import inquirer, { Answers, InputQuestion, ListQuestion } from 'inquirer' import jsonFormat from 'json-format' import ora, { Ora } from 'ora' import path from 'path' import { log } from '../ulits/log' import { regAppId, regCn, regEn } from '../ulits/ulits' import Base from './base' import { CreatePageFs } from './create-page-fs' interface CreateProjectInterface { init(): void create(): Promise<void> } export default class CreateProject extends Base implements CreateProjectInterface { protected name: string = '' protected depict: string = '' protected appid: string = '' protected mode: 'javascript' | 'typescript' = 'javascript' protected css: 'wxss' | 'less' = 'wxss' constructor() { super() } public init(): void { inquirer.prompt([ this.__projectName(), this.__projectDescription(), this.__projectAppId(), this.__projectMode(), this.__projectCss() ]).then(async ({name, depict, appid, mode, css}: Answers): Promise<void> => { this.name = name this.depict = depict this.appid = appid this.mode = mode this.css = css await this.create() }).catch((err) => { console.log(err) }) } public __projectName(): InputQuestion<Answers> { const that = this return { type: 'input', name: 'name', message: '请输入项目名称:', async validate(input: string): Promise<boolean | string> { // 校验文件名是否符合规范 return new Promise<boolean | string>(async (resolve) => { if (regEn.test(input) || regCn.test(input)) { // 验证项目名是否符合规则 resolve(chalk.red('项目名不符合规则,请重新输入项目名!')) } else if (await that.checkFileIsExists(path.join(that.projectRoot, input))) { // 获取当前打开的目录,验证当前要创建的项目是否跟当前目录里的文件夹命名冲突 resolve(chalk.red('该项目已创建,请重新输入项目名!')) } resolve(true) }) }, default: 'app' } } public __projectDescription(): InputQuestion<Answers> { return { type: 'input', name: 'depict', message: '请输入项目描述:' } } public __projectAppId(): InputQuestion<Answers> { return { type: 'input', name: 'appid', message: (answers) => `请输入[${answers.name}]的AppId:`, async validate(input: string): Promise<boolean | string> { return new Promise<boolean | string>((resolve) => { if (!regAppId.test(input)) resolve(chalk.red('请输入正确的AppId!')) resolve(true) }) } } } public __projectMode(): ListQuestion<Answers> { return { type: 'list', name: 'mode', message: '选择项目脚本语言:', choices: [ 'javascript', 'typescript' ] } } public __projectCss(): ListQuestion<Answers> { return { type: 'list', name: 'css', message: '选择项目样式语言:', choices: [ 'wxss', 'less' ] } } private async _copyTypeFiles(copyRoot, projectRoot, type): Promise<void> { const root: string = path.join(copyRoot, type) const files: string[] = await this.readDirs(root) await this.copyFilesArr(root, projectRoot, files) .catch(({result}) => this.fileIsRepeat(result)) } public async create(): Promise<void> { const loading: Ora = ora('creating project...').start() // 创建项目文件夹 let projectRoot: string = path.join(this.projectRoot, this.name) await this.makeDir(projectRoot) // 获取模板文件 let tempRoot: string = path.join(this.templateRoot, 'project') let files: string[] = await this.readDirs(tempRoot) // 创建小程序默认文件 await this.copyFilesArr(tempRoot, projectRoot, files) // 创建脚本文件 this._copyTypeFiles(tempRoot, projectRoot, this.mode) // 创建样式文件 this._copyTypeFiles(tempRoot, projectRoot, this.css) // 初始化npm项目 const bash: ChildProcessWithoutNullStreams = process.spawn('bash') bash.on('error', () => loading.fail(chalk.red('初始化失败'))) bash.on('close', async () => { loading.text = '初始化成功' // 修改npm配置文件 await this._modifyPackageJson(projectRoot, 'package.json', loading) // 修改小程序配置文件 await this._modifyProjectConfigJson(projectRoot, 'project.config.json', loading) // 创建默认页面 let pageRoot: string = path.join(projectRoot, this.pageRoot) await this.makeDir(pageRoot) CreatePageFs.create({ root: projectRoot, name: 'index' }).then(() => { loading.succeed(chalk.green(`项目【${this.name}】创建成功`)) log.table([ ['项目名称', this.name], ['APPID', this.appid], ['项目描述', this.depict], ['项目路径', this.projectRoot], ['脚本语言', this.mode], ['样式语言', this.css], ['操作提示', `Please switch to the project directory! Run ${chalk.bgWhite('cd ' + this.name)} to directory! Run ${chalk.bgWhite('npm install')} to start!`] ], false) }) }) bash.stdin.write(`cd ${this.name}\n`) bash.stdin.write('npm init -y \n') bash.stdin.end() } private async _modifyProjectConfigJson(path: string, file: string, loading: Ora): Promise<void> { // 读取配置文件 let json = JSON.parse(await this.readFile(path, file)) let modify = { miniprogramRoot: this.miniprogramRoot, projectname: this.name, projectmode: this.mode, projectcss: this.css, appid: this.appid } await this.writeFile(path, file, jsonFormat({...json, ...modify})) loading.text = `修改${file}成功` } private async _modifyPackageJson(path: string, file: string, loading: Ora): Promise<void> { // 读取文件 let json = JSON.parse(await this.readFile(path, file)) let modify = { scripts: { compile: './node_modules/typescript/bin/tsc', tsc: 'node ./node_modules/typescript/lib/tsc.js' }, description: this.depict ? this.depict : 'project depict...', devDependencies: { typescript: '^3.5.3' }, dependencies: { 'miniprogram-api-typings': '^2.7.7', 'tslint-config-alloy': '^0.2.1', 'tslint-eslint-rules': '^5.4.0' } } await this.writeFile(path, file, jsonFormat({...json, ...modify})) loading.text = `修改${file}成功` } } export const CreateProjectFs = new CreateProject()