# fri-cli **Repository Path**: fessor/fri-cli ## Basic Information - **Project Name**: fri-cli - **Description**: 开发项目或者组件的初始化脚手架 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-03-19 - **Last Updated**: 2022-05-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 描述 该仓库是开发项目或者组件的初始化脚手架的尝试 ## 目录结构 ``` |---commands | |---init | |---lib | |---__tests__ |---core | |---cli | | |---bin | | |---dist | | |---lib | | |---__tests__ | |---exec | |---lib | |---__tests__ |---models | |---command | | |---lib | | |---__tests__ | |---package | |---lib | |---__tests__ |---templates | |---vue3-vite | | |---template | | |---public | | |---src | | |---assets | | |---components | |---vue3-webpack | |---template | |---public | |---src | |---assets | |---components | |---router | |---store | |---views |---utils |---get-npm-info | |---lib | |---__tests__ |---log | |---lib | |---__tests__ |---mongo | |---lib | |---__tests__ |---request | |---lib | |---__tests__ |---utils |---lib |---__tests__ ``` ## 准备工作 ```javascript async function prepare () { // 检查cli版本号 输出本地版本号 checkPackageVersion(); // 检查Node版本号 // checkNodeVersion(); // 检查是否root启动 防止root创建 以后因为权限不能修改 checkRoot(); // 检查是否用户主目录 checkUserHome(); // 检查环境变量 checkEnv(); } ``` ## 注册命令 //声明命令行名称 //帮助信息 用户提示 命令 参数 //声明版本 // 定义选项-d --debug 开启调试模式 定义选项-tp --target_path 脚本路径如 使用本地脚本初始化项目 传入该参数; 注册 init 命令,-f| --force 是否强制初始化项目 匹配不到对应命令 将会报错未知命令; 不传入参数 将会显示帮助信息; ```javascript function registerCommand() { program .name(pkName) .usage(" [options]") .version(pkg.name) .option("-d, --debug", "display some debugging") // 放在command写不行 一定要现在这样 .option('-tp, --target_path ', "the path of executable file"); program .command("init [project-name]") .description("project init") .option('-f, --force', '是否强制初始化项目') .action(async (...args) => { await cmdPreAction(); exec(...args); }); program.on("option:debug", function () { process.env.LOG_LEVEL = "verbose"; log.level = process.env.LOG_LEVEL; }); // 放在command写不行 一定要现在这样 program.on("option:target_path", function (val) { process.env.targetPath = val; }); program.on("command:*", function (operands) { const availableCommands = program.commands.map((cmd) => cmd.name()); if (!availableCommands.includes(operands[0])) { log.warn( colors.yellow( `未知命令${operands[0]},可用命令:${availableCommands.join(",")}` ) ); } }); // console.log(process.argv, program.opts()); // 如果没有参数和命令 // program.parse(process.argv); // 处理函数支持async,相应的,需要使用.parseAsync代替.parse。 program.parseAsync(process.argv); // 没有执行命令 提示program.args 只有命令,process.argv.slice(2):命令+options if (!program.args || program.args.length < 1) { program.outputHelp(); } } ``` ### commander.js #### .usage 和 .name 通过这两个选项可以修改帮助信息的首行提示,name属性也可以从参数中推导出来。例如: program .name("my-command") .usage("[global options] command") 帮助信息开头如下: Usage: my-command [global options] command ## fri init 开始前: 是否使用淘宝源 : await useTaobaoRegistry(); 检查cli是否最新版本-》否提示更新: await chekckGlobalUpdate(); 然后 开始执行@fri-cli/exec ### @fri-cli/exec 1.如果用户传入targe_path参数值 则通过路径获取其Npm包名;实例化Npm包管理类Package; 没有tp target_path传参,默认Npm为@fri-cli/init,实例化Package 检查是否本地缓存没有下载,有则更新到最新版本; 2.获取对应初始化Npm根执行脚本,运用spawn创建子进程进行初始化 ```javascript const rootFile = pk.getNpmRootFile(); if (rootFile) { try { const args = Array.from(arguments); let cmdObj = args[args.length - 1]; let o = Object.assign({}); Object.keys(cmdObj).forEach(key => { if (key !== 'parent' && !key.startsWith('_') && cmdObj.hasOwnProperty(key)) { o[key] = cmdObj[key]; } }); args[args.length - 1] = o; const code = `require('${rootFile}').apply(null, ${JSON.stringify(args)})`; // log.verbose(code); const res = await execPromise('node', ['-e', code], { cwd: process.cwd(), stdio: 'inherit', }); log.verbose('res:', res); if (res) throw new Error('执行不成功!'); } catch (error) { log.error(error.message); } } ``` ### @fri-cli/init ![1.png](https://cdn.nlark.com/yuque/0/2021/png/825673/1633649186062-81d40666-d6eb-477b-a7da-f8825580cfc8.png#clientId=uf1a01460-17e1-4&crop=0&crop=0&crop=1&crop=1&from=drop&id=u39f17870&margin=%5Bobject%20Object%5D&name=1.png&originHeight=534&originWidth=882&originalType=binary&ratio=1&rotation=0&showTitle=false&size=24801&status=done&style=none&taskId=u9ed3a6fb-4777-4691-ac28-7a99bcf7117&title=)![2.png](https://cdn.nlark.com/yuque/0/2021/png/825673/1633649192962-a9831616-8969-468c-93cc-f1339c4134ff.png#clientId=uf1a01460-17e1-4&crop=0&crop=0&crop=1&crop=1&from=drop&id=ufcac5e69&margin=%5Bobject%20Object%5D&name=2.png&originHeight=484&originWidth=884&originalType=binary&ratio=1&rotation=0&showTitle=false&size=14301&status=done&style=none&taskId=ued9806bd-2fa3-4cd7-b263-07005e4dbab&title=)