@maiyunnet/kebab 2.0.13 → 2.0.15
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/core.d.ts +39 -15
- package/lib/core.js +139 -144
- package/lib/db.d.ts +1 -1
- package/lib/db.js +29 -70
- package/lib/fs.js +17 -9
- package/lib/jwt.js +1 -1
- package/lib/session.js +1 -1
- package/lib/sql.d.ts +1 -1
- package/lib/sql.js +4 -34
- package/lib/text.d.ts +5 -0
- package/lib/text.js +8 -0
- package/lib/ws.js +1 -1
- package/package.json +5 -4
- package/sys/child.js +37 -78
- package/sys/cmd.js +1 -0
- package/sys/ctr.d.ts +2 -2
- package/sys/master.js +123 -1
- package/sys/route.js +12 -12
- package/www/example/ctr/test.d.ts +1 -0
- package/www/example/ctr/test.js +62 -9
- package/www/example/ws/test.js +2 -1
package/lib/db.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Project: Kebab, User: JianSuoQiYue
|
|
4
4
|
* Date: 2019-4-15 13:40
|
|
5
|
-
* Last: 2020-4-13 15:34:45, 2022-09-12 13:10:34, 2023-5-24 18:29:38, 2024-7-11 14:37:54, 2024-8-25 00:32:53, 2024-9-22 17:30:47
|
|
5
|
+
* Last: 2020-4-13 15:34:45, 2022-09-12 13:10:34, 2023-5-24 18:29:38, 2024-7-11 14:37:54, 2024-8-25 00:32:53, 2024-9-22 17:30:47, 2025-8-3 20:24:03
|
|
6
6
|
*/
|
|
7
7
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
8
|
if (k2 === undefined) k2 = k;
|
|
@@ -47,8 +47,8 @@ const mysql2 = __importStar(require("mysql2/promise"));
|
|
|
47
47
|
// --- 库和定义 ---
|
|
48
48
|
const time = __importStar(require("~/lib/time"));
|
|
49
49
|
const lSql = __importStar(require("~/lib/sql"));
|
|
50
|
-
const
|
|
51
|
-
const
|
|
50
|
+
const lCore = __importStar(require("~/lib/core"));
|
|
51
|
+
const lText = __importStar(require("~/lib/text"));
|
|
52
52
|
const ctr = __importStar(require("~/sys/ctr"));
|
|
53
53
|
/** --- 连接列表池 --- */
|
|
54
54
|
const connections = [];
|
|
@@ -71,23 +71,14 @@ async function checkConnection() {
|
|
|
71
71
|
if (connection.getLast() <= now - 60) {
|
|
72
72
|
// --- 1 分钟之前开始的 ---
|
|
73
73
|
const ls = connection.getLastSql();
|
|
74
|
-
const sql = ls[1] ?? ls[0];
|
|
75
|
-
console.log(`[child] [db] [error] There is a transactional connection[${i}] that is not closed, last sql: ${sql?.sql ?? 'undefined'}.`);
|
|
76
74
|
const newarr = ls.map(item => {
|
|
77
75
|
if (!item.values) {
|
|
78
76
|
return item.sql;
|
|
79
77
|
}
|
|
80
78
|
return lSql.format(item.sql, item.values);
|
|
81
79
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
'urlFull': '',
|
|
85
|
-
'hostname': '',
|
|
86
|
-
'req': null,
|
|
87
|
-
'get': {},
|
|
88
|
-
'cookie': {},
|
|
89
|
-
'headers': {}
|
|
90
|
-
}, `(db.checkConnection)There is a transactional connection[${i}] that is not closed, last sql: ${newarr.join(', ')}.`, '-error');
|
|
80
|
+
lCore.display(`[DB][error] There is a transactional connection[${i}] that is not closed, last sql: ${newarr.join(', ')}.`);
|
|
81
|
+
lCore.log({}, `[DB][checkConnection] There is a transactional connection[${i}] that is not closed, last sql: ${newarr.join(', ')}.`, '-error');
|
|
91
82
|
await connection.rollback();
|
|
92
83
|
}
|
|
93
84
|
continue;
|
|
@@ -103,12 +94,12 @@ async function checkConnection() {
|
|
|
103
94
|
--i;
|
|
104
95
|
}
|
|
105
96
|
setTimeout(function () {
|
|
106
|
-
checkConnection().catch(e => {
|
|
107
|
-
},
|
|
97
|
+
checkConnection().catch(e => { lCore.display('[DB][checkConnection]', e); });
|
|
98
|
+
}, 30_000);
|
|
108
99
|
}
|
|
109
100
|
setTimeout(function () {
|
|
110
|
-
checkConnection().catch(e => {
|
|
111
|
-
},
|
|
101
|
+
checkConnection().catch(e => { lCore.display('[DB][checkConnection]', e); });
|
|
102
|
+
}, 30_000);
|
|
112
103
|
/** --- 数据库连接池对象 --- */
|
|
113
104
|
class Pool {
|
|
114
105
|
constructor(etc) {
|
|
@@ -209,7 +200,7 @@ class Pool {
|
|
|
209
200
|
c.using();
|
|
210
201
|
link.on('error', function (err) {
|
|
211
202
|
if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
|
|
212
|
-
|
|
203
|
+
lCore.display('[DB][_getConnection]', err);
|
|
213
204
|
}
|
|
214
205
|
c.setLost();
|
|
215
206
|
}).on('end', function () {
|
|
@@ -219,15 +210,7 @@ class Pool {
|
|
|
219
210
|
connections.push(conn);
|
|
220
211
|
}
|
|
221
212
|
catch (e) {
|
|
222
|
-
|
|
223
|
-
'path': '',
|
|
224
|
-
'urlFull': '',
|
|
225
|
-
'hostname': '',
|
|
226
|
-
'req': null,
|
|
227
|
-
'get': {},
|
|
228
|
-
'cookie': {},
|
|
229
|
-
'headers': {}
|
|
230
|
-
}, '(db._getConnection)' + text.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
213
|
+
lCore.log({}, '[DB][Pool][_getConnection]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
231
214
|
}
|
|
232
215
|
}
|
|
233
216
|
return conn;
|
|
@@ -260,12 +243,12 @@ class Transaction {
|
|
|
260
243
|
const warning = opts.warning ?? 1_500;
|
|
261
244
|
this._timer.warning = setTimeout(() => {
|
|
262
245
|
this._timer.warning = undefined;
|
|
263
|
-
|
|
246
|
+
lCore.display('[WARNING][DB][Transaction] time too long, ms: ' + warning + ' ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr'));
|
|
264
247
|
}, warning);
|
|
265
248
|
const danger = opts.danger ?? 5_000;
|
|
266
249
|
this._timer.danger = setTimeout(() => {
|
|
267
250
|
this._timer.danger = undefined;
|
|
268
|
-
|
|
251
|
+
lCore.display('[DANGER][DB][Transaction] time too long, ms:', danger, this._ctr?.getPrototype('_config').const.path ?? 'no ctr');
|
|
269
252
|
}, danger);
|
|
270
253
|
}
|
|
271
254
|
/**
|
|
@@ -276,16 +259,8 @@ class Transaction {
|
|
|
276
259
|
async query(sql, values) {
|
|
277
260
|
if (!this._conn) {
|
|
278
261
|
// --- 当前连接已不可用 ---
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
'path': '',
|
|
282
|
-
'urlFull': '',
|
|
283
|
-
'hostname': '',
|
|
284
|
-
'req': null,
|
|
285
|
-
'get': {},
|
|
286
|
-
'cookie': {},
|
|
287
|
-
'headers': {}
|
|
288
|
-
}, '(db.Transaction.query) has been closed, ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr') + ': ' + sql, '-error');
|
|
262
|
+
lCore.display('[DB][Transaction][query] has been closed ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr') + ': ' + sql);
|
|
263
|
+
lCore.log({}, '[DB][Transaction][query] has been closed ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr') + ': ' + sql, '-error');
|
|
289
264
|
return {
|
|
290
265
|
'rows': null,
|
|
291
266
|
'fields': [],
|
|
@@ -306,16 +281,8 @@ class Transaction {
|
|
|
306
281
|
async execute(sql, values) {
|
|
307
282
|
if (!this._conn) {
|
|
308
283
|
// --- 当前连接已不可用 ---
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
'path': '',
|
|
312
|
-
'urlFull': '',
|
|
313
|
-
'hostname': '',
|
|
314
|
-
'req': null,
|
|
315
|
-
'get': {},
|
|
316
|
-
'cookie': {},
|
|
317
|
-
'headers': {}
|
|
318
|
-
}, '(db.Transaction.execute) has been closed, ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr') + ': ' + sql, '-error');
|
|
284
|
+
lCore.display('[DB][Transaction][execute] has been closed ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr') + ': ' + sql);
|
|
285
|
+
lCore.log({}, '(db.Transaction.execute) has been closed ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr') + ': ' + sql, '-error');
|
|
319
286
|
return {
|
|
320
287
|
'packet': null,
|
|
321
288
|
'fields': [],
|
|
@@ -331,16 +298,8 @@ class Transaction {
|
|
|
331
298
|
async commit() {
|
|
332
299
|
if (!this._conn) {
|
|
333
300
|
// --- 当前连接已不可用 ---
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
'path': '',
|
|
337
|
-
'urlFull': '',
|
|
338
|
-
'hostname': '',
|
|
339
|
-
'req': null,
|
|
340
|
-
'get': {},
|
|
341
|
-
'cookie': {},
|
|
342
|
-
'headers': {}
|
|
343
|
-
}, '(db.Transaction.commit) has been closed: ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr'), '-error');
|
|
301
|
+
lCore.display('[DB][Transaction][commit] has been closed ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr'));
|
|
302
|
+
lCore.log({}, '[DB][Transaction][commit] has been closed ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr'), '-error');
|
|
344
303
|
return false;
|
|
345
304
|
}
|
|
346
305
|
const r = await this._conn.commit();
|
|
@@ -360,16 +319,8 @@ class Transaction {
|
|
|
360
319
|
async rollback() {
|
|
361
320
|
if (!this._conn) {
|
|
362
321
|
// --- 当前连接已不可用 ---
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
'path': '',
|
|
366
|
-
'urlFull': '',
|
|
367
|
-
'hostname': '',
|
|
368
|
-
'req': null,
|
|
369
|
-
'get': {},
|
|
370
|
-
'cookie': {},
|
|
371
|
-
'headers': {}
|
|
372
|
-
}, '(db.Transaction.rollback) has been closed: ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr'), '-error');
|
|
322
|
+
lCore.display('[DB][Transaction][rollback] has been closed: ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr'));
|
|
323
|
+
lCore.log({}, '[DB][Transaction][rollback] has been closed: ' + (this._ctr?.getPrototype('_config').const.path ?? 'no ctr'), '-error');
|
|
373
324
|
return false;
|
|
374
325
|
}
|
|
375
326
|
const r = await this._conn.rollback();
|
|
@@ -501,7 +452,11 @@ class Connection {
|
|
|
501
452
|
'sql': sql,
|
|
502
453
|
'values': values
|
|
503
454
|
});
|
|
455
|
+
const time = Date.now();
|
|
504
456
|
res = await this._link.query(sql, values);
|
|
457
|
+
if (Date.now() - time > 200) {
|
|
458
|
+
lCore.log({}, '[WARNING][DB][Connection][query] slow sql 200ms: ' + sql, '-warning');
|
|
459
|
+
}
|
|
505
460
|
}
|
|
506
461
|
catch (e) {
|
|
507
462
|
if (!this._transaction) {
|
|
@@ -539,7 +494,11 @@ class Connection {
|
|
|
539
494
|
'sql': sql,
|
|
540
495
|
'values': values
|
|
541
496
|
});
|
|
497
|
+
const time = Date.now();
|
|
542
498
|
res = await this._link.execute(sql, values);
|
|
499
|
+
if (Date.now() - time > 200) {
|
|
500
|
+
lCore.log({}, '[WARNING][DB][Connection][execute] slow sql 200ms: ' + sql, '-warning');
|
|
501
|
+
}
|
|
543
502
|
}
|
|
544
503
|
catch (e) {
|
|
545
504
|
if (!this._transaction) {
|
package/lib/fs.js
CHANGED
|
@@ -75,8 +75,8 @@ async function getContent(path, options) {
|
|
|
75
75
|
'encoding': options
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
-
else
|
|
79
|
-
options
|
|
78
|
+
else {
|
|
79
|
+
options ??= {};
|
|
80
80
|
}
|
|
81
81
|
const encoding = options.encoding;
|
|
82
82
|
const start = options.start;
|
|
@@ -337,6 +337,16 @@ async function readDir(path, encoding) {
|
|
|
337
337
|
}
|
|
338
338
|
list.push(item);
|
|
339
339
|
}
|
|
340
|
+
// --- 将 list 根据先目录后文件排序,如果是同是目录或文件,则以名称排序 ---
|
|
341
|
+
list.sort((a, b) => {
|
|
342
|
+
// --- 目录排在文件前面 ---
|
|
343
|
+
if (a.isDirectory() && !b.isDirectory())
|
|
344
|
+
return -1;
|
|
345
|
+
if (!a.isDirectory() && b.isDirectory())
|
|
346
|
+
return 1;
|
|
347
|
+
// --- 同类型按名称排序 ---
|
|
348
|
+
return a.name.localeCompare(b.name);
|
|
349
|
+
});
|
|
340
350
|
return list;
|
|
341
351
|
}
|
|
342
352
|
catch {
|
|
@@ -413,8 +423,8 @@ function createReadStream(path, options) {
|
|
|
413
423
|
'encoding': options
|
|
414
424
|
};
|
|
415
425
|
}
|
|
416
|
-
else
|
|
417
|
-
options
|
|
426
|
+
else {
|
|
427
|
+
options ??= {};
|
|
418
428
|
}
|
|
419
429
|
return fs.createReadStream(path, {
|
|
420
430
|
'flags': options.flags,
|
|
@@ -450,8 +460,8 @@ function createWriteStream(path, options) {
|
|
|
450
460
|
'encoding': options
|
|
451
461
|
};
|
|
452
462
|
}
|
|
453
|
-
else
|
|
454
|
-
options
|
|
463
|
+
else {
|
|
464
|
+
options ??= {};
|
|
455
465
|
}
|
|
456
466
|
return fs.createWriteStream(path, {
|
|
457
467
|
'flags': options.flags,
|
|
@@ -469,9 +479,7 @@ function createWriteStream(path, options) {
|
|
|
469
479
|
* @param stat 文件的 stat(如果有)
|
|
470
480
|
*/
|
|
471
481
|
async function readToResponse(path, req, res, stat) {
|
|
472
|
-
|
|
473
|
-
stat = await stats(path);
|
|
474
|
-
}
|
|
482
|
+
stat ??= await stats(path);
|
|
475
483
|
if (!stat) {
|
|
476
484
|
res.setHeader('content-length', 22);
|
|
477
485
|
res.writeHead(404);
|
package/lib/jwt.js
CHANGED
|
@@ -98,7 +98,7 @@ class Jwt {
|
|
|
98
98
|
renew() {
|
|
99
99
|
const time = lTime.stamp();
|
|
100
100
|
const data = this._ctr.getPrototype('_jwt');
|
|
101
|
-
const token = data['token'] ?
|
|
101
|
+
const token = lText.isFalsy(data['token']) ? lCore.random(16, lCore.RANDOM_LUN) : data['token'];
|
|
102
102
|
data['exp'] = time + this._ttl;
|
|
103
103
|
data['token'] = token;
|
|
104
104
|
// --- 拼装 ---
|
package/lib/session.js
CHANGED
package/lib/sql.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Project: Kebab, User: JianSuoQiYue
|
|
3
3
|
* Date: 2019-5-27 20:18:50
|
|
4
|
-
* Last: 2020-3-29 19:37:25, 2022-07-24 22:38:11, 2023-5-24 18:49:18, 2023-6-13 22:20:21, 2023-12-11 13:58:54, 2023-12-14 13:14:40, 2023-12-21 00:04:40, 2024-4-11 19:29:29, 2024-9-2 17:15:28
|
|
4
|
+
* Last: 2020-3-29 19:37:25, 2022-07-24 22:38:11, 2023-5-24 18:49:18, 2023-6-13 22:20:21, 2023-12-11 13:58:54, 2023-12-14 13:14:40, 2023-12-21 00:04:40, 2024-4-11 19:29:29, 2024-9-2 17:15:28, 2025-8-3 21:28:18
|
|
5
5
|
*/
|
|
6
6
|
import * as ctr from '~/sys/ctr';
|
|
7
7
|
import * as types from '~/types';
|
package/lib/sql.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Project: Kebab, User: JianSuoQiYue
|
|
4
4
|
* Date: 2019-5-27 20:18:50
|
|
5
|
-
* Last: 2020-3-29 19:37:25, 2022-07-24 22:38:11, 2023-5-24 18:49:18, 2023-6-13 22:20:21, 2023-12-11 13:58:54, 2023-12-14 13:14:40, 2023-12-21 00:04:40, 2024-4-11 19:29:29, 2024-9-2 17:15:28
|
|
5
|
+
* Last: 2020-3-29 19:37:25, 2022-07-24 22:38:11, 2023-5-24 18:49:18, 2023-6-13 22:20:21, 2023-12-11 13:58:54, 2023-12-14 13:14:40, 2023-12-21 00:04:40, 2024-4-11 19:29:29, 2024-9-2 17:15:28, 2025-8-3 21:28:18
|
|
6
6
|
*/
|
|
7
7
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
8
|
if (k2 === undefined) k2 = k;
|
|
@@ -116,17 +116,7 @@ class Sql {
|
|
|
116
116
|
// --- v1 是项目值,如 {'x': 1, 'y': 2}, 'string', 0 ---
|
|
117
117
|
if (v1 === undefined || Number.isNaN(v1)) {
|
|
118
118
|
// --- 异常情况 ---
|
|
119
|
-
lCore.log({
|
|
120
|
-
'path': '',
|
|
121
|
-
'urlFull': '',
|
|
122
|
-
'hostname': '',
|
|
123
|
-
'req': null,
|
|
124
|
-
'get': {},
|
|
125
|
-
'cookie': {},
|
|
126
|
-
'headers': {}
|
|
127
|
-
}, '(sql.values) value error', '-error').catch(() => {
|
|
128
|
-
//
|
|
129
|
-
});
|
|
119
|
+
lCore.log({}, '[SQL][values] value error', '-error');
|
|
130
120
|
sql += `'', `;
|
|
131
121
|
}
|
|
132
122
|
else if (v1 === null) {
|
|
@@ -200,17 +190,7 @@ class Sql {
|
|
|
200
190
|
sql += this.field(k) + ', ';
|
|
201
191
|
if (v === undefined || Number.isNaN(v)) {
|
|
202
192
|
// --- 异常情况 ---
|
|
203
|
-
lCore.log({
|
|
204
|
-
'path': '',
|
|
205
|
-
'urlFull': '',
|
|
206
|
-
'hostname': '',
|
|
207
|
-
'req': null,
|
|
208
|
-
'get': {},
|
|
209
|
-
'cookie': {},
|
|
210
|
-
'headers': {}
|
|
211
|
-
}, '(sql.values) value error', '-error').catch(() => {
|
|
212
|
-
//
|
|
213
|
-
});
|
|
193
|
+
lCore.log({}, '[SQL][values] value error', '-error');
|
|
214
194
|
values += `'', `;
|
|
215
195
|
}
|
|
216
196
|
else if (v === null) {
|
|
@@ -413,17 +393,7 @@ class Sql {
|
|
|
413
393
|
sql += this.field(k) + ' = ';
|
|
414
394
|
if (v === undefined || Number.isNaN(v)) {
|
|
415
395
|
// --- 异常情况 ---
|
|
416
|
-
lCore.log({
|
|
417
|
-
'path': '',
|
|
418
|
-
'urlFull': '',
|
|
419
|
-
'hostname': '',
|
|
420
|
-
'req': null,
|
|
421
|
-
'get': {},
|
|
422
|
-
'cookie': {},
|
|
423
|
-
'headers': {}
|
|
424
|
-
}, '(sql._updateSub) value error, key: ' + k, '-error').catch(() => {
|
|
425
|
-
//
|
|
426
|
-
});
|
|
396
|
+
lCore.log({}, '[SQL][_updateSub] value error, key: ' + k, '-error');
|
|
427
397
|
sql += '"", ';
|
|
428
398
|
}
|
|
429
399
|
else if (v === null) {
|
package/lib/text.d.ts
CHANGED
|
@@ -139,6 +139,11 @@ type TFalsy = false | '' | 0 | null | undefined | typeof NaN;
|
|
|
139
139
|
* @param val 要判断的值
|
|
140
140
|
*/
|
|
141
141
|
export declare function isFalsy(val: any): val is TFalsy;
|
|
142
|
+
/**
|
|
143
|
+
* --- 判断一个值是否是真实的(不为 null/undefined/空字符串/false/0) ---
|
|
144
|
+
* @param val 要判断的值
|
|
145
|
+
*/
|
|
146
|
+
export declare function isTruthy(val: any): val is Exclude<typeof val, TFalsy>;
|
|
142
147
|
/**
|
|
143
148
|
* --- 类似 || 运算符的效果 ---
|
|
144
149
|
* @param v1 比对值
|
package/lib/text.js
CHANGED
|
@@ -58,6 +58,7 @@ exports.parseJson = parseJson;
|
|
|
58
58
|
exports.stringifyJson = stringifyJson;
|
|
59
59
|
exports.stringifyBuffer = stringifyBuffer;
|
|
60
60
|
exports.isFalsy = isFalsy;
|
|
61
|
+
exports.isTruthy = isTruthy;
|
|
61
62
|
exports.logicalOr = logicalOr;
|
|
62
63
|
exports.str2int = str2int;
|
|
63
64
|
exports.int2str = int2str;
|
|
@@ -587,6 +588,13 @@ function stringifyBuffer(buf) {
|
|
|
587
588
|
function isFalsy(val) {
|
|
588
589
|
return (val === null) || (val === undefined) || (val === '') || (val === false) || (val === 0);
|
|
589
590
|
}
|
|
591
|
+
/**
|
|
592
|
+
* --- 判断一个值是否是真实的(不为 null/undefined/空字符串/false/0) ---
|
|
593
|
+
* @param val 要判断的值
|
|
594
|
+
*/
|
|
595
|
+
function isTruthy(val) {
|
|
596
|
+
return !isFalsy(val);
|
|
597
|
+
}
|
|
590
598
|
/**
|
|
591
599
|
* --- 类似 || 运算符的效果 ---
|
|
592
600
|
* @param v1 比对值
|
package/lib/ws.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maiyunnet/kebab",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.15",
|
|
4
4
|
"description": "Simple, easy-to-use, and fully-featured Node.js framework that is ready-to-use out of the box.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kebab",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"kebab": "./bin/kebab.js"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@aws-sdk/client-s3": "^3.
|
|
18
|
-
"@aws-sdk/lib-storage": "^3.
|
|
17
|
+
"@aws-sdk/client-s3": "^3.844.0",
|
|
18
|
+
"@aws-sdk/lib-storage": "^3.844.0",
|
|
19
19
|
"@litert/http-client": "^1.1.2",
|
|
20
20
|
"@litert/mime": "^0.1.3",
|
|
21
21
|
"@litert/redis": "^3.0.5",
|
|
@@ -26,12 +26,13 @@
|
|
|
26
26
|
"mysql2": "^3.14.1",
|
|
27
27
|
"ssh2": "^1.16.0",
|
|
28
28
|
"svg-captcha": "^1.4.0",
|
|
29
|
+
"tencentcloud-sdk-nodejs": "^4.1.74",
|
|
29
30
|
"ts-alias-loader": "^0.1.5"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"@litert/eslint-plugin-rules": "^0.3.1",
|
|
33
34
|
"@types/ejs": "^3.1.5",
|
|
34
|
-
"@types/node": "^24.0.
|
|
35
|
+
"@types/node": "^24.0.12",
|
|
35
36
|
"tsc-alias": "^1.8.16",
|
|
36
37
|
"typescript": "^5.8.3"
|
|
37
38
|
}
|
package/sys/child.js
CHANGED
|
@@ -61,9 +61,11 @@ const hbTimer = setInterval(function () {
|
|
|
61
61
|
});
|
|
62
62
|
}, 10_000);
|
|
63
63
|
/** --- 加载的证书列表(path: { sc, cert }) --- */
|
|
64
|
-
|
|
64
|
+
let certList = [];
|
|
65
65
|
/** --- server: index --- */
|
|
66
66
|
let certHostIndex = {};
|
|
67
|
+
/** --- 最后一次加载证书到内存的时间 --- */
|
|
68
|
+
let certLastLoad = 0;
|
|
67
69
|
/** --- 当前的虚拟主机配置列表 - 读取于 conf/vhost/*.json --- */
|
|
68
70
|
let vhosts = [];
|
|
69
71
|
/** --- http 服务器 --- */
|
|
@@ -82,6 +84,12 @@ async function run() {
|
|
|
82
84
|
http2Server = http2.createSecureServer({
|
|
83
85
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
84
86
|
'SNICallback': (servername, cb) => {
|
|
87
|
+
if (Date.now() - certLastLoad > 60_000 * 60 * 24) {
|
|
88
|
+
// --- 不能用异步,不要干扰 SNI 进程 ---
|
|
89
|
+
reloadCert().catch(e => {
|
|
90
|
+
lCore.display('[CHILD][run] reloadCert error', e);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
85
93
|
const i = certHostIndex[servername];
|
|
86
94
|
if (i !== undefined) {
|
|
87
95
|
cb(null, certList[i].sc);
|
|
@@ -119,16 +127,8 @@ async function run() {
|
|
|
119
127
|
if (!linkCount[key]) {
|
|
120
128
|
delete linkCount[key];
|
|
121
129
|
}
|
|
122
|
-
})().catch(
|
|
123
|
-
|
|
124
|
-
'path': '',
|
|
125
|
-
'urlFull': '',
|
|
126
|
-
'hostname': '',
|
|
127
|
-
'req': req,
|
|
128
|
-
'get': {},
|
|
129
|
-
'cookie': {},
|
|
130
|
-
'headers': {}
|
|
131
|
-
}, '[child][http2][request]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
130
|
+
})().catch(function (e) {
|
|
131
|
+
lCore.log({}, '[CHILD][http2][request] ' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
132
132
|
--linkCount[key];
|
|
133
133
|
if (!linkCount[key]) {
|
|
134
134
|
delete linkCount[key];
|
|
@@ -153,16 +153,8 @@ async function run() {
|
|
|
153
153
|
if (!linkCount[key]) {
|
|
154
154
|
delete linkCount[key];
|
|
155
155
|
}
|
|
156
|
-
})().catch(
|
|
157
|
-
|
|
158
|
-
'path': '',
|
|
159
|
-
'urlFull': '',
|
|
160
|
-
'hostname': '',
|
|
161
|
-
'req': req,
|
|
162
|
-
'get': {},
|
|
163
|
-
'cookie': {},
|
|
164
|
-
'headers': {}
|
|
165
|
-
}, '[child][http2][upgrade]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
156
|
+
})().catch(function (e) {
|
|
157
|
+
lCore.log({}, '[CHILD][http2][upgrade] ' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
166
158
|
--linkCount[key];
|
|
167
159
|
if (!linkCount[key]) {
|
|
168
160
|
delete linkCount[key];
|
|
@@ -186,16 +178,8 @@ async function run() {
|
|
|
186
178
|
if (!linkCount[key]) {
|
|
187
179
|
delete linkCount[key];
|
|
188
180
|
}
|
|
189
|
-
})().catch(
|
|
190
|
-
|
|
191
|
-
'path': '',
|
|
192
|
-
'urlFull': '',
|
|
193
|
-
'hostname': '',
|
|
194
|
-
'req': req,
|
|
195
|
-
'get': {},
|
|
196
|
-
'cookie': {},
|
|
197
|
-
'headers': {}
|
|
198
|
-
}, '[child][http][request]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
181
|
+
})().catch(function (e) {
|
|
182
|
+
lCore.log({}, '[CHILD][http][request] ' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
199
183
|
--linkCount[key];
|
|
200
184
|
if (!linkCount[key]) {
|
|
201
185
|
delete linkCount[key];
|
|
@@ -218,16 +202,8 @@ async function run() {
|
|
|
218
202
|
if (!linkCount[key]) {
|
|
219
203
|
delete linkCount[key];
|
|
220
204
|
}
|
|
221
|
-
})().catch(
|
|
222
|
-
|
|
223
|
-
'path': '',
|
|
224
|
-
'urlFull': '',
|
|
225
|
-
'hostname': '',
|
|
226
|
-
'req': req,
|
|
227
|
-
'get': {},
|
|
228
|
-
'cookie': {},
|
|
229
|
-
'headers': {}
|
|
230
|
-
}, '[child][http][upgrade]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
205
|
+
})().catch(function (e) {
|
|
206
|
+
lCore.log({}, '[CHILD][http][upgrade] ' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
231
207
|
--linkCount[key];
|
|
232
208
|
if (!linkCount[key]) {
|
|
233
209
|
delete linkCount[key];
|
|
@@ -335,7 +311,7 @@ async function requestHandler(req, res, https) {
|
|
|
335
311
|
}
|
|
336
312
|
}
|
|
337
313
|
catch (e) {
|
|
338
|
-
|
|
314
|
+
lCore.log({
|
|
339
315
|
'path': path.slice(('/' + pathList.slice(0, i).join('/')).length + 1),
|
|
340
316
|
'urlFull': (uri.protocol ?? '') + '//' + (uri.host ?? '') + '/' + now,
|
|
341
317
|
'hostname': uri.hostname ?? '',
|
|
@@ -343,7 +319,7 @@ async function requestHandler(req, res, https) {
|
|
|
343
319
|
'get': uri.query ? lText.queryParse(uri.query) : {},
|
|
344
320
|
'cookie': {},
|
|
345
321
|
'headers': {}
|
|
346
|
-
}, '
|
|
322
|
+
}, '[CHILD][requestHandler][E0]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
347
323
|
res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
348
324
|
res.setHeader('content-length', 25);
|
|
349
325
|
res.writeHead(500);
|
|
@@ -381,15 +357,7 @@ async function requestHandler(req, res, https) {
|
|
|
381
357
|
}
|
|
382
358
|
}
|
|
383
359
|
catch (e) {
|
|
384
|
-
|
|
385
|
-
'path': path.slice(1),
|
|
386
|
-
'urlFull': (uri.protocol ?? '') + '//' + (uri.host ?? '') + '/' + now,
|
|
387
|
-
'hostname': uri.hostname ?? '',
|
|
388
|
-
'req': req,
|
|
389
|
-
'get': uri.query ? lText.queryParse(uri.query) : {},
|
|
390
|
-
'cookie': {},
|
|
391
|
-
'headers': {}
|
|
392
|
-
}, '(E02)' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
360
|
+
lCore.log({}, '[CHILD][requestHandler][E1]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
393
361
|
res.setHeader('content-type', 'text/html; charset=utf-8');
|
|
394
362
|
res.setHeader('content-length', 25);
|
|
395
363
|
res.writeHead(500);
|
|
@@ -540,7 +508,17 @@ async function reload() {
|
|
|
540
508
|
}
|
|
541
509
|
}
|
|
542
510
|
// --- 重新加载证书对 ---
|
|
543
|
-
|
|
511
|
+
await reloadCert();
|
|
512
|
+
// --- 其他操作 ---
|
|
513
|
+
sRoute.clearKebabConfigs();
|
|
514
|
+
sCtr.clearLocaleData();
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* --- 重新加载证书对 ---
|
|
518
|
+
*/
|
|
519
|
+
async function reloadCert() {
|
|
520
|
+
certLastLoad = Date.now();
|
|
521
|
+
const cl = [];
|
|
544
522
|
try {
|
|
545
523
|
const certConfig = await fs.getContent(kebab.CONF_CWD + 'cert.json', 'utf8');
|
|
546
524
|
if (certConfig) {
|
|
@@ -556,7 +534,7 @@ async function reload() {
|
|
|
556
534
|
'key': key,
|
|
557
535
|
'cert': cert
|
|
558
536
|
});
|
|
559
|
-
|
|
537
|
+
cl.push({
|
|
560
538
|
'cert': certo,
|
|
561
539
|
'sc': sc
|
|
562
540
|
});
|
|
@@ -566,10 +544,8 @@ async function reload() {
|
|
|
566
544
|
catch {
|
|
567
545
|
// --- NOTHING ---
|
|
568
546
|
}
|
|
547
|
+
certList = cl;
|
|
569
548
|
certHostIndex = {};
|
|
570
|
-
// --- 其他操作 ---
|
|
571
|
-
sRoute.clearKebabConfigs();
|
|
572
|
-
sCtr.clearLocaleData();
|
|
573
549
|
}
|
|
574
550
|
// --- 接收主进程回传信号,主要用来 reload,restart ---
|
|
575
551
|
process.on('message', function (msg) {
|
|
@@ -598,17 +574,8 @@ process.on('message', function (msg) {
|
|
|
598
574
|
for (const key in linkCount) {
|
|
599
575
|
str.push(key + ':' + linkCount[key].toString());
|
|
600
576
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
await lCore.log({
|
|
604
|
-
'path': '',
|
|
605
|
-
'urlFull': '',
|
|
606
|
-
'hostname': '',
|
|
607
|
-
'req': null,
|
|
608
|
-
'get': {},
|
|
609
|
-
'cookie': {},
|
|
610
|
-
'headers': {}
|
|
611
|
-
}, `[child] Worker ${process.pid} busy: ${str.join(',')}.`, '-error');
|
|
577
|
+
lCore.display(`[CHILD] Worker ${process.pid} busy: ${str.join(',')}.`);
|
|
578
|
+
lCore.log({}, `[CHILD] Worker ${process.pid} busy: ${str.join(',')}.`, '-error');
|
|
612
579
|
await lCore.sleep(30_000);
|
|
613
580
|
waiting += 30_000;
|
|
614
581
|
if (waiting > 3600_000) {
|
|
@@ -635,16 +602,8 @@ process.on('message', function (msg) {
|
|
|
635
602
|
break;
|
|
636
603
|
}
|
|
637
604
|
}
|
|
638
|
-
})().catch(
|
|
639
|
-
|
|
640
|
-
'path': '',
|
|
641
|
-
'urlFull': '',
|
|
642
|
-
'hostname': '',
|
|
643
|
-
'req': null,
|
|
644
|
-
'get': {},
|
|
645
|
-
'cookie': {},
|
|
646
|
-
'headers': {}
|
|
647
|
-
}, '[child][process][message]' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
605
|
+
})().catch(function (e) {
|
|
606
|
+
lCore.log({}, '[CHILD][process][message] ' + lText.stringifyJson(e.stack).slice(1, -1), '-error');
|
|
648
607
|
});
|
|
649
608
|
});
|
|
650
609
|
/**
|