-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
lipeizhong
committed
Nov 17, 2019
0 parents
commit 8de12b8
Showing
29 changed files
with
1,390 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#!/usr/bin/env node | ||
|
||
// 检测node版本相关依赖 | ||
const chalk = require('chalk') | ||
const semver = require('semver') | ||
const requiredVersion = require('../package.json').engines.node | ||
|
||
// 检测node版本函数 | ||
/** | ||
* | ||
* @param {*} wanted | ||
* @param {*} id | ||
*/ | ||
function checkNodeVersion (wanted, id) { | ||
if (!semver.satisfies(process.version, wanted)) { | ||
console.log(chalk.red( | ||
'你是用的Node版本号为: ' + process.version + ', 但 ' + id + | ||
' 需运行在 ' + wanted + '.\n请升级你的Node版本' | ||
)) | ||
process.exit(1) | ||
} | ||
} | ||
|
||
checkNodeVersion(requiredVersion, 'awesome-test-cli') | ||
|
||
if (semver.satisfies(process.version, '9.x')) { | ||
console.log(chalk.red( | ||
`你是用的Node版本是 ${process.version}.\n` + | ||
`强烈建议你使用最新 LTS 版本` | ||
)) | ||
} | ||
|
||
// 开始处理命令 | ||
const program = require('commander') | ||
const minimist = require('minimist') | ||
|
||
program | ||
.version(require('../package').version) | ||
.usage('<command> [options]') | ||
|
||
// 创建命令 | ||
program | ||
.command('create <app-name>') | ||
.description('create a new project') | ||
.option('-p, --preset <presetName>', 'Skip prompts and use saved or remote preset') | ||
.option('-d, --default', 'Skip prompts and use default preset') | ||
.action((name, cmd) => { | ||
const options = cleanArgs(cmd) | ||
if (minimist(process.argv.slice(3))._.length > 1) { | ||
console.log(chalk.yellow('\n ⚠️ 检测到您输入了多个名称,将以第一个参数为项目名,舍弃后续参数哦')) | ||
} | ||
require('../lib/create')(name, options) | ||
}) | ||
|
||
// 创建页面命令 | ||
program | ||
.command('page <page-name>') | ||
.description('create a new page') | ||
.option('-f, --force', 'Overwrite target directory if it exists') | ||
.action((name, cmd) => { | ||
const options = cleanArgs(cmd) | ||
require('../lib/page')(name, options) | ||
}) | ||
|
||
program | ||
.arguments('<command>') | ||
.action((cmd) => { | ||
program.outputHelp() | ||
console.log(` ` + chalk.red(`Unknown command ${chalk.yellow(cmd)}.`)) | ||
console.log() | ||
// suggestCommands(cmd) | ||
}) | ||
|
||
|
||
// 自定义错误提示信息 | ||
const enhanceErrorMessages = require('../lib/utils/enhanceErrorMessages') | ||
// 缺少参数的错误提示 | ||
enhanceErrorMessages('missingArgument', argName => { | ||
return `缺少必要参数 ${chalk.yellow(`<${argName}>`)}.` | ||
}) | ||
|
||
// 调用 | ||
program.parse(process.argv) | ||
|
||
if (!process.argv.slice(2).length) { | ||
program.outputHelp() | ||
} | ||
|
||
function camelize (str) { | ||
return str.replace(/-(\w)/g, (_, c) => c ? c.toUpperCase() : '') | ||
} | ||
|
||
// 获取参数 | ||
function cleanArgs (cmd) { | ||
const args = {} | ||
cmd.options.forEach(o => { | ||
const key = camelize(o.long.replace(/^--/, '')) | ||
// 如果没有传递option或者有与之相同的命令,则不被拷贝 | ||
if (typeof cmd[key] !== 'function' && typeof cmd[key] !== 'undefined') { | ||
args[key] = cmd[key] | ||
} | ||
}) | ||
return args | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
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, | ||
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 | ||
|
||
if (cliOptions.preset) { | ||
// awesome-test create foo --preset mobx | ||
preset = await this.resolvePreset(cliOptions.preset, cliOptions.clone) | ||
} else { | ||
preset = await this.resolvePreset(defaults.presets.default, cliOptions.clone) | ||
} | ||
|
||
await clearConsole() | ||
log(chalk.blue.bold(`Awesome-test CLI v${require('../package.json').version}`)) | ||
logWithSpinner(`✨`, `正在创建项目 ${chalk.yellow(context)}.`) | ||
this.emit('creation', { event: 'creating' }) | ||
|
||
stopSpinner() | ||
// 设置文件名,版本号等 | ||
const { pkgVers, pkgDes } = await inquirer.prompt([ | ||
{ | ||
name: 'pkgVers', | ||
message: `请输入项目版本号`, | ||
default: '1.0.0', | ||
}, | ||
{ | ||
name: 'pkgDes', | ||
message: `请输入项目简介`, | ||
default: 'project created by awesome-test-cli', | ||
} | ||
]) | ||
|
||
// 将下载的临时文件拷贝到项目中 | ||
const pkgJson = await copyFile(preset.tmpdir, preset.targetDir) | ||
|
||
const pkg = Object.assign(pkgJson, { | ||
version: pkgVers, | ||
description: pkgDes | ||
}) | ||
|
||
// write package.json | ||
log() | ||
logWithSpinner('📄', `生成 ${chalk.yellow('package.json')} 等模板文件`) | ||
await writeFileTree(context, { | ||
'package.json': JSON.stringify(pkg, null, 2) | ||
}) | ||
|
||
// 包管理 | ||
const packageManager = ( | ||
(hasYarn() ? 'yarn' : null) || | ||
(hasPnpm3OrLater() ? 'pnpm' : 'npm') | ||
) | ||
await writeFileTree(context, { | ||
'README.md': generateReadme(pkg, packageManager) | ||
}) | ||
|
||
const shouldInitGit = this.shouldInitGit(cliOptions) | ||
if (shouldInitGit) { | ||
logWithSpinner(`🗃`, `初始化Git仓库`) | ||
this.emit('creation', { event: 'git-init' }) | ||
await run('git init') | ||
} | ||
|
||
// 安装依赖 | ||
stopSpinner() | ||
log() | ||
logWithSpinner(`⚙`, `安装依赖`) | ||
// log(`⚙ 安装依赖中,请稍等...`) | ||
|
||
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 | ||
} | ||
} | ||
|
||
// log instructions | ||
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 }) | ||
} | ||
|
||
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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const chalk = require('chalk') | ||
const EventEmitter = require('events') | ||
const fs = require('fs-extra') | ||
|
||
const generatePage = require('./utils/generatePage') | ||
|
||
|
||
const { | ||
log, | ||
error, | ||
logWithSpinner, | ||
clearConsole, | ||
stopSpinner, | ||
exit | ||
} = require('../lib/utils/common') | ||
|
||
module.exports = class PageCreator extends EventEmitter { | ||
constructor(name, context) { | ||
super() | ||
|
||
this.name = name | ||
this.context = context | ||
} | ||
|
||
async create(cliOptions = {}) { | ||
const fileNameObj = this.getName() | ||
const {context} = this | ||
await clearConsole() | ||
log(chalk.blue.bold(`Awesome-test CLI v${require('../package.json').version}`)) | ||
logWithSpinner(`✨`, `正在创建页面...`) | ||
// 创建文件夹 | ||
await fs.mkdir(context, { recursive: true }) | ||
this.emit('creation', { event: 'creating' }) | ||
|
||
stopSpinner() | ||
|
||
console.log(context) | ||
await generatePage(context, fileNameObj) | ||
} | ||
|
||
getName() { | ||
const originName = this.name | ||
const tailName = originName.slice(1) | ||
const upperName = originName.charAt(0).toUpperCase() + tailName | ||
const lowerName = originName.charAt(0).toLowerCase() + tailName | ||
return { | ||
upperName, | ||
lowerName | ||
} | ||
} | ||
} |
Oops, something went wrong.