@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.
- package/index.d.ts +11 -1
- package/index.js +13 -1
- package/lib/buffer.d.ts +25 -0
- package/lib/buffer.js +30 -5
- package/lib/captcha.d.ts +15 -0
- package/lib/captcha.js +20 -0
- package/lib/consistent.d.ts +51 -0
- package/lib/consistent.js +59 -0
- package/lib/core.d.ts +134 -0
- package/lib/core.js +176 -0
- package/lib/crypto.d.ts +75 -6
- package/lib/crypto.js +206 -38
- package/lib/db.d.ts +104 -0
- package/lib/db.js +126 -0
- package/lib/dns.d.ts +51 -0
- package/lib/dns.js +54 -2
- package/lib/fs.d.ts +100 -0
- package/lib/fs.js +118 -0
- package/lib/jwt.d.ts +43 -0
- package/lib/jwt.js +45 -0
- package/lib/kv.d.ts +362 -0
- package/lib/kv.js +377 -0
- package/lib/lan.d.ts +6 -0
- package/lib/lan.js +7 -0
- package/lib/net/formdata.d.ts +38 -0
- package/lib/net/formdata.js +43 -0
- package/lib/net/request.d.ts +62 -0
- package/lib/net/request.js +57 -0
- package/lib/net/response.d.ts +21 -0
- package/lib/net/response.js +16 -0
- package/lib/net.d.ts +86 -0
- package/lib/net.js +140 -0
- package/lib/s3.d.ts +52 -0
- package/lib/s3.js +51 -0
- package/lib/scan.d.ts +52 -0
- package/lib/scan.js +84 -0
- package/lib/session.d.ts +31 -0
- package/lib/session.js +52 -1
- package/lib/sql.d.ts +176 -0
- package/lib/sql.js +287 -2
- package/lib/ssh/sftp.d.ts +106 -0
- package/lib/ssh/sftp.js +106 -0
- package/lib/ssh/shell.d.ts +37 -0
- package/lib/ssh/shell.js +31 -0
- package/lib/ssh.d.ts +32 -0
- package/lib/ssh.js +32 -0
- package/lib/text.d.ts +131 -0
- package/lib/text.js +188 -0
- package/lib/time.d.ts +53 -0
- package/lib/time.js +55 -0
- package/lib/ws.d.ts +68 -0
- package/lib/ws.js +74 -0
- package/lib/zip.d.ts +53 -0
- package/lib/zip.js +73 -0
- package/lib/zlib.d.ts +76 -0
- package/lib/zlib.js +78 -0
- package/main.d.ts +5 -0
- package/main.js +12 -0
- package/package.json +3 -2
- package/sys/child.js +104 -0
- package/sys/cmd.js +28 -0
- package/sys/ctr.d.ts +166 -0
- package/sys/ctr.js +177 -0
- package/sys/master.js +63 -0
- package/sys/mod.d.ts +266 -0
- package/sys/mod.js +335 -0
- package/sys/route.d.ts +34 -0
- package/sys/route.js +164 -0
- package/www/example/ctr/test.d.ts +3 -0
- package/www/example/ctr/test.js +63 -1
- package/www/example/mod/test.js +14 -0
- package/www/example/mod/testdata.js +9 -0
- package/www/example/ws/test.js +1 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/details.md +0 -82
- package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +0 -15
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +0 -2
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +0 -19
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +0 -22
- package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +0 -69
- package/.VSCodeCounter/2025-02-14_14-46-44/results.json +0 -1
- package/.VSCodeCounter/2025-02-14_14-46-44/results.md +0 -48
- package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +0 -118
- package/.vscode/tasks.json +0 -15
package/sys/ctr.js
CHANGED
|
@@ -42,9 +42,15 @@ const crypto = __importStar(require("../lib/crypto"));
|
|
|
42
42
|
const session = __importStar(require("../lib/session"));
|
|
43
43
|
const text = __importStar(require("../lib/text"));
|
|
44
44
|
const sRoute = __importStar(require("../sys/route"));
|
|
45
|
+
/** --- 已加载的 DATA 数据缓存(不是语言包)-- */
|
|
45
46
|
let loadedData = {};
|
|
47
|
+
/** --- 已加载的语言文件列表 --- */
|
|
46
48
|
let localeFiles = [];
|
|
49
|
+
/** --- 已经加载的语言包(全局) --- */
|
|
47
50
|
let localeData = {};
|
|
51
|
+
/**
|
|
52
|
+
* --- 清除已经加载的 data 与语言包文件缓存 ---
|
|
53
|
+
*/
|
|
48
54
|
function clearLocaleData() {
|
|
49
55
|
loadedData = {};
|
|
50
56
|
localeFiles = [];
|
|
@@ -52,26 +58,45 @@ function clearLocaleData() {
|
|
|
52
58
|
}
|
|
53
59
|
class Ctr {
|
|
54
60
|
constructor(config, req, res) {
|
|
61
|
+
/** --- 路由参数序列数组 --- */
|
|
55
62
|
this._param = [];
|
|
63
|
+
/** --- 当前的 action 名 --- */
|
|
56
64
|
this._action = '';
|
|
65
|
+
/** --- 请求的 header 列表,key 均为小写 --- */
|
|
57
66
|
this._headers = {};
|
|
67
|
+
/** --- 原始 POST 数据 --- */
|
|
58
68
|
this._rawPost = {};
|
|
69
|
+
/** --- POST 数据 --- */
|
|
59
70
|
this._post = {};
|
|
71
|
+
/** --- 原始 input 字符串 */
|
|
60
72
|
this._input = '';
|
|
73
|
+
/** --- 上传的文件列表 --- */
|
|
61
74
|
this._files = {};
|
|
75
|
+
/** --- Cookie 数组 --- */
|
|
62
76
|
this._cookie = {};
|
|
77
|
+
/** --- Jwt 数组 --- */
|
|
63
78
|
this._jwt = {};
|
|
79
|
+
/** --- Session 数组 --- */
|
|
64
80
|
this._session = {};
|
|
81
|
+
/** --- Session --- 对象 */
|
|
65
82
|
this._sess = null;
|
|
83
|
+
/** --- XSRF TOKEN 值 --- */
|
|
66
84
|
this._xsrf = '';
|
|
85
|
+
/** --- 自定义 http code --- */
|
|
67
86
|
this._httpCode = 0;
|
|
87
|
+
// --- Kebab: true,Mutton: false,全局常量等对象 ---
|
|
88
|
+
/** --- 当前语言名 --- */
|
|
68
89
|
this._locale = 'en';
|
|
90
|
+
/** --- 本 ctr 已加载的语言文件列表 --- */
|
|
69
91
|
this._localeFiles = [];
|
|
92
|
+
/** --- 本 ctr 的 locale data --- */
|
|
70
93
|
this._localeData = {};
|
|
94
|
+
/** --- 一些需要等待的事项的记录(异步任务、事务) --- */
|
|
71
95
|
this._waitInfo = {
|
|
72
96
|
'asyncTask': {
|
|
73
97
|
'count': 0,
|
|
74
98
|
'resolve': () => {
|
|
99
|
+
// --- NOTHING ---
|
|
75
100
|
},
|
|
76
101
|
'callback': function () {
|
|
77
102
|
return new Promise((resolve) => {
|
|
@@ -81,6 +106,7 @@ class Ctr {
|
|
|
81
106
|
},
|
|
82
107
|
'transaction': 0
|
|
83
108
|
};
|
|
109
|
+
/** --- auth 对象,user, pwd --- */
|
|
84
110
|
this._authorization = null;
|
|
85
111
|
this._config = config;
|
|
86
112
|
this._req = req;
|
|
@@ -89,12 +115,17 @@ class Ctr {
|
|
|
89
115
|
}
|
|
90
116
|
this._cacheTTL = config.set.cacheTtl;
|
|
91
117
|
}
|
|
118
|
+
/** --- 当前用户连接是否还在连接中 --- */
|
|
92
119
|
get isAvail() {
|
|
93
120
|
return this._req.socket.writable;
|
|
94
121
|
}
|
|
122
|
+
/** --- 获取当前过期时间 --- */
|
|
95
123
|
get timeout() {
|
|
96
124
|
return this._timer?.timeout ?? 30_000;
|
|
97
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* --- 设置当前过期时间 ---
|
|
128
|
+
*/
|
|
98
129
|
set timeout(num) {
|
|
99
130
|
if (!this._timer) {
|
|
100
131
|
return;
|
|
@@ -103,6 +134,10 @@ class Ctr {
|
|
|
103
134
|
clearTimeout(this._timer.timer);
|
|
104
135
|
this._timer.timer = setTimeout(this._timer.callback, num);
|
|
105
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* --- 执行一段跳出堆栈的异步代码,代码执行完成前,热更新不会杀死当面进程 且 ftmp 临时文件不会被清除 ---
|
|
139
|
+
* @param func 异步代码
|
|
140
|
+
*/
|
|
106
141
|
_asyncTask(func) {
|
|
107
142
|
++this._waitInfo.asyncTask.count;
|
|
108
143
|
setTimeout(() => {
|
|
@@ -125,15 +160,26 @@ class Ctr {
|
|
|
125
160
|
getPrototype(name) {
|
|
126
161
|
return this[name];
|
|
127
162
|
}
|
|
163
|
+
/** --- 设置类内部的 prototype --- */
|
|
128
164
|
setPrototype(name, val) {
|
|
129
165
|
this[name] = val;
|
|
130
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* --- 实例化后会执行的方法,可重写此方法 ---
|
|
169
|
+
*/
|
|
131
170
|
onLoad() {
|
|
132
171
|
return true;
|
|
133
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* --- 整个结束前会执行本方法,可重写此方法对输出结果再处理一次(Websocket 模式无效) ---
|
|
175
|
+
* @param rtn 之前用户的输出结果
|
|
176
|
+
*/
|
|
134
177
|
onUnload(rtn) {
|
|
135
178
|
return rtn;
|
|
136
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* --- WebSocket 下在建立 Server 连接之前可对 WebSocket 的信息进行配置 ---
|
|
182
|
+
*/
|
|
137
183
|
onUpgrade() {
|
|
138
184
|
return {};
|
|
139
185
|
}
|
|
@@ -143,19 +189,37 @@ class Ctr {
|
|
|
143
189
|
onMessage() {
|
|
144
190
|
return;
|
|
145
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* --- WebSocket 下连接恢复可写入状态后会调用此事件,可重写此方法 ---
|
|
194
|
+
*/
|
|
146
195
|
onDrain() {
|
|
147
196
|
return;
|
|
148
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* --- WebSocket 下连接被终止后会自动被调用的事件,可重写此方法 ---
|
|
200
|
+
*/
|
|
149
201
|
onClose() {
|
|
150
202
|
return;
|
|
151
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* --- 获取截止当前时间的总运行时间 ---
|
|
206
|
+
* @param ms 为 true 为毫秒,否则为秒
|
|
207
|
+
*/
|
|
152
208
|
_getRunTime(ms = false) {
|
|
153
209
|
const t = process.hrtime.bigint() - this._config.const.startTime;
|
|
154
210
|
return ms ? Number(t) / 1000000 : Number(t) / 1000000000;
|
|
155
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* --- 获取截止当前内存的使用情况 ---
|
|
214
|
+
*/
|
|
156
215
|
_getMemoryUsage() {
|
|
157
216
|
return process.memoryUsage().rss - this._config.const.startMemory;
|
|
158
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* --- 加载视图 ---
|
|
220
|
+
* @param path
|
|
221
|
+
* @param data
|
|
222
|
+
*/
|
|
159
223
|
async _loadView(path, data = {}) {
|
|
160
224
|
const content = await fs.getContent(this._config.const.viewPath + path + '.ejs', 'utf8');
|
|
161
225
|
if (!content) {
|
|
@@ -167,21 +231,34 @@ class Ctr {
|
|
|
167
231
|
data._staticVer = this._config.set.staticVer;
|
|
168
232
|
data._staticPath = this._config.set.staticPath;
|
|
169
233
|
data._staticPathFull = this._config.set.staticPathFull;
|
|
234
|
+
// --- 语言包 ---
|
|
170
235
|
data.l = (key, data) => {
|
|
171
236
|
return this._l(key, data);
|
|
172
237
|
};
|
|
173
238
|
return lCore.purify(ejs.render(content, data));
|
|
174
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* --- 检测提交的数据类型 ---
|
|
242
|
+
* @param input 要校验的输入项
|
|
243
|
+
* @param rule 规则
|
|
244
|
+
* @param rtn 返回值
|
|
245
|
+
*/
|
|
175
246
|
_checkInput(input, rule, rtn) {
|
|
247
|
+
// --- 遍历规则 ---
|
|
248
|
+
// --- input, {'xx': ['require', '> 6', [0, 'xx 必须大于 6']], 'yy': [], '_xsrf': []], rtn ---
|
|
176
249
|
for (const key in rule) {
|
|
177
250
|
const val = rule[key];
|
|
251
|
+
// --- key 就是上面的 xx ---
|
|
178
252
|
if (input[key] === undefined) {
|
|
253
|
+
// --- 原值不存在则设定为 null ---
|
|
179
254
|
input[key] = null;
|
|
180
255
|
}
|
|
256
|
+
// --- 判断是否需要遍历 val ---
|
|
181
257
|
const c = val.length;
|
|
182
258
|
if (c === 0) {
|
|
183
259
|
continue;
|
|
184
260
|
}
|
|
261
|
+
// --- ['require', '> 6', [0, 'xx 必须大于 6']] ---
|
|
185
262
|
const lastK = c - 1;
|
|
186
263
|
if ((val[lastK][0] === undefined) || (val[lastK][1] === undefined) || !Number.isInteger(val[lastK][0]) || (typeof val[lastK][1] !== 'string')) {
|
|
187
264
|
rtn[0] = 0;
|
|
@@ -199,10 +276,12 @@ class Ctr {
|
|
|
199
276
|
}
|
|
200
277
|
return false;
|
|
201
278
|
}
|
|
279
|
+
// --- 判断提交的数据是否在此 array 之内,若没有提交数据,则自动设置为第一个项 ---
|
|
202
280
|
if (input[key] === null) {
|
|
203
281
|
input[key] = v[0];
|
|
204
282
|
}
|
|
205
283
|
else if (!v.includes(input[key])) {
|
|
284
|
+
// --- 不在 ---
|
|
206
285
|
rtn[0] = val[lastK][0];
|
|
207
286
|
rtn[1] = val[lastK][1];
|
|
208
287
|
if (val[lastK][2]) {
|
|
@@ -212,6 +291,7 @@ class Ctr {
|
|
|
212
291
|
}
|
|
213
292
|
}
|
|
214
293
|
else if (v instanceof RegExp) {
|
|
294
|
+
// --- 正则 ---
|
|
215
295
|
if (input[key] !== null && !v.test(input[key])) {
|
|
216
296
|
rtn[0] = val[lastK][0];
|
|
217
297
|
rtn[1] = val[lastK][1];
|
|
@@ -222,6 +302,7 @@ class Ctr {
|
|
|
222
302
|
}
|
|
223
303
|
}
|
|
224
304
|
else if (typeof v === 'object' && v.type !== undefined) {
|
|
305
|
+
// --- core.checkType ---
|
|
225
306
|
if (input[key] !== null) {
|
|
226
307
|
const r = lCore.checkType(input[key], v.type);
|
|
227
308
|
if (r) {
|
|
@@ -297,6 +378,7 @@ class Ctr {
|
|
|
297
378
|
case 'bool':
|
|
298
379
|
case 'boolean': {
|
|
299
380
|
if (input[key] !== null && (typeof input[key] !== 'boolean')) {
|
|
381
|
+
// --- 如果不是 bool 直接失败,字符串的 true, false 也会失败 ---
|
|
300
382
|
rtn[0] = val[lastK][0];
|
|
301
383
|
rtn[1] = val[lastK][1];
|
|
302
384
|
if (val[lastK][2]) {
|
|
@@ -308,6 +390,7 @@ class Ctr {
|
|
|
308
390
|
}
|
|
309
391
|
case 'string': {
|
|
310
392
|
if (input[key] !== null && (typeof input[key] !== 'string')) {
|
|
393
|
+
// --- 如果不是 string 直接失败 ---
|
|
311
394
|
rtn[0] = val[lastK][0];
|
|
312
395
|
rtn[1] = val[lastK][1];
|
|
313
396
|
if (val[lastK][2]) {
|
|
@@ -321,6 +404,7 @@ class Ctr {
|
|
|
321
404
|
let match;
|
|
322
405
|
if (input[key] !== null) {
|
|
323
406
|
if (v[0] === '/') {
|
|
407
|
+
// --- 正则 ---
|
|
324
408
|
if (!(new RegExp(v.slice(1, -1))).test(input[key])) {
|
|
325
409
|
rtn[0] = val[lastK][0];
|
|
326
410
|
rtn[1] = val[lastK][1];
|
|
@@ -331,6 +415,7 @@ class Ctr {
|
|
|
331
415
|
}
|
|
332
416
|
}
|
|
333
417
|
else if ((match = /^([><=]+) *([0-9]+)$/.exec(v))) {
|
|
418
|
+
// --- 判断表达式 ---
|
|
334
419
|
let needReturn = false;
|
|
335
420
|
const inputNum = Number(input[key]);
|
|
336
421
|
const num = Number(match[2]);
|
|
@@ -402,11 +487,22 @@ class Ctr {
|
|
|
402
487
|
}
|
|
403
488
|
return true;
|
|
404
489
|
}
|
|
490
|
+
/**
|
|
491
|
+
* --- 检测提交的数据类型(会检测 XSRF) ---
|
|
492
|
+
* @param input 要校验的输入项
|
|
493
|
+
* @param rule 规则
|
|
494
|
+
* @param rtn 返回值
|
|
495
|
+
*/
|
|
405
496
|
_checkXInput(input, rule, rtn) {
|
|
406
497
|
rule['_xsrf'] ??= ['require', this._cookie['XSRF-TOKEN'], [0, 'Bad request, no permission.']];
|
|
407
498
|
return this._checkInput(input, rule, rtn);
|
|
408
499
|
}
|
|
500
|
+
/**
|
|
501
|
+
* --- 当前页面开启 XSRF 支持(主要检测 cookie 是否存在) ---
|
|
502
|
+
* --- 如果当前页面有 CDN,请不要使用 ---
|
|
503
|
+
*/
|
|
409
504
|
_enabledXsrf() {
|
|
505
|
+
// --- 设置 XSRF 值 ---
|
|
410
506
|
if (this._cookie['XSRF-TOKEN'] === undefined) {
|
|
411
507
|
const xsrf = lCore.random(16, lCore.RANDOM_LUN);
|
|
412
508
|
this._xsrf = xsrf;
|
|
@@ -420,9 +516,17 @@ class Ctr {
|
|
|
420
516
|
this._xsrf = this._cookie['XSRF-TOKEN'];
|
|
421
517
|
}
|
|
422
518
|
}
|
|
519
|
+
/**
|
|
520
|
+
* --- 获取 Auth 字符串,用于客户端提交 ---
|
|
521
|
+
* @param user 用户名
|
|
522
|
+
* @param pwd 密码
|
|
523
|
+
*/
|
|
423
524
|
_getBasicAuth(user, pwd) {
|
|
424
525
|
return 'Basic ' + crypto.base64Encode(user + ':' + pwd);
|
|
425
526
|
}
|
|
527
|
+
/**
|
|
528
|
+
* --- 根据用户 ua 获取当前用户的设备类型 ---
|
|
529
|
+
*/
|
|
426
530
|
_device() {
|
|
427
531
|
const ua = this._req.headers['user-agent']?.toLowerCase();
|
|
428
532
|
if (!ua) {
|
|
@@ -437,6 +541,9 @@ class Ctr {
|
|
|
437
541
|
}
|
|
438
542
|
return 'unknown';
|
|
439
543
|
}
|
|
544
|
+
/**
|
|
545
|
+
* --- 通过 header 或 _auth 获取鉴权信息或 JWT 信息(不解析) ---
|
|
546
|
+
*/
|
|
440
547
|
getAuthorization() {
|
|
441
548
|
if (this._authorization !== null) {
|
|
442
549
|
return this._authorization;
|
|
@@ -459,6 +566,7 @@ class Ctr {
|
|
|
459
566
|
return false;
|
|
460
567
|
}
|
|
461
568
|
if (authArr[1].includes('.')) {
|
|
569
|
+
// --- 不解析,解析使用 JWT 类解析 ---
|
|
462
570
|
return authArr[1];
|
|
463
571
|
}
|
|
464
572
|
if (!(auth = crypto.base64Decode(authArr[1]))) {
|
|
@@ -468,6 +576,10 @@ class Ctr {
|
|
|
468
576
|
this._authorization = { 'user': authArr[0], 'pwd': authArr[1] ?? '' };
|
|
469
577
|
return this._authorization;
|
|
470
578
|
}
|
|
579
|
+
/**
|
|
580
|
+
* --- 获取 data 数据 ---
|
|
581
|
+
* @param path 文件路径(不含扩展名)
|
|
582
|
+
*/
|
|
471
583
|
async _loadData(path) {
|
|
472
584
|
const realPath = this._config.const.dataPath + path + '.json';
|
|
473
585
|
if (loadedData[realPath]) {
|
|
@@ -481,22 +593,41 @@ class Ctr {
|
|
|
481
593
|
loadedData[realPath] = json;
|
|
482
594
|
return json;
|
|
483
595
|
}
|
|
596
|
+
/**
|
|
597
|
+
* --- 跳转(302临时跳转),支持相对本项目根路径的路径或绝对路径 ---
|
|
598
|
+
* @param location 相对或绝对网址
|
|
599
|
+
*/
|
|
484
600
|
_location(location) {
|
|
485
601
|
if (this._res) {
|
|
486
602
|
this._res.setHeader('location', text.urlResolve(this._config.const.urlBase, location));
|
|
603
|
+
// this._res.writeHead(302); Kebab 中要在最后设置,否则会报错:ERR_HTTP_HEADERS_SENT
|
|
487
604
|
}
|
|
488
605
|
return false;
|
|
489
606
|
}
|
|
607
|
+
/**
|
|
608
|
+
* --- 开启 Session ---
|
|
609
|
+
* @param link Kv 或 Db 实例
|
|
610
|
+
* @param auth 设为 true 则从头 Authorization 或 post _auth 值读取 token
|
|
611
|
+
* @param opt name, ttl, ssl, sqlPre
|
|
612
|
+
*/
|
|
490
613
|
async _startSession(link, auth = false, opt = {}) {
|
|
491
614
|
this._sess = new session.Session();
|
|
492
615
|
await this._sess.init(this, link, auth, opt);
|
|
493
616
|
}
|
|
617
|
+
// --- 本地化 ---
|
|
618
|
+
/**
|
|
619
|
+
* --- 设定语言并加载语言包 ---
|
|
620
|
+
* @param loc 要加载的目标语言
|
|
621
|
+
* @param pkg 包名,为空自动填充为 default
|
|
622
|
+
*/
|
|
494
623
|
async _loadLocale(loc, pkg = 'default') {
|
|
495
624
|
const lName = loc + '.' + pkg;
|
|
496
625
|
this._locale = loc;
|
|
497
626
|
if (!this._localeFiles.includes(lName)) {
|
|
627
|
+
// --- 检测全局缓存是否加载 ---
|
|
498
628
|
const lPath = this._config.const.dataPath + 'locale/' + lName;
|
|
499
629
|
if (!localeFiles.includes(lPath)) {
|
|
630
|
+
// --- 全局缓存没有,先加载全局缓存 ---
|
|
500
631
|
const locData = await this._loadData('locale/' + lName);
|
|
501
632
|
if (locData === null) {
|
|
502
633
|
return false;
|
|
@@ -509,6 +640,7 @@ class Ctr {
|
|
|
509
640
|
else {
|
|
510
641
|
this._locale = loc;
|
|
511
642
|
}
|
|
643
|
+
// --- 缓存中一定有文件 ---
|
|
512
644
|
this._localeData[loc] ??= {};
|
|
513
645
|
for (const key in localeData[lPath]) {
|
|
514
646
|
this._localeData[loc][key] = localeData[lPath][key];
|
|
@@ -531,6 +663,10 @@ class Ctr {
|
|
|
531
663
|
}
|
|
532
664
|
}
|
|
533
665
|
}
|
|
666
|
+
/**
|
|
667
|
+
* --- 根据当前后台语言包设置情况获取 JSON 字符串传输到前台 ---
|
|
668
|
+
* @return string
|
|
669
|
+
*/
|
|
534
670
|
_getLocaleJsonString() {
|
|
535
671
|
if (this._localeData[this._locale] !== undefined) {
|
|
536
672
|
return text.stringifyJson(this._localeData[this._locale]);
|
|
@@ -539,9 +675,16 @@ class Ctr {
|
|
|
539
675
|
return '{}';
|
|
540
676
|
}
|
|
541
677
|
}
|
|
678
|
+
/**
|
|
679
|
+
* --- 获取当前语言名 ---
|
|
680
|
+
*/
|
|
542
681
|
_getLocale() {
|
|
543
682
|
return this._locale;
|
|
544
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* --- 开启跨域请求 ---
|
|
686
|
+
* 返回 true 接续执行,返回 false 需要中断用户本次访问(options请求)
|
|
687
|
+
*/
|
|
545
688
|
_cross() {
|
|
546
689
|
this._res.setHeader('access-control-allow-origin', '*');
|
|
547
690
|
this._res.setHeader('access-control-allow-headers', '*');
|
|
@@ -552,6 +695,13 @@ class Ctr {
|
|
|
552
695
|
}
|
|
553
696
|
return true;
|
|
554
697
|
}
|
|
698
|
+
// --- 以下:Mutton: false, Kebab: true ---
|
|
699
|
+
/**
|
|
700
|
+
* --- 获取语言包值 ---
|
|
701
|
+
* @param key
|
|
702
|
+
* @param data 要替换的数据
|
|
703
|
+
*/
|
|
704
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
555
705
|
_l(key, data) {
|
|
556
706
|
if (!this._localeData[this._locale]) {
|
|
557
707
|
return '[LocaleError]' + key;
|
|
@@ -573,24 +723,51 @@ class Ctr {
|
|
|
573
723
|
return this._localeData[this._locale][key];
|
|
574
724
|
}
|
|
575
725
|
}
|
|
726
|
+
/**
|
|
727
|
+
* --- 发送 socket 文本 ---
|
|
728
|
+
* @param data 要发送的信息
|
|
729
|
+
*/
|
|
576
730
|
_writeText(data) {
|
|
577
731
|
return this._socket.writeText(data);
|
|
578
732
|
}
|
|
733
|
+
/**
|
|
734
|
+
* --- 发送结果对象文本 ---
|
|
735
|
+
* @param data 要发送的结果对象,如 [0, 'Failed.']
|
|
736
|
+
*/
|
|
579
737
|
_writeResult(data) {
|
|
580
738
|
return this._socket.writeResult(data);
|
|
581
739
|
}
|
|
740
|
+
/**
|
|
741
|
+
* --- 发送 socket 二进制 ---
|
|
742
|
+
* @param data 要发送的信息
|
|
743
|
+
*/
|
|
582
744
|
_writeBinary(data) {
|
|
583
745
|
return this._socket.writeBinary(data);
|
|
584
746
|
}
|
|
747
|
+
/**
|
|
748
|
+
* --- 发送 socket ping ---
|
|
749
|
+
* @param data 要发送的信息
|
|
750
|
+
*/
|
|
585
751
|
_ping() {
|
|
586
752
|
return this._socket.ping();
|
|
587
753
|
}
|
|
754
|
+
/**
|
|
755
|
+
* --- 发送 socket pong ---
|
|
756
|
+
* @param data 要发送的信息
|
|
757
|
+
*/
|
|
588
758
|
_pong() {
|
|
589
759
|
return this._socket.pong();
|
|
590
760
|
}
|
|
761
|
+
/**
|
|
762
|
+
* --- 主动关闭当前 socket 连接 ---
|
|
763
|
+
*/
|
|
591
764
|
_end() {
|
|
592
765
|
this._socket.end();
|
|
593
766
|
}
|
|
767
|
+
/**
|
|
768
|
+
* --- 获取 formdata 的信息 ---
|
|
769
|
+
* @param events 文件处理情况
|
|
770
|
+
*/
|
|
594
771
|
async _handleFormData(events = {}) {
|
|
595
772
|
const rtn = await sRoute.getFormData(this._req, events);
|
|
596
773
|
if (!rtn) {
|