如何使用交互式的命令行工具下载项目模板
这部分代码实现了一个用户交互的 GitHub 模板下载工具。首先你需要在github上创建一个项目,然后使用下面介绍的代码就可以用命令行拉取到本地,并解压了。
它使用 enquirer
库提示用户输入仓库的创建者、名称、分支、和目标目录,然后使用 downloadTemplate
函数下载模板,最后使用 fs-extra
库存储下载的文件。 print
函数封装了日志记录的函数。
代码的具体实现如下:
1.引入依赖:fs-extra
、enquirer
、downloadTemplate
和 print
。(print函数实现下面会有)
import fs from 'fs-extra';
import enquirer from 'enquirer';
import downloadTemplate from './download';
import print from './print';
2.定义接口 IRepo
和 IAnswers
,用来描述仓库信息和用户输入的答案。
type IRepo = {owner: string;name: string;branch: string;
};
type IAnswers = IRepo & {targetDir?: string;
};
3.定义函数 githubDownloadUrl
,用来构造仓库的下载 URL。
function githubDownloadUrl(repo: IRepo) {return 'https://github.com/' + repo.owner + '/' + repo.name + '/archive/refs/heads/' + repo.branch + '.zip';
}
4.定义一个问题数组,包含需要提示用户输入的问题及其验证逻辑。* questions 数组包含了四个问题对象,每个问题对象都有以下几个属性:* type:表示问题的类型,例如输入、选择、确认等。这里的问题都是输入类型。* name:表示问题产生的结果值的 key,例如当你在回答问题时输入的值会以 name 作为 key 存储在答案对象中。* message:表示问题的提示语,例如 “请输入仓库的创建者”。* default:表示问题的默认值,如果用户没有输入答案,则使用默认值。* validate:表示问题的验证函数,用来验证用户输入的答案是否合法。如果答案不合法,可以返回一个错误消息,提示用户重新输入。* 这些问题将用于提示用户输入,并根据用户输入的答案计算下载模板的 URL 和存储文件的目录。
const questions = [{type: 'input', // type为交互的类型name: 'owner', // 产生的值的key,比如你输入''message: '请输入仓库的创建者(example: "lio-mengxiang")', // 提示语default: 'lio-mengxiang',validate(val) {if (!val) {return '请输入文件名'; // 验证一下输入是否不为空}if (fs.accessSync(val, fs.constants.F_OK)) {return '文件已存在'; // 判断文件是否存在} else {return true;}},},{type: 'input',name: 'name',message: '请输入仓库名称(example: "react")',default: 'react-pnpm-monorepo-subTemplate',validate(val) {if (!val) {return '请输入仓库名'; // 验证一下输入是否不为空}return true;},},{type: 'input',name: 'branch',message: '请输入分支名(example: "main")',default: 'main',validate(val) {if (!val) {return '请输入分支名'; // 验证一下输入是否不为空}return true;},},{type: 'input',name: 'targetDir',message: '请输入放文件的目录(默认当前目录: "./")',default: './',},
];
3.使用 enquirer.prompt
方法提示用户输入,并处理用户输入的答案。如果输入有误,则输出错误信息并退出程序。
enquirer.prompt(questions).then((answers: IAnswers) => {// 获取用户输入值const owner = answers.owner;const name = answers.name;const branch = answers.branch;const targetDir = answers.targetDir;downloadTemplate({ url: githubDownloadUrl({ owner, name, branch }), targetDir });}).catch((err) => {print.error(err);process.exit(1);});
如果用户输入的答案合法,则使用 downloadTemplate