@maiyunnet/kebab 2.0.7 → 2.0.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.
Files changed (83) hide show
  1. package/index.d.ts +11 -1
  2. package/index.js +13 -1
  3. package/lib/buffer.d.ts +25 -0
  4. package/lib/buffer.js +30 -5
  5. package/lib/captcha.d.ts +15 -0
  6. package/lib/captcha.js +20 -0
  7. package/lib/consistent.d.ts +51 -0
  8. package/lib/consistent.js +59 -0
  9. package/lib/core.d.ts +134 -0
  10. package/lib/core.js +176 -0
  11. package/lib/crypto.d.ts +75 -6
  12. package/lib/crypto.js +206 -38
  13. package/lib/db.d.ts +104 -0
  14. package/lib/db.js +126 -0
  15. package/lib/dns.d.ts +51 -0
  16. package/lib/dns.js +54 -2
  17. package/lib/fs.d.ts +100 -0
  18. package/lib/fs.js +118 -0
  19. package/lib/jwt.d.ts +43 -0
  20. package/lib/jwt.js +45 -0
  21. package/lib/kv.d.ts +362 -0
  22. package/lib/kv.js +377 -0
  23. package/lib/lan.d.ts +6 -0
  24. package/lib/lan.js +7 -0
  25. package/lib/net/formdata.d.ts +38 -0
  26. package/lib/net/formdata.js +43 -0
  27. package/lib/net/request.d.ts +62 -0
  28. package/lib/net/request.js +57 -0
  29. package/lib/net/response.d.ts +21 -0
  30. package/lib/net/response.js +16 -0
  31. package/lib/net.d.ts +86 -0
  32. package/lib/net.js +140 -0
  33. package/lib/s3.d.ts +52 -0
  34. package/lib/s3.js +51 -0
  35. package/lib/scan.d.ts +52 -0
  36. package/lib/scan.js +84 -0
  37. package/lib/session.d.ts +31 -0
  38. package/lib/session.js +52 -1
  39. package/lib/sql.d.ts +176 -0
  40. package/lib/sql.js +287 -2
  41. package/lib/ssh/sftp.d.ts +106 -0
  42. package/lib/ssh/sftp.js +106 -0
  43. package/lib/ssh/shell.d.ts +37 -0
  44. package/lib/ssh/shell.js +31 -0
  45. package/lib/ssh.d.ts +32 -0
  46. package/lib/ssh.js +32 -0
  47. package/lib/text.d.ts +131 -0
  48. package/lib/text.js +188 -0
  49. package/lib/time.d.ts +53 -0
  50. package/lib/time.js +55 -0
  51. package/lib/ws.d.ts +68 -0
  52. package/lib/ws.js +74 -0
  53. package/lib/zip.d.ts +53 -0
  54. package/lib/zip.js +73 -0
  55. package/lib/zlib.d.ts +76 -0
  56. package/lib/zlib.js +78 -0
  57. package/main.d.ts +5 -0
  58. package/main.js +12 -0
  59. package/package.json +3 -2
  60. package/sys/child.js +104 -0
  61. package/sys/cmd.js +28 -0
  62. package/sys/ctr.d.ts +166 -0
  63. package/sys/ctr.js +177 -0
  64. package/sys/master.js +63 -0
  65. package/sys/mod.d.ts +266 -0
  66. package/sys/mod.js +335 -0
  67. package/sys/route.d.ts +34 -0
  68. package/sys/route.js +164 -0
  69. package/www/example/ctr/test.d.ts +3 -0
  70. package/www/example/ctr/test.js +63 -1
  71. package/www/example/mod/test.js +14 -0
  72. package/www/example/mod/testdata.js +9 -0
  73. package/www/example/ws/test.js +1 -0
  74. package/.VSCodeCounter/2025-02-14_14-46-44/details.md +0 -82
  75. package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +0 -15
  76. package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +0 -2
  77. package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +0 -19
  78. package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +0 -22
  79. package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +0 -69
  80. package/.VSCodeCounter/2025-02-14_14-46-44/results.json +0 -1
  81. package/.VSCodeCounter/2025-02-14_14-46-44/results.md +0 -48
  82. package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +0 -118
  83. package/.vscode/tasks.json +0 -15
