UNPKG

11.4 kBJavaScriptView Raw
1const fs = require('fs');
2const fse = require("fs-extra");
3const path = require('path');
4const ora = require('ora');
5const chalk = require('chalk');
6const inquirer = require('inquirer');
7const decompress = require('decompress');
8const md5File = require('md5-file');
9const request = require('request');
10const logger = require('./logger');
11const config = require("../../config");
12const utils = require("./index");
13
14function start() {
15 let projectPath = path.resolve(process.cwd());
16 let configInfo = require(path.resolve(projectPath, "eeui.config.js"));
17 let serviceUrl = utils.getObject(configInfo, "serviceUrl");
18 if (utils.count(serviceUrl) > 0) {
19 logger.fatal("当前项目已自定义服务端网址(" + serviceUrl + "),自搭建服务端不支持一键云修复文件!");
20 }
21 //
22 let zipPackPath = path.resolve(config.zipPackDir);
23 utils.mkdirsSync(zipPackPath);
24 let count = utils.count(zipPackPath);
25 let lists = utils.fileDirDisplay(zipPackPath, true);
26 let files = lists.file.sort().reverse();
27 let choices = [];
28 for (let index in files) {
29 if (!files.hasOwnProperty(index)) continue;
30 if (choices.length >= 100) break;
31 let tmp = files[index];
32 choices.push(tmp.substr(count + 1));
33 }
34 if (choices.length === 0) {
35 logger.fatal(`未找到buildZip文件包!`);
36 }
37 if (choices.length === 1) {
38 logger.fatal(`未找到可对比的buildZip文件包!`);
39 }
40 //
41 let newZip,
42 oldZip;
43 inquirer.prompt([{
44 type: 'list',
45 name: 'name',
46 message: `请选择修复包(新包):`,
47 choices: choices,
48 }]).then(function(newAnswers) {
49 newZip = path.join(zipPackPath, newAnswers.name);
50 choices.some((item, index) => {
51 if (item === newAnswers.name) {
52 choices.splice(index, 1);
53 return true;
54 }
55 });
56 inquirer.prompt([{
57 type: 'list',
58 name: 'name',
59 message: `请选择被修复包(旧包):`,
60 choices: choices,
61 }]).then(function(oldAnswers) {
62 oldZip = path.join(zipPackPath, oldAnswers.name);
63 let spinFetch = ora('正在生成差异包...');
64 spinFetch.start();
65 //
66 let newPath = utils.rightDelete(newZip, '.zip');
67 let oldPath = utils.rightDelete(oldZip, '.zip');
68 fse.removeSync(newPath);
69 fse.removeSync(oldPath);
70 utils.mkdirsSync(newPath);
71 utils.mkdirsSync(oldPath);
72 decompress(newZip, newPath).then(() => {
73 decompress(oldZip, oldPath).then(() => {
74 let newLists = utils.fileDirDisplay(newPath).file;
75 if (newLists.length === 0) {
76 spinFetch.stop();
77 fse.removeSync(newPath);
78 fse.removeSync(oldPath);
79 logger.fatal(`修复包没有任何文件`);
80 return
81 }
82 let fileLists = [];
83 newLists.forEach((newFile) => {
84 let oldFile = newFile.replace(newPath, oldPath);
85 if (!fs.existsSync(oldFile) || md5File.sync(newFile) !== md5File.sync(oldFile)) {
86 fileLists.push(newFile)
87 }
88 });
89 if (fileLists.length === 0) {
90 spinFetch.stop();
91 fse.removeSync(newPath);
92 fse.removeSync(oldPath);
93 logger.fatal(`没有差异的文件`);
94 return
95 }
96 //
97 let diffPackPath = path.resolve(config.diffPackDir);
98 utils.mkdirsSync(diffPackPath);
99 let zipPath = diffPackPath + "/differ-" + utils.rightDelete(utils.leftDelete(newAnswers.name, 'build-'), '.zip') + "-" + utils.rightDelete(utils.leftDelete(oldAnswers.name, 'build-'), '.zip') + ".zip";
100 if (fs.existsSync(zipPath)) {
101 fse.removeSync(zipPath);
102 }
103 let entry = [];
104 fileLists.forEach((tmp) => {
105 entry.push({
106 type: "file",
107 root: newPath,
108 path: tmp,
109 });
110 });
111 utils.zipCompress({
112 output: zipPath,
113 entry: entry
114 }, (output, err) => {
115 spinFetch.stop();
116 fse.removeSync(newPath);
117 fse.removeSync(oldPath);
118 if (err) {
119 logger.fatal(`打包差异文件失败:${err}`);
120 } else {
121 step2(output, fileLists);
122 }
123 });
124 });
125 });
126 });
127 });
128}
129
130function step2(zipPath, fileLists) {
131 logger.sep();
132 logger.success(`找到修复文件${fileLists.length}个。`);
133 logger.sep();
134 //
135 let spinFetch = ora('正在获取应用版本...');
136 spinFetch.start();
137 request(utils.apiUrl(true) + 'apps/update?act=applists&token=' + utils.getToken(), (err, res, body) => {
138 spinFetch.stop();
139 let data = utils.jsonParse(body);
140 if (data.ret === -1) {
141 logger.warn('请先登录后再继续!');
142 utils.login(true, () => {
143 step2(zipPath, fileLists);
144 });
145 return;
146 }
147 if (data.ret !== 1) {
148 logger.fatal(data.msg || '系统繁忙,请稍后再试!');
149 }
150 if (data.data.length === 0) {
151 logger.fatal('没有找到应用,请先到控制台添加吧。');
152 }
153 //
154 let choices = [];
155 data.data.forEach((item) => {
156 choices.push({
157 name: item.title + '(ID:' + item.id + ')',
158 value: item.id
159 })
160 });
161 inquirer.prompt([{
162 type: 'list',
163 name: 'appid',
164 message: `请选择修复的应用:`,
165 choices: choices,
166 }, {
167 type: 'input',
168 name: 'version',
169 message: "请输入修复的应用版本号(多个半角逗号分隔):",
170 validate: function (value) {
171 let array = (value + "").split(",");
172 if (array.length === 0) {
173 return '请输入要修复的版本号。';
174 }
175 let error = false;
176 array.some((val) => {
177 if (!(Math.ceil(val) === Math.floor(val) && Math.ceil(val) > 0)) {
178 return error = true;
179 }
180 });
181 if (error) {
182 return '输入格式错误,版本号应为整数(多个半角逗号分隔)。';
183 }
184 return true;
185 }
186 }, {
187 type: 'list',
188 name: 'platform',
189 message: '请选择修复的应用平台:',
190 choices: [{
191 name: '修复 Android、iOS',
192 value: 'android,ios'
193 }, {
194 name: '仅修复 Android',
195 value: 'android'
196 }, {
197 name: '仅修复 iOS',
198 value: 'ios'
199 }]
200 }, {
201 type: 'list',
202 name: 'debug',
203 message: '选择是否修复DEBUG版本:',
204 choices: [{
205 name: '排除DEBUG版本',
206 value: 0
207 }, {
208 name: '包含DEBUG版本',
209 value: 1
210 }, {
211 name: '仅DEBUG版本',
212 value: 2
213 }]
214 }, {
215 type: 'list',
216 name: 'update_mode',
217 message: '选择更新模式:',
218 choices: [{
219 name: '启动时触发更新',
220 value: 0
221 }, {
222 name: '客户手动触发更新',
223 value: 1
224 }]
225 }, {
226 type: 'list',
227 name: 'reboot',
228 message: '选择修复完成后行为事件:',
229 choices: [{
230 name: '提示重启',
231 value: 2
232 }, {
233 name: '静默',
234 value: 0
235 }, {
236 name: '自动重启',
237 value: 1
238 }]
239 }, {
240 type: 'list',
241 name: 'clear_cache',
242 message: '选择修复完成后缓存管理:',
243 choices: [{
244 name: '保留缓存',
245 value: 0
246 }, {
247 name: '清除缓存',
248 value: 1
249 }]
250 }, {
251 type: 'input',
252 name: 'title',
253 default: () => {
254 return '一键修复包';
255 },
256 message: "请输入修复备注:",
257 validate: (value) => {
258 return value !== ''
259 }
260 }]).then(function(answers) {
261 answers.zipPath = zipPath;
262 step3(answers, fileLists);
263 });
264 });
265}
266
267function step3(answers, fileLists) {
268 let spinFetch = ora('正在上传差异包...').start();
269 request.post({
270 url: utils.apiUrl(true) + 'apps/update',
271 formData: {
272 act: 'upload',
273 token: utils.getToken(),
274 zipfile: fs.createReadStream(answers.zipPath),
275 }
276 }, (error, response, body) => {
277 spinFetch.stop();
278 let data = utils.jsonParse(body);
279 if (data.ret === -1) {
280 logger.warn('请先登录后再继续!');
281 utils.login(true, () => {
282 step3(answers, fileLists);
283 });
284 return;
285 }
286 if (data.ret !== 1) {
287 logger.fatal(data.msg || '系统繁忙,请稍后再试!');
288 }
289 answers.title = answers.title || "一键修复包";
290 answers.valid = 1;
291 answers.fileinfo = data.data;
292 step4(answers, fileLists);
293 });
294}
295
296function step4(answers, fileLists) {
297 let spinFetch = ora('正在添加修复包...').start();
298 request.post({
299 url: utils.apiUrl(true) + 'apps/update',
300 formData: {
301 act: 'add-from-cli',
302 token: utils.getToken(),
303 D: JSON.stringify(answers),
304 }
305 }, (error, response, body) => {
306 spinFetch.stop();
307 let data = utils.jsonParse(body);
308 if (data.ret === -1) {
309 logger.warn('请先登录后再继续!');
310 utils.login(true, () => {
311 step4(answers, fileLists);
312 });
313 return;
314 }
315 if (data.ret !== 1) {
316 logger.fatal(data.msg || '系统繁忙,请稍后再试!');
317 }
318 logger.sep();
319 logger.success(`添加修复包成功(共${fileLists.length}个文件)。`);
320 logger.info('更多详细设置可登录控制台 ' + chalk.underline(utils.consoleUrl(true)) + ' 查看。');
321 logger.sep();
322 });
323}
324
325module.exports = {start};