From a88e087831528c7a8858933aef8accdf63ce79d9 Mon Sep 17 00:00:00 2001 From: lrl <742798240@qq.com> Date: Fri, 18 Nov 2022 14:23:37 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=9B=B4=E5=8F=8B=E5=A5=BD=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=8F=90=E7=A4=BA=E5=8F=8A=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=8C=87=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.en-US.md | 2 +- README.md | 2 +- package.json | 1 + src/create-dir/index.ts | 9 ++--- src/index.ts | 24 +++++++------ src/prompt/index.ts | 11 ++++++ src/types.ts | 4 ++- src/utils/clone.ts | 75 +++++++++++++++++++++++++++++++++++++++++ src/utils/index.ts | 54 ++--------------------------- src/utils/log.ts | 18 ++++++++++ 10 files changed, 130 insertions(+), 70 deletions(-) create mode 100644 src/utils/clone.ts create mode 100644 src/utils/log.ts diff --git a/README.en-US.md b/README.en-US.md index cff0e0a..53f8d51 100644 --- a/README.en-US.md +++ b/README.en-US.md @@ -34,5 +34,5 @@ - Or, you want to create a project through interactive selection template: ```bash - pure create myproject + pure create ``` diff --git a/README.md b/README.md index 286794f..48aed7d 100644 --- a/README.md +++ b/README.md @@ -34,5 +34,5 @@ - 或者,你想通过交互式选择模板创建项目: ```bash - pure create myproject + pure create ``` diff --git a/package.json b/package.json index 43279b0..1bd1541 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "bin/www.js", "scripts": { "dev": "pnpm build && pure init thin demo", + "devc": "pnpm build && pure init aa demo", "build": "tsup", "typecheck": "tsc --noEmit", "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts}\" --fix", diff --git a/src/create-dir/index.ts b/src/create-dir/index.ts index 645df0c..85a4256 100644 --- a/src/create-dir/index.ts +++ b/src/create-dir/index.ts @@ -4,6 +4,7 @@ import pc from 'picocolors' import ora, { Ora } from 'ora' import { Ioptions } from '../types' import { isOverwriteDir } from '../prompt' +import { clg } from '../utils' const spinner: Ora = ora() @@ -23,16 +24,16 @@ export const isExistsFile = async (projectName: string, options: Ioptions) => { const isOverwrite = await isOverwriteDir() // 选择 Cancel if (!isOverwrite) { - console.log(pc.green('Cancel')) + clg(pc.green('取消成功')) return true } else { // 选择 Overwirte ,先删除掉原有重名目录 try { - spinner.start('removing') + spinner.start('删除中...') await fs.remove(targetDirectory) - spinner.succeed(`Success remove ${pc.gray(projectName)}`) + spinner.succeed(`成功删除 ${pc.gray(projectName)}`) } catch (error) { - spinner.fail('Overwrite fail, Please try again') + spinner.fail('覆盖失败, 请重试') process.exit(1) } return false diff --git a/src/index.ts b/src/index.ts index 291abb1..4bb0717 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,8 @@ import { create } from './template' import { templates } from './constants' import { TTemplateName } from './types' import { isExistsFile } from './create-dir' +import { hasTemplate, clg } from './utils' +import { inputProjectName } from './prompt' // eslint-disable-next-line @typescript-eslint/no-var-requires const version: string = require('../package.json').version @@ -13,25 +15,27 @@ const cli = cac('pure') cli.version(version) cli - .command('create ', 'create a new project') // 增加创建指令 - .option('-f, --force', 'overwrite target directory if it exists') // 强制覆盖 - .action(async (projectName, cmd) => { + .command('create', '创建一个新项目') // 增加创建指令 + .option('-f, --force', '如果目标文件存在,则强制覆盖') // 强制覆盖 + .action(async (cmd) => { + const projectName = await inputProjectName() const isExists = await isExistsFile(projectName, cmd) if (isExists) return create(projectName) }) cli - .command('init ', 'create a new project') // 增加创建指令 - .option('-f, --force', 'overwrite target directory if it exists') // 强制覆盖 + .command('init ', '创建一个新项目') // 增加创建指令 + .option('-f, --force', '如果目标文件存在,则强制覆盖') // 强制覆盖 .action(async (templateName, projectName, cmd) => { + if (!hasTemplate(templateName)) return const isExists = await isExistsFile(projectName, cmd) if (isExists) return create(projectName, templateName) }) cli.help(() => { - console.log( + clg( '\r\n' + figlet.textSync('pure', { font: '3D-ASCII', @@ -41,14 +45,12 @@ cli.help(() => { whitespaceBreak: true }) ) - console.log() - console.log(`Run ${pc.cyan('pure --help')} for detailed usage of given command.`) - console.log() + clg(`运行 ${pc.cyan('pure --help')} 查看有关命令的详细用法. \r\n`) }) -cli.command('list', 'view all available templates').action(() => { +cli.command('list', '查看所有模板类型').action(() => { Object.keys(templates).forEach((key: string) => { - console.log(`${key} ${templates[key as TTemplateName].description}`) + clg(`${key} ${templates[key as TTemplateName].description}`) }) }) diff --git a/src/prompt/index.ts b/src/prompt/index.ts index df56f46..2a12f76 100644 --- a/src/prompt/index.ts +++ b/src/prompt/index.ts @@ -29,6 +29,17 @@ export const chooseTemplate = async () => { return template } +export const inputProjectName = async () => { + const { projectName } = await inquirer.prompt([ + { + name: 'projectName', + type: 'input', + message: '请输入项目名称' + } + ]) + return projectName +} + export const isOverwriteDir = async () => { const { isOverwrite } = await inquirer.prompt([ // 返回值为promise diff --git a/src/types.ts b/src/types.ts index b167449..57f7ace 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,13 +5,15 @@ export interface Ioptions { interface ITemplatesItem { downloadUrl: string description: string + branch: string } export interface ITemplates { thin: ITemplatesItem i18n: ITemplatesItem tauri: ITemplatesItem + electron: ITemplatesItem admin: ITemplatesItem } -export type TTemplateName = 'thin' | 'i18n' | 'tauri' | 'admin' +export type TTemplateName = 'thin' | 'i18n' | 'tauri' | 'electron' | 'admin' diff --git a/src/utils/clone.ts b/src/utils/clone.ts new file mode 100644 index 0000000..9c3cca2 --- /dev/null +++ b/src/utils/clone.ts @@ -0,0 +1,75 @@ +import { log, clg } from './log' +import pc from 'picocolors' +import ora, { Ora, Options } from 'ora' +import { TTemplateName } from '../types' +import { templates } from '../constants' +import simpleGit, { SimpleGit, SimpleGitOptions, SimpleGitProgressEvent } from 'simple-git' + +const oraOptions: Options = { + spinner: 'runner' +} +const spinner: Ora = ora(oraOptions) + +const progress = ({ progress }: SimpleGitProgressEvent) => { + const proText = `进度: ${pc.cyan(progress + '%')}` + spinner.start().text = proText + if (progress === 100) { + spinner.start().text = proText + pc.green(' 下载完成') + } +} + +const gitOptions: Partial = { + baseDir: process.cwd(), + binary: 'git', + maxConcurrentProcesses: 6, + progress +} + +// https://git-scm.com/docs/git-clone#Documentation/git-clone.txt +export const clone = async ( + repo: string, + projectName: string, + options: string[], + templateName: TTemplateName +): Promise => { + const git: SimpleGit = simpleGit(gitOptions) + try { + clg(`项目下载自 ${pc.cyan(repo)}`) + await git.clone(repo, projectName, options) + } catch (err) { + spinner.fail() + log.err('请求失败, 请重试') + } + + spinner.succeed() // 下载成功提示 + // 模板使用提示 + clg(`\r\n 已成功创建项目 ${pc.cyan(projectName)}`) + clg(`\r\n cd ${pc.cyan(projectName)}`) + clg(' pnpm install \r\n') + if (templateName === 'tauri') { + return clg(' pnpm tauri:dev \r\n') + } + clg(' pnpm dev \r\n') +} + +/** + * 判断当前模板类型是否存在 + * @param templateName 模板类型 + * @returns { boolean } + */ +export const hasTemplate = (templateName: TTemplateName): boolean => { + const templateKeys = Reflect.ownKeys(templates) + const hasTemplate = templateKeys.includes(templateName) + if (!hasTemplate) { + log.err(`当前模板类型 ${pc.cyan(`${templateName}`)} 不存在 \r\n `) + log.info(`请输入以下其中一种模板类型: `) + templateKeys.forEach((key) => { + clg( + pc.bold( + pc.green(`${key as string} `) + pc.gray(`${templates[key as TTemplateName].description}`) + ) + ) + }) + } + return hasTemplate +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 0a150aa..824dfb0 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,52 +1,2 @@ -import pc from 'picocolors' -import logSymbols from 'log-symbols' -import ora, { Ora, Options } from 'ora' -import { TTemplateName } from '../types' -import simpleGit, { SimpleGit, SimpleGitOptions, SimpleGitProgressEvent } from 'simple-git' - -const oraOptions: Options = { - spinner: 'runner' -} -const spinner: Ora = ora(oraOptions) - -const progress = ({ progress }: SimpleGitProgressEvent) => { - const proText = `Progress: ${pc.cyan(progress + '%')}` - spinner.start().text = proText - if (progress === 100) { - spinner.start().text = proText + pc.green(' Download Completed') - } -} - -const gitOptions: Partial = { - baseDir: process.cwd(), - binary: 'git', - maxConcurrentProcesses: 6, - progress -} - -// https://git-scm.com/docs/git-clone#Documentation/git-clone.txt -export const clone = async ( - repo: string, - projectName: string, - options: string[], - templateName: TTemplateName -): Promise => { - const git: SimpleGit = simpleGit(gitOptions) - try { - console.log(`download from ${pc.cyan(repo)}`) - await git.clone(repo, projectName, options) - } catch (err) { - spinner.fail() - console.log(logSymbols.error, pc.red('Request fail, Please try again')) - } - - spinner.succeed() // 下载成功提示 - // 模板使用提示 - console.log(`\r\n Successfully created project ${pc.cyan(projectName)}`) - console.log(`\r\n cd ${pc.cyan(projectName)}`) - console.log(' pnpm install \r\n') - if (templateName === 'tauri') { - return console.log(' pnpm tauri:dev \r\n') - } - console.log(' pnpm dev \r\n') -} +export * from './log' +export * from './clone' diff --git a/src/utils/log.ts b/src/utils/log.ts new file mode 100644 index 0000000..8fd5576 --- /dev/null +++ b/src/utils/log.ts @@ -0,0 +1,18 @@ +import pc from 'picocolors' +import logSymbols from 'log-symbols' + +export const clg = console.log + +export const log = { + err: (msg: string) => { + clg(logSymbols.error, pc.red(msg)) + }, + warning: (msg: string) => { + clg(logSymbols.warning, pc.yellow(msg)) + }, + info: (msg: string) => { + clg(logSymbols.info, pc.bold(msg)) + } +} + +export default log