package/sys/child.js CHANGED
@@ -33,16 +33,24 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ /**
37
+ * Project: Kebab, User: JianSuoQiYue
38
+ * Date: 2019-5-3 23:54
39
+ * Last: 2020-3-31 15:01:07, 2020-4-9 22:28:50, 2022-07-22 14:19:46, 2022-9-29 22:11:07, 2023-5-1 18:26:57, 2024-1-12 13:32:00, 2024-3-4 16:49:19
40
+ */
36
41
  const http2 = __importStar(require("http2"));
37
42
  const tls = __importStar(require("tls"));
38
43
  const http = __importStar(require("http"));
39
44
  const crypto = __importStar(require("crypto"));
45
+ // --- 库和定义 ---
40
46
  const fs = __importStar(require("../lib/fs"));
41
47
  const lCore = __importStar(require("../lib/core"));
42
48
  const lText = __importStar(require("../lib/text"));
43
49
  const sCtr = __importStar(require("../sys/ctr"));
44
50
  const kebab = __importStar(require("../index"));
51
+ // --- 初始化 ---
45
52
  const sRoute = __importStar(require("../sys/route"));
53
+ /** --- 10 秒往主线程发送一次心跳的 Timer --- */
46
54
  const hbTimer = setInterval(function () {
47
55
  if (!process.connected || !process.send) {
48
56
  return;
@@ -52,25 +60,39 @@ const hbTimer = setInterval(function () {
52
60
  pid: process.pid
53
61
  });
54
62
  }, 10_000);
63
+ /** --- 加载的证书列表(path: { sc, cert }) --- */
55
64
  const certList = [];
65
+ /** --- server: index --- */
56
66
  let certHostIndex = {};
67
+ /** --- 当前的虚拟主机配置列表 - 读取于 conf/vhost/*.json --- */
57
68
  let vhosts = [];
69
+ /** --- http 服务器 --- */
58
70
  let httpServer;
71
+ /** --- http2 服务器 --- */
59
72
  let http2Server;
73
+ /** --- 当前使用中的连接 --- */
60
74
  const linkCount = {};
75
+ /**
76
+ * --- 最终调用执行的函数块,创建 http 服务器等 ---
77
+ */
61
78
  async function run() {
79
+ // --- 加载 全局、vhosts、sni 证书 ---
62
80
  await reload();
81
+ // --- 创建服务器并启动(支持 http2/https/http/websocket) ---
63
82
  http2Server = http2.createSecureServer({
83
+ // eslint-disable-next-line @typescript-eslint/naming-convention
64
84
  'SNICallback': (servername, cb) => {
65
85
  const i = certHostIndex[servername];
66
86
  if (i !== undefined) {
67
87
  cb(null, certList[i].sc);
68
88
  return;
69
89
  }
90
+ // --- 查找 servername ---
70
91
  for (let i = 0; i < certList.length; ++i) {
71
92
  if (!certList[i].cert.checkHost(servername)) {
72
93
  continue;
73
94
  }
95
+ // --- 找到 ---
74
96
  cb(null, certList[i].sc);
75
97
  certHostIndex[servername] = i;
76
98
  return;
@@ -213,7 +235,14 @@ async function run() {
213
235
  });
214
236
  }).listen(lCore.globalConfig.httpPort);
215
237
  }
238
+ /**
239
+ * --- http / https / http2 请求的回调函数 ---
240
+ * @param req 请求对象
241
+ * @param res 响应对象
242
+ * @param https 是否是 ssl
243
+ */
216
244
  async function requestHandler(req, res, https) {
245
+ // --- 打开计时器 ---
217
246
  const timer = {
218
247
  'timer': {},
219
248
  'timeout': 30_000,
@@ -222,6 +251,7 @@ async function requestHandler(req, res, https) {
222
251
  return;
223
252
  }
224
253
  if (res.headersSent) {
254
+ // --- 已经开始输出的,需要用户自行处理 ---
225
255
  return;
226
256
  }
227
257
  res.setHeader('content-length', 37);
@@ -230,7 +260,9 @@ async function requestHandler(req, res, https) {
230
260
  }
231
261
  };
232
262
  timer.timer = setTimeout(timer.callback, timer.timeout);
263
+ // --- 设置服务器名版本 ---
233
264
  res.setHeader('Server', 'Kebab/' + kebab.VER);
265
+ // --- 当前 uri ---
234
266
  let host = req.headers[':authority'];
235
267
  if (host === undefined || typeof host !== 'string') {
236
268
  host = req.headers['host'];
@@ -240,25 +272,41 @@ async function requestHandler(req, res, https) {
240
272
  }
241
273
  }
242
274
  const uri = lText.parseUrl(`http${https ? 's' : ''}://${host}${req.url ?? ''}`);
275
+ /** --- 当前的 vhost 配置文件 --- */
243
276
  const vhost = getVhostByHostname(uri.hostname ?? '');
244
277
  if (!vhost) {
245
278
  req.socket.destroy();
246
279
  return;
280
+ /*
281
+ const text = '<h1>Kebab: No permissions</h1>host: ' + (req.headers[':authority'] as string | undefined ?? req.headers['host'] ?? '') + '<br>url: ' + (lText.htmlescape(req.url ?? ''));
282
+ res.setHeader('content-type', 'text/html; charset=utf-8');
283
+ res.setHeader('content-length', Buffer.byteLength(text));
284
+ res.writeHead(403);
285
+ res.end(text);
286
+ return;
287
+ */
247
288
  }
248
289
  const vhostRoot = vhost.root.replace(/\${example}/g, kebab.ROOT_PATH + 'www/example/');
290
+ /** --- 网站绝对根目录,末尾带 / --- */
249
291
  let rootPath = lText.isRealPath(vhostRoot) ? vhostRoot : kebab.WWW_CWD + vhostRoot;
250
292
  if (!rootPath.endsWith('/')) {
251
293
  rootPath += '/';
252
294
  }
295
+ /** --- 请求的路径部分,前导带 / 末尾不一定,用户怎么请求就是什么 --- */
253
296
  let path = uri.pathname ?? '/';
254
297
  if (path !== '/') {
298
+ // --- 去除 ../ ./ 之类的 ---
255
299
  path = lText.urlResolve('/', path);
256
300
  }
301
+ /** --- [''] / ['', 'abc', 'def'] --- */
257
302
  const pathList = path.split('/');
303
+ /** --- 当前处理的路径,前导不带 / 末尾带 /,例如 abc/ --- */
258
304
  let now = '';
259
305
  for (let i = 0; i < pathList.length; ++i) {
260
306
  const item = pathList[i];
261
307
  if (item !== '') {
308
+ // --- 判断 item 是文件还是文件夹 ---
309
+ /** --- 'abc' / 'def.json' --- */
262
310
  let stat = await fs.stats(rootPath + now + item);
263
311
  if (!stat) {
264
312
  res.setHeader('content-type', 'text/html; charset=utf-8');
@@ -269,8 +317,10 @@ async function requestHandler(req, res, https) {
269
317
  }
270
318
  if (stat.isDirectory()) {
271
319
  now += item + '/';
320
+ // --- 判断是不是动态层 ---
272
321
  stat = await fs.stats(rootPath + now + 'kebab.json');
273
322
  if (stat) {
323
+ // --- 动态层,交给 Route 处理器 ---
274
324
  try {
275
325
  if (await sRoute.run({
276
326
  'req': req,
@@ -303,16 +353,20 @@ async function requestHandler(req, res, https) {
303
353
  }
304
354
  }
305
355
  else {
356
+ // --- 文件,直接输出并结束 ---
306
357
  await fs.readToResponse(rootPath + now + item, req, res, stat);
307
358
  return;
308
359
  }
309
360
  }
310
361
  else {
362
+ // --- item 为空,但是 i 不是 0,则是最后一个空,直接 break ---
311
363
  if (i > 0) {
312
364
  break;
313
365
  }
366
+ // --- 本层是根,判断根是不是动态层 ---
314
367
  const stat = await fs.stats(rootPath + now + 'kebab.json');
315
368
  if (stat) {
369
+ // --- 动态层,交给 Route 处理器 ---
316
370
  try {
317
371
  if (await sRoute.run({
318
372
  'req': req,
@@ -345,6 +399,7 @@ async function requestHandler(req, res, https) {
345
399
  }
346
400
  }
347
401
  }
402
+ // --- 最后一层是目录,且不是动态层,判断有没有主页,有则输出,没有则 403 出错 ---
348
403
  const indexFiles = ['index.html', 'index.htm'];
349
404
  for (const indexFile of indexFiles) {
350
405
  const stat = await fs.isFile(rootPath + now + indexFile);
@@ -358,28 +413,43 @@ async function requestHandler(req, res, https) {
358
413
  res.writeHead(403);
359
414
  res.end('<h1>403 Forbidden</h1><hr>Kebab');
360
415
  }
416
+ /**
417
+ * --- WebSocket 响应 handler ---
418
+ * @param req 请求对象
419
+ * @param socket socket 对象
420
+ * @param https 是否是 https
421
+ */
361
422
  async function upgradeHandler(req, socket, https) {
362
423
  socket.removeAllListeners('error');
424
+ // --- 当前 uri ---
363
425
  const uri = lText.parseUrl(`ws${https ? 's' : ''}://${req.headers['host'] ?? ''}${req.url ?? ''}`);
426
+ /** --- 当前的 vhost 配置文件 --- */
364
427
  const vhost = getVhostByHostname(uri.hostname ?? '');
365
428
  if (!vhost) {
366
429
  socket.destroy();
367
430
  return;
368
431
  }
369
432
  const vhostRoot = vhost.root.replace(/\${example}/g, kebab.ROOT_PATH + 'www/example/');
433
+ /** --- 网站绝对根目录,末尾带 / --- */
370
434
  let rootPath = lText.isRealPath(vhostRoot) ? vhostRoot : kebab.WWW_CWD + vhostRoot;
371
435
  if (!rootPath.endsWith('/')) {
372
436
  rootPath += '/';
373
437
  }
438
+ /** --- 请求的路径部分,前导带 / 末尾不一定,用户怎么请求就是什么 --- */
374
439
  let path = uri.pathname ?? '/';
375
440
  if (path !== '/') {
441
+ // --- 去除 ../ ./ 之类的 ---
376
442
  path = lText.urlResolve('/', path);
377
443
  }
444
+ /** --- [''] / ['', 'abc', 'def'] --- */
378
445
  const pathList = path.split('/');
446
+ /** --- 当前处理的路径,前导不带 / 末尾带 /,例如 abc/ --- */
379
447
  let now = '';
380
448
  for (let i = 0; i < pathList.length; ++i) {
381
449
  const item = pathList[i];
382
450
  if (item !== '') {
451
+ // --- 判断 item 是文件还是文件夹 ---
452
+ /** --- 'abc' / 'def.json' --- */
383
453
  let stat = await fs.stats(rootPath + now + item);
384
454
  if (!stat) {
385
455
  socket.destroy();
@@ -387,8 +457,10 @@ async function upgradeHandler(req, socket, https) {
387
457
  }
388
458
  if (stat.isDirectory()) {
389
459
  now += item + '/';
460
+ // --- 判断是不是动态层 ---
390
461
  stat = await fs.stats(rootPath + now + 'kebab.json');
391
462
  if (stat) {
463
+ // --- 动态层,交给 Route 处理器 ---
392
464
  if (await sRoute.run({
393
465
  'req': req,
394
466
  'socket': socket,
@@ -402,16 +474,20 @@ async function upgradeHandler(req, socket, https) {
402
474
  }
403
475
  }
404
476
  else {
477
+ // --- 文件,报错 ---
405
478
  socket.destroy();
406
479
  return;
407
480
  }
408
481
  }
409
482
  else {
483
+ // --- item 为空,但是 i 不是 0,则是最后一个空,直接 break ---
410
484
  if (i > 0) {
411
485
  break;
412
486
  }
487
+ // --- 判断根是不是动态层 ---
413
488
  const stat = await fs.stats(rootPath + now + 'kebab.json');
414
489
  if (stat) {
490
+ // --- 动态层,交给 Route 处理器 ---
415
491
  if (await sRoute.run({
416
492
  'req': req,
417
493
  'socket': socket,
@@ -425,9 +501,14 @@ async function upgradeHandler(req, socket, https) {
425
501
  }
426
502
  }
427
503
  }
504
+ // --- 最后一层,又不是动态层 ---
428
505
  socket.destroy();
429
506
  }
507
+ /**
508
+ * --- 加载/重载 vhosts 信息、重新加载全局 config、重新加载证书。(清除动态 kebab.json 信息、data 信息、语言包信息) ---
509
+ */
430
510
  async function reload() {
511
+ // --- 清除全局 config,并重新加载全局信息 ---
431
512
  const configContent = await fs.getContent(kebab.CONF_CWD + 'config.json', 'utf8');
432
513
  if (!configContent) {
433
514
  throw `File '${kebab.CONF_CWD}config.json' not found.`;
@@ -439,6 +520,7 @@ async function reload() {
439
520
  for (const key in config) {
440
521
  lCore.globalConfig[key] = config[key];
441
522
  }
523
+ // --- 重新加载 VHOST 信息(/conf/vhost/) ---
442
524
  const files = await fs.readDir(kebab.VHOST_CWD);
443
525
  vhosts = [];
444
526
  for (const file of files) {
@@ -457,6 +539,7 @@ async function reload() {
457
539
  vhosts.push(item);
458
540
  }
459
541
  }
542
+ // --- 重新加载证书对 ---
460
543
  certList.length = 0;
461
544
  try {
462
545
  const certConfig = await fs.getContent(kebab.CONF_CWD + 'cert.json', 'utf8');
@@ -481,32 +564,41 @@ async function reload() {
481
564
  }
482
565
  }
483
566
  catch {
567
+ // --- NOTHING ---
484
568
  }
485
569
  certHostIndex = {};
570
+ // --- 其他操作 ---
486
571
  sRoute.clearKebabConfigs();
487
572
  sCtr.clearLocaleData();
488
573
  }
574
+ // --- 接收主进程回传信号,主要用来 reload,restart ---
489
575
  process.on('message', function (msg) {
490
576
  (async function () {
491
577
  switch (msg.action) {
492
578
  case 'reload': {
493
579
  await reload();
580
+ // eslint-disable-next-line no-console
494
581
  console.log(`[child] Worker ${process.pid} reload execution succeeded.`);
495
582
  break;
496
583
  }
497
584
  case 'stop': {
585
+ // --- 需要停止监听,等待已有连接全部断开,然后关闭线程 ---
498
586
  httpServer.close();
499
587
  http2Server.close();
500
588
  clearInterval(hbTimer);
589
+ // --- 等待连接全部断开 ---
590
+ /** --- 当前已等待时间,等待不超过 1 小时 --- */
501
591
  let waiting = 0;
502
592
  while (true) {
503
593
  if (!Object.keys(linkCount).length) {
504
594
  break;
505
595
  }
596
+ // --- 有长连接,等待中 ---
506
597
  const str = [];
507
598
  for (const key in linkCount) {
508
599
  str.push(key + ':' + linkCount[key].toString());
509
600
  }
601
+ // eslint-disable-next-line no-console
510
602
  console.log(`[child] Worker ${process.pid} busy: ${str.join(',')}.`);
511
603
  await lCore.log({
512
604
  'path': '',
@@ -523,6 +615,7 @@ process.on('message', function (msg) {
523
615
  break;
524
616
  }
525
617
  }
618
+ // --- 链接全部断开 ---
526
619
  process.exit();
527
620
  break;
528
621
  }
@@ -532,6 +625,7 @@ process.on('message', function (msg) {
532
625
  break;
533
626
  }
534
627
  if (msg.key === '__init__') {
628
+ // --- 初始化 ---
535
629
  for (const key in msg.data) {
536
630
  lCore.global[key] = msg.data[key];
537
631
  }
@@ -553,20 +647,28 @@ process.on('message', function (msg) {
553
647
  }, '[child][process][message]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
554
648
  });
555
649
  });
650
+ /**
651
+ * --- 获取匹配的 vhost 对象 ---
652
+ * --- 如果有精准匹配,以精准匹配为准,否则为 2 级泛匹配(vSub),最后全局泛匹配(vGlobal) ---
653
+ * @param hostname 当前的 hostname,不带端口
654
+ */
556
655
  function getVhostByHostname(hostname) {
557
656
  let vGlobal, vSub;
558
657
  for (const vhost of vhosts) {
559
658
  for (let domain of vhost.domains) {
560
659
  if (domain === '*') {
660
+ // --- 全局泛匹配 ---
561
661
  vGlobal = vhost;
562
662
  }
563
663
  else if (domain.includes('*')) {
664
+ // --- 2 级泛匹配 ---
564
665
  domain = domain.replace(/\*/, '^.+?').replace(/\./, '\\.');
565
666
  if (new RegExp(domain + '$').test(hostname)) {
566
667
  vSub = vhost;
567
668
  }
568
669
  }
569
670
  else if (domain === hostname) {
671
+ // --- 完全匹配 ---
570
672
  return vhost;
571
673
  }
572
674
  }
@@ -580,6 +682,8 @@ function getVhostByHostname(hostname) {
580
682
  return null;
581
683
  }
582
684
  run().catch(function (e) {
685
+ /* eslint-disable no-console */
583
686
  console.log('[child] ------ [Process fatal Error] ------');
584
687
  console.log(e);
688
+ /* eslint-enable */
585
689
  });
package/sys/cmd.js CHANGED
@@ -33,6 +33,11 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ /**
37
+ * Project: Kebab, User: JianSuoQiYue
38
+ * Date: 2020-3-7 23:51:15
39
+ * Last: 2020-3-7 23:51:18, 2022-07-22 14:14:09, 2022-9-27 14:52:19, 2023-5-23 21:42:46, 2024-7-2 15:12:28
40
+ */
36
41
  const http = __importStar(require("http"));
37
42
  const lFs = __importStar(require("../lib/fs"));
38
43
  const lText = __importStar(require("../lib/text"));
@@ -40,7 +45,9 @@ const lTime = __importStar(require("../lib/time"));
40
45
  const lCore = __importStar(require("../lib/core"));
41
46
  const lCrypto = __importStar(require("../lib/crypto"));
42
47
  const kebab = __importStar(require("../index"));
48
+ /** --- 解析命令 --- */
43
49
  const cmds = process.argv.slice(2);
50
+ /** --- 批量创建目录 --- */
44
51
  async function initDir(paths) {
45
52
  for (const path of paths) {
46
53
  if (await lFs.isDir(path)) {
@@ -59,8 +66,10 @@ async function initDir(paths) {
59
66
  }
60
67
  return true;
61
68
  }
69
+ /** --- cmd 解析 --- */
62
70
  async function run() {
63
71
  if (cmds[0] === 'init' || cmds[0] === 'update') {
72
+ // --- 初始化、更新 ---
64
73
  if (!await initDir([
65
74
  kebab.CERT_CWD + 'default/',
66
75
  kebab.VHOST_CWD,
@@ -73,6 +82,7 @@ async function run() {
73
82
  ])) {
74
83
  return;
75
84
  }
85
+ // --- /conf/cert.json ---
76
86
  if (!await lFs.isFile(kebab.CONF_CWD + 'cert.json')) {
77
87
  lCore.display('KEBAB', 'CREATE', 'FILE', kebab.CONF_CWD + 'cert.json');
78
88
  if (!await lFs.putContent(kebab.CONF_CWD + 'cert.json', lText.stringifyJson([
@@ -85,6 +95,7 @@ async function run() {
85
95
  return;
86
96
  }
87
97
  }
98
+ // --- /conf/config.json ---
88
99
  let config = {};
89
100
  if (await lFs.isFile(kebab.CONF_CWD + 'config.json')) {
90
101
  config = lText.parseJson((await lFs.getContent(kebab.CONF_CWD + 'config.json'))?.toString() ?? '{}');
@@ -92,18 +103,21 @@ async function run() {
92
103
  else {
93
104
  lCore.display('KEBAB', 'CREATE', 'FILE', kebab.CONF_CWD + 'config.json');
94
105
  }
106
+ // --- 修复 config ---
95
107
  config.httpPort ??= 8080;
96
108
  config.httpsPort ??= 4333;
97
109
  config.rpcPort ??= 10630;
98
110
  config.rpcSecret ??= 'MUSTCHANGE';
99
111
  config.debug ??= true;
100
112
  config.max ??= 64;
113
+ // --- config - set ---
101
114
  config.set ??= {};
102
115
  config.set.timezone ??= 8;
103
116
  config.set.mustHttps ??= false;
104
117
  config.set.cacheTtl ??= 0;
105
118
  config.set.staticVer ??= '20200314174905';
106
119
  config.set.staticPath ??= '';
120
+ // --- config - db ---
107
121
  config.db ??= {};
108
122
  config.db.host ??= '127.0.0.1';
109
123
  config.db.port ??= 3306;
@@ -111,12 +125,14 @@ async function run() {
111
125
  config.db.name ??= 'maiyun';
112
126
  config.db.user ??= 'root';
113
127
  config.db.pwd ??= 'DashAdmin';
128
+ // --- config - jwt ---
114
129
  config.jwt ??= {};
115
130
  config.jwt.name ??= 'KE_JWT';
116
131
  config.jwt.ttl ??= 172800;
117
132
  config.jwt.ssl ??= false;
118
133
  config.jwt.secret ??= 'MUSTCHANGE';
119
134
  config.jwt.auth ??= false;
135
+ // --- config - dns ---
120
136
  config.dns ??= {};
121
137
  config.dns['DNSPOD'] ??= {};
122
138
  config.dns['DNSPOD'].sid ??= '';
@@ -124,6 +140,7 @@ async function run() {
124
140
  config.dns['CF'] ??= {};
125
141
  config.dns['CF'].sid ??= '';
126
142
  config.dns['CF'].skey ??= '';
143
+ // --- config - kv ---
127
144
  config.kv ??= {};
128
145
  config.kv.host ??= '127.0.0.1';
129
146
  config.kv.port ??= 6379;
@@ -131,12 +148,15 @@ async function run() {
131
148
  config.kv.pre ??= 'm_';
132
149
  config.kv.user ??= '';
133
150
  config.kv.pwd ??= '';
151
+ // --- config - session ---
134
152
  config.session ??= {};
135
153
  config.session.name ??= 'KE_SESSION';
136
154
  config.session.ttl ??= 172800;
137
155
  config.session.ssl ??= false;
156
+ // --- config - sql ---
138
157
  config.sql ??= {};
139
158
  config.sql.pre ??= 'm_';
159
+ // --- config - s3 ---
140
160
  config.s3 ??= {};
141
161
  config.s3['CF'] ??= {};
142
162
  config.s3['CF'].account = '';
@@ -149,11 +169,14 @@ async function run() {
149
169
  config.s3['TENCENT'].skey = '';
150
170
  config.s3['TENCENT'].region = '';
151
171
  config.s3['TENCENT'].bucket = '';
172
+ // --- 保存 config.json ---
152
173
  if (!await lFs.putContent(kebab.CONF_CWD + 'config.json', lText.stringifyJson(config, 4))) {
153
174
  lCore.display('KEBAB', 'CREATE', 'FILE', kebab.CONF_CWD + 'config.json', '[FAILED]');
154
175
  return;
155
176
  }
177
+ // --- 只在初始化时 ---
156
178
  if (cmds[0] === 'init') {
179
+ // --- /conf/vhost/default.json ---
157
180
  if (!await lFs.isFile(kebab.VHOST_CWD + 'default.json')) {
158
181
  lCore.display('KEBAB', 'CREATE', 'FILE', kebab.VHOST_CWD + 'default.json');
159
182
  if (!await lFs.putContent(kebab.VHOST_CWD + 'default.json', lText.stringifyJson([
@@ -178,24 +201,29 @@ async function run() {
178
201
  lCore.display('DONE');
179
202
  process.exit();
180
203
  }
204
+ // --- 读取配置文件 ---
181
205
  const configContent = await lFs.getContent(kebab.CONF_CWD + 'config.json', 'utf8');
182
206
  if (!configContent) {
183
207
  throw `File '${kebab.CONF_CWD}config.json' not found.`;
184
208
  }
209
+ /** --- 系统 config.json --- */
185
210
  const config = lText.parseJson(configContent);
186
211
  for (const key in config) {
187
212
  lCore.globalConfig[key] = config[key];
188
213
  }
189
214
  if (cmds[0] === '--ind' || cmds[0] === '-i') {
215
+ // --- 运行独立文件,如 node ./index --ind gps ---
190
216
  if (!await lFs.isFile(kebab.IND_CWD + cmds[1] + '/index.js')) {
191
217
  lCore.display('CMD ERROR', 'IND FILE "' + cmds[1] + '" NOT FOUND.');
192
218
  return;
193
219
  }
220
+ // --- 载入独立文件入口 ---
194
221
  Promise.resolve(`${'../ind/' + cmds[1] + '/index'}`).then(s => __importStar(require(s))).catch((e) => {
195
222
  lCore.display('CMD ERROR', 'E', e);
196
223
  });
197
224
  }
198
225
  else {
226
+ // --- 其他,如 node ./index reload 或 restart ---
199
227
  const time = lTime.stamp();
200
228
  http.request({
201
229
  'hostname': '127.0.0.1',