jsir 2.4.6 → 2.4.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
@@ -674,6 +674,9 @@ async function joinServer(uniqueName) {
674
674
  let pair = parseUniqueName(uniqueName)
675
675
  for (let key of Object.keys(exportLib)) {
676
676
  let val = exportLib[key];
677
+ Server.setRoute('get', `/${pair[0]}/${trimJsirFileName(pair[1])}/${key}`,async (req, res) => {
678
+ res.result = await val(...req);
679
+ })
677
680
  Server.setRoute('post', `/${pair[0]}/${trimJsirFileName(pair[1])}/${key}`,async (req, res) => {
678
681
  res.result = await val(...req);
679
682
  })
@@ -1031,7 +1034,6 @@ async function showRooms() {
1031
1034
  let room = setting.rooms[i]
1032
1035
  let isLocal = setting.selfRoom.selfNode === room.selfNode;
1033
1036
  results.push({
1034
- mid: i,
1035
1037
  name: (isLocal ? "*" : " ") + room.name,
1036
1038
  node: room.selfNode,
1037
1039
  active: room.active,
@@ -1040,17 +1042,18 @@ async function showRooms() {
1040
1042
  let jsir = room.jsirs[key]
1041
1043
  let pidStr = (process.pid === jsir.pid ? "*" : " ") + jsir.pid;
1042
1044
  results.push({
1043
- mid: i,
1044
1045
  name: (isLocal ? "*" : " ") + room.name,
1045
1046
  node: room.selfNode,
1046
1047
  active: room.active,
1047
1048
  pid: jsir.newError ? errorStr(pidStr):pidStr,
1049
+ up: jsir.upTime || '',
1050
+ version: jsir.version || '',
1048
1051
  space: jsir.space,
1049
1052
  running: jsir.active,
1050
1053
  port: jsir.port,
1051
1054
  back: jsir.back,
1052
1055
  busy: jsir.busy,
1053
- tips: Object.keys(jsir.tips).map(i => i + ': ' + jsir.tips[i]).join('\n'),
1056
+ tips: Object.keys(jsir.tips).map(i => infoStr(i) + ': ' + jsir.tips[i]).join('\n'),
1054
1057
  services: Object.keys(jsir.services || []).map(msgStr).join('\n')
1055
1058
  });
1056
1059
  }
@@ -1484,7 +1487,7 @@ const keywordDef = {
1484
1487
  suffix = 'error'
1485
1488
  }
1486
1489
  if (type.indexOf("t") !== -1) {
1487
- cmdStr = 'less -R +F'
1490
+ cmdStr = 'tail -n 50 -f'
1488
1491
  }
1489
1492
  path = path + '.' + suffix;
1490
1493
  if (!fs.existsSync(path)) {
package/deps/room.js CHANGED
@@ -2,7 +2,7 @@ const os = require('os');
2
2
  const {fileJson, fileLock, vl, createConsole, getKeyTips, getValTips,
3
3
  getRoomsDir, e, regEach, isRunningInBackground,
4
4
  batchAsync, debugStr, trim, getOr, errorTag, warnStr, getConfig, getConfigDir,
5
- fileExist
5
+ fileExist, formatUptime
6
6
  } = require('./util');
7
7
  const {setRoute, createSign} = require('../deps/server')
8
8
  const roomDataFile = "jsirRoom.json"
@@ -17,6 +17,7 @@ const http = require('http');
17
17
  const tailscalePath = os.platform() === 'darwin' ?
18
18
  '/Applications/Tailscale.app/Contents/MacOS/Tailscale':'tailscale';
19
19
  const configMain = getConfig("configMain");
20
+ const packageJson = require("../package.json");
20
21
 
21
22
  function debug(...args) {
22
23
  if (global.$DEBUG) {
@@ -117,19 +118,26 @@ function getSelfIP(nodes) {
117
118
 
118
119
  async function getTailscaleNodes() {
119
120
  let resp = await e(`${tailscalePath} status`);
120
- let nodes = []
121
- regEach(resp, /^(\d+\.\d+\.\d+\.\d+)\s+/mg, arr => {
122
- nodes.push(arr[1])
123
- });
124
- return [...new Set(nodes)];
121
+ let nodes = {}
122
+ for (let line of resp.split("\n").map(trim)) {
123
+ if (line.indexOf('offline') !== -1) {
124
+ continue
125
+ }
126
+ let ss = line.split(/\s+/);
127
+ if (/^\d+\.\d+\.\d+\.\d+$/.test(ss[0])) {
128
+ nodes[ss[0]] = ss[1]
129
+ }
130
+ }
131
+ return nodes;
125
132
  }
126
133
 
127
134
  async function updateRoomInfo() {
128
- let nodes = await getTailscaleNodes();
135
+ let nodeMap = await getTailscaleNodes();
136
+ let nodes = Object.keys(nodeMap)
129
137
  let ip = getSelfIP(nodes)
130
138
  await fileJson(roomDataFile, async room => {
131
139
  // 设置roomName
132
- let name = os.hostname();
140
+ let name = nodeMap[ip] || os.hostname();
133
141
  if (!vl(room.name) || room.name !== name) {
134
142
  room.name = name;
135
143
  debug("set roomName", name)
@@ -315,7 +323,7 @@ async function cleanRoom(room) {
315
323
  for (let pid of Object.keys(room.jsirs || {})) {
316
324
  let jsir = room.jsirs[pid]
317
325
  let active = Date.now() - (jsir.lastUpdateTime || 0) <= setting.roomHeartbeatExpire;
318
- if (!active && isPidAlive(pid)) {
326
+ if (jsir.back && !active && isPidAlive(pid)) {
319
327
  try {
320
328
  debug(`kill inactive jsir ${pid}`)
321
329
  process.kill(parseInt(pid), 'SIGKILL'); // 强制终止进程
@@ -371,7 +379,9 @@ async function initRoomJsir(room) {
371
379
  lastUpdateTime: Date.now(),
372
380
  port: setting.server ? setting.server.address().port:null,
373
381
  services: services,
374
- newError: global.$newError
382
+ newError: global.$newError,
383
+ version: packageJson.version,
384
+ upTime: formatUptime()
375
385
  }
376
386
  }
377
387
 
@@ -523,6 +533,5 @@ module.exports = {
523
533
  offRoom,
524
534
  syncSetting,
525
535
  reqNode,
526
- reqFn,
527
- localConfigs
536
+ reqFn
528
537
  }
package/deps/server.js CHANGED
@@ -7,6 +7,7 @@ const preferredPort = setting.defaultPort;
7
7
  // 路由存储
8
8
  const routes = setting.routes;
9
9
  let invokeStart = false;
10
+ const apiReg = /[^a-zA-Z]api[^a-zA-Z]|[^a-zA-Z]api$/i;
10
11
 
11
12
  function debug(...args) {
12
13
  if (global.$DEBUG) {
@@ -36,7 +37,15 @@ function createSign() {
36
37
  async function createServer(port) {
37
38
  const server = http.createServer(async (req, res) => {
38
39
  const method = req.method.toLowerCase();
39
- const url = decodeURI(req.url);
40
+ const originUrl = decodeURI(req.url);
41
+
42
+ let url = originUrl;
43
+ let params = '[]'
44
+ let sepIndex = originUrl.indexOf("?");
45
+ if (sepIndex !== -1) {
46
+ url = originUrl.substring(0, sepIndex).trim()
47
+ params = JSON.stringify([...new URLSearchParams(originUrl.substring(sepIndex).trim()).values()]);
48
+ }
40
49
 
41
50
  // 获取客户端的 IP 地址
42
51
  const clientIp = req.socket.remoteAddress || req.connection.remoteAddress;
@@ -45,22 +54,25 @@ async function createServer(port) {
45
54
  debug(`Received ${routeKey} from ${clientIp}`);
46
55
 
47
56
  if (routes[routeKey]) {
48
- // 取header里的sign字段
49
- const sign = req.headers['sign'];
50
- if (sign) {
51
- const decodedTime = verifySign(sign);
52
- const currentTime = Date.now();
57
+ if (!apiReg.test(routeKey)) {
58
+ // 如果不是api接口,则校验签名
59
+ // 取header里的sign字段
60
+ const sign = req.headers['sign'];
61
+ if (sign) {
62
+ const decodedTime = verifySign(sign);
63
+ const currentTime = Date.now();
53
64
 
54
- if (decodedTime === null || Math.abs(currentTime - decodedTime) > setting.serverSignExpire) {
65
+ if (decodedTime === null || Math.abs(currentTime - decodedTime) > setting.serverSignExpire) {
66
+ res.writeHead(403, { 'Content-Type': 'text/plain' });
67
+ res.end('Forbidden: Invalid Sign');
68
+ return;
69
+ }
70
+ } else {
71
+ // 如果没有sign字段,返回403
55
72
  res.writeHead(403, { 'Content-Type': 'text/plain' });
56
- res.end('Forbidden: Invalid Sign');
73
+ res.end('Forbidden: Missing Sign');
57
74
  return;
58
75
  }
59
- } else {
60
- // 如果没有sign字段,返回403
61
- res.writeHead(403, { 'Content-Type': 'text/plain' });
62
- res.end('Forbidden: Missing Sign');
63
- return;
64
76
  }
65
77
  // 如果签名通过,继续处理请求
66
78
  try {
@@ -77,7 +89,7 @@ async function createServer(port) {
77
89
  resolve()
78
90
  })
79
91
  })
80
- await routes[routeKey](body, res);
92
+ await routes[routeKey](body || params, res);
81
93
  } catch (e) {
82
94
  res.writeHead(500, { 'Content-Type': 'text/plain' });
83
95
  res.end(String(isError(e) ? e.message:e));
package/deps/util.js CHANGED
@@ -2048,7 +2048,7 @@ function getValTips() {
2048
2048
  }
2049
2049
  return item;
2050
2050
  }).join("|");
2051
- items.push(val)
2051
+ items.push(val || trim(key))
2052
2052
  }
2053
2053
  return items
2054
2054
  }
@@ -2078,7 +2078,7 @@ function interceptStdStreams() {
2078
2078
  if(setting.enterOutputs) {
2079
2079
  setting.enterOutputs.push(chunk.toString());
2080
2080
  } else if (isRunningInBackground()) {
2081
- console.$log(process.pid, "STDOUT", "\n" + chunk.toString().trimEnd());
2081
+ console.$log(process.pid, "stdout", "\n" + chunk.toString().trimEnd());
2082
2082
  } else {
2083
2083
  originalStdoutWrite(chunk, ...args); // 保留原始行为
2084
2084
  }
@@ -2089,14 +2089,34 @@ function interceptStdStreams() {
2089
2089
  if(setting.enterOutputs) {
2090
2090
  setting.enterOutputs.push(chunk.toString());
2091
2091
  } else if (isRunningInBackground()) {
2092
- console.$error(process.pid, errorStr("STDERR"), "\n" + chunk.toString().trimEnd());
2092
+ console.$error(process.pid, errorStr("stderr"), "\n" + chunk.toString().trimEnd());
2093
2093
  } else {
2094
2094
  originalStderrWrite(chunk, ...args); // 保留原始行为
2095
2095
  }
2096
2096
  };
2097
2097
  }
2098
2098
 
2099
+ function formatUptime() {
2100
+ const uptimeSeconds = process.uptime();
2101
+
2102
+ const days = Math.floor(uptimeSeconds / (3600 * 24)); // 计算天数
2103
+ const hours = Math.floor((uptimeSeconds % (3600 * 24)) / 3600); // 计算小时
2104
+ const minutes = Math.floor((uptimeSeconds % 3600) / 60); // 计算分钟
2105
+ const seconds = Math.floor(uptimeSeconds % 60); // 计算秒数
2106
+
2107
+ if (days > 0) {
2108
+ return `${days}d${hours}h`;
2109
+ } else if (hours > 0) {
2110
+ return `${hours}h${minutes}m`;
2111
+ } else if (minutes > 0) {
2112
+ return `${minutes}m${seconds}s`;
2113
+ } else {
2114
+ return `${seconds}s`;
2115
+ }
2116
+ }
2117
+
2099
2118
  module.exports = {
2119
+ formatUptime,
2100
2120
  wrapperJsirText,
2101
2121
  run,
2102
2122
  reget,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsir",
3
- "version": "2.4.6",
3
+ "version": "2.4.9",
4
4
  "description": "JavaScript Script Management Tool",
5
5
  "main": "index.js",
6
6
  "scripts": {