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 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
- await dealStartGlobalMode(rows, items, text);
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
- if (_cmdMap[args[0]]){
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
- await runScript(cmds[0], args.slice(1))
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/room`
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/jsir`
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]) === setting.exeKey)
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
- let serviceKey = `${pair[0]}/${trimJsirFileName(pair[1])}`
2167
- if (setting.defaultSpace !== 'local' && !force && setting.services[serviceKey]) {
2168
- let serviceObj = {};
2169
- for (let fn of setting.services[serviceKey]) {
2170
- serviceObj[fn] = async (...args) => {
2171
- return await Room.reqFn(`${serviceKey}/${fn}`, args);
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(wrapperInput)
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, regEach, isRunningInBackground,
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(wrapperInput) {
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 (!configMain && setting.serviceFns[setting.configMainFnKey]) {
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 && !apiReg.test(routeKey)) {
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
@@ -40,5 +40,7 @@ module.exports = {
40
40
  roomTimer: 1000,
41
41
  serverSignExpire: 6000,
42
42
  roomHeartbeatExpire: 9000,
43
- configMainFnKey: "config/main"
43
+ configMainFnKey: "config/main",
44
+ serviceReg: /[^a-zA-Z]service[^a-zA-Z]|[^a-zA-Z]service$/i,
45
+ wrapperInput: null
44
46
  }
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.error('Error during SyncQueue operation:', error);
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 roomLog = createLimitLogger(`room.log`, {
100
+ const $log = createLimitLogger(`${setting.name}.log`, {
100
101
  logInfo: false
101
102
  });
102
- const roomError = createLimitLogger(`room.error`, {
103
+ const $error = createLimitLogger(`${setting.name}.error`, {
103
104
  logInfo: false,
104
105
  error: true,
105
- syncLogs: [roomLog]
106
+ syncLogs: [$log]
106
107
  });
107
108
 
108
- const $log = createLimitLogger(`${setting.name}.log`, {
109
+ const roomLog = createLimitLogger(`room.log`, {
109
110
  logInfo: false,
110
- syncLogs: [roomLog]
111
+ syncLogs: [$log]
111
112
  });
112
- const $error = createLimitLogger(`${setting.name}.error`, {
113
+ const roomError = createLimitLogger(`room.error`, {
113
114
  logInfo: false,
114
115
  error: true,
115
- syncLogs: [$log, roomError]
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
- const console = createConsole();
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.error(e)
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
- let content = String(await fp.readFile(path))
1409
- let newContext = content.slice(-Math.floor(maxChars * 0.7));
1410
- await fp.writeFile(path, newContext)
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsir",
3
- "version": "2.5.6",
3
+ "version": "2.5.8",
4
4
  "description": "JavaScript Script Management Tool",
5
5
  "main": "index.js",
6
6
  "scripts": {