jsir 2.3.8 → 2.3.9

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.
package/cmd/oaa.js CHANGED
@@ -11,7 +11,7 @@ const {
11
11
  createConsole, setTips, delTips,
12
12
  getEditor, errorStr, getConfigDir,
13
13
  getFullPath, parseUniqueName, toUniqueName, isJsirFileName, toJsirFileName,
14
- getAlias, wrapperJsirText, eia, getKeyTips, getValTips, getRoomsDir
14
+ getAlias, wrapperJsirText, eia, getKeyTips, getValTips, getJsirTypeKey
15
15
  } = $lib;
16
16
  const _args = process.argv.slice(2).map(trim);
17
17
  const evalCode = require('../deps/evalCode')
@@ -437,9 +437,10 @@ async function save(args) {
437
437
  return
438
438
  }
439
439
  let resp;
440
- if (args[0].startsWith(setting.exeKey)) {
440
+ let typeKey = getJsirTypeKey(args[0]);
441
+ if (typeKey === setting.exeKey) {
441
442
  resp = example.exeFile;
442
- } else if (args[0].startsWith(setting.initKey)) {
443
+ } else if (typeKey === setting.initKey) {
443
444
  resp = example.initFile;
444
445
  } else {
445
446
  resp = await getCbText();
@@ -498,8 +499,8 @@ function listCmd(tmpMap) {
498
499
  a = parseUniqueName(a)[1];
499
500
  b = parseUniqueName(b)[1];
500
501
  let typeKeys = Object.keys(_types);
501
- let orderA = typeKeys.indexOf(a.split(/\s+/)[0]);
502
- let orderB = typeKeys.indexOf(b.split(/\s+/)[0]);
502
+ let orderA = typeKeys.indexOf(getJsirTypeKey(a));
503
+ let orderB = typeKeys.indexOf(getJsirTypeKey(b));
503
504
  orderA = orderA === -1 ? 999999:orderA;
504
505
  orderB = orderB === -1 ? 999999:orderB;
505
506
  return orderA - orderB
@@ -521,7 +522,7 @@ function listCmd(tmpMap) {
521
522
  let item = {
522
523
  key: ' ' + i,
523
524
  name: pair[0] + '/' + name,
524
- type: [_types[name.substring(0, 1)] || setting.defaultType, suffix].map(trim).join(".")
525
+ type: [_types[getJsirTypeKey(name)] || setting.defaultType, suffix].map(trim).join(".")
525
526
  }
526
527
  items.push(item)
527
528
 
@@ -620,7 +621,7 @@ async function _wrapperInput(str) {
620
621
  let path = getFullPath(_cmdMap[strs[0]])
621
622
  let uniqueName = trim(_cmdMap[strs[0]]);
622
623
  let fileName = parseUniqueName(uniqueName)[1]
623
- let firstName = fileName.substring(0, 1)
624
+ let firstName = getJsirTypeKey(fileName)
624
625
  if (firstName === setting.fileKey) {
625
626
  await workFile(uniqueName)
626
627
  } else if (firstName !== setting.exeKey) {
@@ -964,6 +965,41 @@ let compareMode = {
964
965
  }
965
966
  }
966
967
 
968
+ async function showRooms() {
969
+ let results = [];
970
+ for (let i = 0; i < setting.rooms.length; i++) {
971
+ let room = setting.rooms[i]
972
+ let isLocal = setting.selfRoom.selfNode === room.selfNode;
973
+ results.push({
974
+ mid: i,
975
+ name: (isLocal ? "*" : " ") + room.name,
976
+ node: room.selfNode,
977
+ active: room.active,
978
+ })
979
+ for (let key of Object.keys(room.jsirs)) {
980
+ let jsir = room.jsirs[key]
981
+ results.push({
982
+ mid: i,
983
+ name: (isLocal ? "*" : " ") + room.name,
984
+ node: room.selfNode,
985
+ active: room.active,
986
+ pid: (process.pid === jsir.pid ? "*" : " ") + jsir.pid,
987
+ space: jsir.space,
988
+ running: jsir.active,
989
+ port: jsir.port,
990
+ back: jsir.back,
991
+ busy: jsir.busy,
992
+ tips: Object.keys(jsir.tips).map(i => i + ': ' + jsir.tips[i]).join('\n')
993
+ });
994
+ }
995
+ }
996
+ if (results.length > 0) {
997
+ console.nable(results)
998
+ } else {
999
+ console.warn("no items")
1000
+ }
1001
+ }
1002
+
967
1003
  const keywordDef = {
968
1004
  help: {
969
1005
  comment: 'Help documentation',
@@ -1404,39 +1440,17 @@ const keywordDef = {
1404
1440
  short: 'D'
1405
1441
  },
1406
1442
  room: {
1407
- comment: 'manage room',
1443
+ comment: 'manage room ([node])',
1408
1444
  exeFn: async (args) => {
1409
- let results = [];
1410
1445
  await room.syncSetting();
1411
- for (let i = 0; i < setting.rooms.length; i++) {
1412
- let room = setting.rooms[i]
1413
- results.push({
1414
- mid: i,
1415
- name: (room.local ? "*":" ") + room.name,
1416
- node: room.selfNode,
1417
- active: room.active,
1418
- })
1419
- for (let key of Object.keys(room.jsirs)) {
1420
- let jsir = room.jsirs[key]
1421
- results.push({
1422
- mid: i,
1423
- name: (room.local ? "*":"") + room.name,
1424
- node: room.selfNode,
1425
- active: room.active,
1426
- pid: (process.pid === jsir.pid ? "*":" ") + jsir.pid,
1427
- space: jsir.space,
1428
- running: jsir.active,
1429
- port: jsir.port,
1430
- back: jsir.back,
1431
- busy: jsir.busy,
1432
- tips: Object.keys(jsir.tips).map(i => i + ': ' + jsir.tips[i]).join('\n')
1433
- });
1446
+ if (args[0]) {
1447
+ if (setting.selfRoom.nodes.indexOf(args[0]) !== -1) {
1448
+ await eia("ssh", [args[0]])
1449
+ } else {
1450
+ console.warn("invalid node")
1434
1451
  }
1435
- }
1436
- if (results.length > 0) {
1437
- console.nable(results)
1438
1452
  } else {
1439
- console.warn("no items")
1453
+ await showRooms();
1440
1454
  }
1441
1455
  },
1442
1456
  short: 'm'
@@ -1450,7 +1464,7 @@ function getQuickRunCmds(input, matchStr) {
1450
1464
  } else if (input.startsWith("/")) {
1451
1465
  matchStr = '/' + matchStr;
1452
1466
  }
1453
- return filterCmd(matchStr).filter(i => parseUniqueName(i)[1].startsWith(setting.exeKey))
1467
+ return filterCmd(matchStr).filter(i => getJsirTypeKey(parseUniqueName(i)[1]) === setting.exeKey)
1454
1468
  }
1455
1469
 
1456
1470
  async function preLoad(text, fnNameMatch, fn, packages = [], space) {
@@ -1963,7 +1977,7 @@ function parseArgDef(inputString) {
1963
1977
  }
1964
1978
 
1965
1979
  function getArgDef(text, uniqueName) {
1966
- if (uniqueName && !parseUniqueName(uniqueName)[1].startsWith(setting.exeKey)) {
1980
+ if (uniqueName && getJsirTypeKey(parseUniqueName(uniqueName)[1]) !== setting.exeKey) {
1967
1981
  return {}
1968
1982
  }
1969
1983
  if (text.indexOf("$defArgs") === -1) {
@@ -2025,7 +2039,7 @@ function filterRequire(currSpace, cmdMatchStr) {
2025
2039
  cmds = cmds.filter(cmd => parseUniqueName(cmd)[0] === (appointSpace || currSpace))
2026
2040
  }
2027
2041
  if (cmds.length > 0) {
2028
- cmds = cmds.filter(cmd => parseUniqueName(cmd)[1].startsWith(setting.initKey))
2042
+ cmds = cmds.filter(cmd => getJsirTypeKey(parseUniqueName(cmd)[1]) === setting.initKey)
2029
2043
  }
2030
2044
  }
2031
2045
  if (cmds.length > 1) {
@@ -2042,9 +2056,10 @@ async function _requireSource(currSpace, cmdMatchStr) {
2042
2056
  let path = getFullPath(uniqueName)
2043
2057
  let text = String(await fp.readFile(path))
2044
2058
  let pair = parseUniqueName(uniqueName)
2045
- if (pair[1].startsWith(setting.initKey)) {
2059
+ let typeKey = getJsirTypeKey(pair[1]);
2060
+ if (typeKey === setting.initKey) {
2046
2061
  result = await evalText(text, uniqueName)
2047
- } else if (pair[1].startsWith(setting.exeKey)) {
2062
+ } else if (typeKey === setting.exeKey) {
2048
2063
  result = async (argsStr) => {
2049
2064
  return await runCmd(trim(argsStr), uniqueName, text)
2050
2065
  }
package/deps/room.js CHANGED
@@ -1,7 +1,9 @@
1
1
  const os = require('os');
2
2
  const {fileJson, fileLock, vl, createConsole, getKeyTips, getValTips,
3
- getRoomsDir, e, regEach} = require('./util');
4
- const {setRoute} = require('../deps/server')
3
+ getRoomsDir, e, regEach, isRunningInBackground,
4
+ batchAsync
5
+ } = require('./util');
6
+ const {setRoute, createSign} = require('../deps/server')
5
7
  const roomDataFile = "jsirRoom.json"
6
8
  const roomsDirLockKey = "RW_" + getRoomsDir();
7
9
  const syncRoomsLockKey = "SyncRooms_" + getRoomsDir();
@@ -71,7 +73,6 @@ function getSelfIP(nodes) {
71
73
  }
72
74
 
73
75
  async function getTailscaleNodes() {
74
- console.$log("getNodes")
75
76
  let resp = await e(`${tailscalePath} status`);
76
77
  let nodes = []
77
78
  regEach(resp, /^(\d+\.\d+\.\d+\.\d+)\s+/mg, arr => {
@@ -94,28 +95,36 @@ async function enrichRoomInfo() {
94
95
  room.nodes = nodes;
95
96
  room.lastUpdateTime = Date.now()
96
97
  console.$log("init room", room.name)
98
+
99
+ // 提前设置一下
100
+ setting.selfRoom = Object.assign(setting.selfRoom || {}, room);
97
101
  })
98
102
  }
99
103
 
100
104
  async function syncRooms() {
101
- console.$log('syncRooms')
102
105
  let roomsDir = getRoomsDir();
103
106
  let room = await fileJson(roomDataFile)
104
107
 
105
108
  let syncRooms = []
109
+ let fns = []
106
110
  for (let node of room.nodes) {
107
111
  if (node === room.selfNode) {
108
112
  continue
109
113
  }
110
- try {
111
- let respBody = await reqNode(node, "get", "/");
112
- syncRooms.push(JSON.parse(respBody))
113
- } catch (e) {
114
- console.$log(`sync ${node} failed`, e);
115
- }
114
+ fns.push(async () => {
115
+ let respBody = ''
116
+ try {
117
+ respBody = await reqNode(node, "get", "/");
118
+ syncRooms.push(JSON.parse(respBody))
119
+ console.$log(`sync ${node} success`);
120
+ } catch (e) {
121
+ console.$log(`sync ${node} failed:`, respBody, e);
122
+ }
123
+ })
116
124
  }
125
+ await batchAsync(fns, 9, 3000);
117
126
  await fileLock(roomsDirLockKey, async () => {
118
- for (let syncRoom of syncRooms) {
127
+ for (let syncRoom of [...syncRooms]) {
119
128
  if (syncRoom.selfNode) {
120
129
  await fp.writeFile(roomsDir + "/" + syncRoom.selfNode, JSON.stringify(syncRoom, null, 2))
121
130
  }
@@ -134,6 +143,7 @@ async function syncRooms() {
134
143
  }
135
144
  }
136
145
  }
146
+ console.$log('syncRooms done')
137
147
  }
138
148
 
139
149
  async function syncSetting() {
@@ -143,7 +153,6 @@ async function syncSetting() {
143
153
 
144
154
  async function _syncSetting(room) {
145
155
  setting.selfRoom = room;
146
- setting.selfRoom.local = true;
147
156
  let roomDir = getRoomsDir();
148
157
  let rooms = []
149
158
  let files = await fp.readdir(roomDir);
@@ -184,7 +193,7 @@ async function initRoom() {
184
193
 
185
194
  if (roomUpdateTouchTime) {
186
195
  await fileLock(enrichRoomInfoLockKey, enrichRoomInfo, false)
187
- await fileLock(syncRoomsLockKey, syncRooms, false);
196
+ fileLock(syncRoomsLockKey, syncRooms, false);
188
197
  }
189
198
 
190
199
  await syncSetting();
@@ -216,11 +225,6 @@ async function initRoomJsir(room) {
216
225
  lastUpdateTime: Date.now(),
217
226
  port: setting.server ? setting.server.address().port:null
218
227
  }
219
- console.$log("init jsir", process.pid)
220
- }
221
-
222
- function isRunningInBackground() {
223
- return !(process.stdout.isTTY && process.stdin.isTTY);
224
228
  }
225
229
 
226
230
  /**
@@ -295,12 +299,18 @@ function checkPortOpen(ip, port) {
295
299
  });
296
300
  }
297
301
 
302
+ function isDisableConnect(node, port) {
303
+ let disableTime = setting.disableConnect[node + ":" + port] || 0;
304
+ return disableTime > Date.now()
305
+ }
306
+
298
307
  async function reqNode(node, method, url) {
299
308
  let port = 52108;
300
309
  let room = setting.rooms.filter(i => i.selfNode === node)[0]
301
310
  if (room) {
302
311
  let activeJsir = Object.values(room.jsirs)
303
- .filter(i => i.active).sort((a,b) => a.busy - b.busy);
312
+ .filter(i => !isDisableConnect(node, i.port))
313
+ .sort((a,b) => a.busy - b.busy);
304
314
  if (activeJsir.length > 0) {
305
315
  port = activeJsir[0].port;
306
316
  }
@@ -310,6 +320,9 @@ async function reqNode(node, method, url) {
310
320
  port: port, // HTTP 默认端口
311
321
  path: url,
312
322
  method: method.toUpperCase(),
323
+ headers: {
324
+ 'sign': createSign()
325
+ }
313
326
  };
314
327
  console.$log('reqRoom', JSON.stringify(opt))
315
328
  return await new Promise((resolve, reject) => {
@@ -327,6 +340,9 @@ async function reqNode(node, method, url) {
327
340
 
328
341
  // 错误处理
329
342
  req.on('error', (e) => {
343
+ if (room) {
344
+ setting.disableConnect[node + ":" + port] = Date.now() + 9000
345
+ }
330
346
  reject(e)
331
347
  });
332
348
 
package/deps/server.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const http = require('http');
2
- const {createConsole, vl} = require('./util');
2
+ const {createConsole, vl, aesDecipher, md5, aesCipher} = require('./util');
3
3
  const console = createConsole();
4
4
  const setting = require('../deps/setting')
5
5
  // 尝试监听的端口
@@ -8,6 +8,24 @@ const preferredPort = 52108;
8
8
  const routes = {};
9
9
  let invokeStart = false;
10
10
 
11
+ function verifySign(sign) {
12
+ try {
13
+ let key = md5([...setting.selfRoom.nodes].sort().join(":")).substring(0, 16);
14
+ return parseInt(aesDecipher(sign, key), 10); // 假设sign是base64编码的毫秒数
15
+ } catch (e) {
16
+ return null; // 解码失败返回null
17
+ }
18
+ }
19
+
20
+ function createSign() {
21
+ try {
22
+ let key = md5([...setting.selfRoom.nodes].sort().join(":")).substring(0, 16);
23
+ return aesCipher(String(Date.now()), key)
24
+ } catch (e) {
25
+ return null; // 解码失败返回null
26
+ }
27
+ }
28
+
11
29
  // 创建一个 HTTP 服务
12
30
  async function createServer(port) {
13
31
  const server = http.createServer(async (req, res) => {
@@ -17,6 +35,26 @@ async function createServer(port) {
17
35
  // 查找对应的路由处理函数
18
36
  const routeKey = `${method} ${url}`;
19
37
  if (routes[routeKey]) {
38
+ // 取header里的sign字段
39
+ const sign = req.headers['sign'];
40
+ if (sign) {
41
+ const decodedTime = verifySign(sign);
42
+ const currentTime = Date.now();
43
+
44
+ if (decodedTime === null || Math.abs(currentTime - decodedTime) > 3000) {
45
+ // 解码失败或者时间差大于9秒,返回403
46
+ res.writeHead(403, { 'Content-Type': 'text/plain' });
47
+ res.end('Forbidden: Invalid Sign\n');
48
+ return;
49
+ }
50
+ } else {
51
+ // 如果没有sign字段,返回403
52
+ res.writeHead(403, { 'Content-Type': 'text/plain' });
53
+ res.end('Forbidden: Missing Sign\n');
54
+ return;
55
+ }
56
+
57
+ // 如果签名通过,继续处理请求
20
58
  await routes[routeKey](req, res);
21
59
  } else {
22
60
  res.writeHead(404, { 'Content-Type': 'text/plain' });
@@ -107,5 +145,6 @@ function jsonHandle(req, res, fn) {
107
145
  module.exports = {
108
146
  setRoute,
109
147
  delRoute,
110
- jsonHandle
148
+ jsonHandle,
149
+ createSign
111
150
  };
package/deps/setting.js CHANGED
@@ -26,5 +26,6 @@ module.exports = {
26
26
  roomTid: [],
27
27
  selfRoom: {},
28
28
  rooms: [],
29
- server: null
29
+ server: null,
30
+ disableConnect: {}
30
31
  }
package/deps/util.js CHANGED
@@ -14,6 +14,7 @@ const initModulePaths = Object.assign([], module.paths)
14
14
  const path = require('path')
15
15
  const _types = setting.fileType
16
16
  const _typeKeys = Object.keys(_types)
17
+ const util = require('util')
17
18
 
18
19
  global.$newInput = false
19
20
  global.$newError = false
@@ -26,6 +27,37 @@ let configDir;
26
27
  let roomsDir;
27
28
  let dataDir;
28
29
 
30
+
31
+ function isRunningInBackground() {
32
+ return !(process.stdout.isTTY && process.stdin.isTTY);
33
+ }
34
+
35
+ /**
36
+ * 模拟 console.log 的输出字符串,返回打印的完整字符串
37
+ * @param {...any} args - 传入的参数
38
+ * @returns {string} - 返回最终打印的完整字符串
39
+ */
40
+ function consoleStrs(...args) {
41
+ // 如果没有参数,返回空字符串
42
+ if (args.length === 0) {
43
+ return '';
44
+ }
45
+
46
+ // 格式化第一个参数
47
+ if (typeof args[0] === 'string') {
48
+ return util.format(...args); // 处理格式化字符串 (%s, %d 等)
49
+ }
50
+
51
+ // 如果第一个参数不是字符串,直接用空格拼接其他参数的字符串化结果
52
+ return args
53
+ .map((arg) =>
54
+ typeof arg !== 'string'
55
+ ? util.inspect(arg, { depth: 2, colors: true }) // 对象序列化
56
+ : String(arg) // 其他类型转为字符串
57
+ )
58
+ .join(' ');
59
+ }
60
+
29
61
  class SyncQueue {
30
62
  constructor() {
31
63
  this.queue = [];
@@ -135,15 +167,15 @@ function dealLevelArgs(levelStrFn, args) {
135
167
  if (args.length <= 0) {
136
168
  return args;
137
169
  }
138
- if (typeof args[0] !== 'string') {
139
- return args;
140
- }
141
- let ss = args[0].split("\n");
142
- if (ss[0]) {
143
- ss[0] = levelStrFn(ss[0])
170
+ let text = consoleStrs(...args)
171
+ if (typeof args[0] === "string" && args[0].trim() && text.startsWith(args[0])) {
172
+ if(text.length === args[0].length) {
173
+ text = levelStrFn(args[0])
174
+ } else {
175
+ text = levelStrFn(args[0]) + ' ' + consoleStrs(...args.slice(1))
176
+ }
144
177
  }
145
- args[0] = ss.join("\n");
146
- return args
178
+ return text;
147
179
  }
148
180
 
149
181
  const _console =Object.assign({}, global.console);
@@ -162,23 +194,23 @@ const _consoleFns= {
162
194
  },
163
195
  info: {
164
196
  fn: _console.info,
165
- args: args => [infoStr('[info]'), ...dealLevelArgs(infoStr, args)]
197
+ args: args => [infoStr('[info]'), dealLevelArgs(infoStr, args)]
166
198
  },
167
199
  msg: {
168
200
  fn: _console.log,
169
- args: args => [msgStr('[msg]'), ...dealLevelArgs(msgStr, args)]
201
+ args: args => [msgStr('[msg]'), dealLevelArgs(msgStr, args)]
170
202
  },
171
203
  warn: {
172
204
  fn: _console.warn,
173
- args: args => [warnStr('[warn]'), ...dealLevelArgs(warnStr, args)],
205
+ args: args => [warnStr('[warn]'), dealLevelArgs(warnStr, args)],
174
206
  },
175
207
  error: {
176
208
  fn: _console.error,
177
- args: args => [errorStr('[error]'), ...dealLevelArgs(errorStr, args)]
209
+ args: args => [errorStr('[error]'), dealLevelArgs(errorStr, args)]
178
210
  },
179
211
  debug: {
180
212
  fn: _console.debug,
181
- args: args => [debugStr('[debug]'), ...dealLevelArgs(debugStr, args)]
213
+ args: args => [debugStr('[debug]'), dealLevelArgs(debugStr, args)]
182
214
  }
183
215
  }
184
216
 
@@ -224,7 +256,7 @@ function createConsole(uniqueName) {
224
256
  if ('debug' === key && !global.$DEBUG) {
225
257
  return;
226
258
  }
227
- if (uniqueName && quite) {
259
+ if (isRunningInBackground() || (uniqueName && quite)) {
228
260
  if ((key === 'table' || key === 'nable') && typeof args[0] === "object") {
229
261
  args = ['', ...args]
230
262
  }
@@ -660,16 +692,15 @@ function createLimitLogger(fileName, {
660
692
  if (args.length <= 0) {
661
693
  return
662
694
  }
663
- // 处理参数
664
- args = args.map(i => isError(i) ? errorStack(i):i);
665
695
 
666
696
  // 处理同步函数
667
697
  syncLogs.forEach(i => i(...args));
668
698
 
669
- let text = args.join(" ")
699
+ let text = consoleStrs(...args)
670
700
  if (error) {
671
701
  global.$newError = true;
672
702
  }
703
+ text = `${pad(3, String(process.pid%1000), ' ')}> ${text}`
673
704
  if (time) {
674
705
  text = `${timeStr('YYYY-MM-DD HH:mm:ss.SSS')} ${text}`
675
706
  }
@@ -700,10 +731,10 @@ function getInitName(fileName) {
700
731
  fileName = trim(fileName)
701
732
  let homeDir = setting.workspaceMap[setting.defaultSpace]
702
733
  if (!fileName.startsWith("/")) {
703
- fileName = setting.initKey + ' ' + fileName.replace(new RegExp(`^${setting.initKey}\\s+`), '')
704
- if (!/\..+/.test(fileName)) {
705
- fileName = fileName + '.js'
734
+ if (getJsirTypeKey(fileName) !== setting.initKey) {
735
+ fileName = setting.initKey + ' ' + fileName
706
736
  }
737
+ fileName = toJsirFileName(fileName)
707
738
  fileName = homeDir + '/' + fileName
708
739
  }
709
740
  return fileName;
@@ -768,7 +799,7 @@ async function fileJson(key, fn = null, fmt = true, safeMs = 49000) {
768
799
  let fileName = trim(key)
769
800
  let path = dataDir + "/" + fileName;
770
801
  let homeDir = setting.workspaceMap[setting.defaultSpace]
771
- let isInit = fileName.startsWith(setting.initKey);
802
+ let isInit = getJsirTypeKey(fileName) === setting.initKey;
772
803
  if (isInit) {
773
804
  path = homeDir + '/' + toJsirFileName(fileName);
774
805
  }
@@ -868,7 +899,7 @@ function aesCipher(str, key){
868
899
  const cipher = crypto.createCipheriv('aes-128-ecb', pad(key, 16, '0'), null);
869
900
  return cipher.update(str, 'utf8', 'hex') + cipher.final('hex');
870
901
  } catch(err) {
871
- $error(err)
902
+ $log(err)
872
903
  throw 'aesCipher failed: ' + String(err)
873
904
  }
874
905
  }
@@ -885,7 +916,7 @@ function aesDecipher(str, key){
885
916
  const decipher = crypto.createDecipheriv('aes-128-ecb', pad(key, 16, '0'), null);
886
917
  return decipher.update(str, 'hex', 'utf8') + decipher.final('utf8');
887
918
  } catch(err) {
888
- $error(err)
919
+ $log(err)
889
920
  throw 'aesDecipher failed: ' + String(err)
890
921
  }
891
922
  }
@@ -1813,7 +1844,7 @@ function md5(message) {
1813
1844
  return crypto.createHash('md5').update(message).digest('hex');
1814
1845
  }
1815
1846
 
1816
- async function batchAsync(fns = [], asyncNum = 1) {
1847
+ async function batchAsync(fns = [], asyncNum = 1, limitMs = 9000) {
1817
1848
  if (fns.length <= 0 || asyncNum < 1) {
1818
1849
  return []
1819
1850
  }
@@ -1823,9 +1854,9 @@ async function batchAsync(fns = [], asyncNum = 1) {
1823
1854
  for(let i = 0; i< fns.length; i++) {
1824
1855
  let pro = new Promise(async (resolve, reject) => {
1825
1856
  try {
1826
- let resp = await fns[i]();
1857
+ let resp = await timeLimit([fns[i]()], limitMs);
1827
1858
  doneMap[i] = pro;
1828
- resolve(resp)
1859
+ resolve(resp[0])
1829
1860
  } catch (e) {
1830
1861
  doneMap[i] = pro;
1831
1862
  resolve(isError(e) ? e:new Error(e));
@@ -1931,8 +1962,8 @@ function getTextComments(text) {
1931
1962
 
1932
1963
  function wrapperJsirText(text) {
1933
1964
  return text
1934
- .replace(/^require\s*\(\s*(["'`][ei]\s+)/mg, 'await $require($2')
1935
- .replace(/([\s=;])require\s*\(\s*(["'`][ei]\s+)/g, '$1await $require($2')
1965
+ .replace(/^require\s*\(\s*(["'`][ei][^a-zA-Z]+)/mg, 'await $require($2')
1966
+ .replace(/([\s=;])require\s*\(\s*(["'`][ei][^a-zA-Z]+)/g, '$1await $require($2')
1936
1967
  .replace(/([\s=;])import\s*\(/g, '$1$import(')
1937
1968
  .replace(/^import\s*\(/mg, '$import(')
1938
1969
  .replace(/^module\.exports\s*=\s*/m, 'return ')
@@ -1980,6 +2011,10 @@ function getValTips() {
1980
2011
  return items
1981
2012
  }
1982
2013
 
2014
+ function getJsirTypeKey(fileName) {
2015
+ return fileName.split(/[^a-zA-Z]+/)[0] || ''
2016
+ }
2017
+
1983
2018
  module.exports = {
1984
2019
  wrapperJsirText,
1985
2020
  run,
@@ -2084,5 +2119,7 @@ module.exports = {
2084
2119
  getKeyTips,
2085
2120
  getValTips,
2086
2121
  getRoomsDir,
2087
- getDataDir
2122
+ getDataDir,
2123
+ getJsirTypeKey,
2124
+ isRunningInBackground
2088
2125
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsir",
3
- "version": "2.3.8",
3
+ "version": "2.3.9",
4
4
  "description": "JavaScript Script Management Tool",
5
5
  "main": "index.js",
6
6
  "scripts": {