UNPKG

@fuse-oo/cli

Version:

fuse内部脚手架工具

189 lines (167 loc) 5.34 kB
const chalk = require('chalk') const execa = require('execa') const inquirer = require('inquirer') const EventEmitter = require('events') const loadRemotePreset = require('../lib/utils/loadRemotePreset') const writeFileTree = require('../lib/utils/writeFileTree') const copyFile = require('../lib/utils/copyFile') const generateReadme = require('../lib/utils/generateReadme') const {installDeps} = require('../lib/utils/installDeps') const { defaults } = require('../lib/options') const { log, error, hasYarn, hasGit, hasPnpm3OrLater, hasProjectGit, logWithSpinner, clearConsole, stopSpinner, exit } = require('../lib/utils/common') module.exports = class Creator extends EventEmitter { constructor(name, context) { super() this.name = name this.context = context this.run = this.run.bind(this) } async create(cliOptions = {}, preset = null) { const { run, name, context } = this // ------- step 1 下载远程模版 --------- if (cliOptions.preset) { // fuse-cli create foo --preset mobx preset = await this.resolvePreset(cliOptions.preset, cliOptions.clone) } else { preset = await this.resolvePreset(defaults.presets.default, cliOptions.clone) } // ------- step 2 cli信息打印 --------- await clearConsole() log(chalk.blue.bold(`Fuse CLI v${require('../package.json').version}`)) logWithSpinner(`🐼`, `正在创建项目 ${chalk.yellow(context)}.`) this.emit('creation', { event: 'creating' }) stopSpinner() // ------- step 3 基本信息配置 --------- const { pkgVers, pkgDes } = await inquirer.prompt([ { name: 'pkgVers', message: `请输入项目版本号`, default: '1.0.0', }, { name: 'pkgDes', message: `请输入项目简介`, default: 'project created by fuse-cli', } ]) // 将下载的临时文件拷贝到项目中 const pkgJson = await copyFile(preset.tmpdir, preset.targetDir) const pkg = Object.assign(pkgJson, { version: pkgVers, description: pkgDes }) // 写入 package.json log() logWithSpinner('🐶', `生成 ${chalk.yellow('package.json')} 等模板文件`) await writeFileTree(context, { 'package.json': JSON.stringify(pkg, null, 2) }) // 获取包管理工具 const packageManager = ( (hasYarn() ? 'yarn' : null) || (hasPnpm3OrLater() ? '' : 'npm') ) // 写入 readme 文档 await writeFileTree(context, { 'README.md': generateReadme(pkg, packageManager) }) // ------- step 4 git 初始化 依赖下载 --------- const shouldInitGit = this.shouldInitGit(cliOptions) if (shouldInitGit) { logWithSpinner(`🐸`, `初始化Git仓库`) this.emit('creation', { event: 'git-init' }) await run('git init') } // 安装依赖 stopSpinner() log() logWithSpinner(`🐒`, `安装依赖中,请稍等...`) await installDeps(context, packageManager, cliOptions.registry) // commit initial state let gitCommitFailed = false if (shouldInitGit) { await run('git add -A') const msg = typeof cliOptions.git === 'string' ? cliOptions.git : 'init' try { await run('git', ['commit', '-m', msg]) } catch (e) { gitCommitFailed = true } } // ------- step 5 项目创建成功 --------- stopSpinner() log() log(`🎉 项目创建成功 ${chalk.yellow(name)}.`) if (!cliOptions.skipGetStarted) { log( `👉 请按如下命令,开始愉快开发吧!\n\n` + (this.context === process.cwd() ? `` : chalk.cyan(` ${chalk.gray('$')} cd ${name}\n`)) + chalk.cyan(` ${chalk.gray('$')} ${packageManager === 'yarn' ? 'yarn start' : packageManager === 'pnpm' ? 'pnpm run start' : 'npm start'}`) ) } log() this.emit('creation', { event: 'done' }) if (gitCommitFailed) { warn( `因您的git username或email配置不正确,无法为您初始化git commit,\n` + `请稍后自行git commit。\n` ) } } // 拉取远程模版的方法 async resolvePreset (name, clone) { let preset logWithSpinner(`🐔`, `Fetching remote preset ${chalk.cyan(name)}...`) this.emit('creation', { event: 'fetch-remote-preset' }) try { preset = await loadRemotePreset(name, this.context, clone) stopSpinner() } catch (e) { stopSpinner() error(`Failed fetching remote preset ${chalk.cyan(name)}:`) throw e } // 默认使用default参数 if (name === 'default' && !preset) { preset = defaults.presets.default } if (!preset) { error(`preset "${name}" not found.`) exit(1) } return preset } run (command, args) { if (!args) { [command, ...args] = command.split(/\s+/) } return execa(command, args, { cwd: this.context }) } // 是否能 git 初始化 shouldInitGit (cliOptions) { if (!hasGit()) { return false } // --git if (cliOptions.forceGit) { return true } // --no-git if (cliOptions.git === false || cliOptions.git === 'false') { return false } // default: true unless already in a git repo return !hasProjectGit(this.context) } }