jsir 2.5.0 → 2.5.2
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 +33 -34
- package/deps/room.js +25 -19
- package/deps/server.js +24 -12
- package/deps/setting.js +1 -0
- package/deps/util.js +27 -17
- package/package.json +1 -1
package/cmd/oaa.js
CHANGED
|
@@ -585,8 +585,7 @@ function wrapperAlias(str) {
|
|
|
585
585
|
return str;
|
|
586
586
|
}
|
|
587
587
|
let fstr = str.split(/\s+/)[0];
|
|
588
|
-
|
|
589
|
-
return [fstr, str.substring(fstr.length)].map(trim).filter(i => i).join(' ')
|
|
588
|
+
return [getAlias(aliasMap, fstr), str.substring(fstr.length)].map(trim).filter(i => i).join(' ')
|
|
590
589
|
}
|
|
591
590
|
|
|
592
591
|
async function _wrapperInput(str) {
|
|
@@ -646,7 +645,7 @@ async function _wrapperInput(str) {
|
|
|
646
645
|
if (strs[1] === '-') {
|
|
647
646
|
await offServer(uniqueName)
|
|
648
647
|
} else {
|
|
649
|
-
await joinServer(uniqueName)
|
|
648
|
+
await joinServer(uniqueName, strs[1] === '+')
|
|
650
649
|
}
|
|
651
650
|
} else {
|
|
652
651
|
console.log(String(fs.readFileSync(path)));
|
|
@@ -657,7 +656,7 @@ async function _wrapperInput(str) {
|
|
|
657
656
|
}
|
|
658
657
|
}
|
|
659
658
|
|
|
660
|
-
async function joinServer(uniqueName) {
|
|
659
|
+
async function joinServer(uniqueName, isApi) {
|
|
661
660
|
let exportLib = await _requireSource(setting.defaultSpace, uniqueName, true);
|
|
662
661
|
let asyncFnSize = 0
|
|
663
662
|
for (let key of Object.keys(exportLib)) {
|
|
@@ -676,12 +675,12 @@ async function joinServer(uniqueName) {
|
|
|
676
675
|
let val = exportLib[key];
|
|
677
676
|
Server.setRoute('get', `/${pair[0]}/${trimJsirFileName(pair[1])}/${key}`,async (req, res) => {
|
|
678
677
|
res.result = await val(...req);
|
|
679
|
-
})
|
|
678
|
+
}, isApi)
|
|
680
679
|
Server.setRoute('post', `/${pair[0]}/${trimJsirFileName(pair[1])}/${key}`,async (req, res) => {
|
|
681
680
|
res.result = await val(...req);
|
|
682
|
-
})
|
|
681
|
+
}, isApi)
|
|
683
682
|
}
|
|
684
|
-
console.msg(uniqueName,
|
|
683
|
+
console.msg(uniqueName, `has become a ${isApi ? "api ":""}service.`);
|
|
685
684
|
}
|
|
686
685
|
|
|
687
686
|
async function offServer(uniqueName) {
|
|
@@ -1405,13 +1404,11 @@ const keywordDef = {
|
|
|
1405
1404
|
}
|
|
1406
1405
|
}
|
|
1407
1406
|
let pair = parseUniqueName(keyword)
|
|
1408
|
-
let cmds
|
|
1409
|
-
if (
|
|
1410
|
-
cmds = getQuickRunCmds(keyword,
|
|
1411
|
-
} else {
|
|
1412
|
-
cmds = getQuickRunCmds(keyword, '^e ' + toJsirFileName(pair[1]) + '$')
|
|
1407
|
+
let cmds = getQuickRunCmds(keyword, pair[1])
|
|
1408
|
+
if (cmds.length > 1) {
|
|
1409
|
+
cmds = getQuickRunCmds(keyword, '^' + toJsirFileName(pair[1]) + '$')
|
|
1413
1410
|
if (cmds.length === 0) {
|
|
1414
|
-
cmds = getQuickRunCmds(keyword,
|
|
1411
|
+
cmds = getQuickRunCmds(keyword, '^e[^a-zA-Z]' + toJsirFileName(pair[1]) + '$')
|
|
1415
1412
|
}
|
|
1416
1413
|
}
|
|
1417
1414
|
if (cmds.length === 1) {
|
|
@@ -1421,7 +1418,7 @@ const keywordDef = {
|
|
|
1421
1418
|
await runScript(cmds[0], args.slice(1))
|
|
1422
1419
|
}
|
|
1423
1420
|
} else {
|
|
1424
|
-
console.warn(
|
|
1421
|
+
console.warn(`require "${keyword}" not unique`)
|
|
1425
1422
|
}
|
|
1426
1423
|
},
|
|
1427
1424
|
args: {
|
|
@@ -1635,17 +1632,17 @@ async function _dealKeyword(keyword, args) {
|
|
|
1635
1632
|
if (item.short === shortKey) {
|
|
1636
1633
|
unMatched = false;
|
|
1637
1634
|
if (item === keywordDef.run) {
|
|
1638
|
-
console.$log('
|
|
1635
|
+
console.$log('Execute', key)
|
|
1639
1636
|
await item.exeFn(args);
|
|
1640
1637
|
} else {
|
|
1641
|
-
console.$log('
|
|
1638
|
+
console.$log('Execute', key)
|
|
1642
1639
|
await item.exeFn(args.map(trim));
|
|
1643
1640
|
}
|
|
1644
1641
|
break;
|
|
1645
1642
|
}
|
|
1646
1643
|
}
|
|
1647
1644
|
if (unMatched) {
|
|
1648
|
-
console.$log('
|
|
1645
|
+
console.$log('Execute run', keyword)
|
|
1649
1646
|
await keywordDef.run.exeFn([keyword, ...args])
|
|
1650
1647
|
}
|
|
1651
1648
|
}
|
|
@@ -2135,25 +2132,24 @@ function filterRequire(currSpace, cmdMatchStr) {
|
|
|
2135
2132
|
}
|
|
2136
2133
|
cmdMatchStr = trim(cmdMatchStr);
|
|
2137
2134
|
|
|
2138
|
-
let
|
|
2139
|
-
let
|
|
2140
|
-
let
|
|
2141
|
-
if (
|
|
2142
|
-
cmds = [
|
|
2143
|
-
} else {
|
|
2144
|
-
let appointSpace = parseUniqueName(cmdMatchStr)[0]
|
|
2145
|
-
cmds = filterCmd(cmdMatchStr);
|
|
2146
|
-
if (cmds.length > 0) {
|
|
2147
|
-
cmds = cmds.filter(cmd => parseUniqueName(cmd)[0] === (appointSpace || currSpace))
|
|
2148
|
-
}
|
|
2149
|
-
if (cmds.length > 0) {
|
|
2150
|
-
cmds = cmds.filter(cmd => getJsirTypeKey(parseUniqueName(cmd)[1]) === setting.initKey)
|
|
2151
|
-
}
|
|
2135
|
+
let pair = parseUniqueName(cmdMatchStr);
|
|
2136
|
+
let appointSpace = pair[0] || currSpace;
|
|
2137
|
+
let cmds = filterCmd(appointSpace + '/' + pair[1]);
|
|
2138
|
+
if (cmds.length > 1) {
|
|
2139
|
+
cmds = cmds.filter(cmd => [setting.initKey, setting.exeKey].indexOf(getJsirTypeKey(parseUniqueName(cmd)[1])) !== -1)
|
|
2152
2140
|
}
|
|
2153
2141
|
if (cmds.length > 1) {
|
|
2154
|
-
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2142
|
+
cmds = cmds.filter(cmd => setting.initKey === getJsirTypeKey(parseUniqueName(cmd)[1]))
|
|
2143
|
+
}
|
|
2144
|
+
if (cmds.length > 1) {
|
|
2145
|
+
let jsirFileName = toJsirFileName(pair[1])
|
|
2146
|
+
cmds = filterCmd(appointSpace + '/^' + jsirFileName + "$");
|
|
2147
|
+
if (cmds.length === 0) {
|
|
2148
|
+
cmds = filterCmd(appointSpace + '/^[ei][^a-zA-Z]' + jsirFileName + "$");
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
if (cmds.length !== 1) {
|
|
2152
|
+
throw `require "${cmdMatchStr}" not unique`
|
|
2157
2153
|
}
|
|
2158
2154
|
return cmds[0];
|
|
2159
2155
|
}
|
|
@@ -2217,6 +2213,9 @@ function addErrorTag(text) {
|
|
|
2217
2213
|
}
|
|
2218
2214
|
|
|
2219
2215
|
async function evalText($text = '', $cmdName = '', $args = []) {
|
|
2216
|
+
if ($cmdName) {
|
|
2217
|
+
console.$log(`Execute ${$cmdName}`);
|
|
2218
|
+
}
|
|
2220
2219
|
let currSpace;
|
|
2221
2220
|
if ($cmdName) {
|
|
2222
2221
|
let pair = parseUniqueName($cmdName)
|
package/deps/room.js
CHANGED
|
@@ -54,7 +54,6 @@ async function localConfigs() {
|
|
|
54
54
|
function onRoom(wrapperInput) {
|
|
55
55
|
if (!setting.roomTid[0]) {
|
|
56
56
|
try {
|
|
57
|
-
setRoute("post", "/", (req, res) => setting.selfRoom)
|
|
58
57
|
setRoute("get", "/", (req, res) => setting.selfRoom)
|
|
59
58
|
setRoute("post", "/enter", async (req, res) => {
|
|
60
59
|
if (!getConfig("enableRemote", true)) {
|
|
@@ -71,6 +70,7 @@ function onRoom(wrapperInput) {
|
|
|
71
70
|
let outputs = setting.enterOutputs || [];
|
|
72
71
|
setting.enterOutputs = null;
|
|
73
72
|
res.output = outputs.join('');
|
|
73
|
+
global.$newInput = true;
|
|
74
74
|
}
|
|
75
75
|
})
|
|
76
76
|
if (configMain) {
|
|
@@ -113,44 +113,45 @@ function offRoom() {
|
|
|
113
113
|
function getSelfIP(nodes) {
|
|
114
114
|
let ips = getLocalIPs().ipv4;
|
|
115
115
|
ips = ips.filter(i => nodes.indexOf(i) !== -1);
|
|
116
|
-
return ips[0]
|
|
116
|
+
return ips[0] || '127.0.0.1'
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
async function getTailscaleNodes() {
|
|
120
120
|
let resp = await e(`${tailscalePath} status`);
|
|
121
121
|
let nodes = {}
|
|
122
122
|
for (let line of resp.split("\n").map(trim)) {
|
|
123
|
-
|
|
124
|
-
continue
|
|
125
|
-
}
|
|
123
|
+
let offline = line.indexOf('offline') !== -1
|
|
126
124
|
let ss = line.split(/\s+/);
|
|
127
125
|
if (/^\d+\.\d+\.\d+\.\d+$/.test(ss[0])) {
|
|
128
|
-
nodes[ss[0]] =
|
|
126
|
+
nodes[ss[0]] = {
|
|
127
|
+
name: ss[1],
|
|
128
|
+
offline
|
|
129
|
+
}
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
return nodes;
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
async function updateRoomInfo() {
|
|
135
|
-
|
|
136
|
-
let nodes = Object.keys(nodeMap)
|
|
136
|
+
setting.nodeMap = await getTailscaleNodes();
|
|
137
|
+
let nodes = Object.keys(setting.nodeMap)
|
|
137
138
|
let ip = getSelfIP(nodes)
|
|
138
139
|
await fileJson(roomDataFile, async room => {
|
|
140
|
+
room = {
|
|
141
|
+
jsirs: room.jsirs
|
|
142
|
+
}
|
|
139
143
|
// 设置roomName
|
|
140
|
-
let name = nodeMap[ip] || os.hostname();
|
|
144
|
+
let name = setting.nodeMap[ip]?.name || os.hostname();
|
|
141
145
|
if (!vl(room.name) || room.name !== name) {
|
|
142
146
|
room.name = name;
|
|
143
147
|
debug("set roomName", name)
|
|
144
148
|
}
|
|
145
149
|
room.selfNode = ip;
|
|
146
|
-
room.nodes = nodes;
|
|
147
150
|
room.lastUpdateTime = Date.now()
|
|
148
151
|
debug("init room", room.name)
|
|
149
152
|
|
|
150
|
-
// 提前设置一下
|
|
151
|
-
setting.selfRoom = Object.assign(setting.selfRoom || {}, room);
|
|
152
|
-
|
|
153
153
|
await cleanRoom(room)
|
|
154
|
+
return room;
|
|
154
155
|
})
|
|
155
156
|
}
|
|
156
157
|
|
|
@@ -160,10 +161,13 @@ async function syncRooms() {
|
|
|
160
161
|
|
|
161
162
|
let syncRooms = []
|
|
162
163
|
let fns = []
|
|
163
|
-
for (let node of
|
|
164
|
+
for (let node of Object.keys(setting.nodeMap)) {
|
|
164
165
|
if (node === room.selfNode) {
|
|
165
166
|
continue
|
|
166
167
|
}
|
|
168
|
+
if (setting.nodeMap[node]?.offline) {
|
|
169
|
+
continue
|
|
170
|
+
}
|
|
167
171
|
fns.push(async () => {
|
|
168
172
|
let respBody = ''
|
|
169
173
|
try {
|
|
@@ -195,9 +199,8 @@ async function syncRooms() {
|
|
|
195
199
|
|
|
196
200
|
// 清理 roomsDir
|
|
197
201
|
let files = await fp.readdir(roomsDir)
|
|
198
|
-
let nodes = room.nodes;
|
|
199
202
|
for (let file of files) {
|
|
200
|
-
if (
|
|
203
|
+
if (!setting.nodeMap[file]) {
|
|
201
204
|
try {
|
|
202
205
|
await fp.unlink(roomsDir + '/' + file)
|
|
203
206
|
} catch (e) {
|
|
@@ -218,7 +221,7 @@ async function _syncSetting(room) {
|
|
|
218
221
|
let roomDir = getRoomsDir();
|
|
219
222
|
let rooms = []
|
|
220
223
|
let files = await fp.readdir(roomDir);
|
|
221
|
-
for (let node of setting.
|
|
224
|
+
for (let node of Object.keys(setting.nodeMap)) {
|
|
222
225
|
if (setting.selfRoom.selfNode === node) {
|
|
223
226
|
continue
|
|
224
227
|
}
|
|
@@ -246,6 +249,9 @@ async function _syncSetting(room) {
|
|
|
246
249
|
setting.services = {}
|
|
247
250
|
setting.serviceFns = {}
|
|
248
251
|
for (const room of setting.rooms) {
|
|
252
|
+
if (setting.nodeMap[room.selfNode]?.offline) {
|
|
253
|
+
continue
|
|
254
|
+
}
|
|
249
255
|
for (const pid of Object.keys(room.jsirs || {})) {
|
|
250
256
|
let jsir = room.jsirs[pid];
|
|
251
257
|
for (const service of Object.keys(jsir.services || {})) {
|
|
@@ -280,7 +286,7 @@ async function initRoom() {
|
|
|
280
286
|
if (roomUpdateTouchTime) {
|
|
281
287
|
await fileLock(updateRoomInfoLockKey, updateRoomInfo, false)
|
|
282
288
|
fileLock(syncRoomsLockKey, syncRooms, false);
|
|
283
|
-
if (!configMain && setting.serviceFns
|
|
289
|
+
if (!configMain && setting.serviceFns[setting.configMainFnKey]) {
|
|
284
290
|
fileLock(syncConfigsLockKey, syncConfigs, false);
|
|
285
291
|
}
|
|
286
292
|
}
|
|
@@ -381,7 +387,7 @@ async function initRoomJsir(room) {
|
|
|
381
387
|
busy: await getEventLoopDelay() || (lastJsir ? lastJsir.busy:0),
|
|
382
388
|
back: isRunningInBackground(),
|
|
383
389
|
lastUpdateTime: Date.now(),
|
|
384
|
-
port: setting.server ? setting.server.address()
|
|
390
|
+
port: setting.server ? setting.server.address()?.port:null,
|
|
385
391
|
services: services,
|
|
386
392
|
newError: global.$newError,
|
|
387
393
|
version: packageJson.version,
|
package/deps/server.js
CHANGED
|
@@ -7,7 +7,6 @@ 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;
|
|
11
10
|
|
|
12
11
|
function debug(...args) {
|
|
13
12
|
if (global.$DEBUG) {
|
|
@@ -17,7 +16,7 @@ function debug(...args) {
|
|
|
17
16
|
|
|
18
17
|
function verifySign(sign) {
|
|
19
18
|
try {
|
|
20
|
-
let key = md5(
|
|
19
|
+
let key = md5(Object.keys(setting.nodeMap).sort().join(":")).substring(0, 16);
|
|
21
20
|
return parseInt(aesDecipher(sign, key), 10); // 假设sign是base64编码的毫秒数
|
|
22
21
|
} catch (e) {
|
|
23
22
|
return null; // 解码失败返回null
|
|
@@ -26,16 +25,23 @@ function verifySign(sign) {
|
|
|
26
25
|
|
|
27
26
|
function createSign() {
|
|
28
27
|
try {
|
|
29
|
-
let key = md5(
|
|
28
|
+
let key = md5(Object.keys(setting.nodeMap).sort().join(":")).substring(0, 16);
|
|
30
29
|
return aesCipher(String(Date.now()), key)
|
|
31
30
|
} catch (e) {
|
|
32
31
|
return null; // 解码失败返回null
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
async function process(routeKey, req, res, params) {
|
|
37
|
-
if (
|
|
38
|
-
|
|
35
|
+
async function process(routeKey, req, res, params, clientIp) {
|
|
36
|
+
if (!clientIp.endsWith(":" + setting.selfRoom.selfNode)) {
|
|
37
|
+
res.writeHead(403, {'Content-Type': 'text/plain'});
|
|
38
|
+
res.end('Forbidden: Not Allowed');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let router = routes[routeKey]
|
|
43
|
+
if (router) {
|
|
44
|
+
if ("get /" !== routeKey && !router.isApi) {
|
|
39
45
|
// 如果不是api接口,则校验签名
|
|
40
46
|
// 取header里的sign字段
|
|
41
47
|
const sign = req.headers['sign'];
|
|
@@ -70,7 +76,7 @@ async function process(routeKey, req, res, params) {
|
|
|
70
76
|
resolve()
|
|
71
77
|
})
|
|
72
78
|
})
|
|
73
|
-
await
|
|
79
|
+
await router.fn(body || params, res);
|
|
74
80
|
} catch (e) {
|
|
75
81
|
res.writeHead(500, {'Content-Type': 'text/plain'});
|
|
76
82
|
res.end(String(isError(e) ? e.message : e));
|
|
@@ -101,7 +107,7 @@ async function createServer(port) {
|
|
|
101
107
|
const routeKey = `${method} ${url}`;
|
|
102
108
|
let time = Date.now();
|
|
103
109
|
try {
|
|
104
|
-
await process(routeKey, req, res, params);
|
|
110
|
+
await process(routeKey, req, res, params, clientIp);
|
|
105
111
|
} finally {
|
|
106
112
|
debug(`Process cost ${Date.now() - time}ms for ${routeKey} from ${clientIp}`);
|
|
107
113
|
}
|
|
@@ -140,16 +146,22 @@ async function startServer() {
|
|
|
140
146
|
method, url, fn(req, res, err), null
|
|
141
147
|
err: {code, msg}
|
|
142
148
|
*/
|
|
143
|
-
function setRoute(method, url, fn, handler = jsonHandle) {
|
|
149
|
+
function setRoute(method, url, fn, handler = jsonHandle, isApi) {
|
|
144
150
|
startServer();
|
|
145
151
|
|
|
146
152
|
const routeKey = `${method.toLowerCase()} ${url}`;
|
|
147
153
|
if (handler) {
|
|
148
|
-
routes[routeKey] =
|
|
149
|
-
|
|
154
|
+
routes[routeKey] = {
|
|
155
|
+
fn: async (req, res) => {
|
|
156
|
+
await handler(req, res, fn)
|
|
157
|
+
},
|
|
158
|
+
isApi
|
|
150
159
|
};
|
|
151
160
|
} else {
|
|
152
|
-
routes[routeKey] =
|
|
161
|
+
routes[routeKey] = {
|
|
162
|
+
fn,
|
|
163
|
+
isApi
|
|
164
|
+
};
|
|
153
165
|
}
|
|
154
166
|
debug(`setRoute: ${method.toUpperCase()} ${url} ${handler ? handler.name:''}`);
|
|
155
167
|
return setting.server;
|
package/deps/setting.js
CHANGED
package/deps/util.js
CHANGED
|
@@ -935,21 +935,25 @@ function validStr(str, name) {
|
|
|
935
935
|
}
|
|
936
936
|
}
|
|
937
937
|
|
|
938
|
-
function aesCipher(str, key){
|
|
938
|
+
function aesCipher(str, key, useIv = false){
|
|
939
939
|
validStr(str, "str");
|
|
940
940
|
validStr(key, "key");
|
|
941
941
|
|
|
942
942
|
key = trim(key);
|
|
943
943
|
if (!key || key.length > 16) {
|
|
944
|
-
throw "aesCipher key length should between 1 and 16"
|
|
944
|
+
throw "aesCipher key length should be between 1 and 16"
|
|
945
945
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
946
|
+
if (useIv) {
|
|
947
|
+
// Generate random IV
|
|
948
|
+
const iv = crypto.randomBytes(16);
|
|
949
|
+
const cipher = crypto.createCipheriv('aes-128-cbc', pad(key, 16, '0'), iv);
|
|
950
|
+
|
|
951
|
+
// Return IV and ciphertext, as IV is needed for decryption
|
|
952
|
+
const ciphertext = cipher.update(str, 'utf8', 'hex') + cipher.final('hex');
|
|
953
|
+
return iv.toString('hex') + ':' + ciphertext; // Combine IV and ciphertext
|
|
952
954
|
}
|
|
955
|
+
const cipher = crypto.createCipheriv('aes-128-ecb', pad(key, 16, '0'), null);
|
|
956
|
+
return cipher.update(str, 'utf8', 'hex') + cipher.final('hex');
|
|
953
957
|
}
|
|
954
958
|
|
|
955
959
|
function aesDecipher(str, key){
|
|
@@ -958,15 +962,21 @@ function aesDecipher(str, key){
|
|
|
958
962
|
|
|
959
963
|
key = trim(key);
|
|
960
964
|
if (!key || key.length > 16) {
|
|
961
|
-
throw "aesCipher key length should between 1 and 16"
|
|
965
|
+
throw "aesCipher key length should be between 1 and 16";
|
|
962
966
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
967
|
+
|
|
968
|
+
// Extract IV and ciphertext
|
|
969
|
+
if(str.indexOf(":") !== -1) {
|
|
970
|
+
const [ivHex, ciphertext] = str.split(':');
|
|
971
|
+
if (!ivHex || !ciphertext) {
|
|
972
|
+
throw "Invalid encrypted string format";
|
|
973
|
+
}
|
|
974
|
+
const iv = Buffer.from(ivHex, 'hex');
|
|
975
|
+
const decipher = crypto.createDecipheriv('aes-128-cbc', pad(key, 16, '0'), iv);
|
|
976
|
+
return decipher.update(ciphertext, 'hex', 'utf8') + decipher.final('utf8');
|
|
969
977
|
}
|
|
978
|
+
const decipher = crypto.createDecipheriv('aes-128-ecb', pad(key, 16, '0'), null);
|
|
979
|
+
return decipher.update(str, 'hex', 'utf8') + decipher.final('utf8');
|
|
970
980
|
}
|
|
971
981
|
|
|
972
982
|
function getConfig(key, defaultVal) {
|
|
@@ -2089,7 +2099,7 @@ function interceptStdStreams() {
|
|
|
2089
2099
|
if(setting.enterOutputs) {
|
|
2090
2100
|
setting.enterOutputs.push(chunk.toString());
|
|
2091
2101
|
} else if (isRunningInBackground()) {
|
|
2092
|
-
console.$log(
|
|
2102
|
+
console.$log(chunk.toString().trimEnd());
|
|
2093
2103
|
} else {
|
|
2094
2104
|
originalStdoutWrite(chunk, ...args); // 保留原始行为
|
|
2095
2105
|
}
|
|
@@ -2100,7 +2110,7 @@ function interceptStdStreams() {
|
|
|
2100
2110
|
if(setting.enterOutputs) {
|
|
2101
2111
|
setting.enterOutputs.push(chunk.toString());
|
|
2102
2112
|
} else if (isRunningInBackground()) {
|
|
2103
|
-
console.$error(
|
|
2113
|
+
console.$error(chunk.toString().trimEnd());
|
|
2104
2114
|
} else {
|
|
2105
2115
|
originalStderrWrite(chunk, ...args); // 保留原始行为
|
|
2106
2116
|
}
|