UNPKG

madp-cli1

Version:

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

1,641 lines (1,570 loc) 57.1 kB
const fs = require("fs"); const fse = require("fs-extra"); const path = require("path"); const urls = require("url"); const chalk = require("chalk"); const lodash = require("lodash"); const tmp = require('tmp'); const child_process = require("child_process"); const inquirer = require("inquirer"); const ora = require("ora"); const request = require("request"); const compressing = require("compressing"); const decompress = require("decompress"); delete require.cache[require.resolve('../../config')]; let config = require("../../config"); const logger = require("../utils/logger"); const os = require("os"); const plugin = require("./../../lib/plugin"); const buildApp = require("./../../lib/builder/buildApp"); const shell = require("shelljs"); const qrcode = require("qrcode-terminal"); var FormData = require("form-data"); const LocalStorage = require("node-localstorage").LocalStorage, localStorage = new LocalStorage(os.homedir() + "/.scratch"); const exec = require("child_process").execFile; const zipDir = require('./transferZip') const { idePath } = require("../../config"); let questions = (releaseLists) => { return [ { type: "list", name: "release", message: "请选择命令", choices: releaseLists, }, ]; }; // process.stdin.setEncoding('utf8'); const utils = { delTemplate() { if(!localStorage.getItem("token")){ console.log('请先登录!'); return false } let typeList = localStorage.getItem('typeList') if (typeList) { typeList = eval('(' + typeList + ')') } else { 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 ) typeList = body.data localStorage.setItem("typeList", JSON.stringify(body.data)); } } ) } inquirer .prompt([ { type: "list", // 类型(数字) name: "type", message: "请选择要删除的模板类型", choices: typeList, }, ]) .then((res) => { request( { url: config.serverUrl + "/cli/template/list?code=" + res.type, method: "GET", json: true, headers: { "content-type": "application/json", authToken: localStorage.getItem("token"), }, body: { // code:ret.code }, }, function (error, response, body) { // console.log(body); if (body.code == '00000' && body.data.length > 0) { body.data.map((v) => { v.value = v.code v.name=v.name+'('+v.version+')'+v.description }); inquirer .prompt([ { type: "list", // 类型(数字) name: "code", message: "请选择要删除的模板", // filter: function (v) {// 最终结果 // return 'name['+v+']' // }, choices: body.data, }, ]) .then((answers) => { // console.log(answers); request( { url: config.serverUrl + "/cli/template/delete", method: "POST", json: true, headers: { "content-type": "application/json", authToken: localStorage.getItem("token"), }, body: { code: answers.code, }, }, function (error, response, body) { console.log(body.msg); } ); }); } else if (body.data && body.data.length == 0) { console.log('该类型下无数据'); } else { console.log(body.msg); } } ); }); }, saveTemplate() { if(!localStorage.getItem("token")){ console.log('请先登录!'); return false } if (!fs.existsSync(path.resolve(config.savePackDir))) { utils.mkdirsSync(config.savePackDir); } let zipName = config.savePackDir +`/uniapp-save${utils.formatDate("YmdHis")}.zip` let loading = ora('处理中...').start(); zipDir.zipFolder(process.cwd(),zipName,function(){ loading.stop() let typeList = localStorage.getItem('typeList') if (typeList) { typeList = eval('(' + typeList + ')') } inquirer .prompt([ { type: "input", // name: "name", message: "请输入模板名称", default: '默认模板' }, { type: "input", name: "description", message: "请输入模板描述", default: '模板描述' }, { type: "input", // 类型(数字) name: "version", message: "请输入模板版本", default: '1.0.1' }, { type: "list", // 类型(数字) name: "type", message: "请选择模板类型", choices: typeList || ["ui_project", "seed_project", "template_project"], }, ]).then(answers => { let loading = ora('保存中...').start(); let form = new FormData(); const file = fs.createReadStream(path.join(process.cwd(), zipName)); form.append("pack", file); form.append("name", answers.name); form.append("description", answers.description); form.append("version", answers.version); form.append("type", answers.type); request( { url: config.serverUrl + "/cli/template/save", method: "POST", headers: { // "Content-Type": `multipart/form-data; boundary=${form.getBoundary()}`, "Content-Type": `multipart/form-data; boundary=${form.getBoundary()}`, authToken: localStorage.getItem("token"), }, body: form, }, function (error, response, body) { loading.stop(); const data = JSON.parse(body); data ? console.log(`保存${data.msg}`) : console.log(body); } ); }) } ) }, saveTemplate1() { logger.info("不包含项目中的node_modules及.git等文件"); if(!localStorage.getItem("token")){ console.log('请先登录!'); return false } let currentPath = process.cwd(); let originPath = path.join(currentPath, '\/node_modules') let destinationPath = os.homedir() + '\/.temp_node_modules' let fileName = `temp-nodemodules` let finalFilePath = '' //打包文件如存在先删除 if (fs.existsSync(path.resolve(config.savePackDir))) { // copyMObj.del(path.resolve(config.savePackDir)) fse.remove(path.resolve(config.savePackDir)); } //存在nodemodules,先压缩到destinationPath下,并删除当前项目下的nodemodules if (fs.existsSync(originPath)) { let loadingO = ora('依赖处理中...').start(); this.compressFile( fileName, destinationPath, function (path) { finalFilePath = path loadingO.stop() // console.log(finalFilePath) fse.remove(originPath); let typeList = localStorage.getItem('typeList') if (typeList) { typeList = eval('(' + typeList + ')') } const _this = this inquirer .prompt([ { type: "input", // name: "name", message: "请输入模板名称", default: '默认模板' }, { type: "input", name: "description", message: "请输入模板描述", default: '模板描述' }, { type: "input", // 类型(数字) name: "version", message: "请输入模板版本", default: '1.0.1' }, { type: "list", // 类型(数字) name: "type", message: "请选择模板类型", choices: typeList || ["ui_project", "seed_project", "template_project"], }, ]) .then((answers) => { let loading = ora('处理中...').start(); utils.compressFile( "uniapp-template", config.savePackDir, function (path) { let form = new FormData(); const file = fs.createReadStream(path); form.append("pack", file); form.append("name", answers.name); form.append("description", answers.description); form.append("version", answers.version); form.append("type", answers.type); request( { url: config.serverUrl + "/cli/template/save", method: "POST", headers: { // "Content-Type": `multipart/form-data; boundary=${form.getBoundary()}`, "Content-Type": `multipart/form-data; boundary=${form.getBoundary()}`, authToken: localStorage.getItem("token"), }, body: form, }, function (error, response, body) { loading.stop(); const data = JSON.parse(body); data ? console.log(`保存${data.msg}`) : console.log(body); } ); if (fs.existsSync(finalFilePath)) { let loading1 = ora('依赖恢复中...').start(); utils.mkdirsSync(originPath); decompress(finalFilePath, originPath).then(() => { console.log('解压成功'); fse.remove(finalFilePath); }) loading1.stop() } }, currentPath ); }); }, originPath) } else { let typeList = localStorage.getItem('typeList') if (typeList) { typeList = eval('(' + typeList + ')') } inquirer .prompt([ { type: "input", // name: "name", message: "请输入模板名称", default: '默认模板' }, { type: "input", name: "description", message: "请输入模板描述", default: '模板描述' }, { type: "input", // 类型(数字) name: "version", message: "请输入模板版本", default: '1.0.1' }, { type: "list", // 类型(数字) name: "type", message: "请选择模板类型", choices: typeList || ["ui_project", "seed_project", "template_project"], }, ]) .then((answers) => { let loading = ora('处理中...').start(); this.compressFile( "uniapp-template", config.savePackDir, function (path) { let form = new FormData(); const file = fs.createReadStream(path); form.append("pack", file); form.append("name", answers.name); form.append("description", answers.description); form.append("version", answers.version); form.append("type", answers.type); request( { url: config.serverUrl + "/cli/template/save", method: "POST", headers: { // "Content-Type": `multipart/form-data; boundary=${form.getBoundary()}`, "Content-Type": `multipart/form-data; boundary=${form.getBoundary()}`, authToken: localStorage.getItem("token"), }, body: form, }, function (error, response, body) { loading.stop(); const data = JSON.parse(body); data ? console.log(`保存${data.msg}`) : console.log(body); } ); }, currentPath ); }); } // }) }, saveConfig(args) { // console.log(args); let datas = `module.exports = ${JSON.stringify(args, "", "\t")}`; // console.log(datas); fs.writeFile("./config.js", datas, "utf8", (err) => { // \n为换行符 if (err) { console.log("写入失败"); } console.log("写入成功"); console.log("如需查看配置内容,请使用config l 命令"); }); }, openIDE() { let idePath = '' fs.readFile('./config.js', 'utf8', function (err, result) { if (err) { return console.log('文件读取失败!' + err.message); } idePath = result.split('idePath":')[1].trim() idePath = idePath.slice(1, idePath.length - 3) console.log(idePath); if (idePath) { inquirer .prompt([ { type: "input", // 类型(数字) name: "projectName", message: "请输入当前目录下的项目名称", }, ]) .then((answers) => { switch (process.platform) { case "darwin": //unix 系统内核 shell.exec( `open -a ${idePath} ${answers.projectName}`, function (code, stdout, stderr) { } ); break; case "win32": //windows 系统内核 if (!idePath) { logger.error("请先配置要打开的IDE安装路径"); return false; } exec(idePath, [answers.projectName], function (err, data) { if (err) { throw err; } }); break; } }); } else { console.log('未找到要打开的IDE,请先使用config命令配置') } }); }, showQRcode() { //1. //2.在控制台打印二维码 qrcode.generate( "http://10.110.193.208:8084/", { small: true }, function (qrcode) { console.log(qrcode); } ); }, uploadCode() { if(!localStorage.getItem("token")){ console.log('请先登录!'); return false } const dir = "./dist/build"; try { const files = fs.readdirSync(dir); if (files && files.length > 0) { inquirer .prompt([ { type: "input", // name: "appId", message: "请输入小程序APPID", }, { type: "input", // name: "description", message: "请输入描述", }, { type: "input", // name: "version", message: "请输入版本号", }, { type: "list", // name: "uploadDir", message: "请选择要上传的文件夹", choices: files, }, ]) .then((answers) => { console.log(answers); this.compressFile( answers.uploadDir || "upload-build", path.resolve(config.uploadPackDir), function (path) { console.log(path); let form = new FormData(); const file = fs.createReadStream(path); form.append("pack", file); form.append("appId", answers.appId); form.append("description", answers.description); form.append("version", answers.version); request( { url: config.serverUrl + "/cli/upload", method: "POST", headers: { "Content-Type": `multipart/form-data; boundary=${form.getBoundary()}`, authToken: localStorage.getItem("token"), }, body: form, }, function (error, response, body) { const data = JSON.parse(body); console.log(data); } ); }, path.resolve("dist/build") + "/" + answers.uploadDir ); }); } else { console.log("请先运行build命令,编译后再执行upload进行上传"); } } catch (err) { console.log(err); } }, compressFile(name, url, callback, currentDir) { let zipName = name + "-" + utils.formatDate("YmdHis"); let zipPackPath = url; utils.mkdirsSync(zipPackPath); let reUrl = zipPackPath + "/" + zipName + ".zip"; // console.log(reUrl); utils.zipCompress( { output: reUrl, entry: [ { type: "dir", path: currentDir || path.resolve(config.distDir), }, ], }, () => { // console.log(reUrl) typeof callback == "function" && callback(reUrl); } ); }, //读当前文件夹package。json 缺少就报错 vertPackJson(support, str) { if (support === true) { let configFile = path.resolve(process.cwd(), "package.json"); if (fs.existsSync(configFile)) { fs.readFile("package.json", (err, data) => { if (err) { console.log("读取错误"); return; } const { scripts } = JSON.parse(data.toString()); //将十六进制转化为字符串,进而转换成对象 let arr = []; for (key in scripts) { // console.log(key.includes(str)) // if(key.search('dev')!==-1){ if (key.includes(str)) { arr.push({ name: key, shell: scripts[key] }); } } if (arr.length > 0) { inquirer.prompt(questions(arr)).then((answers) => { // console.log("anser", answers); const myHost = this.getIpAddress(); // console.log(myHost); this.exec(`npm run ${answers.release}`, false).then((res) => { }); }); } }); } else { this.verifyeeuiProject(); this.verifyeeuiTemplate(); if (str == "build") { plugin.eeuiScript(null, true, () => { buildApp.build(argv.s === true); }); } if (str == "dev") { plugin.eeuiScript(null, true, () => { buildApp.dev(argv.s === true); }); } } } }, //获取本机ip getIpAddress() { /**os.networkInterfaces() 返回一个对象,该对象包含已分配了网络地址的网络接口 */ var interfaces = os.networkInterfaces(); for (var devName in interfaces) { var iface = interfaces[devName]; for (var i = 0; i < iface.length; i++) { var alias = iface[i]; if ( alias.family === "IPv4" && alias.address !== "127.0.0.1" && !alias.internal ) { return alias.address; } } } }, consoleUrl(support) { if (support === true) { let configFile = path.resolve(process.cwd(), "madp.config.js"); if (fs.existsSync(configFile)) { let releaseConfig = {}; try { releaseConfig = require(configFile); } catch (e) { // } if ( releaseConfig["consoleUrl"] && this.leftExists(releaseConfig["consoleUrl"], "http") ) { return releaseConfig["consoleUrl"]; } } } return "https://console.eeui.app/"; }, apiUrl(support) { return this.consoleUrl(support) + "api/"; }, buildJS(cmd = "build") { console.log(` => ${chalk.blue.bold("npm install&build")}`); return this.exec("npm install", true).then(() => { return this.exec("webpack --env.NODE_ENV=" + cmd); }); }, execute(command, callback) { exec1(command, function (error, stdout, stderr) { callback(stdout); }); }, exec(command, quiet) { return new Promise((resolve, reject) => { try { let child = child_process.exec( command, { encoding: "utf8" }, (error, stdout, stderr) => { resolve(); } ); if (!quiet) { child.stdout.pipe(process.stdout); } // console.log(process.stderr,'22222') child.stderr.pipe(process.stderr); } catch (e) { console.error("execute command failed :", command); reject(e); } }); }, parseDevicesResult(result) { if (!result) { return []; } const devices = []; const lines = result.trim().split(/\r?\n/); for (let i = 0; i < lines.length; i++) { let words = lines[i].split(/[ ,\t]+/).filter((w) => w !== ""); if (words[1] === "device") { devices.push(words[0]); } } return devices; }, mkdirsSync(dirname) { if (fse.existsSync(dirname)) { return true; } else { if (this.mkdirsSync(path.dirname(dirname))) { fse.mkdirSync(dirname); return true; } } }, getMiddle(string, start, end) { if (this.isHave(start) && this.strExists(string, start)) { string = string.substring(string.indexOf(start) + start.length); } else if (start !== null) { return ""; } if (this.isHave(end) && this.strExists(string, end)) { string = string.substring(0, string.indexOf(end)); } else if (end !== null) { return ""; } return string; }, isHave(set) { return !!( set !== null && set !== "null" && set !== undefined && set !== "undefined" && set ); }, isNullOrUndefined(obj) { return typeof obj === "undefined" || obj === null; }, isObject(obj) { return this.isNullOrUndefined(obj) ? false : typeof obj === "object"; }, likeArray(obj) { return this.isObject(obj) && typeof obj.length === "number"; }, isJson(obj) { return this.isObject(obj) && !this.likeArray(obj); }, strExists(string, find, lower) { string += ""; find += ""; if (lower !== true) { string = string.toLowerCase(); find = find.toLowerCase(); } return string.indexOf(find) !== -1; }, leftExists(string, find) { string += ""; find += ""; return string.substring(0, find.length) === find; }, rightExists(string, find) { string += ""; find += ""; return string.substring(string.length - find.length) === find; }, leftDelete(string, find) { string += ""; find += ""; if (this.leftExists(string, find)) { string = string.substring(find.length); } return string ? string : ""; }, rightDelete(string, find) { string += ""; find += ""; if (this.rightExists(string, find)) { string = string.substring(0, string.length - find.length); } return string ? string : ""; }, findIndexOf(str, cha, num) { str += ""; cha += ""; let x = str.indexOf(cha); for (let i = 0; i < num; i++) { x = str.indexOf(cha, x + 1); if (x === -1) { break; } } return x; }, clone(myObj) { if (typeof myObj !== "object") return myObj; if (myObj === null) return myObj; // if (this.likeArray(myObj)) { let [...myNewObj] = myObj; return myNewObj; } else { let { ...myNewObj } = myObj; return myNewObj; } }, count(obj) { try { if (typeof obj === "undefined") { return 0; } if (typeof obj === "number") { obj += ""; } if (typeof obj.length === "number") { return obj.length; } else { let i = 0, key; for (key in obj) { i++; } return i; } } catch (e) { return 0; } }, each(elements, callback) { let i, key; if (this.likeArray(elements)) { if (typeof elements.length === "number") { for (i = 0; i < elements.length; i++) { if (callback.call(elements[i], i, elements[i]) === false) return elements; } } } else { for (key in elements) { if (!elements.hasOwnProperty(key)) continue; if (callback.call(elements[key], key, elements[key]) === false) return elements; } } return elements; }, getObject(obj, keys) { let object = obj; if (this.count(obj) === 0 || this.count(keys) === 0) { return ""; } let arr = keys.replace(/,/g, "|").replace(/\./g, "|").split("|"); this.each(arr, (index, key) => { object = typeof object[key] === "undefined" ? "" : object[key]; }); return object; }, moveEmptyDirParent(dirPath) { let lists = this.fileDirDisplay(dirPath); if (lists.dir.length === 0 && lists.file.length === 0) { if (fs.existsSync(dirPath)) { fse.removeSync(dirPath); } this.moveEmptyDirParent(path.resolve(dirPath, "../")); } }, fileDirDisplay(dirPath, currentDir) { let lists = { dir: [], file: [], }; let stats = this.pathType(dirPath); switch (stats) { case 1: lists.file.push(dirPath); return lists; case 0: return lists; } let files = fs.readdirSync(dirPath); files.some((filename) => { let filedir = path.join(dirPath, filename); if ([".git", ".DS_Store", "__MACOSX"].indexOf(filename) !== -1) { return false; } if ( this.rightExists(filename, ".iml") || this.rightExists(filename, ".xcuserdatad") ) { return false; } if (this.rightExists(filedir, path.join("android", "build"))) { return false; } let stats = this.pathType(filedir); if (stats === 1) { lists.file.push(filedir); } else if (stats === 2 && currentDir !== true) { lists.dir.push(filedir); let tmps = this.fileDirDisplay(filedir); lists.dir = lists.dir.concat(tmps.dir); lists.file = lists.file.concat(tmps.file); } }); return lists; }, replaceDictString(path, key, value) { if (!fs.existsSync(path)) { return; } let content = fs.readFileSync(path, "utf8"); let matchs = content.match(/<dict>(.*?)<\/dict>/g); if (matchs) { matchs.forEach((oldText) => { oldText = oldText.substring( oldText.lastIndexOf("<dict>"), oldText.length ); if (this.strExists(oldText, "<string>" + key + "</string>", true)) { let searchValue = this.getMiddle(oldText, "<array>", "</array>"); if (searchValue) { searchValue = "<array>" + searchValue + "</array>"; let stringValue = "<string>" + this.getMiddle(searchValue, "<string>", "</string>") + "</string>"; let replaceValue = searchValue.replace( new RegExp(stringValue, "g"), "<string>" + value + "</string>" ); let newText = oldText.replace( new RegExp(searchValue, "g"), replaceValue ); let result = fs .readFileSync(path, "utf8") .replace(new RegExp(oldText, "g"), newText); if (result) { fs.writeFileSync(path, result, "utf8"); } } } }); } }, replaceEeuiLog(source) { let rege = new RegExp( "((\\s|{|\\[|\\(|,|;)console)\\.(debug|log|info|warn|error)\\((.*?)\\)", "g" ); let result; while ((result = rege.exec(source)) != null) { let newString = result[0].replace(result[1], result[2] + "eeuiLog"); source = source.replace(result[0], newString); } return source; }, replaceModule(source) { var rege = new RegExp( "\\.(requireModule|isRegisteredModule)\\((['\"])(.*?)\\2\\)", "g" ); var result; while ((result = rege.exec(source)) != null) { var name = result[3]; if ( [ "websocket", "screenshots", "citypicker", "picture", "rongim", "umeng", "pay", "audio", "deviceInfo", "communication", "geolocation", "recorder", "accelerometer", "compass", "amap", "seekbar", "network", ].indexOf(name) !== -1 ) { name = "eeui/" + name; } if (utils.strExists(name, "/")) { var newString = result[0].replace( result[3], utils.spritUpperCase(name) ); source = source.replace(result[0], newString); } } return source; }, getQueryString: (search, name) => { let reg = new RegExp("(^|&|\\?)" + name + "=([^&]*)", "i"); let r = search.match(reg); if (r != null) return r[2]; return ""; }, removeRubbish(dirPath) { let lists = []; try { let files = fs.readdirSync(dirPath); files.some((filename) => { let filedir = path.join(dirPath, filename); if ([".git", ".DS_Store", "__MACOSX"].indexOf(filename) !== -1) { fse.removeSync(filedir); lists.push(filedir); return false; } if ( this.rightExists(filename, ".iml") || this.rightExists(filename, ".xcuserdatad") ) { fse.removeSync(filedir); lists.push(filedir); return false; } if (this.rightExists(filedir, path.join("android", "build"))) { fse.removeSync(filedir); lists.push(filedir); return false; } // let stats = this.pathType(filedir); if (stats === 2) { this.removeRubbish(filedir); } }); return lists; } catch (e) { return lists; } }, /** * @param str * @param defaultVal * @returns {Object|*} */ jsonParse(str, defaultVal) { try { return JSON.parse(str); } catch (e) { return defaultVal ? defaultVal : {}; } }, /** * * @param json * @param defaultVal * @returns {string|*} */ jsonStringify(json, defaultVal) { try { return JSON.stringify(json); } catch (e) { return defaultVal ? defaultVal : ""; } }, runNum(str, fixed) { let _s = Number(str); if (_s + "" === "NaN") { _s = 0; } if (/^[0-9]*[1-9][0-9]*$/.test(fixed)) { _s = _s.toFixed(fixed); let rs = _s.indexOf("."); if (rs < 0) { _s += "."; for (let i = 0; i < fixed; i++) { _s += "0"; } } } return _s; }, zeroFill(str, length, after) { str += ""; if (str.length >= length) { return str; } let _str = "", _ret = ""; for (let i = 0; i < length; i++) { _str += "0"; } if (after || typeof after === "undefined") { _ret = (_str + "" + str).substr(length * -1); } else { _ret = (str + "" + _str).substr(0, length); } return _ret; }, timeStamp() { return Math.round(new Date().getTime() / 1000); }, formatDate(format, v) { if (format === "") { format = "Y-m-d H:i:s"; } if (typeof v === "undefined") { v = new Date().getTime(); } else if (/^(-)?\d{1,10}$/.test(v)) { v = v * 1000; } else if (/^(-)?\d{1,13}$/.test(v)) { v = v * 1000; } else if (/^(-)?\d{1,14}$/.test(v)) { v = v * 100; } else if (/^(-)?\d{1,15}$/.test(v)) { v = v * 10; } else if (/^(-)?\d{1,16}$/.test(v)) { v = v * 1; } else { return v; } let dateObj = new Date(v); if (parseInt(dateObj.getFullYear()) + "" === "NaN") { return v; } // format = format.replace(/Y/g, dateObj.getFullYear()); format = format.replace(/m/g, this.zeroFill(dateObj.getMonth() + 1, 2)); format = format.replace(/d/g, this.zeroFill(dateObj.getDate(), 2)); format = format.replace(/H/g, this.zeroFill(dateObj.getHours(), 2)); format = format.replace(/i/g, this.zeroFill(dateObj.getMinutes(), 2)); format = format.replace(/s/g, this.zeroFill(dateObj.getSeconds(), 2)); return format; }, renderSize(value) { if (null == value || value === "") { return "0B"; } let unitArr = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; let index, srcsize = parseFloat(value); index = Math.floor(Math.log(srcsize) / Math.log(1024)); let size = srcsize / Math.pow(1024, index); if (srcsize > 1024 * 1024) { size = size.toFixed(2); } else { size = Math.round(size); } let ret = size + unitArr[index] + ""; return ret.indexOf("NaN") !== -1 ? "0B" : ret; }, execPath(originPath) { return !/(\.web\.map|\.DS_Store|__MACOSX|Thumbs\.db|\.vue)$/.exec( originPath ); }, setToken(token) { let cachePath = path.join( require("os").homedir(), "." + config.cacheDirName, "token.cache" ); fse.ensureFileSync(cachePath); let cache = this.jsonParse(fs.readFileSync(cachePath, "utf8")); cache.token = token; fs.writeFileSync(cachePath, this.jsonStringify(cache), "utf8"); }, getToken() { let cachePath = path.join( require("os").homedir(), "." + config.cacheDirName, "token.cache" ); fse.ensureFileSync(cachePath); let cache = this.jsonParse(fs.readFileSync(cachePath, "utf8")); return this.getObject(cache, "token"); }, login(support, type, callback) { if (typeof support === "function") { callback = support; support = false; } // console.log(localStorage) logger.warn("请使用管理员提供给您到的账号密码"); inquirer .prompt([ { type: "input", name: "username", message: "请输入用户名:", }, { type: "password", name: "password", message: "请输入登录密码:", }, ]) .then((answers) => { // console.log(answers, localStorage) if (type == "minprogram") { let spinFetch = ora("正在登录...").start(); request( { url: config.serverUrl + "/cli/login", method: "POST", json: true, headers: { "content-type": "application/json", }, body: answers, }, function (error, response, body) { spinFetch.stop(); // console.log(body) if (body.code == "00000" && body.data) { localStorage.setItem("token", body.data); } console.log(body.msg); } ); } else { let spinFetch = ora("正在登录...").start(); request( utils.apiUrl(support) + "users/login?username=" + answers.username + "&userpass=" + answers.userpass, (err, res, body) => { spinFetch.stop(); let data = this.jsonParse(body); if (data.ret !== 1) { logger.fatal(`登录失败:${data.msg}`); } this.setToken(data.data.token); // if (typeof callback === "function") { callback(data.data); } } ); } }) .catch(console.error); }, logout(callback) { this.setToken(""); if (typeof callback === "function") { callback(); } }, projectVersion() { let file = path.resolve(process.cwd(), "madp.config.js"); let pack = path.resolve(process.cwd(), "package.json"); let vers = ""; if (fse.existsSync(file) && fse.existsSync(pack)) { vers = require(path.resolve(process.cwd(), "package.json")).version; } return vers; }, versionFunegt(v1, v2) { //相等:0,前面大:1,前面小:-1 v1 = (v1 + "") .toLowerCase() .replace(/^\s+|\s+$/g, "") .replace(/^\.|\.$/g, "") .replace(/^\s+|\s+$/g, ""); v2 = (v2 + "") .toLowerCase() .replace(/^\s+|\s+$/g, "") .replace(/^\.|\.$/g, "") .replace(/^\s+|\s+$/g, ""); if (v1 === v2) { return 0; } if (/^[0-9]+$/.test(v1) && /^[0-9]+$/.test(v2)) { v1 = Number(v1); v2 = Number(v2); if (v1 === v2) { return 0; } return v1 > v2 ? 1 : -1; } let res; let e1 = /^\d+/.exec(v1); let e2 = /^\d+/.exec(v2); if (e1 == null || e2 == null) { res = [v1, v2].sort()[1]; return res === v1 ? 1 : -1; } res = utils.versionFunegt(e1[0], e2[0]); if (res !== 0) { return res; } return utils.versionFunegt( v1.substring(e1[0].length), v2.substring(e2[0].length) ); }, verifyeeuiProject() { //判断是否eeui项目 let file = path.resolve(process.cwd(), "madp.config.js"); if (!fs.existsSync(file)) { logger.fatal(`当前目录缺少madp.config.js,无法进行此操作!`); } //判断eeui-cli版本需求 file = path.resolve(process.cwd(), "package.json"); if (fs.existsSync(file)) { let packageInfo = utils.jsonParse(fs.readFileSync(file, "utf8")); let current = require("../../package.json").version; let eeuiclimin = packageInfo.eeuiclimin; if ( utils.isHave(eeuiclimin) && utils.versionFunegt(eeuiclimin, current) > 0 ) { logger.fatal( `当前${chalk.underline( `eeui-cli@${current}` )}版本过低,请升级至${chalk.underline( `eeui-cli@${eeuiclimin}` )}或以上!${chalk.underline( `https://www.npmjs.com/package/eeui-cli` )}` ); } } // } }, verifyeeuiTemplate() { //判断是否新eeuiApp模板 // if (utils.versionFunegt("2.0.0", utils.projectVersion()) > 0) { // logger.fatal(`当前${chalk.underline(`主程序@${utils.projectVersion()}`)}版本过低,请升级主程序!${chalk.underline(`https://eeui.app/guide/update.html`)}`); // } }, pluginsJson(isInstall, op) { let configFile = path.resolve(op.rootDir, "plugins/config.json"); let configInfo = utils.jsonParse( !fs.existsSync(configFile) ? {} : fs.readFileSync(configFile, "utf8") ); if (!utils.isJson(configInfo["dependencies"])) { configInfo["dependencies"] = {}; } if (isInstall) { if (typeof configInfo["dependencies"][op.name] !== "object") { configInfo["dependencies"][op.name] = {}; } configInfo["dependencies"][op.name]["requireName"] = op.requireName || op.name; configInfo["dependencies"][op.name]["name"] = op.name; configInfo["dependencies"][op.name]["url"] = op.url || "local"; } else { if (typeof configInfo["dependencies"][op.name] !== "undefined") { delete configInfo["dependencies"][op.name]; } } fs.writeFileSync( configFile, JSON.stringify(this.sortObject(configInfo), null, "\t"), "utf8" ); }, sortObject(obj) { return Object.keys(obj) .sort() .reduce((a, v) => { a[v] = obj[v]; return a; }, {}); }, sendWebSocket(ws, ver, data) { if (data == null || typeof data !== "object") { data = {}; } data.version = ver; if (ver === 2) { ws.send(this.jsonStringify(data)); } else { ws.send(data.type + ":" + data.value); } }, getAllAppboards(rundir) { let lists = fs.readdirSync(path.resolve(rundir, "appboard")); let array = []; lists.forEach((item) => { let sourcePath = path.resolve(rundir, "appboard/" + item); let distPath = path.resolve( rundir, "../", config.distDir, "appboard/" + item ); if (utils.rightExists(sourcePath, ".js")) { let content = fs.readFileSync( fs.existsSync(distPath) ? distPath : sourcePath, "utf8" ); let sourceName = path.relative(path.resolve(rundir), sourcePath); if (/^win/.test(process.platform)) { sourceName = sourceName.replace(/\\/g, "/"); } array.push({ path: sourceName, content: this.replaceModule(this.replaceEeuiLog(content)), }); } }); return array; }, /** * 获取演示模板列表(在线版) * @param callback */ getOnlineDemoLists(type, callback) { let array = []; let loading = ora("正在获取演示模板列表...").start(); try { //获取所有模板 // https://console.eeui.app/api/editor/case/cli_lists // request(utils.apiUrl() + 'editor/case/cli_lists', (err, res, body) => { request(config.templateReleaseUrl, (err, res, body) => { let data = JSON.parse(body); // let data={"ret":1,"msg":"success","data":[ // {"release":"1.1","title":"空模板","desc":"空模板","tree":"-1","config":{}}, // {"release":"1.1","title":"madp动态首页","desc":"根据内容管理的配置(json)动态组装eeui首页","tree":"123","config":{}} // ]} // body={"ret":1,"msg":"success","data":[{"release":"1.1","title":"helloword","desc":"Hello Word","tree":"5994504e5a799ea62c825224040a28e2","config":{}},{"release":"2.4","title":"official","desc":"\u5b98\u65b9\u6f14\u793a\u6a21\u677f (\u56fd\u9645\u5316)","tree":"b26e17af31027e6cc8551faec428e9a0","config":{}},{"release":"1.2","title":"official-cn","desc":"\u5b98\u65b9\u6f14\u793a\u6a21\u677f (\u4e2d\u6587\u7248)","tree":"6ec02866ffb4b281713241368911b5ab","config":{}},{"release":"1.0","title":"eleme","desc":"\u4eff\u997f\u4e86\u4e48\u5916\u5356","tree":"ad963a9828d2e3028fa368e1a7136345","config":{}},{"release":"1.2","title":"echarts","desc":"echarts\u56fe\u6807","tree":"931f6e86a8d0dd0b8370ee2f58045575","config":{}},{"release":"1.0","title":"login","desc":"\u767b\u5f55\u6ce8\u518c\u9875","tree":"dacffe0319b66a4e0dc530182b5e884b","config":{}},{"release":"1.01","title":"example-demo","desc":"\u4fee\u590d\u56fe\u7247\u663e\u793a\u4e0d\u51fa\u7684bug","tree":"6fcf2d1bfe043acb0b09768c84fb9c05","config":{}},{"release":"1.0","title":"bindingx-demo","desc":"bindingx\u6f14\u793a","tree":"08cac38e81a882bfad6c4174bf0c02d2","config":{}},{"release":"1.0","title":"music-player","desc":"\u97f3\u4e50\u64ad\u653e\u5668","tree":"600c9423e960ddc6e64fe50d1988f07c","config":{}},{"release":"1.0","title":"tiktok","desc":"\u9ad8\u4eff\u6296\u97f3\u6574\u9875\u64ad\u653e\u89c6\u9891","tree":"e93948b23c4567b22540456c08835f7d","config":{}},{"release":"1.0","title":"tabbar-tabcenter","desc":"tabbar\u9876\u90e8tab\u83dc\u5355\u5c45\u4e2d","tree":"fcd0a82ee9ebd1a502f33c27943a5ed8","config":{}},{"release":"1.0","title":"tabbar-coherence","desc":"\u6eda\u52a8\u9875\u9762\u4e2d\u589e\u52a0\u4e00\u4e2atabbar","tree":"7e1da5a752584aa0b45f2528aa9bb200","config":{}},{"release":"1.0","title":"tabbar-immersion","desc":"tabbar\u6bcf\u4e2a\u5b50\u9875\u9762\u9876\u90e8\u72b6\u6001\u680f\u4e0d\u540c\u6548\u679c","tree":"94caefb1595f612b12368ea28d10784c","config":{}}]} loading.stop(); // let data = utils.jsonParse(body); // if (data.ret === 1) { data.forEach((item) => { if (item.type == type) { array.push({ name: item.name + " (" + item.tag_version + ")", value: item, }); } }); callback("", array); // }else{ // callback(data.msg); // } }); } catch (e) { loading.stop(); callback("获取演示模板失败!"); } }, /** * 下载演示模板-①(在线版) * @param tree * @param callback */ downOnlineDemo(info, callback) { let loadText = `正在下载演示模板...`; let loading = ora(loadText); loading.start(); try { // https://console.eeui.app/api/editor/case/cli_downzip?tree=5994504e5a799ea62c825224040a28e2 // request(utils.apiUrl() + 'editor/case/cli_downzip?tree=' + tree, (err, res, body) => { // {"ret":1,"msg":"success","data":{"size":5163,"zipurl":"https:\/\/console.eeui.app\/uploads\/temp\/editor\/1\/helloword\/5994504e5a799ea62c825224040a28e2.zip"}} // let data={"ret":1,"msg":"success","data":{"name":"madp-template-cm","size":5163,"zipurl":"http://localhost:5000/madp-template-cm.zip"}} // loading.stop(); // let data = utils.jsonParse(body); // if (data.ret === 1) { let savePath = path.join( require("os").homedir(), "." + config.cacheDirName, "demo" ); // console.log(info) utils.mkdirsSync(savePath); savePath = path.join(savePath, info.id + ".zip"); // loading.start(); if (!info.zipball_url) { loading.stop(); callback("", "", info.tag_name); return; } utils._downloadOnlineDemo( info.zipball_url, savePath, (err) => { loading.stop(); if (err) { callback(err); } else { callback("", savePath, info.tag_name); } }, (res) => { loading.text = loadText + `(${res.progress}, ${res.speed})`; } ); // }else{ // callback(data.msg || '下载演示模板失败!'); // } // }); } catch (e) { loading.stop(); callback("下载演示模板错误!"); } }, /** * 下载演示模板-②(在线版) * @param url * @param savePath * @param callback * @param progressCall */ _downloadOnlineDemo(url, savePath, callback, progressCall) { let file = fs.createWriteStream(savePath); file .on("close", () => { callback(); }) .on("error", (err) => { callback(err); }); // let receivedBytes = 0; let totalBytes = 0; let speedBytes = 0; let speedPer = "0B/S"; let speedInt = setInterval(() => { speedPer = utils.renderSize(Math.max(0, receivedBytes - speedBytes)) + "/S"; speedBytes = receivedBytes; }, 1000); request .get(url) .on("error", function (err) { callback(`下载模板错误: ${err}`); }) .on("response", function (res) { if (res.statusCode !== 200) { callback("Get zipUrl return a non-200 response."); } totalBytes = parseInt(res.headers["content-length"], 10); if (isNaN(totalBytes)) totalBytes = 0; }) .on("data", (chunk) => { receivedBytes += chunk.length; let progress = "0%"; if (totalBytes > 0) { progress = parseFloat( Math.max(0, (receivedBytes / totalBytes) * 100).toFixed(2) ) + "%"; } else { progress = utils.renderSize(receivedBytes); } progressCall && progressCall({ received: receivedBytes, total: totalBytes, speed: speedPer, progress: progress, }); }) .on("end", function () { clearInterval(speedInt); }) .pipe(file); }, /** * 压缩目录 * @param params = {?output:输出压缩包路径, entry:[{type:'dir', path:原文件夹路径, ?root:压缩根路径}, {type:'file', path:原文件路径, ?root:压缩根路径}]} * @param callback */ zipCompress(params, callback) { // console.log(params); let output = this.getObject(params, "output"); //输出压缩包路径 let entry = this.getObject(params, "entry"); //压缩的文件夹路径或文件数组 if (this.count(output) === 0) { output = tmp.tmpNameSync({ dir: require("os").tmpdir() }) + ".zip"; } if (typeof entry === "string") { entry = [ { type: "dir", root: entry, path: entry, }, ]; } if (!this.likeArray(entry)) { entry = [entry]; } // let tmpPath = tmp.tmpNameSync({ dir: require("os").tmpdir() }); entry.forEach((item) => { let filePath = item.path; let fileRoot = item.root; let leftPath = path.join(path.resolve(fileRoot || filePath), "/"); switch (item.type) { case "dir": let lists = this.fileDirDisplay(path.resolve(filePath)); lists