UNPKG

madp-cli1

Version:

A simple CLI for scaffolding madp projects, we provide madp-template to quickly build small and medium sized app.

753 lines (737 loc) 23.2 kB
#!/usr/bin/env node const yargs = require("yargs"); const path = require("path"); const fse = require("fs-extra"); const chalk = require("chalk"); const inquirer = require("inquirer"); const ora = require("ora"); const decompress = require("decompress"); let config = require("./config"); const logger = require("./lib/utils/logger"); const utils = require("./lib/utils"); const project = require("./lib/utils/project"); const buildApp = require("./lib/builder/buildApp"); const plugin = require("./lib/plugin"); const create = require("./lib/plugin/create"); const publish = require("./lib/plugin/publish"); const update = require("./lib/utils/update"); const shell = require("shelljs"); const processChild = require("child_process"); const tmp = require('tmp'); const os = require("os"); const TemplateRelease = require("./template-release"); const templateRelease = new TemplateRelease( config.cacheDirName, config.versionReleaseUrl, config.templateReleaseUrl, config.methodsReleaseUrl ); const isWin = /^win/.test(process.platform); const fs = require("fs"); const request = require("request"); const LocalStorage = require("node-localstorage").LocalStorage, localStorage = new LocalStorage(os.homedir()+"/.scratch"); let questions = (inputName, typeLists) => { let applicationid = ""; return [ { type: "input", name: "name", default: () => { if (typeof inputName !== "string") inputName = ""; return inputName.trim() ? inputName.trim() : "madp-demo"; }, message: "请输入项目名称", validate: (value) => { let pass = value.match(/^[0-9a-z\-_]+$/i); if (!pass) { return "输入格式错误,请重新输入。"; } if (value.indexOf("PluginDemo") > -1) { return "名称不可包含:PluginDemo。"; } if (fse.existsSync(value)) { return "目录[" + value + "]已经存在,请重新输入。"; } return true; }, }, { type: "list", name: "projectType", message: "请选择项目工程", choices: typeLists, }, ]; }; let questions1 = (releaseLists) => { return [ { type: "list", name: "release", message: "请选择框架版本", choices: releaseLists, }, { type: "list", name: "location", message: "请选择下载服务器", choices: [ { name: "Github服务器", value: "github", }, ], }, ]; }; let methodsQuestions = (methodsTypeList) => { return [ { type: "list", name: "methodsType", message: "请选择方法集类型", choices: methodsTypeList, }, ]; }; let methodsQuestions1 = (methodsList) => { return [ { type: "list", name: "methodsRelease", message: "请选择需要添加方法集", choices: methodsList, }, ]; }; /** * 创建 eeui 工程. */ function initProject(createName) { // console.log(os.homedir()) if(!localStorage.getItem("token")){ console.log('请先登录!'); return false } let spinFetch = ora("正在请求,请稍后..."); spinFetch.start(); //发送请求获取项目类型 request( { url: config.serverUrl + "/cli/template/type", method: "GET", json: true, headers: { "content-type": "application/json", authToken: localStorage.getItem("token"), }, body: {}, }, function (error, response, body) { spinFetch.stop(); if (body.code == "00000") { body.data.map(v=>v.value=v.code) // console.log(body.data) localStorage.setItem("typeList",JSON.stringify( body.data)); inquirer .prompt([ { type: "list", name: "type", message: "请选创建项目类型", choices: body.data, }, ]) .then((res) => { // console.log(res) const ret = body.data.find((v) => v.code == res.type); if (ret.code) { //根据项目类型,获取模板列表 request( { url: config.serverUrl + "/cli/template/list?code=" + ret.code, method: "GET", json: true, headers: { "content-type": "application/json", authToken: localStorage.getItem("token"), }, body: {}, }, function (error, response, body) { // console.log(body.data) let tempArray = []; if (body.code == "00000") { body.data.map((v) => { v.value = v.code; v.name=v.name+'('+v.version+')'+v.description tempArray.push(v); }); // console.log(tempArray,'tempArray272') inquirer .prompt(questions(createName, tempArray)) .then((res) => { // console.log('answer', res) let obj = tempArray.find( (v) => v.code == res.projectType ); res.projectType = obj.type; res.zipball_url = obj.downloadUrl; res.tag_name = obj.name; res.tag_version = obj.version; res.release = obj.value; let _answers = JSON.parse(JSON.stringify(res)); // console.log('_answers', _answers) let rundir = path.resolve(process.cwd(), res.name); if (fse.existsSync(_answers.name)) { logger.fatal(`目录[${_answers.name}]已经存在。`); return; } // templateRelease.fetchRelease(_answers.release, _answers.location, _answers, (error, releasePath) => { templateRelease._fetchMothods( _answers, (err, releasePath) => { let finalLog = () => { logger.success("创建项目完成。"); logger.sep(); logger.info("您可以运行一下命令开始。"); logger.info( chalk.white(`1. cd ${_answers.name}`) ); logger.info(chalk.white(`2. npm install`)); logger.info(chalk.white(`3. npm run dev`)); }; if (!err) { finalLog(); } } ); }); } } ); } }); } else if (body.code == "A0103") { console.log(body.msg, ",请先登录"); } else { console.log(body.msg); } } ); } /** * 初始化演示模板 */ function initDemo(type, callback) { utils.getOnlineDemoLists(type, (error, demoLists) => { if (error) { typeof callback === "function" && callback(error); return; } inquirer .prompt([ { type: "list", name: "demoInfo", message: "请选择初始化模板", choices: demoLists, }, ]) .then((answers) => { // answers=JSON.parse(answers) utils.downOnlineDemo(answers.demoInfo, (error, downFile, name) => { if (error) { typeof callback === "function" && callback(error); return; } typeof callback === "function" && callback("", downFile, answers.demoInfo, name); }); }) .catch(console.error); }); } /** * 设置模板 * @param rundir */ function setTemplate(rundir) { inquirer .prompt([ { type: "confirm", message: `此操作将重置src开发目录,是否继续操作?`, name: "ok", }, ]) .then((answers) => { if (answers.ok) { let type = "madp"; initDemo(type, (error, downFile, info, pathName) => { if (error) { logger.warn(error); return; } let srcDir = rundir + "/src"; let srcDir1 = rundir + "/src1"; let srcTmp = "/" + pathName; decompress(downFile, path.resolve(srcDir1)).then(() => { fse.copySync(path.resolve(srcDir1) + srcTmp, path.resolve(rundir)); fse.remove(path.resolve(srcDir1), (err) => {}); }); }); } else { logger.fatal(`放弃设置模板操作!`); } }) .catch(console.error); } /** * 列出可用的种子工程版本 */ function displayReleases() { let spinPod = ora("正在获取版本信息..."); spinPod.start(); templateRelease.fetchReleaseVersions((err, result) => { spinPod.stop(); // if (err) { // logger.fatal(err); // return; // } // let array = []; // result.some(t => { // if (!utils.leftExists(t, "2")) { // return false; // } // array.push(t); // if (array.length >= 10) { // return true; // } // }); let array = result; // array=[{ name: 'madp-seed(1.0.0)', value: '1.0.0' }] if (array.length === 0) { logger.fatal("无可用版本!"); } else { console.log("可用的种子工程版本:"); array.forEach((t) => { console.log(chalk.green.underline(t.name)); }); } }); } /** * 列出可用的模板版本 */ function displayTemplateReleases() { let spinPod = ora("正在获取模板信息..."); spinPod.start(); templateRelease.fetchTemplateReleaseVersions((err, result) => { spinPod.stop(); let array = result; if (array.length === 0) { logger.fatal("无可用版本!"); } else { console.log("可用的模板列表:"); array.forEach((t) => { console.log(chalk.green.underline(t.name)); }); } }); } /** * 生成appKey * @param {string} path 文件路径. */ function changeAppKey(path) { let configPath = path + "/madp.config.js"; if (!fse.existsSync(configPath)) { return; } let config = require(configPath); let content = ""; if (config === null || typeof config !== "object") { return; } if (typeof config.appKey === "undefined") { return; } let createRand = (len) => { len = len || 32; let $chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678oOLl9gqVvUuI1"; let maxPos = $chars.length; let pwd = ""; for (let i = 0; i < len; i++) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; }; logger.info("正在创建appKey..."); config.appKey = createRand(32); content += "/**\n * 配置文件\n * 参数详细说明:https://eeui.app/guide/config.html\n */\n"; content += "module.exports = "; content += JSON.stringify(config, null, "\t"); content += ";"; fse.writeFileSync(configPath, content, "utf8"); // let androidPath = path + "/platforms/android/eeuiApp/app/src/main/assets/eeui/config.json"; if (fse.existsSync(androidPath)) { fse.writeFileSync(androidPath, JSON.stringify(config), "utf8"); } let iosPath = path + "/platforms/ios/eeuiApp/bundlejs/eeui/config.json"; if (fse.existsSync(androidPath)) { fse.writeFileSync(iosPath, JSON.stringify(config), "utf8"); } } /** * 追加方法集 * 第一步 列出可选择的方法集 * 第二步 选择某个方法集 * 第三步 将选择的方法集追加到已创建工程的src/utils目录下, * utils目录不存在则先创建空目录,再copy */ function addMethods() { let spinFetch = ora("正在下载方法集列表..."); spinFetch.start(); templateRelease.fetchMethodsRelease((err, result) => { spinFetch.stop(); console.log("addMethods fetchMethodsRelease||||", result); let lists = []; let info = {}; let methodsTypeList = []; let methodsList = []; result.some((t) => { t.value = t.name; lists.push(t); methodsList.push(t); info[t.type] = t.type_name; }); for (let i in info) { methodsTypeList.push({ name: info[i], value: i }); } if (lists.length === 0) { logger.fatal("没有找到可用的方法集。"); return; } inquirer.prompt(methodsQuestions(methodsTypeList)).then((res) => { console.log(res); let info = JSON.parse(JSON.stringify(res)); let methodsReleaseList = []; result.some((t) => { if (t.type == info.methodsType) methodsReleaseList.push(t); }); console.log("选择类型后的方法集列表||||", methodsReleaseList); inquirer.prompt(methodsQuestions1(methodsReleaseList)).then((answer) => { console.log(answer); console.log(methodsReleaseList); let _answer = JSON.parse(JSON.stringify(answer)); console.log("选择的方法集====", _answer.methodsRelease); for (var [i, methods] of methodsReleaseList.entries()) { if (methods.name === _answer.methodsRelease) { _answer = Object.assign(_answer, methods); } } console.log("选择的方法集data===", _answer); templateRelease.fetchMothods(_answer, (error, releasePath) => { console.log("templateRelease.fetchMothods=====", releasePath); }); }); }); }); } let args = yargs .command({ command: "create [name]", desc: "创建一个madp项目", handler: (argv) => { if (typeof argv.name === "string") { if (fse.existsSync(argv.name)) { logger.fatal(`目录“${argv.name}”已经存在。`); return; } } initProject(argv.name); }, }) .command({ command: "lists", desc: "列出创建可用的种子工程版本", handler: () => { displayReleases(); }, }) .command({ command: "template", // desc: "设置App模板(初始化演示模板)", desc: "列出创建可用的模板版本", handler: () => { displayTemplateReleases(); // utils.verifyeeuiProject(); // setTemplate(path.resolve(process.cwd())); }, }) // .command({ // command: "update", // desc: "项目主框架升级至最新版本", // handler: () => { // utils.verifyeeuiProject(); // utils.verifyeeuiTemplate(); // update.start(); // } // }) .command({ command: "add methods", desc: "追加方法集", handler: (argv) => { addMethods(); }, }) .command({ command: "vue [pageName]", desc: "创建vue页面示例模板", handler: (argv) => { utils.verifyeeuiProject(); utils.verifyeeuiTemplate(); let pageName = utils.rightDelete(argv.pageName, ".vue").trim(); if (pageName) { let dir = path.resolve(process.cwd(), "src"); if (!fse.existsSync(dir)) { logger.fatal(`目录“src”不存在,当前目录非eeui项目。`); return; } let filePath = dir + "/pages/" + pageName + ".vue"; if (fse.existsSync(filePath)) { logger.fatal(`文件“${pageName}.vue”已经存在。`); return; } let tmlPath = __dirname + "/lib/template/_template.vue"; if (!fse.existsSync(tmlPath)) { logger.fatal(`模板文件不存在。`); return; } fse.copySync(tmlPath, filePath); logger.success(`模板文件“${pageName}.vue”成功创建。`); } else { logger.fatal(`请输入要创建的文件名称。`); } }, }) // .command({ // command: "plugin [command] [name]", // desc: "添加、删除、创建或发布插件", // handler: (argv) => { // utils.verifyeeuiProject(); // utils.verifyeeuiTemplate(); // let op = {}; // op.name = argv.name; // op.rootDir = process.cwd(); // op.dir = path.basename(process.cwd()); // op.simple = argv.s === true; // switch (argv.command) { // case 'add': // case 'install': // case 'i': // plugin.add(op); // break; // case 'del': // case 'remove': // case 'uninstall': // case 'u': // plugin.remove(op); // break; // case 'repair': // case 'r': // plugin.repair(op); // break; // case 'script': // plugin.eeuiScript(argv.name, true); // break; // case 'unscript': // plugin.eeuiScript(argv.name, false); // break; // case 'create': // case 'c': // create.create(op); // break; // case 'publish': // case 'upload': // case 'p': // publish.publish(op); // break; // } // } // }) .command({ command: "login", desc: "登录", handler: (argv) => { utils.login(false, "minprogram"); }, }) .command({ command: "dev", desc: "编译构造", handler: (argv) => { utils.vertPackJson(true, "dev"); // utils.verifyeeuiProject(); // utils.verifyeeuiTemplate(); // plugin.eeuiScript(null, true, () => { // buildApp.dev(argv.s === true); // }); }, }) .command({ command: "build", desc: "编译构造并最小化输出结果", handler: (argv) => { utils.vertPackJson(true, "build"); // utils.verifyeeuiProject(); // utils.verifyeeuiTemplate(); // plugin.eeuiScript(null, true, () => { // buildApp.build(argv.s === true); // }); }, }) // .command({ // command: "preview", // desc: "预览", // handler: (argv) => { // utils.showQRcode(); // }, // }) .command({ command: "upload", desc: "上传", handler: (argv) => { // console.log(config) utils.uploadCode(); }, }) .command({ command: "config [name]", desc: "配置基本项", handler: (argv) => { if (argv.name && argv.name == "l") { fs.readFile('./config.js', 'utf8', function (err, result) { if (err) { return console.log('文件读取失败!' + err.message); } result=result.split('{')[1].split('}')[0].split(',') console.log('config.js文件读取成功,内容是:' + result); }); } else { switch (process.platform) { case "darwin": //unix 系统内核 inquirer .prompt([ { type: "input", // 类型(数字) name: "serverUrl", message: '请输入你的工具与服务端通信的服务器地址,例如"https://xxxbank.cn/cliserver/api/"', default: config.serverUrl, }, { type: "input", // 类型(数字) name: "idePath", message: "请输入mac环境下IDE名称,不能包含空格,如HBuilderX", default:'HBuilderX' }, ]) .then((answers) => { // console.log('anser', answers) config.serverUrl = answers.serverUrl; config.idePath = answers.idePath; // console.log(config) utils.saveConfig(config); }); break; case "win32": //windows 系统内核 inquirer .prompt([ { type: "input", // 类型(数字) name: "serverUrl", message: '请输入你的工具与服务端通信的服务器地址,例如"https://xxxbank.cn/cliserver/api/"', default: config.serverUrl, }, { type: "input", // 类型(数字) name: "idePath", message: "请输入windows环境下IDE打开路径,如D:\\HBuilderX\\HBuilderX.exe", default:'D:\\HBuilderX\\HBuilderX.exe' }, ]) .then((answers) => { // console.log('anser', answers) config.serverUrl = answers.serverUrl; config.idePath = answers.idePath; utils.saveConfig(config); }); break; } } }, }) .command({ command: "ide", desc: "打开IDE", handler: (argv) => { utils.openIDE(); }, }) // .command({ // command: 'config [name]', // desc: '查看配置', // handler: (argv) => { // console.log(argv.name) // // console.log(config) // }, // }) .command({ command: "save", desc: "保存模板", handler: (argv) => { utils.saveTemplate(); }, }) .command({ command: "delete", desc: "删除模板", handler: (argv) => { utils.delTemplate(); }, }) // .command({ // command: "publish", // desc: "发布", // handler: (argv) => { // shell.exec(`npm login `, function (code, stdout, stderr) { // console.log("code", code); // console.log("Program output:", stdout); // console.log("Program stderr:", stderr); // }); // }, // }) .version(() => { let text = "madp-cli: " + chalk.underline(require("./package.json").version); if (utils.projectVersion()) { text += "\nmadp-template: " + chalk.underline(utils.projectVersion()); } return text; }) .help() .alias({ h: "help", v: "version", s: "simple", }) .strict(true).argv; //发布模块: npm publish