crabatool 1.0.13 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ {
2
+ // 使用 IntelliSense 了解相关属性。
3
+ // 悬停以查看现有属性的描述。
4
+ // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "type": "pwa-node",
9
+ "request": "launch",
10
+ "name": "Launch Program",
11
+ "skipFiles": [
12
+ "<node_internals>/**"
13
+ ],
14
+ "program": "${workspaceFolder}\\index.js"
15
+ }
16
+ ]
17
+ }
package/index.js CHANGED
@@ -5,9 +5,7 @@ var fs = require('fs');
5
5
  var path = require('path');
6
6
  var readline = require('readline');
7
7
 
8
- exports = module.exports;
9
-
10
- exports.run = function(options) {
8
+ module.exports.run = function(options) {
11
9
  Object.assign(config, options);
12
10
  checkConfig();
13
11
  waitInput();
@@ -33,9 +31,8 @@ function checkConfig() {
33
31
  throw new Error('平台前端组件不存在,请检查指定的webPath路径是否为craba前端框架的根目录。' + crabaJs);
34
32
  }
35
33
 
36
- var localData = upgrade.getLocalVersion();
34
+ showLocalVersion();
37
35
 
38
- console.log(`\r\n\r\n本地craba版本:[${localData.version}]\r\n本地craba日期:[${localData.date}]`);
39
36
  console.log("---------------------------------------------------------------------------------------------------------");
40
37
  }
41
38
 
@@ -56,18 +53,21 @@ function waitInput() {
56
53
 
57
54
  (async () => {
58
55
  var ques = [
59
- "1. 启动服务。\t\t\t\t主要包含:自动打包init.js和biz.js,后期还有es6语法兼容等",
60
- "2. 更新平台后启动服务。\t\t\t[内网才可用]",
61
- "3. 查询最新平台版本和日期。\t\t[内网才可用]",
62
- "4. 安装或更新IDEA环境。\t\t\t[内网才可用] 主要包含:智能语法、新增页面模板",
63
- "5. 安装或更新vscode环境。\t\t[内网才可用] 主要包含:智能语法、新增页面模板、ctrl+alt+n、alt+j快捷键",
64
- "6. 新建Craba空白项目。\t\t\t[内网才可用]",
65
- "7. 结束 \t\t\t\t或按Ctrl+C即可退出",
56
+ "1. 启动服务。\t\t\t\t主要包含:自动合并打包init.js和biz.js,查看本地平台的版本。",
57
+ "2. 更新当前项目的平台,然后启动服务。\t[内网才可用] 主要包含:从内网服务器拉取最新平台资源,再拷贝到webPath路径下覆盖老文件,解决npm不稳定问题。",
58
+ "3. 查询最新平台版本和日期。\t\t[内网才可用] 主要包含:获取内网服务器上面平台资源最新版本,方便查看最新平台版本",
59
+ "4. 校验当前项目前端所有js语法兼容性。\t主要包含:对本地js语法做一次初步预检避免上线后才发现问题;比如:编码乱码、let、const、=>、async、await、then、funName(){}",
60
+ "5. 打包当前项目前端所有js。\t\t[待定] 主要包含:前端es6语法的打包和js的统一压缩处理",
61
+ "6. 安装或更新IDEA环境。\t\t\t[待定] 主要包含:智能语法、新增页面模板",
62
+ "7. 安装或更新vscode环境。\t\t[待定] 主要包含:智能语法、新增页面模板、ctrl+alt+n、alt+j快捷键",
63
+ "8. 新建Craba项目。\t\t\t[待定]",
64
+ "9. 结束 \t\t\t\t或按Ctrl+C即可退出",
65
+ "已实现功能:1、2、3、4",
66
66
  "---------------------------------------------------------------------------------------------------------",
67
67
  "请输入对应功能的编号(数字):"
68
68
  ];
69
69
  const num = await question(ques.join('\r\n'));
70
- if (num != 6) {
70
+ if (num != 8) {
71
71
  rl.close(); // 关闭输入等待
72
72
  }
73
73
 
@@ -79,14 +79,18 @@ function waitInput() {
79
79
  showNewVersion();
80
80
  waitInput(); // 重复
81
81
  } else if (num == 4) {
82
- installIDEA();
82
+ checkAllJs();
83
83
  } else if (num == 5) {
84
- installvscode();
84
+ compressAllJs();
85
85
  } else if (num == 6) {
86
+ installIDEA();
87
+ } else if (num == 7) {
88
+ installvscode();
89
+ } else if (num == 8) {
86
90
  const webFolder = await question('请输入项目路径:');
87
91
  rl.close(); // 关闭输入等待
88
92
  createProject(webFolder);
89
- } else if (num != 7) {
93
+ } else if (num != 9) {
90
94
  console.error('无效输入,请继续。\r\n\r\n');
91
95
  waitInput(); // 重复
92
96
  }
@@ -103,10 +107,17 @@ function update() {
103
107
  upgrade.updateCraba(start);
104
108
  }
105
109
 
110
+ function showLocalVersion() {
111
+ var localData = upgrade.getLocalVersion();
112
+ console.log(`\r\n\r\n本地craba版本:[${localData.version}]\r\n本地craba日期:[${localData.date}]`);
113
+ }
114
+
106
115
  function showNewVersion() {
116
+ showLocalVersion();
117
+
107
118
  var data = upgrade.getNewVersion();
108
- console.log(`最新平台版本:[${data.version}]`);
109
- console.log(`最新平台日期:[${data.date}]\r\n\r\n`);
119
+ utils.error(`最新craba版本:[${data.version}]`);
120
+ utils.error(`最新craba日期:[${data.date}]`);
110
121
  }
111
122
 
112
123
  // 安装或更新IDEA环境,主要包含:智能语法、新增页面模板
@@ -119,6 +130,14 @@ function installvscode() {
119
130
  console.log('待实现');
120
131
  }
121
132
 
133
+ function checkAllJs() {
134
+ require('./tool/checkjs.js').start();
135
+ }
136
+
137
+ function compressAllJs() {
138
+ console.log('待实现');
139
+ }
140
+
122
141
  // 新建Craba空白项目,Hello
123
142
  function createProject(webFolder) {
124
143
  console.log('待实现');
package/lib/config.js CHANGED
@@ -1,2 +1,3 @@
1
- exports = module.exports;
2
- exports = {};
1
+ module.exports = {
2
+ debug: false
3
+ };
package/lib/server.js CHANGED
@@ -9,7 +9,13 @@ var compression = require('compression');
9
9
  var app = new express();
10
10
  app.use(compression()); // 开启压缩
11
11
 
12
- // 自动刷新
12
+
13
+ // 自定义打包js
14
+ if (config.childModList && config.childModList.length > 0) {
15
+ require('../tool/ngptool.js');
16
+ }
17
+
18
+ // 自动刷新浏览器
13
19
  if (config.refresh) {
14
20
  utils.log('已开启自动刷新');
15
21
 
@@ -17,7 +23,7 @@ if (config.refresh) {
17
23
  config.socketPort = config.port + 6000;
18
24
  }
19
25
 
20
- require('./sockettool.js');
26
+ require('../tool/sockettool.js');
21
27
 
22
28
  // 统一拦截客户端的api路由
23
29
  app.use(utils.rewriteCrabaJs);
@@ -25,7 +31,6 @@ if (config.refresh) {
25
31
 
26
32
  app.use(express.static(config.webPath))
27
33
 
28
-
29
34
  var server = http.createServer(app);
30
35
  var hostname = '127.0.0.1';
31
36
  server.listen(config.port, hostname, () => {
@@ -43,8 +48,4 @@ server.listen(config.port, hostname, () => {
43
48
  if (cmd) {
44
49
  require('child_process').exec(cmd);
45
50
  }
46
- });
47
-
48
-
49
- // 自定义打包js
50
- require('./ngptool.js');
51
+ });
package/lib/utils.js CHANGED
@@ -3,6 +3,7 @@ var path = require('path');
3
3
  const crypto = require('crypto');
4
4
  var iconv = require('iconv-lite');
5
5
  var config = require('./config.js');
6
+ var logErr = console.dir.bind(console);
6
7
 
7
8
  Buffer.prototype.toByteArray = function() {
8
9
  return Array.prototype.slice.call(this, 0)
@@ -31,7 +32,7 @@ Date.prototype.toJSON = function() {
31
32
 
32
33
 
33
34
  /* 全局公共类 */
34
- class utils {
35
+ class Utils {
35
36
  constructor() {
36
37
  this.cryptoKey = '$wssf20119@.Z+Q$';
37
38
  }
@@ -93,7 +94,7 @@ class utils {
93
94
  }
94
95
 
95
96
  getQueryInt(req, key) {
96
- var v = that.getQueryValue(req, key);
97
+ var v = utils.getQueryValue(req, key);
97
98
  if (v == null) return 0;
98
99
  v = parseInt(v);
99
100
  if (isNaN(v)) return 0;
@@ -101,7 +102,7 @@ class utils {
101
102
  }
102
103
 
103
104
  getFormValue(req, key) {
104
- var query = that.getReqBody(req);
105
+ var query = utils.getReqBody(req);
105
106
  if (!query) return null;
106
107
  if (query[key] == undefined) return null;
107
108
  var value = query[key];
@@ -134,7 +135,7 @@ class utils {
134
135
  }
135
136
 
136
137
  var errorObj = {
137
- "Message": that.makeExceptionHtml(ex, false)
138
+ "Message": utils.makeExceptionHtml(ex, false)
138
139
  };
139
140
  res.end(JSON.stringify(errorObj));
140
141
  }
@@ -173,7 +174,7 @@ class utils {
173
174
  // 设置允许跨域
174
175
  var origin = res.req.headers["origin"];
175
176
  var host = res.req.headers['host'];
176
- if (origin == undefined || that.endsWithIgnoreCase(origin, host)) return; // 非跨域请求
177
+ if (origin == undefined || utils.endsWithIgnoreCase(origin, host)) return; // 非跨域请求
177
178
  if (allowOrigins.length > 0 && !allowOrigins.includes(origin)) return; // 如果当前请求域名不在运行范围内,不添加跨域请求头
178
179
 
179
180
  if (!isOPTIONS) {
@@ -196,7 +197,7 @@ class utils {
196
197
  var isOPTIONS = req.method == "OPTIONS";
197
198
  var allowHeaders = 'X-Requested-With,Content-Type';
198
199
 
199
- that.setCORSHeader(res, [], allowHeaders, isOPTIONS); // 预先检查并统一输出跨域请求头
200
+ utils.setCORSHeader(res, [], allowHeaders, isOPTIONS); // 预先检查并统一输出跨域请求头
200
201
 
201
202
  if (isOPTIONS) { // 跨域请求预检查
202
203
  res.end('ok'); // 完成正常的响应,则允许跨域
@@ -206,39 +207,55 @@ class utils {
206
207
  next(); // 继续处理
207
208
  }
208
209
 
210
+ // 清空整个目录,包括子目录和文件
209
211
  cleardirsSync(dirname) {
210
212
  if (!fs.existsSync(dirname)) return;
211
213
 
212
- var files = fs.readdirSync(dirname);
213
- files.forEach(function(itm, index) {
214
- var file = path.join(dirname, itm);
215
- var stat = fs.statSync(file);
216
- if (stat.isDirectory()) {
214
+ fs.readdirSync(dirname).forEach(function(file) {
215
+ var filePath = path.join(dirname, file);
216
+ if (fs.statSync(filePath).isDirectory()) {
217
217
  //递归读取文件
218
- that.cleardirsSync(file);
218
+ utils.cleardirsSync(filePath);
219
219
  } else {
220
- fs.unlinkSync(file);
220
+ //utils.debug('del path ' + filePath);
221
+ fs.unlinkSync(filePath);
221
222
  }
222
223
  });
224
+
225
+ //utils.debug('del file ' + dirname);
226
+ fs.rmdirSync(dirname);
223
227
  }
224
228
 
229
+ // 递归创建目录
225
230
  mkdirsSync(dirname) {
226
231
  if (fs.existsSync(dirname)) {
227
232
  return true;
228
233
  }
229
- if (that.mkdirsSync(path.dirname(dirname))) {
234
+ if (utils.mkdirsSync(path.dirname(dirname))) {
230
235
  fs.mkdirSync(dirname);
231
236
  return true;
232
237
  }
233
238
  }
234
239
 
235
- toUtf8(byte) {
240
+ toUtf8(byte) {
236
241
  if (byte[0] == 0xef && byte[1] == 0xbb || byte[0] == 0xfe && byte[1] == 0xff || byte[0] == 0xff && byte[1] == 0xfe) {
237
242
  return byte.toString(); //utf8 + bom
238
243
  } else {
239
- var newByte = iconv.decode(byte, __from_code);
244
+ var newByte = iconv.decode(byte, 'UTF8');
240
245
  if (newByte.indexOf('�') > -1) return byte.toString(); // utf8上面没法识别出来,转换后反而会乱码,其实utf8不用转换,直接返回就行了
241
- return newByte.toString(__to_code);
246
+ return newByte.toString('UTF8');
247
+ }
248
+ }
249
+
250
+ isUtf8(byte, from_code) {
251
+ // 84, 121
252
+ // 239, 187
253
+ if (byte[0] == 0xef && byte[1] == 0xbb || byte[0] == 0xfe && byte[1] == 0xff || byte[0] == 0xff && byte[1] == 0xfe) {
254
+ return true;
255
+ } else {
256
+ var newByte = iconv.decode(byte, from_code || 'utf-8');
257
+ if (newByte.indexOf('�') > -1) return true; // utf8上面没法识别出来,转换后反而会乱码,其实utf8不用转换,直接返回就行了
258
+ return false;
242
259
  }
243
260
  }
244
261
 
@@ -251,16 +268,25 @@ class utils {
251
268
 
252
269
  log() {
253
270
  var args = [];
254
- args.push(`[${new Date().toString()}]`);
271
+ if (config.debug) args.push(`[${new Date().toString()}]`);
255
272
  for (var i = 0, count = arguments.length; i < count; i++) {
256
273
  args.push(arguments[i]);
257
274
  }
258
275
  console.log.apply(console, args);
259
276
  }
260
277
 
278
+ error(text) {
279
+ logErr(text);
280
+ }
281
+
282
+ debug() {
283
+ if (!config.debug) return;
284
+ utils.log.apply(utils, arguments);
285
+ }
286
+
261
287
  rewriteCrabaJs(req, res, next) {
262
288
  var url = req.originalUrl;
263
- that.log(url);
289
+ //utils.log(url);
264
290
 
265
291
  /*
266
292
  var apiStart = '/apis/';
@@ -278,7 +304,7 @@ class utils {
278
304
  throw new Error('平台前端组件不存在,请检查:' + crabaJs);
279
305
  }
280
306
 
281
- var clientSocketJs = path.join(__dirname, 'client/client.js');
307
+ var clientSocketJs = path.join(__dirname, '../tool/client.js');
282
308
  var content = fs.readFileSync(crabaJs).toString();
283
309
 
284
310
  var clientContent = fs.readFileSync(clientSocketJs).toString();
@@ -290,6 +316,53 @@ class utils {
290
316
  });
291
317
  res.end(content);
292
318
  }
293
- }
294
319
 
295
- var that = module.exports = new utils();
320
+ getFiles(options, fileList) {
321
+ var ignores = options.ignores;
322
+ var exts = options.exts;
323
+ var source = options.source;
324
+ if (ignores && !fileList) {
325
+ ignores = ignores.map((item) => { return path.join(source, item) });
326
+ }
327
+
328
+ if (!fileList) fileList = [];
329
+ var files = fs.readdirSync(source);
330
+ files.forEach(function(fileName) {
331
+ var filePath = path.join(source, fileName);
332
+ if (ignores && ignores.includes(filePath)) {
333
+ return;
334
+ }
335
+
336
+ var stat = fs.statSync(filePath);
337
+ if (stat.isDirectory()) {
338
+ options.source = filePath;
339
+ utils.getFiles(options, fileList);
340
+ } else {
341
+ if (exts && !exts.includes(path.extname(filePath))) {
342
+ return;
343
+ }
344
+
345
+ fileList.push(filePath);
346
+ }
347
+ });
348
+ return fileList;
349
+ }
350
+
351
+ copyFiles(source, dest, ignores, cb) {
352
+ var files = utils.getFiles({ source: source, ignores: ignores });
353
+ files.forEach(function(fileName) {
354
+ fileName = fileName.replace(source, ''); // 去掉根路径
355
+
356
+ if (cb) cb(fileName);
357
+
358
+ var filePath = path.join(source, fileName);
359
+ var destPath = path.join(dest, fileName);
360
+
361
+ utils.mkdirsSync(destPath);
362
+
363
+ fs.writeFileSync(destPath, fs.readFileSync(filePath), 'utf8');
364
+ });
365
+ }
366
+ }
367
+ var utils = new Utils();
368
+ module = module.exports = utils;
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "crabatool",
3
- "version": "1.0.13",
3
+ "version": "1.0.16",
4
4
  "description": "crabatool",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "start": "node index.js"
7
+ "start": "node index.js",
8
+ "test": "node ./test/test.js"
8
9
  },
9
10
  "author": "wssf",
10
11
  "dependencies": {
@@ -20,7 +21,8 @@
20
21
  "sync-request": "^6.1.0",
21
22
  "axios": "^0.27.2",
22
23
  "single-line-log": "^1.1.2",
23
- "node-stream-zip": "^1.15.0"
24
+ "node-stream-zip": "^1.15.0",
25
+ "iconv-jschardet": "^2.0.26"
24
26
  },
25
27
  "repository": {
26
28
  "type": "git",
package/test/ngp.js CHANGED
@@ -1,3 +1,38 @@
1
- const config = require('./config.js');
2
- var crabaTool = require('crabatool');
3
- crabaTool.run(config);
1
+ /**
2
+ * 项目环境使用工具包
3
+ */
4
+
5
+ var crabaTool = require('crabatool'); // 引入craba脚手架工具包
6
+
7
+
8
+ // 当前项目相关配置,注意必填项和非必填项哦
9
+ var config = {
10
+ //【必填】
11
+ // 告诉工具当前项目的端路径地址,填绝对路径哦
12
+ webPath: "F:/shell_master/web/src/main/resources/static/shell",
13
+
14
+ //【必填】
15
+ // 告诉工具当前项目前端服务器端口地址
16
+ port: 3001,
17
+
18
+ //【ngp必填】【非ngp项目不是必填】
19
+ // 当前项目模块名称,各组按需修改
20
+ modName: "shell", // 如:modName:"jxc"
21
+
22
+ // 【不是必填】
23
+ // 告诉工具当webPath目录下面的js、css、gspx文件发生改变就自动刷新网页
24
+ refresh: false,
25
+
26
+ //【不是必填】
27
+ // 1. 当前模块是由哪些过去的模块合并来的,各组按需修改
28
+ // 2. 如果配置了子模块清单,工具会自动将所有子模块下的init.js和当前模块的jxc/js/jxc.js,合并打包到:jxc/js/init.js,实际运行过程中只加载:jxc/js/init.js,不会加载子模块下面的init.js,这样就可以大大减少http请求
29
+ // 3. 同2,biz.js也是相同思路进行合并打包
30
+ childModList: [], // 如: ['recordsheet', 'baseinfo', 'accounting'],
31
+
32
+ // 【不是必填】
33
+ // 上一步中打包后的文件是否压缩, true为忽略【不压缩】,false为【要压缩】,各组按需修改
34
+ ignoreCompress: true
35
+
36
+ }
37
+
38
+ crabaTool.run(config); // 传入配置参数,启动工具
@@ -1,3 +1,11 @@
1
+ /**
2
+ * 本地测试工具包
3
+ */
4
+
5
+ var crabaTool = require('../index.js'); // 引入craba脚手架工具包
6
+
7
+
8
+ // 当前项目相关配置,注意必填项和非必填项哦
1
9
  var config = {
2
10
  //【必填】
3
11
  // 告诉工具当前项目的端路径地址,填绝对路径哦
@@ -13,17 +21,18 @@ var config = {
13
21
 
14
22
  // 【不是必填】
15
23
  // 告诉工具当webPath目录下面的js、css、gspx文件发生改变就自动刷新网页
16
- refresh: false,
24
+ refresh: true,
17
25
 
18
26
  //【不是必填】
19
27
  // 1. 当前模块是由哪些过去的模块合并来的,各组按需修改
20
28
  // 2. 如果配置了子模块清单,工具会自动将所有子模块下的init.js和当前模块的jxc/js/jxc.js,合并打包到:jxc/js/init.js,实际运行过程中只加载:jxc/js/init.js,不会加载子模块下面的init.js,这样就可以大大减少http请求
21
29
  // 3. 同2,biz.js也是相同思路进行合并打包
22
- childModList: [], // 如: ['recordsheet', 'baseinfo', 'accounting'],
30
+ childModList: ['recordsheet', 'baseinfo', 'accounting'],
23
31
 
24
32
  // 【不是必填】
25
33
  // 上一步中打包后的文件是否压缩, true为忽略【不压缩】,false为【要压缩】,各组按需修改
26
34
  ignoreCompress: true
27
35
 
28
36
  }
29
- module.exports = config;
37
+
38
+ crabaTool.run(config); // 传入配置参数,启动工具
@@ -0,0 +1,93 @@
1
+ var utils = require('../lib/utils.js');
2
+ var config = require('../lib/config.js');
3
+ var fs = require('fs');
4
+ var ProgressBar = require('./progressbar.js');
5
+ var jschardet = require('iconv-jschardet');
6
+ var path = require('path');
7
+
8
+ module.exports.start = function() {
9
+ var jsFiles = utils.getFiles({ source: config.webPath, exts: '.js' });
10
+
11
+ var fileSize = 300;
12
+ var errList = [];
13
+ var errRegList = [];
14
+ var bigList = [];
15
+ var notUtf8List = [];
16
+ var utf8List = [];
17
+ var blackList = ['craba.min.js', 'crabaEx.min.js', 'crabaNgp.js', 'echarts-all.js', 'echarts.min.js', 'math.min.js'];
18
+ // let、const、=>、async、await、then、funName(){}
19
+ var dangerousJs = ['\\slet\\s', '\\sconst\\s', '\=\>', '\\sasync\\s', '\\sawait\\s', '\\.then\\('];
20
+ var noFunction = new RegExp('\w.*\(.*\)(\s*|\n){');
21
+
22
+ var pb = new ProgressBar('检查进度', jsFiles.length);
23
+ jsFiles.forEach(function(filePath) {
24
+ pb.value++;
25
+ pb.render({ value: pb.value, text: filePath });
26
+
27
+ var byte = fs.readFileSync(filePath);
28
+ var stats = fs.statSync(filePath);
29
+ if (stats.size / 1024 > fileSize) { // 大于300k的js视为大文件
30
+ if (!blackList.includes(path.basename(filePath))) {
31
+ bigList.push(`路径:${filePath} 大小:${parseInt(stats.size / 1024)}kb`);
32
+ }
33
+ }
34
+
35
+ var content = byte.toString();
36
+ var ret = jschardet.detect(byte);
37
+ if (utils.isUtf8(byte, ret.encoding) || ret.encoding == 'UTF-8') {
38
+ utf8List.push(filePath);
39
+ } else {
40
+ var reg = /[\u4e00-\u9FA5]+/;
41
+ if (!reg.test(content)) { // 不包含中文的情况,jschardet把utf-8也认为是gbk了
42
+ utf8List.push(filePath);
43
+ } else {
44
+ notUtf8List.push(`路径:${filePath} 编码:${ret.encoding}`);
45
+ content = utils.toUtf8(byte);
46
+ }
47
+ }
48
+
49
+ var reg = new RegExp(dangerousJs.join('|'), 'ig');
50
+ if (reg.test(content)) { // 先检查是否有危险字符
51
+ errList.push(filePath);
52
+
53
+ var nreg = new RegExp(dangerousJs.join('|'), 'ig');
54
+ var all = content.matchAll(nreg);
55
+ var m = [];
56
+ var v = all.next()
57
+ while (!v.done) {
58
+ m.push(`不兼容字符:${v.value[0]} 位置:${v.value.index}`);
59
+ v = all.next()
60
+ }
61
+
62
+ errRegList.push({ errList: m });
63
+ }
64
+
65
+ });
66
+ pb.clear('检验完成');
67
+
68
+ var info = [];
69
+ info.push(`检验结果:一共检查${jsFiles.length}个js文件`);
70
+ info.push(`语法异常文件数:【${errList.length}】个`);
71
+ info.push(`utf8文件数:【${utf8List.length}】个`);
72
+ info.push(`非utf8文件数:【${notUtf8List.length}】个`);
73
+ console.log(info.join('\r\n'));
74
+
75
+ if (errList.length > 0) {
76
+ console.log('语法异常文件清单');
77
+ errList.forEach((s, index) => {
78
+
79
+ console.log(s);
80
+
81
+ var m = errRegList[index];
82
+ console.log(m);
83
+ });
84
+ }
85
+
86
+ if (notUtf8List.length > 0) {
87
+ console.log('非utf8文件清单', notUtf8List);
88
+ }
89
+
90
+ if (bigList.length > 0) {
91
+ console.log(`超过${fileSize}kb的文件清单`, bigList);
92
+ }
93
+ }
@@ -15,9 +15,9 @@
15
15
  }
16
16
  });
17
17
  ngp_socket.add_close(function(e) {
18
- $common.showInfo('前端自动刷新服务关闭');
18
+ $common.showInfo('服务器已退出,前端自动刷新服务关闭');
19
19
  });
20
20
  ngp_socket.add_error(function(e) {
21
- $common.showError('前端自动刷新服务异常');
21
+ $common.showError('服务器异常,前端自动刷新服务异常');
22
22
  });
23
23
  })();
@@ -38,11 +38,11 @@ function readFileList(folder, filesList) {
38
38
 
39
39
  var files = fs.readdirSync(folder);
40
40
  files.forEach(function(itm, index) {
41
- var file = folder + '/' + itm;
41
+ var file = path.join(folder, itm);
42
42
  var stat = fs.statSync(file);
43
43
  if (stat.isDirectory()) {
44
44
  //递归读取文件
45
- readFileList(folder + itm + "/", filesList)
45
+ readFileList(file, filesList)
46
46
  } else {
47
47
  if (filesList.indexOf(file) >= 0) {
48
48
  return;
@@ -66,7 +66,9 @@ function buildFolder(folderInPath, fileOutPath) {
66
66
 
67
67
  filesList.forEach(function(filePath) {
68
68
  if (!filePath) return;
69
- utils.log(filePath);
69
+ if (!fs.existsSync(filePath)) return;
70
+
71
+ utils.debug(filePath);
70
72
  filePath = getAbsPath(filePath);
71
73
  var stats = fs.statSync(filePath);
72
74
  if (!stats.isFile()) return;
@@ -81,7 +83,7 @@ function buildFolder(folderInPath, fileOutPath) {
81
83
  fileOutPath = getAbsPath(fileOutPath);
82
84
  mkdirsSync(npath.dirname(fileOutPath));
83
85
  fs.writeFileSync(fileOutPath, __bom + __filesContent.join('\n'), 'utf8'); // "\ufeff"->> utf-8 BOM标记
84
- utils.log("out file:" + fileOutPath);
86
+ utils.debug("out file:" + fileOutPath);
85
87
  }
86
88
  };
87
89
 
@@ -122,7 +124,7 @@ function replaceBlackFunction(content) {
122
124
  }
123
125
 
124
126
  function compressFile(filePath) {
125
- utils.log("compress and merge:" + filePath);
127
+ utils.debug("compress and merge:" + filePath);
126
128
 
127
129
  var content = fs.readFileSync(filePath);
128
130
 
@@ -175,13 +177,11 @@ __blackFileName = args[3]; // 黑名单文件
175
177
 
176
178
  if (!__inPath || !__outPath) throw ("args参数不能为空");
177
179
 
178
- utils.log("source files:" + __inPath);
179
- utils.log("out file:" + __outPath);
180
- utils.log("start merge...\r\n");
180
+ utils.debug("source files:" + __inPath);
181
+ utils.debug("out file:" + __outPath);
182
+ utils.debug("start merge...\r\n");
181
183
 
182
184
  var startT = new Date();
183
185
  buildFolder(__inPath, __outPath);
184
186
  var endT = new Date();
185
- utils.log("\r\nALL Done, Files:" + (__filesContent.length / 2) + " js");
186
- utils.log("Total Times:" + (endT.getTime() - startT.getTime()));
187
- utils.log("\r\n-------压缩合并任务完成----------use -ignorecompress:" + __ignoreCompress);
187
+ utils.log(`打包完成\t 耗时:${endT.getTime() - startT.getTime()}毫秒\t-ignorecompress:${__ignoreCompress}\t合并文件数:${(__filesContent.length / 2)}个`);
@@ -1,18 +1,19 @@
1
- var config = require('./config.js');
1
+ var config = require('../lib/config.js');
2
2
  var path = require('path');
3
3
  var chokidar = require('chokidar');
4
4
  var fs = require('fs');
5
5
  var fork = require('child_process').fork;
6
- var utils = require('./utils.js');
6
+ var utils = require('../lib/utils.js');
7
7
 
8
- var mergeJs = path.join(__dirname, '/merge/merge.js');
9
- var log = console.dir.bind(console);
8
+ var mergeJs = path.join(__dirname, 'merge.js');
10
9
  var compressArgs = config.ignoreCompress ? ['-ignorecompress'] : []; // 是否压缩
11
10
 
12
11
  // 打包biz.js
13
12
  function mergeBiz() {
14
13
  var bizPath = path.join(config.webPath, '/js/biz');
15
- utils.mkdirsSync(bizPath);
14
+ if (!fs.existsSync(bizPath)) {
15
+ return utils.error('error biz.js关联打包的路径不存在,已经取消打包功能。如需打包请先创建目录:' + bizPath);
16
+ }
16
17
 
17
18
  var watcher = chokidar.watch([bizPath], {
18
19
  persistent: true,
@@ -20,15 +21,15 @@ function mergeBiz() {
20
21
  });
21
22
 
22
23
  var watchAction = function() {
23
- log('文件变动,重新打包中');
24
+ utils.debug('打包中');
24
25
  // 这里进行文件更改后的操作
25
26
  var p = fork(mergeJs, [`${[bizPath]}`, `${[path.join(config.webPath, '/js/biz.js')]}`, compressArgs])
26
27
  p.on('exit', code => {
27
- log('打包完成');
28
+ utils.debug('打包完成');
28
29
  });
29
30
  }
30
31
  watcher
31
- .on('ready', () => log(`${bizPath},Initial scan complete. Ready for changes.`))
32
+ .on('ready', () => utils.debug(`${bizPath},Initial scan complete. Ready for changes.`))
32
33
  //.on('add', path => log(`File ${path} has been added`))
33
34
  .on('change', path => watchAction({ event: 'change', eventPath: path }))
34
35
  .on('unlink', path => watchAction({ event: 'remove', eventPath: path }));
@@ -38,14 +39,20 @@ function mergeBiz() {
38
39
 
39
40
  // 打包生成jxc/js/init.js
40
41
  function mergeInit() {
42
+ var modJs = path.join(config.webPath, '/js/' + config.modName + '.js'); // jxc/js/jxc.js
43
+ if (!fs.existsSync(modJs)) {
44
+ return utils.error(`error 模块对应的资源不存在:${modJs},已经取消打包功能。如需打包,请先将${config.modName}/js/init.js修改为:${config.modName}/js/${config.modName}.js`);
45
+ }
46
+
41
47
  var inits = [];
48
+ inits.push(modJs);
42
49
 
43
50
  var watchAction = function() {
44
- log('文件变动,重新打包中');
51
+ utils.debug('打包中');
45
52
  // 这里进行文件更改后的操作
46
53
  var p = fork(mergeJs, [`${[inits]}`, `${[path.join(config.webPath, '/js/init.js')]}`, compressArgs])
47
54
  p.on('exit', code => {
48
- log('打包完成');
55
+ utils.debug('打包完成');
49
56
  });
50
57
  }
51
58
 
@@ -55,24 +62,21 @@ function mergeInit() {
55
62
  usePolling: true
56
63
  });
57
64
  watcher
58
- .on('ready', () => log(`${jsPath},Initial scan complete. Ready for changes.`))
65
+ .on('ready', () => utils.debug(`${jsPath},Initial scan complete. Ready for changes.`))
59
66
  //.on('add', path => log(`File ${path} has been added`))
60
67
  .on('change', path => watchAction({ event: 'change', eventPath: path }))
61
68
  .on('unlink', path => watchAction({ event: 'remove', eventPath: path }));
62
69
  }
63
70
 
64
- var modJs = path.join(config.webPath, '/js/' + config.modName + '.js'); // jxc/js/jxc.js
65
- if (!fs.existsSync(modJs)) {
66
- console.error(`模块对应的资源不存在:${modJs},请将${config.modName}/js/init.js先修改为:${config.modName}/js/${config.modName}.js`);
67
- }
68
- inits.push(modJs);
69
71
  watchJs(modJs);
70
72
 
71
73
  config.childModList.forEach(childName => {
72
74
  var childInitPath = path.join(config.webPath, childName, 'js/init.js');
73
75
  inits.push(childInitPath);
74
- utils.mkdirsSync(childInitPath);
75
-
76
+ //utils.mkdirsSync(childInitPath);
77
+ if (!fs.existsSync(childInitPath)) {
78
+ utils.error('error 监听打包的资源不存在' + childInitPath);
79
+ }
76
80
  watchJs(childInitPath);
77
81
  });
78
82
  inits = inits.join(',');
@@ -80,12 +84,8 @@ function mergeInit() {
80
84
  watchAction();// 启动就打包一次
81
85
  }
82
86
 
83
- if (config.childModList && config.childModList.length > 0) {
84
- utils.log('启动打包服务', config.childModList);
85
-
86
- utils.mkdirsSync(config.webPath);
87
-
88
- mergeBiz(); // 如果有需要
87
+ utils.log('启动打包服务', config.childModList);
88
+ utils.mkdirsSync(config.webPath);
89
89
 
90
- mergeInit(); // 如果有需要
91
- }
90
+ mergeBiz(); // 如果有需要
91
+ mergeInit(); // 如果有需要
@@ -7,10 +7,14 @@ function ProgressBar(description, bar_length) {
7
7
  this.description = description || 'Progress'; // 命令行开头的文字信息
8
8
  this.length = bar_length || 25; // 进度条的长度(单位:字符),默认设为 25
9
9
 
10
+ var that = this;
11
+ that.value = 0;
12
+
10
13
  // 刷新进度条图案、文字的方法
11
- this.render = function(opts) {
12
- if (!opts.total) opts.total = 100;
13
- var percent = (opts.completed / opts.total).toFixed(4); // 计算进度(子任务的 完成数 除以 总数)
14
+ that.render = function(opts) {
15
+ if (!opts.total) opts.total = this.length;
16
+ that.value = opts.value;
17
+ var percent = (opts.value / opts.total).toFixed(4); // 计算进度(子任务的 完成数 除以 总数)
14
18
  var cell_num = Math.floor(percent * this.length); // 计算需要多少个 █ 符号来拼凑图案
15
19
 
16
20
  // 拼接黑色条
@@ -26,14 +30,14 @@ function ProgressBar(description, bar_length) {
26
30
  }
27
31
 
28
32
  // 拼接最终文本
29
- var cmdText = this.description + ': ' + (100 * percent).toFixed(2) + '% ' + cell + empty + ' ' + (opts.text || '');
33
+ var cmdText = this.description + ': ' + (100 * percent).toFixed(2) + '% ' + cell + empty + ' ' + (opts.text || '') + '\r\n';
30
34
 
31
35
  // 在单行输出文本
32
36
  slog(cmdText);
33
37
  };
34
38
 
35
- this.clear = function(text) {
36
- slog(text || '');
39
+ that.clear = function(text) {
40
+ slog((text || '') + '\r\n');
37
41
  }
38
42
  }
39
43
 
@@ -1,5 +1,5 @@
1
- var utils = require('./utils.js');
2
- var config = require('./config.js');
1
+ var utils = require('../lib/utils.js');
2
+ var config = require('../lib/config.js');
3
3
  var ws = require("nodejs-websocket");
4
4
  var path = require('path');
5
5
  var chokidar = require('chokidar');
@@ -7,7 +7,7 @@ var fs = require('fs');
7
7
  var exts = [".js", ".css", ".html", ".gspx"];
8
8
 
9
9
  function watchWebChange() {
10
- utils.log("创建文件变动监听");
10
+ utils.debug("创建文件变动监听");
11
11
 
12
12
  var watcher = chokidar.watch([config.webPath], {
13
13
  persistent: true,
@@ -19,37 +19,36 @@ function watchWebChange() {
19
19
  if (!exts.includes(ext)) return;
20
20
 
21
21
  utils.log('文件变动,刷新浏览器');
22
- console.log(args);
22
+ //console.log(args);
23
23
 
24
24
  broadcast('refresh');
25
25
  }
26
26
  watcher
27
- .on('ready', () => { utils.log('watchWebPath change ready !!') })
27
+ .on('ready', () => { utils.debug('watch webPath change ready !!') })
28
28
  .on('change', path => watchAction({ event: 'change', eventPath: path }))
29
29
  .on('unlink', path => watchAction({ event: 'remove', eventPath: path }));
30
30
 
31
31
  }
32
32
 
33
33
  function createSocket() {
34
- utils.log("监听浏览器");
35
34
  socketServer = ws.createServer(function(conn) {
36
35
  conn.on("text", function(str) {
37
- utils.log("收到的信息为:" + str);
36
+ utils.debug("收到的信息为:" + str);
38
37
  });
39
38
  conn.on('connect', function(code, reason) {
40
39
  utils.log('connect连接成功');
41
40
  broadcast('ws connect success');
42
41
  });
43
42
  conn.on("close", function(code, reason) {
44
- utils.log("Socket关闭", arguments);
43
+ utils.debug("connect关闭");
45
44
  });
46
45
  conn.on("error", function(code, reason) {
47
- utils.log("Socket异常", arguments);
46
+
48
47
  });
49
48
  }).listen(config.socketPort);
50
49
 
51
50
  socketServer.on('connection', function(code, reason) {
52
- utils.log('connection连接成功');
51
+ utils.debug('connection连接成功');
53
52
  broadcast('ws connection success');
54
53
  });
55
54
  }
package/tool/upgrade.js CHANGED
@@ -71,6 +71,9 @@ class Upgrade {
71
71
  }
72
72
 
73
73
  updateCraba(cb) {
74
+ utils.cleardirsSync(this.SaveFilePath);
75
+
76
+ this.cb = cb;
74
77
  var localData = this.getLocalVersion();
75
78
  var newData = this.getNewVersion();
76
79
  if (localData.version == newData.version) {
@@ -80,8 +83,8 @@ class Upgrade {
80
83
  }
81
84
 
82
85
  this.pb = new ProgressBar('更新进度', 50);
83
- this._deleteCache();
84
-
86
+ this.pb.render({ value: 10, text: '下载资源' });
87
+ utils.mkdirsSync(this.SaveFilePath); // 创建缓存目录
85
88
  this.downloadFile(this.getCrabaFileUrl(), this.CacheFileName, utils.createDelegate(this, this._doCrabaLoaded));
86
89
  }
87
90
 
@@ -90,37 +93,58 @@ class Upgrade {
90
93
  console.log("服务不可用,拉取文件失败,请联系平台管理员");
91
94
  return;
92
95
  }
93
- this.pb.render({ completed: 50, text: '下载完成' });
94
96
 
97
+ this.pb.render({ value: 50, text: '下载完成' });
98
+ var that = this;
95
99
  //console.log(filePath);
96
- var zip = new StreamZip({ file: filePath });
100
+ var zip = new StreamZip({ file: filePath, storeEntries: true, skipEntryNameValidation: true });
97
101
  zip.on('ready', () => {
98
- that.pb.render({ completed: 60, text: '解压文件' });
102
+ that.pb.render({ value: 70, text: '解压并拷贝文件' });
103
+
99
104
  utils.mkdirsSync(that.CachePath);
105
+
100
106
  zip.extract(null, that.CachePath, (err, count) => {
101
- that.pb.render({ completed: 70, text: `解压完成,开始拷贝文件` });
102
107
  zip.close();
103
- that.copyFile();
108
+
109
+ that._copyFiles();
104
110
  });
105
111
  });
106
112
  }
107
113
 
108
- copyFile() {
114
+ _copyFiles() {
115
+ var dest = config.webPath;
116
+ var source = this.CachePath;
117
+ var ignores = ["server", "www"];
118
+
119
+ utils.copyFiles(source, dest, ignores, utils.createDelegate(this, function(fileName) {
120
+ this.pb.render({ value: ++this.pb.value, text: fileName });
121
+ }));
122
+
123
+ this.pb.clear('更新完成');
109
124
 
125
+ if (this.cb) {
126
+ this.cb();
127
+ delete this.cb;
128
+ }
129
+
130
+ // 可能文件占用中
131
+ var fpath = this.SaveFilePath;
132
+ setTimeout(function() {
133
+ utils.cleardirsSync(fpath);
134
+ }, 1000);
110
135
  }
111
136
 
112
137
  downloadFile(uri, filePath, callback) {
113
138
  if (!uri || !filePath) throw new Error('uri或filePath不能为空');
114
139
 
115
140
  //console.log('下载craba文件');
116
-
141
+ var that = this;
117
142
  // 获取远端图片
118
143
  axios({
119
144
  method: 'get',
120
145
  url: this.getCrabaFileUrl(),
121
146
  responseType: 'stream'
122
147
  }).then(function(response) {
123
- that.pb.render({ completed: 40, text: '下载资源' });
124
148
  response.data
125
149
  .pipe(fs.createWriteStream(that.CacheFileName))
126
150
  .on('close', () => {
@@ -130,12 +154,6 @@ class Upgrade {
130
154
  that.pb.clear('[内网才能访问],出错了:', error.message);
131
155
  });
132
156
  }
133
-
134
- _deleteCache() {
135
- this.pb.render({ completed: 10, text: '清理缓存' });
136
- utils.cleardirsSync(this.SaveFilePath);
137
- utils.mkdirsSync(this.SaveFilePath); // 创建缓存目录
138
- this.pb.render({ completed: 20, text: '清理完成' });
139
- }
140
157
  }
141
- that = module.exports = new Upgrade();
158
+
159
+ module.exports = new Upgrade();