UNPKG

ae-biu

Version:

Born For AE, Born To Do

212 lines (185 loc) 5.8 kB
#!/usr/bin/env node // @flow import program from 'commander' import chalk from 'chalk' import Confirm from 'prompt-confirm' import Input from 'prompt-input' import http from 'http' import ProgressBar from 'progress' import fs from 'fs' import { promisify } from 'util' import decompress from 'decompress' import isEmptyDir from './utils/is-empty-dir' import isND from './utils/is-nd' import { spawnSync } from 'child_process' /** * Help */ program.on('--help', () => { console.log() console.log(' Examples:') console.log() console.log(chalk.yellow(' # Create a new project')) console.log() console.log(chalk.blue(' $ ae init')) console.log() console.log(chalk.yellow(' # Create a new project with name')) console.log() console.log(chalk.blue(' $ ae init your-project-name')) console.log() console.log(chalk.yellow(' # Create a new project with specific branch')) console.log() console.log(chalk.blue(' $ ae init -b dev')) }) /** * Usage */ program .usage('[project-name] [--branch]') .option('-b, --branch [branch]', 'Use specific branch as template') .parse(process.argv) let dest = process.cwd() const projectName = program.args[0] || 'ae-example' let branch = program.branch if (typeof branch !== 'string') { branch = 'master' } const AE_TEMPLATE = `http://git.sdp.nd/fed/ae-boilerplate/repository/archive.zip?ref=${branch}` const handleError = async (error: ?Error): Promise<any> => { console.log() error && console.error(error) // clean dest directory await promisify(fs.rmdir)(dest) process.exit(1) } const unzipFile = async (zipFile: string, dest: string): Promise<any> => { try { await decompress(zipFile, dest, { strip: 1 // remove leading directory }) } catch (error) { await handleError(error) } } const installPackage = () => { console.log(chalk.yellow('Install 📦 ')) console.log() const isWin32 = process.platform === 'win32' const subProcess = spawnSync(isWin32 ? 'npm.cmd' : 'npm', ['install'], { stdio: 'inherit' }) console.log() if (subProcess.status === 1) { console.log(chalk.red('😕 There is something wrong 👆 when installing packages, you may need to install packages by yourself')) } else { console.log(chalk.yellow('🎉 All Done, coding now !!!')) } } const updatePkg = async (dest: string): Promise<any> => { const pkgPath = `${dest}/package.json` try { const pkgContent = await promisify(fs.readFile)(pkgPath, 'utf8') const pkg = JSON.parse(pkgContent) console.log() const pkgNameInput = new Input({ name: 'name', message: `Name(${projectName}):` }) let data = await pkgNameInput.run() pkg.name = (data && data.name && data.name.trim()) || projectName pkg.description = `${pkg.name} - Powered By AE(Admin Engine)` const defaultVersion = '0.0.1-alpha.1' const pkgVersionInput = new Input({ name: 'version', message: `Version(${defaultVersion}):` }) data = await pkgVersionInput.run() pkg.version = (data && data.version && data.version.trim()) || defaultVersion // add languages to package.json for ae-i18n if (!pkg.ae) { pkg.ae = {} } pkg.ae.languages = ['zh-CN', 'en'] // default languages // fix wrong scripts, it will be removed after ae-boilerplate update Object.keys(pkg.scripts).map(script => { pkg.scripts[script] = pkg.scripts[script].replace(/\sSDP_ENV=\S+\s/g, ' ') }) data = JSON.stringify(pkg, null, 2) await promisify(fs.writeFile)(pkgPath, data) process.chdir(dest) console.log() await installPackage() process.exit(0) } catch (error) { await handleError(error) } } const downloadFiles = async (dest: string): Promise<any> => { const zipFileName = dest + '/temp.zip' const req = http.get(AE_TEMPLATE) req.on('response', async (res) => { // broken if (res.statusCode >= 400) { console.log() console.log(chalk.red('There is something wrong with your network, maybe wrong branch name')) await handleError() } // length can be NaN, but no why const length = parseInt(res.headers['content-length'], 10) !isNaN(length) && console.log() const bar = !isNaN(length) ? new ProgressBar(chalk.cyan('downloading [:bar] :rate/bps :percent :etas'), { complete: '=', incomplete: '-', width: 20, total: length, clear: true }) : null res.on('data', (chunk) => { fs.appendFileSync(zipFileName, chunk) bar && bar.tick(chunk.length) }) res.on('end', async () => { await unzipFile(zipFileName, dest) try { await promisify(fs.unlink)(zipFileName) } catch (error) { await handleError(error) } console.log() console.log(chalk.yellow('Download success')) await updatePkg(dest) }) }) req.on('error', async (error) => { await handleError(error) }) } const run = async (): Promise<any> => { if (await isND()) { if (isEmptyDir(dest)) { downloadFiles(dest) } else { console.log() const confirm = new Confirm(chalk.yellow(`Current directory is not empty, Do you want to create a new directory named as ${chalk.blue(projectName)}`)) const answer = await confirm.run() if (answer) { dest += `/${projectName}` try { await promisify(fs.mkdir)(dest) } catch (error) { console.log() console.log(chalk.red('Directory already exist, please check')) process.exit(1) } downloadFiles(dest) } else { console.log() console.log(chalk.red('Process exit!!!')) process.exit(0) } } } else { console.log(chalk.red('Maybe you are not a NDer')) } } run()