#!/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' 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 getFiteVersion() { 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 fiteVerion = await getFiteVersion() console.log('[c---------]', '10%') if (res.isSPA) { fs.cp(join(root, './lib/spa'), targetDir) } else { fs.cp(join(root, './lib/mpa'), targetDir) } console.log('[ooc-------]', '30%') fs.cp(join(root, './lib/common'), targetDir) console.log('[oooooc----]', '60%') { fs.echo( ` import { reactive } from 'vue' const store = reactive({ foo: 'bar', version: '${fiteVerion}' }) export default function (app) { app.config.globalProperties.$store = store } `, join(targetDir, res.isSPA ? 'src/store.js' : 'src/pages/index/store.js') ) fs.echo( ` { "name": "fite-app", "type": "module", "scripts": { "start": "fite dev", "build": "fite build", "build:keep": "fite build --no-clean" }, "devDependencies": { "fite": "^${fiteVerion}" } } `, join(targetDir, 'package.json') ) } console.log('[oooooooooo]', '100%') console.log(cyan('初始化完成, 可依次执行以下命令启动项目: ')) console.log(blue('npm i')) console.log(blue('npm start')) })()