@maiyunnet/kebab 7.0.2 → 7.1.1
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/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/ai.js +3 -0
- package/lib/buffer.js +6 -4
- package/lib/captcha.js +1 -0
- package/lib/consistent.js +6 -6
- package/lib/core.d.ts +9 -0
- package/lib/core.js +59 -44
- package/lib/db/conn.js +14 -10
- package/lib/db/pool.js +6 -2
- package/lib/db/tran.js +10 -7
- package/lib/dns.js +2 -0
- package/lib/kv.d.ts +2 -1
- package/lib/kv.js +7 -1
- package/lib/net/formdata.js +14 -17
- package/lib/net/request.js +6 -6
- package/lib/net/response.js +7 -7
- package/lib/s3.js +4 -2
- package/lib/scan.js +9 -8
- package/lib/session.js +12 -6
- package/lib/sql.js +16 -12
- package/lib/ssh/sftp.js +4 -0
- package/lib/ssh/shell.js +2 -0
- package/lib/ssh.js +4 -0
- package/lib/text.js +2 -7
- package/lib/time.js +4 -2
- package/lib/vector.js +2 -0
- package/lib/ws.js +30 -28
- package/lib/zip.js +6 -4
- package/package.json +3 -3
- package/sys/child.js +21 -72
- package/sys/ctr.d.ts +7 -0
- package/sys/ctr.js +112 -189
- package/sys/master.js +23 -0
- package/sys/mod.js +25 -18
- package/sys/route.js +40 -64
- package/www/example/ctr/test.d.ts +1 -0
- package/www/example/ctr/test.js +14 -4
- package/www/example/mod/test.js +4 -4
- package/www/example/mod/testdata.js +2 -2
- package/www/example/ws/test.js +1 -4
package/sys/route.js
CHANGED
|
@@ -25,6 +25,38 @@ let kebabConfigs = {};
|
|
|
25
25
|
export function clearKebabConfigs() {
|
|
26
26
|
kebabConfigs = {};
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* --- 输出 500 错误响应 ---
|
|
30
|
+
* @param res 响应对象
|
|
31
|
+
*/
|
|
32
|
+
function respond500(res) {
|
|
33
|
+
const content = '<h1>500 Server Error</h1><hr>Kebab';
|
|
34
|
+
if (!res.headersSent) {
|
|
35
|
+
res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
36
|
+
res.setHeader('content-length', Buffer.byteLength(content));
|
|
37
|
+
lCore.writeHead(res, 500);
|
|
38
|
+
}
|
|
39
|
+
res.end(content);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* --- 输出 404 错误响应 ---
|
|
43
|
+
* @param res 响应对象
|
|
44
|
+
* @param config 配置对象(用于检查 #404 路由)
|
|
45
|
+
* @param path 请求路径
|
|
46
|
+
*/
|
|
47
|
+
function respond404(res, config, path) {
|
|
48
|
+
if (config?.route?.['#404']) {
|
|
49
|
+
res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
|
|
50
|
+
lCore.writeHead(res, 302);
|
|
51
|
+
res.end('');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const content = '[Error] Controller not found, path: ' + path + '.';
|
|
55
|
+
res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
56
|
+
res.setHeader('content-length', Buffer.byteLength(content));
|
|
57
|
+
lCore.writeHead(res, 404);
|
|
58
|
+
res.end(content);
|
|
59
|
+
}
|
|
28
60
|
/**
|
|
29
61
|
* --- 若为动态路径则执行此函数,此函数不进行判断 kebab.json 是否存在 ---
|
|
30
62
|
* @param data 传导的数据
|
|
@@ -181,17 +213,7 @@ export async function run(data) {
|
|
|
181
213
|
// --- 若文件名为保留的 middle 将不允许进行 ---
|
|
182
214
|
if (pathLeft.startsWith('middle')) {
|
|
183
215
|
if (data.res) {
|
|
184
|
-
|
|
185
|
-
data.res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
|
|
186
|
-
lCore.writeHead(data.res, 302);
|
|
187
|
-
data.res.end('');
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
const content = '[Error] Controller not found, path: ' + path + '.';
|
|
191
|
-
data.res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
192
|
-
data.res.setHeader('content-length', Buffer.byteLength(content));
|
|
193
|
-
lCore.writeHead(data.res, 404);
|
|
194
|
-
data.res.end(content);
|
|
216
|
+
respond404(data.res, config, path);
|
|
195
217
|
}
|
|
196
218
|
else {
|
|
197
219
|
data.socket?.destroy();
|
|
@@ -411,11 +433,7 @@ export async function run(data) {
|
|
|
411
433
|
}
|
|
412
434
|
catch (e) {
|
|
413
435
|
lCore.log(middle, '(E03)' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
414
|
-
|
|
415
|
-
data.res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
416
|
-
data.res.setHeader('content-length', Buffer.byteLength(content));
|
|
417
|
-
lCore.writeHead(data.res, 500);
|
|
418
|
-
data.res.end(content);
|
|
436
|
+
respond500(data.res);
|
|
419
437
|
return true;
|
|
420
438
|
}
|
|
421
439
|
let cacheTTL = middle.getPrototype('_cacheTTL');
|
|
@@ -427,11 +445,7 @@ export async function run(data) {
|
|
|
427
445
|
}
|
|
428
446
|
catch (e) {
|
|
429
447
|
lCore.log(middle, '(E05)' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
430
|
-
|
|
431
|
-
data.res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
432
|
-
data.res.setHeader('content-length', Buffer.byteLength(content));
|
|
433
|
-
lCore.writeHead(data.res, 500);
|
|
434
|
-
data.res.end(content);
|
|
448
|
+
respond500(data.res);
|
|
435
449
|
return true;
|
|
436
450
|
}
|
|
437
451
|
cacheTTL = middle.getPrototype('_cacheTTL');
|
|
@@ -441,17 +455,7 @@ export async function run(data) {
|
|
|
441
455
|
const filePath = config.const.ctrPath + pathLeft + '.js';
|
|
442
456
|
if (!await lFs.isFile(filePath)) {
|
|
443
457
|
// --- 指定的控制器不存在 ---
|
|
444
|
-
|
|
445
|
-
data.res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
|
|
446
|
-
lCore.writeHead(data.res, 302);
|
|
447
|
-
data.res.end('');
|
|
448
|
-
return true;
|
|
449
|
-
}
|
|
450
|
-
const content = '[Error] Controller not found, path: ' + path + '.';
|
|
451
|
-
data.res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
452
|
-
data.res.setHeader('content-length', Buffer.byteLength(content));
|
|
453
|
-
lCore.writeHead(data.res, 404);
|
|
454
|
-
data.res.end(content);
|
|
458
|
+
respond404(data.res, config, path);
|
|
455
459
|
return true;
|
|
456
460
|
}
|
|
457
461
|
// --- 加载控制器文件 ---
|
|
@@ -488,34 +492,14 @@ export async function run(data) {
|
|
|
488
492
|
// --- 检测 action 是否存在,以及排除内部方法 ---
|
|
489
493
|
if (pathRight.startsWith('_') || pathRight === 'onUpgrade' || pathRight === 'onLoad' || pathRight === 'onData' || pathRight === 'onDrain' || pathRight === 'onEnd' || pathRight === 'onClose' || pathRight === 'setPrototype' || pathRight === 'getPrototype' || pathRight === 'getAuthorization') {
|
|
490
494
|
// --- _ 开头的 action 是内部方法,不允许访问 ---
|
|
491
|
-
|
|
492
|
-
data.res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
|
|
493
|
-
lCore.writeHead(data.res, 302);
|
|
494
|
-
data.res.end('');
|
|
495
|
-
return true;
|
|
496
|
-
}
|
|
497
|
-
const content = '[Error] Action not found, path: ' + path + '.';
|
|
498
|
-
data.res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
499
|
-
data.res.setHeader('content-length', Buffer.byteLength(content));
|
|
500
|
-
lCore.writeHead(data.res, 404);
|
|
501
|
-
data.res.end(content);
|
|
495
|
+
respond404(data.res, config, path);
|
|
502
496
|
return true;
|
|
503
497
|
}
|
|
504
498
|
pathRight = pathRight.replace(/-([a-zA-Z0-9])/g, function (t, t1) {
|
|
505
499
|
return t1.toUpperCase();
|
|
506
500
|
});
|
|
507
501
|
if ((cctr[pathRight] === undefined) || (typeof cctr[pathRight] !== 'function')) {
|
|
508
|
-
|
|
509
|
-
data.res.setHeader('location', lText.urlResolve(config.const.urlBase, config.route['#404']));
|
|
510
|
-
lCore.writeHead(data.res, 302);
|
|
511
|
-
data.res.end('');
|
|
512
|
-
return true;
|
|
513
|
-
}
|
|
514
|
-
const content = '[Error] Action not found, path: ' + path + '.';
|
|
515
|
-
data.res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
516
|
-
data.res.setHeader('content-length', Buffer.byteLength(content));
|
|
517
|
-
lCore.writeHead(data.res, 404);
|
|
518
|
-
data.res.end(content);
|
|
502
|
+
respond404(data.res, config, path);
|
|
519
503
|
return true;
|
|
520
504
|
}
|
|
521
505
|
// --- 执行 onLoad 方法 ---
|
|
@@ -538,11 +522,7 @@ export async function run(data) {
|
|
|
538
522
|
}
|
|
539
523
|
catch (e) {
|
|
540
524
|
lCore.log(cctr, '(E05)' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
541
|
-
|
|
542
|
-
data.res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
543
|
-
data.res.setHeader('content-length', Buffer.byteLength(content));
|
|
544
|
-
lCore.writeHead(data.res, 500);
|
|
545
|
-
data.res.end(content);
|
|
525
|
+
respond500(data.res);
|
|
546
526
|
await waitCtr(cctr);
|
|
547
527
|
return true;
|
|
548
528
|
}
|
|
@@ -553,11 +533,7 @@ export async function run(data) {
|
|
|
553
533
|
}
|
|
554
534
|
catch (e) {
|
|
555
535
|
lCore.log(cctr, '(E04)' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
556
|
-
|
|
557
|
-
data.res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
558
|
-
data.res.setHeader('content-length', Buffer.byteLength(content));
|
|
559
|
-
lCore.writeHead(data.res, 500);
|
|
560
|
-
data.res.end(content);
|
|
536
|
+
respond500(data.res);
|
|
561
537
|
await waitCtr(cctr);
|
|
562
538
|
return true;
|
|
563
539
|
}
|
|
@@ -47,6 +47,7 @@ export default class extends sCtr.Ctr {
|
|
|
47
47
|
coreUpdatecode(): Promise<string>;
|
|
48
48
|
coreReload(): Promise<string>;
|
|
49
49
|
coreRestart(): Promise<string>;
|
|
50
|
+
corePm2(): Promise<string>;
|
|
50
51
|
coreGlobal(): Promise<string>;
|
|
51
52
|
crypto(): Promise<string>;
|
|
52
53
|
db(): Promise<kebab.Json>;
|
package/www/example/ctr/test.js
CHANGED
|
@@ -26,10 +26,7 @@ import * as sCtr from '#kebab/sys/ctr.js';
|
|
|
26
26
|
import mTest from '../mod/test.js';
|
|
27
27
|
import mTestData from '../mod/testdata.js';
|
|
28
28
|
export default class extends sCtr.Ctr {
|
|
29
|
-
|
|
30
|
-
super(...arguments);
|
|
31
|
-
this._internalUrl = '';
|
|
32
|
-
}
|
|
29
|
+
_internalUrl = '';
|
|
33
30
|
onLoad() {
|
|
34
31
|
if (this._config.const.hostname !== '127.0.0.1' && this._config.const.hostname !== '172.17.0.1' &&
|
|
35
32
|
this._config.const.hostname !== 'localhost' && !this._config.const.hostname.endsWith('.local.brc-app.com') &&
|
|
@@ -142,6 +139,7 @@ export default class extends sCtr.Ctr {
|
|
|
142
139
|
`<br><a href="${this._config.const.urlBase}test/core-ls">View "test/core-ls"</a>`,
|
|
143
140
|
`<br><a href="${this._config.const.urlBase}test/core-reload">View "test/core-reload"</a>`,
|
|
144
141
|
`<br><a href="${this._config.const.urlBase}test/core-restart">View "test/core-restart"</a>`,
|
|
142
|
+
`<br><a href="${this._config.const.urlBase}test/core-pm2?name=cron&action=restart">View "test/core-pm2"</a>`,
|
|
145
143
|
`<br><a href="${this._config.const.urlBase}test/core-global">View "test/core-global"</a>`,
|
|
146
144
|
`<br><a href="${this._config.const.urlBase}test/core-updatecode">View "test/core-updatecode"</a>`,
|
|
147
145
|
'<br><br><b>Crypto:</b>',
|
|
@@ -1278,6 +1276,18 @@ to: ${to}`
|
|
|
1278
1276
|
await lCore.sendRestart();
|
|
1279
1277
|
return 'The restart request has been sent, please review the console.<br><br>' + this._getEnd();
|
|
1280
1278
|
}
|
|
1279
|
+
async corePm2() {
|
|
1280
|
+
const name = this._get['name'] ?? '';
|
|
1281
|
+
const action = (this._get['action'] ?? 'restart');
|
|
1282
|
+
if (!name) {
|
|
1283
|
+
return 'Please provide the PM2 process name via ?name=xxx&action=restart<br>action: start, stop, restart (default: restart)<br><br>' + this._getEnd();
|
|
1284
|
+
}
|
|
1285
|
+
if (action !== 'start' && action !== 'stop' && action !== 'restart') {
|
|
1286
|
+
return 'Invalid action. Must be: start, stop, restart<br><br>' + this._getEnd();
|
|
1287
|
+
}
|
|
1288
|
+
const list = await lCore.sendPm2(name, action);
|
|
1289
|
+
return `PM2 ${action} request has been sent for "${name}".<br>Success hosts: ${JSON.stringify(list)}<br><br>` + this._getEnd();
|
|
1290
|
+
}
|
|
1281
1291
|
async coreGlobal() {
|
|
1282
1292
|
const ts = lTime.stamp().toString();
|
|
1283
1293
|
const echo = [
|
package/www/example/mod/test.js
CHANGED
|
@@ -38,10 +38,10 @@ CREATE UNIQUE INDEX "utoken" ON "m"."test" USING btree (
|
|
|
38
38
|
);
|
|
39
39
|
*/
|
|
40
40
|
export default class default_1 extends sMod {
|
|
41
|
-
static
|
|
42
|
-
static
|
|
43
|
-
static
|
|
44
|
-
static
|
|
41
|
+
static _$table = 'test';
|
|
42
|
+
static _$primary = 'id';
|
|
43
|
+
static _$key = 'token';
|
|
44
|
+
static _$index = 'utoken';
|
|
45
45
|
/* eslint-enable */
|
|
46
46
|
_keyGenerator() {
|
|
47
47
|
return 'test_' + lCore.rand(0, 3).toString();
|
|
@@ -9,6 +9,6 @@ CREATE TABLE `m_test_data_0` (
|
|
|
9
9
|
) ENGINE=InnoDB DEFAULT CHARSET=ascii COLLATE=ascii_bin;
|
|
10
10
|
*/
|
|
11
11
|
export default class default_1 extends sMod {
|
|
12
|
-
static
|
|
13
|
-
static
|
|
12
|
+
static _$table = 'test_data';
|
|
13
|
+
static _$primary = 'id';
|
|
14
14
|
}
|
package/www/example/ws/test.js
CHANGED
|
@@ -2,10 +2,7 @@ import * as sCtr from '#kebab/sys/ctr.js';
|
|
|
2
2
|
import * as lCrypto from '#kebab/lib/crypto.js';
|
|
3
3
|
import * as lCore from '#kebab/lib/core.js';
|
|
4
4
|
export default class extends sCtr.Ctr {
|
|
5
|
-
|
|
6
|
-
super(...arguments);
|
|
7
|
-
this._nick = '';
|
|
8
|
-
}
|
|
5
|
+
_nick = '';
|
|
9
6
|
onUpgrade() {
|
|
10
7
|
lCore.display('[/test] WebSocket test onUpgrade.');
|
|
11
8
|
return {
|