jsir 2.5.6 → 2.5.8
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 +57 -17
- package/deps/room.js +52 -13
- package/deps/server.js +4 -2
- package/deps/setting.js +3 -1
- package/deps/util.js +22 -13
- package/package.json +1 -1
package/cmd/oaa.js
CHANGED
|
@@ -168,10 +168,13 @@ function checkWorkspaces() {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
async function start() {
|
|
171
|
+
setting.wrapperInput = wrapperInput;
|
|
171
172
|
interceptStdStreams()
|
|
172
173
|
checkWorkspaces()
|
|
173
174
|
initWorkspace()
|
|
174
175
|
|
|
176
|
+
await Room.syncSetting();
|
|
177
|
+
|
|
175
178
|
lastFilterArg = getConfig("lastFilterArg");
|
|
176
179
|
_cmdMap = objDataFile(_cmdMapFile);
|
|
177
180
|
if (_args[0]) {
|
|
@@ -657,6 +660,10 @@ async function _wrapperInput(str) {
|
|
|
657
660
|
}
|
|
658
661
|
|
|
659
662
|
async function joinServer(uniqueName, isApi) {
|
|
663
|
+
Room.onRoom();
|
|
664
|
+
if (!setting.serviceReg.test(uniqueName)) {
|
|
665
|
+
throw 'invalid service name';
|
|
666
|
+
}
|
|
660
667
|
let exportLib = await _requireSource(setting.defaultSpace, uniqueName, true);
|
|
661
668
|
let asyncFnSize = 0
|
|
662
669
|
for (let key of Object.keys(exportLib)) {
|
|
@@ -684,6 +691,9 @@ async function joinServer(uniqueName, isApi) {
|
|
|
684
691
|
}
|
|
685
692
|
|
|
686
693
|
async function offServer(uniqueName) {
|
|
694
|
+
if (!setting.serviceReg.test(uniqueName)) {
|
|
695
|
+
throw 'invalid service name';
|
|
696
|
+
}
|
|
687
697
|
let pair = parseUniqueName(uniqueName)
|
|
688
698
|
let service = `${pair[0]}/${trimJsirFileName(pair[1])}`;
|
|
689
699
|
|
|
@@ -714,7 +724,9 @@ async function dealStar(text) {
|
|
|
714
724
|
if (_cmdMap.hasOwnProperty(items[0])) {
|
|
715
725
|
rows.push(...await dealStarCmd([], _cmdMap[items[0]], items.slice(1).join(' ')))
|
|
716
726
|
} else if (items[0].indexOf("/") !== -1) {
|
|
717
|
-
|
|
727
|
+
for (let cmd of filterCmd(items[0])) {
|
|
728
|
+
dealStarCmd(rows, cmd, items.slice(1).join(" "))
|
|
729
|
+
}
|
|
718
730
|
} else {
|
|
719
731
|
try {
|
|
720
732
|
let result = await evalText(`return ${items[0]}`)
|
|
@@ -739,7 +751,7 @@ function dealStarGlobal(items, text) {
|
|
|
739
751
|
prefix = trim(items[0].substring(0, index + 1))
|
|
740
752
|
text = trim(text.substring(index + 1))
|
|
741
753
|
}
|
|
742
|
-
for (let cmd of filterCmd(prefix + '^i
|
|
754
|
+
for (let cmd of filterCmd(prefix + '^i[^a-zA-Z]')) {
|
|
743
755
|
dealStarCmd(rows, cmd, text)
|
|
744
756
|
}
|
|
745
757
|
return rows;
|
|
@@ -1189,7 +1201,22 @@ const keywordDef = {
|
|
|
1189
1201
|
comment: 'Global settings',
|
|
1190
1202
|
exeFn: async (args) => {
|
|
1191
1203
|
if (args[0]) {
|
|
1192
|
-
|
|
1204
|
+
let configMain = getConfig("configMain");
|
|
1205
|
+
if ("+" === args[0]) {
|
|
1206
|
+
if (!configMain) {
|
|
1207
|
+
throw 'Not Allowed';
|
|
1208
|
+
}
|
|
1209
|
+
Server.setRoute("post", "/" + setting.configMainFnKey, async (req, res) => {
|
|
1210
|
+
res.result = await Room.localConfigs();
|
|
1211
|
+
})
|
|
1212
|
+
console.msg("config service online")
|
|
1213
|
+
} else if ("-" === args[0]) {
|
|
1214
|
+
if (!configMain) {
|
|
1215
|
+
throw 'Not Allowed';
|
|
1216
|
+
}
|
|
1217
|
+
delete setting.routes['post /' + setting.configMainFnKey]
|
|
1218
|
+
console.msg("config service offline")
|
|
1219
|
+
} else if (_cmdMap[args[0]]){
|
|
1193
1220
|
let uniqueName = _cmdMap[args[0]];
|
|
1194
1221
|
await eia(getEditor(), [`${getConfigDir()}/${md5(uniqueName)}.json`])
|
|
1195
1222
|
} else {
|
|
@@ -1415,7 +1442,12 @@ const keywordDef = {
|
|
|
1415
1442
|
if (justList) {
|
|
1416
1443
|
listCmd(arrayToCmdMap(cmds))
|
|
1417
1444
|
} else {
|
|
1418
|
-
|
|
1445
|
+
let typeKey = getJsirTypeKey(parseUniqueName(cmds[0])[1]);
|
|
1446
|
+
if (setting.initKey === typeKey) {
|
|
1447
|
+
await joinServer(cmds[0])
|
|
1448
|
+
} else if (setting.exeKey === typeKey) {
|
|
1449
|
+
await runScript(cmds[0], args.slice(1))
|
|
1450
|
+
}
|
|
1419
1451
|
}
|
|
1420
1452
|
} else {
|
|
1421
1453
|
console.warn(`require "${keyword}" not unique`)
|
|
@@ -1467,7 +1499,7 @@ const keywordDef = {
|
|
|
1467
1499
|
log: {
|
|
1468
1500
|
comment: 'View log (type[[lt][le]], index)',
|
|
1469
1501
|
exeFn: async (args) => {
|
|
1470
|
-
let path = `${getLibDataDir()}/log/
|
|
1502
|
+
let path = `${getLibDataDir()}/log/jsir`
|
|
1471
1503
|
let type = '';
|
|
1472
1504
|
for (let arg of args) {
|
|
1473
1505
|
if (_cmdMap[arg]) {
|
|
@@ -1475,7 +1507,7 @@ const keywordDef = {
|
|
|
1475
1507
|
let fileName = pair[0] + '/' + pair[1].split(".")[0]
|
|
1476
1508
|
path = `${getLibDataDir()}/log/${fileName}`
|
|
1477
1509
|
} else if (arg === '0') {
|
|
1478
|
-
path = `${getLibDataDir()}/log/
|
|
1510
|
+
path = `${getLibDataDir()}/log/room`
|
|
1479
1511
|
} else {
|
|
1480
1512
|
type = arg;
|
|
1481
1513
|
}
|
|
@@ -1569,7 +1601,7 @@ function getQuickRunCmds(input, matchStr) {
|
|
|
1569
1601
|
} else if (input.startsWith("/")) {
|
|
1570
1602
|
matchStr = '/' + matchStr;
|
|
1571
1603
|
}
|
|
1572
|
-
return filterCmd(matchStr).filter(i => getJsirTypeKey(parseUniqueName(i)[1])
|
|
1604
|
+
return filterCmd(matchStr).filter(i => [setting.exeKey, setting.initKey].includes(getJsirTypeKey(parseUniqueName(i)[1])))
|
|
1573
1605
|
}
|
|
1574
1606
|
|
|
1575
1607
|
async function preLoad(text, fnNameMatch, fn, packages = [], space) {
|
|
@@ -2163,17 +2195,25 @@ async function _requireSource(currSpace, cmdMatchStr, force = false) {
|
|
|
2163
2195
|
let typeKey = getJsirTypeKey(pair[1]);
|
|
2164
2196
|
if (typeKey === setting.initKey) {
|
|
2165
2197
|
let pair = parseUniqueName(uniqueName)
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2198
|
+
if (setting.defaultSpace === 'local' || force) {
|
|
2199
|
+
result = await evalText(text, uniqueName)
|
|
2200
|
+
} else {
|
|
2201
|
+
if (setting.serviceReg.test(uniqueName)) {
|
|
2202
|
+
let serviceKey = `${pair[0]}/${trimJsirFileName(pair[1])}`
|
|
2203
|
+
if (setting.services[serviceKey]) {
|
|
2204
|
+
let serviceObj = {};
|
|
2205
|
+
for (let fn of setting.services[serviceKey]) {
|
|
2206
|
+
serviceObj[fn] = async (...args) => {
|
|
2207
|
+
return await Room.reqFn(`${serviceKey}/${fn}`, args);
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
return serviceObj
|
|
2211
|
+
} else {
|
|
2212
|
+
throw `service ${serviceKey} not found`;
|
|
2172
2213
|
}
|
|
2214
|
+
} else {
|
|
2215
|
+
result = await evalText(text, uniqueName)
|
|
2173
2216
|
}
|
|
2174
|
-
return serviceObj
|
|
2175
|
-
} else {
|
|
2176
|
-
result = await evalText(text, uniqueName)
|
|
2177
2217
|
}
|
|
2178
2218
|
} else if (typeKey === setting.exeKey) {
|
|
2179
2219
|
result = async (argsStr) => {
|
|
@@ -2267,7 +2307,7 @@ process.on('beforeExit', function () {
|
|
|
2267
2307
|
delTips();
|
|
2268
2308
|
} else {
|
|
2269
2309
|
nextLine();
|
|
2270
|
-
Room.onRoom(
|
|
2310
|
+
Room.onRoom()
|
|
2271
2311
|
}
|
|
2272
2312
|
});
|
|
2273
2313
|
|
package/deps/room.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
const os = require('os');
|
|
2
2
|
const {fileJson, fileLock, vl, createConsole, getKeyTips, getValTips,
|
|
3
|
-
getRoomsDir, e,
|
|
3
|
+
getRoomsDir, e, isRunningInBackground,
|
|
4
4
|
batchAsync, debugStr, trim, getOr, errorTag, warnStr, getConfig, getConfigDir,
|
|
5
5
|
fileExist, formatUptime
|
|
6
6
|
} = require('./util');
|
|
7
7
|
const {setRoute, createSign} = require('../deps/server')
|
|
8
8
|
const roomDataFile = "jsirRoom.json"
|
|
9
9
|
const jsirNodesFile = "jsirNodes.json"
|
|
10
|
+
const roomTasksFile = "roomTasks.json"
|
|
11
|
+
const roomTasksLockKey = "LOCK_roomTasks.json"
|
|
10
12
|
const roomsDirLockKey = "RW_" + getRoomsDir();
|
|
11
13
|
const syncRoomsLockKey = "SyncRooms_" + getRoomsDir();
|
|
12
14
|
const syncConfigsLockKey = "SyncConfigs_" + getConfigDir();
|
|
@@ -17,8 +19,8 @@ const fp = require('fs').promises
|
|
|
17
19
|
const http = require('http');
|
|
18
20
|
const tailscalePath = os.platform() === 'darwin' ?
|
|
19
21
|
'/Applications/Tailscale.app/Contents/MacOS/Tailscale':'tailscale';
|
|
20
|
-
const configMain = getConfig("configMain");
|
|
21
22
|
const packageJson = require("../package.json");
|
|
23
|
+
const defTasks = getConfig("tasks");
|
|
22
24
|
|
|
23
25
|
function debug(...args) {
|
|
24
26
|
if (global.$DEBUG) {
|
|
@@ -52,7 +54,7 @@ async function localConfigs() {
|
|
|
52
54
|
return configs;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
function onRoom(
|
|
57
|
+
function onRoom() {
|
|
56
58
|
if (!setting.roomTid[0]) {
|
|
57
59
|
try {
|
|
58
60
|
setRoute("get", "/", (req, res) => {
|
|
@@ -71,18 +73,13 @@ function onRoom(wrapperInput) {
|
|
|
71
73
|
return;
|
|
72
74
|
}
|
|
73
75
|
setting.enterOutputs = []
|
|
74
|
-
await wrapperInput(req.input)
|
|
76
|
+
await setting.wrapperInput(req.input)
|
|
75
77
|
let outputs = setting.enterOutputs || [];
|
|
76
78
|
setting.enterOutputs = null;
|
|
77
79
|
res.output = outputs.join('');
|
|
78
80
|
global.$newInput = true;
|
|
79
81
|
}
|
|
80
82
|
})
|
|
81
|
-
if (configMain) {
|
|
82
|
-
setRoute("post", "/" + setting.configMainFnKey, async (req, res) => {
|
|
83
|
-
res.result = await localConfigs();
|
|
84
|
-
})
|
|
85
|
-
}
|
|
86
83
|
} catch (e) {
|
|
87
84
|
debug("initRoute failed", e)
|
|
88
85
|
}
|
|
@@ -130,7 +127,8 @@ async function getTailscaleNodes() {
|
|
|
130
127
|
if (/^\d+\.\d+\.\d+\.\d+$/.test(ss[0])) {
|
|
131
128
|
nodes[ss[0]] = {
|
|
132
129
|
name: ss[1],
|
|
133
|
-
offline
|
|
130
|
+
offline,
|
|
131
|
+
account: ss[2]
|
|
134
132
|
}
|
|
135
133
|
}
|
|
136
134
|
}
|
|
@@ -187,7 +185,13 @@ async function syncRooms() {
|
|
|
187
185
|
}
|
|
188
186
|
if (respBody) {
|
|
189
187
|
let currRoom = JSON.parse(respBody);
|
|
188
|
+
// 处理共享机器
|
|
190
189
|
currRoom.selfNode = node;
|
|
190
|
+
if (setting.nodeMap[node].account !== setting.nodeMap[setting.selfRoom.selfNode].account) {
|
|
191
|
+
currRoom.jsirs = Object.fromEntries(
|
|
192
|
+
Object.entries(currRoom.jsirs || {}).filter(([pid, jsir]) => jsir.port === setting.defaultPort)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
191
195
|
syncRooms.push(currRoom)
|
|
192
196
|
debug(`sync ${node} success`);
|
|
193
197
|
}
|
|
@@ -220,6 +224,7 @@ async function syncRooms() {
|
|
|
220
224
|
}
|
|
221
225
|
|
|
222
226
|
async function syncSetting() {
|
|
227
|
+
setting.nodeMap = await getTailscaleNodes();
|
|
223
228
|
let room = await fileJson(roomDataFile)
|
|
224
229
|
await fileLock(roomsDirLockKey, async () => await _syncSetting(room));
|
|
225
230
|
}
|
|
@@ -249,7 +254,7 @@ async function _syncSetting(room) {
|
|
|
249
254
|
setting.rooms = [setting.selfRoom, ...rooms]
|
|
250
255
|
.map(room => {
|
|
251
256
|
room.active = Date.now() - (room.lastUpdateTime || 0) <= setting.roomHeartbeatExpire;
|
|
252
|
-
Object.entries(room.jsirs).forEach(([key, jsir]) =>
|
|
257
|
+
Object.entries(room.jsirs || {}).forEach(([key, jsir]) =>
|
|
253
258
|
jsir.active = Date.now() - (jsir.lastUpdateTime || 0) <= setting.roomHeartbeatExpire)
|
|
254
259
|
return room;
|
|
255
260
|
});
|
|
@@ -282,6 +287,36 @@ async function _syncSetting(room) {
|
|
|
282
287
|
}
|
|
283
288
|
}
|
|
284
289
|
|
|
290
|
+
async function processTasks() {
|
|
291
|
+
await fileJson(roomTasksFile, async tasks => {
|
|
292
|
+
tasks = Object.fromEntries(
|
|
293
|
+
Object.entries(tasks).filter(([key, pid]) => isPidAlive(pid))
|
|
294
|
+
);
|
|
295
|
+
if (Object.values(tasks).includes(process.pid)) {
|
|
296
|
+
return tasks;
|
|
297
|
+
}
|
|
298
|
+
let unHandleKey = null;
|
|
299
|
+
for (let key of Object.keys(defTasks)) {
|
|
300
|
+
if (!tasks[key]) {
|
|
301
|
+
if (key.indexOf("*") !== -1 && process.pid !== setting.defaultPort) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
unHandleKey = key
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (unHandleKey) {
|
|
309
|
+
console.$log(process.pid, `run task ${unHandleKey}[${defTasks[unHandleKey]}]`)
|
|
310
|
+
await setting.wrapperInput(defTasks[unHandleKey]);
|
|
311
|
+
if (!global.$newError) {
|
|
312
|
+
tasks[unHandleKey] = process.pid;
|
|
313
|
+
console.$log(process.pid, `handle task ${unHandleKey}[${defTasks[unHandleKey]}]`)
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return tasks;
|
|
317
|
+
})
|
|
318
|
+
}
|
|
319
|
+
|
|
285
320
|
async function initRoom() {
|
|
286
321
|
setting.nodeMap = await fileJson(jsirNodesFile);
|
|
287
322
|
let roomUpdateTouchTime = false;
|
|
@@ -295,9 +330,12 @@ async function initRoom() {
|
|
|
295
330
|
if (roomUpdateTouchTime) {
|
|
296
331
|
await fileLock(updateRoomInfoLockKey, updateRoomInfo, false)
|
|
297
332
|
fileLock(syncRoomsLockKey, syncRooms, false);
|
|
298
|
-
if (
|
|
333
|
+
if (setting.serviceFns[setting.configMainFnKey] && !getConfig("configMain")) {
|
|
299
334
|
fileLock(syncConfigsLockKey, syncConfigs, false);
|
|
300
335
|
}
|
|
336
|
+
if (defTasks) {
|
|
337
|
+
fileLock(roomTasksLockKey, processTasks, false)
|
|
338
|
+
}
|
|
301
339
|
}
|
|
302
340
|
|
|
303
341
|
await syncSetting();
|
|
@@ -552,5 +590,6 @@ module.exports = {
|
|
|
552
590
|
offRoom,
|
|
553
591
|
syncSetting,
|
|
554
592
|
reqNode,
|
|
555
|
-
reqFn
|
|
593
|
+
reqFn,
|
|
594
|
+
localConfigs
|
|
556
595
|
}
|
package/deps/server.js
CHANGED
|
@@ -36,7 +36,7 @@ function createSign() {
|
|
|
36
36
|
async function process(routeKey, req, res, params) {
|
|
37
37
|
let router = routes[routeKey]
|
|
38
38
|
if (router) {
|
|
39
|
-
if ("get /" !== routeKey && !router.isApi
|
|
39
|
+
if ("get /" !== routeKey && !router.isApi) {
|
|
40
40
|
// 如果不是api接口,则校验签名
|
|
41
41
|
// 取header里的sign字段
|
|
42
42
|
const sign = req.headers['sign'];
|
|
@@ -143,7 +143,9 @@ async function startServer() {
|
|
|
143
143
|
*/
|
|
144
144
|
function setRoute(method, url, fn, isApi = false, handler = jsonHandle) {
|
|
145
145
|
startServer();
|
|
146
|
-
|
|
146
|
+
if (apiReg.test(url)) {
|
|
147
|
+
isApi = true;
|
|
148
|
+
}
|
|
147
149
|
const routeKey = `${method.toLowerCase()} ${url}`;
|
|
148
150
|
if (handler) {
|
|
149
151
|
routes[routeKey] = {
|
package/deps/setting.js
CHANGED
package/deps/util.js
CHANGED
|
@@ -26,6 +26,7 @@ let tempDir;
|
|
|
26
26
|
let configDir;
|
|
27
27
|
let roomsDir;
|
|
28
28
|
let dataDir;
|
|
29
|
+
let console = global.console
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
function isRunningInBackground() {
|
|
@@ -77,7 +78,7 @@ class SyncQueue {
|
|
|
77
78
|
try {
|
|
78
79
|
await task();
|
|
79
80
|
} catch (error) {
|
|
80
|
-
console
|
|
81
|
+
console.$error('Error during SyncQueue operation:', error);
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
this.isProcessing = false;
|
|
@@ -96,24 +97,25 @@ function syncQueue(task, key) {
|
|
|
96
97
|
return queue.enqueue(task)
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
const
|
|
100
|
+
const $log = createLimitLogger(`${setting.name}.log`, {
|
|
100
101
|
logInfo: false
|
|
101
102
|
});
|
|
102
|
-
const
|
|
103
|
+
const $error = createLimitLogger(`${setting.name}.error`, {
|
|
103
104
|
logInfo: false,
|
|
104
105
|
error: true,
|
|
105
|
-
syncLogs: [
|
|
106
|
+
syncLogs: [$log]
|
|
106
107
|
});
|
|
107
108
|
|
|
108
|
-
const
|
|
109
|
+
const roomLog = createLimitLogger(`room.log`, {
|
|
109
110
|
logInfo: false,
|
|
110
|
-
syncLogs: [
|
|
111
|
+
syncLogs: [$log]
|
|
111
112
|
});
|
|
112
|
-
const
|
|
113
|
+
const roomError = createLimitLogger(`room.error`, {
|
|
113
114
|
logInfo: false,
|
|
114
115
|
error: true,
|
|
115
|
-
syncLogs: [
|
|
116
|
+
syncLogs: [roomLog, $error]
|
|
116
117
|
});
|
|
118
|
+
|
|
117
119
|
let _globalDraft= createLimitLogger(`draft.log`, {
|
|
118
120
|
logInfo: false,
|
|
119
121
|
time: false
|
|
@@ -267,6 +269,9 @@ function createConsole(uniqueName) {
|
|
|
267
269
|
if ('debug' === key && !global.$DEBUG) {
|
|
268
270
|
return;
|
|
269
271
|
}
|
|
272
|
+
if ('error' === key) {
|
|
273
|
+
global.$newError = true;
|
|
274
|
+
}
|
|
270
275
|
if (uniqueName && quite) {
|
|
271
276
|
if ((key === 'table' || key === 'nable') && typeof args[0] === "object") {
|
|
272
277
|
args = ['', ...args]
|
|
@@ -286,7 +291,7 @@ function createConsole(uniqueName) {
|
|
|
286
291
|
return result;
|
|
287
292
|
}
|
|
288
293
|
|
|
289
|
-
|
|
294
|
+
console = createConsole();
|
|
290
295
|
// fix console done
|
|
291
296
|
|
|
292
297
|
|
|
@@ -1374,7 +1379,7 @@ function fileCleaner(path, maxChars) {
|
|
|
1374
1379
|
try {
|
|
1375
1380
|
cleanFile(path, maxChars)
|
|
1376
1381
|
} catch (e) {
|
|
1377
|
-
console
|
|
1382
|
+
console.$error(e)
|
|
1378
1383
|
}
|
|
1379
1384
|
}
|
|
1380
1385
|
}, "f", false);
|
|
@@ -1405,9 +1410,13 @@ function cleanFile(path, maxChars = 9 * 1024 * 1024) {
|
|
|
1405
1410
|
return;
|
|
1406
1411
|
}
|
|
1407
1412
|
await fileLock(path, async () => {
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1413
|
+
const bakFile = `${path}.bak`;
|
|
1414
|
+
// 备份日志
|
|
1415
|
+
try {
|
|
1416
|
+
await fp.rename(path, bakFile);
|
|
1417
|
+
} catch (e) {
|
|
1418
|
+
console.$error(`Failed to rename ${path} -> ${bakFile}`, e);
|
|
1419
|
+
}
|
|
1411
1420
|
}, false)
|
|
1412
1421
|
}, path)
|
|
1413
1422
|
}
|