#!/usr/bin/env node /** * * @author yutent * @date 2022/10/10 15:17:36 */ import { request } from 'https' import { red, cyan, blue } from 'kolorist' import prompts from 'prompts' import fs from 'iofs' import { resolve, join, dirname, normalize } from 'path' import { writePackageJson, writeConfigFile, writeGitIgnore, writePrettierrc } from './lib/demo-config.js' import { writeHtmlFile } from './lib/demo-html.js' import { writeLogo } from './lib/logo.js' import { writeMainJs, writeAppVue, writeHomeVue, writeAboutVue, writeHelloVue, writeRouter, writeStore } from './lib/demo-js.js' const NODE_VERSION = +process.versions.node.split('.').slice(0, 2).join('.') const CURRENT_DIR = process.cwd() const root = normalize( dirname(import.meta.url.slice(process.platform === 'win32' ? 8 : 7)) ) const DEFAULT_NAME = 'fite-app' let targetDir = '' if (NODE_VERSION < 16.6) { console.log(red('Error: 你当前的环境不满足 Vue-live 构建工具的要求')) console.log( 'Vue-live 需要Node.js版本在 %s 以上, \n你当前的Node.js版本为: %s', blue('v16.6.0'), red(process.version), '\n\n' ) process.exit() } function isEmpty(dir) { let list = fs.ls(dir) if (list && list.length) { return false } return true } function getVueLiveVersion() { return new Promise(yes => { request('https://registry.npmmirror.com/fite', res => { let data = '' res.on('data', chunk => (data += chunk)) res.on('end', _ => { try { data = JSON.parse(data) yes(data['dist-tags'].latest) } catch (e) { yes('0.3.1') } }) }).end() }) } function sleep(num = 1) { return new Promise(resolve => setTimeout(resolve, num * 1000)) } !(async function () { let res = await prompts([ { name: 'projectName', type: 'text', message: '项目名称(也是目录名, 只能为英文、数字、-):', initial: DEFAULT_NAME, validate: val => /^[a-zA-Z\d\-\.]+$/.test(val), onState: ({ value }) => (targetDir = join(CURRENT_DIR, value)) }, { name: 'shouldOverwrite', type: _ => (isEmpty(targetDir) ? null : 'toggle'), message: _ => `目录 ${cyan(targetDir)} 非空, 是否${red('删除')}目录下所有的文件?`, initial: false, active: '是', inactive: '否' }, { name: 'confirmCheck', type: shouldOverwrite => { if (shouldOverwrite === false) { console.log(red('✖') + ' 操作取消~~') process.exit() } return null } }, { name: 'isSPA', type: 'toggle', message: _ => `是否初始化为单页应用? (否则为多页应用)`, initial: true, active: '是', inactive: '否' } ]) console.log() if (res.projectName === undefined) { console.log('已取消操作~~') process.exit() } if (res.projectName === '.') { res.projectName = DEFAULT_NAME } targetDir = normalize(targetDir) console.log('指定的项目名为: %s', cyan(res.projectName)) console.log('项目目录为: %s', cyan(targetDir)) if (res.shouldOverwrite) { console.log(red('目录非空, 1s 后将清空目录~~')) await sleep(1) let list = fs.ls(targetDir) list.forEach(it => fs.rm(it, true)) } else { console.log(red('程序将在 1s 后初始化项目~~')) await sleep(1) } console.log(cyan('\n初始化项目...')) let vueLiveVer = await getVueLiveVersion() fs.mkdir(join(targetDir, 'src')) console.log('[c---------]', '10%') writePackageJson(join(targetDir, 'package.json'), res.projectName, vueLiveVer) writeConfigFile(join(targetDir, 'vue.live.js')) writeGitIgnore(join(targetDir, '.gitignore')) writePrettierrc(join(targetDir, '.prettierrc.yaml')) console.log('[ooc-------]', '30%') writeHtmlFile(join(targetDir, 'index.html')) writeLogo(join(targetDir, 'src/assets/logo.svg')) fs.cp(join(root, 'lib/favicon.ico'), join(targetDir, 'public/favicon.ico')) console.log('[oooooc----]', '60%') writeMainJs(join(targetDir, 'src/main.js')) writeAppVue(join(targetDir, 'src/app.vue')) writeHomeVue(join(targetDir, 'src/views/home.vue')) writeAboutVue(join(targetDir, 'src/views/about.vue')) writeHelloVue(join(targetDir, 'src/components/hello.vue')) writeRouter(join(targetDir, 'src/router.js')) writeStore(join(targetDir, 'src/store.js'), vueLiveVer) console.log('[oooooooooo]', '100%') console.log(cyan('初始化完成, 可依次执行以下命令启动项目: ')) console.log(blue('npm i')) console.log(blue('npm start')) })()