@maiyunnet/kebab 9.5.0 → 9.6.0
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/doc/kebab-rag.md +115 -113
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/core.d.ts +33 -9
- package/lib/core.js +38 -19
- package/package.json +1 -1
- package/sys/master.js +1 -1
- package/sys/mod.d.ts +4 -2
- package/sys/mod.js +4 -2
- package/www/example/ctr/test.js +10 -7
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* --- 本文件用来定义每个目录实体地址的常量 ---
|
|
7
7
|
*/
|
|
8
8
|
/** --- 当前系统版本号 --- */
|
|
9
|
-
export const VER = '9.
|
|
9
|
+
export const VER = '9.6.0';
|
|
10
10
|
// --- 服务端用的路径 ---
|
|
11
11
|
const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
|
|
12
12
|
/** --- /xxx/xxx --- */
|
package/lib/core.d.ts
CHANGED
|
@@ -167,12 +167,18 @@ export declare function exec(command: string, options?: {
|
|
|
167
167
|
* --- 向主进程(或局域网同代码机子)发送广播将进行 reload 操作,等待回传 ---
|
|
168
168
|
* --- 主要作用除代码热更新以外的其他情况 ---
|
|
169
169
|
*/
|
|
170
|
-
export declare function sendReload(hosts?: string[] | 'config'): Promise<string
|
|
170
|
+
export declare function sendReload(hosts?: string[] | 'config'): Promise<Record<string, {
|
|
171
|
+
'result': boolean;
|
|
172
|
+
'return': string;
|
|
173
|
+
}>>;
|
|
171
174
|
/**
|
|
172
175
|
* --- 向主进程(或局域网同代码机子)发送广播将进行 restart 操作,停止监听并启动新进程,老进程在连接全部断开后自行销毁 ---
|
|
173
176
|
* --- 主要用作不间断的代码热更新 ---
|
|
174
177
|
*/
|
|
175
|
-
export declare function sendRestart(hosts?: string[] | 'config'): Promise<string
|
|
178
|
+
export declare function sendRestart(hosts?: string[] | 'config'): Promise<Record<string, {
|
|
179
|
+
'result': boolean;
|
|
180
|
+
'return': string;
|
|
181
|
+
}>>;
|
|
176
182
|
/** --- PM2 操作类型 --- */
|
|
177
183
|
export type TPm2Action = 'start' | 'stop' | 'restart';
|
|
178
184
|
/**
|
|
@@ -181,13 +187,19 @@ export type TPm2Action = 'start' | 'stop' | 'restart';
|
|
|
181
187
|
* @param action PM2 操作类型
|
|
182
188
|
* @param hosts 局域网列表
|
|
183
189
|
*/
|
|
184
|
-
export declare function sendPm2(name: string, action?: TPm2Action, hosts?: string[] | 'config'): Promise<string
|
|
190
|
+
export declare function sendPm2(name: string, action?: TPm2Action, hosts?: string[] | 'config'): Promise<Record<string, {
|
|
191
|
+
'result': boolean;
|
|
192
|
+
'return': string;
|
|
193
|
+
}>>;
|
|
185
194
|
/**
|
|
186
195
|
* --- 向本机或局域网 RPC 发送 npm install 操作 ---
|
|
187
196
|
* @param path 路径,如 /home/kebab/
|
|
188
|
-
* @param hosts
|
|
197
|
+
* @param hosts 局域网列表,不填则代表本机
|
|
189
198
|
*/
|
|
190
|
-
export declare function sendNpm(path: string, hosts?: string[] | 'config'): Promise<string
|
|
199
|
+
export declare function sendNpm(path: string, hosts?: string[] | 'config'): Promise<Record<string, {
|
|
200
|
+
'result': boolean;
|
|
201
|
+
'return': string;
|
|
202
|
+
}>>;
|
|
191
203
|
/** --- 跨进程全局变量 --- */
|
|
192
204
|
export declare const global: Record<string, any>;
|
|
193
205
|
/**
|
|
@@ -196,13 +208,19 @@ export declare const global: Record<string, any>;
|
|
|
196
208
|
* @param data 变量值
|
|
197
209
|
* @param hosts 局域网列表
|
|
198
210
|
*/
|
|
199
|
-
export declare function setGlobal(key: string, data: any, hosts?: string[] | 'config'): Promise<string
|
|
211
|
+
export declare function setGlobal(key: string, data: any, hosts?: string[] | 'config'): Promise<Record<string, {
|
|
212
|
+
'result': boolean;
|
|
213
|
+
'return': string;
|
|
214
|
+
}>>;
|
|
200
215
|
/**
|
|
201
216
|
* --- 移除某个跨线程/跨内网服务器全局变量 ---
|
|
202
217
|
* @param key 变量名
|
|
203
218
|
* @param hosts 局域网列表
|
|
204
219
|
*/
|
|
205
|
-
export declare function removeGlobal(key: string, hosts?: string[]): Promise<string
|
|
220
|
+
export declare function removeGlobal(key: string, hosts?: string[] | 'config'): Promise<Record<string, {
|
|
221
|
+
'result': boolean;
|
|
222
|
+
'return': string;
|
|
223
|
+
}>>;
|
|
206
224
|
/**
|
|
207
225
|
* --- 上传并覆盖代码文件,config.json、kebab.json、.js.map、.ts, .gitignore 不会被覆盖和新创建 ---
|
|
208
226
|
* @param sourcePath zip 文件
|
|
@@ -222,13 +240,19 @@ export declare function updateCode(sourcePath: string, path: string, hosts?: str
|
|
|
222
240
|
* @param value 要更新的值
|
|
223
241
|
* @param hosts 局域网列表
|
|
224
242
|
*/
|
|
225
|
-
export declare function sendProject(path: string, key: string, value: string, hosts?: string[] | 'config'): Promise<string
|
|
243
|
+
export declare function sendProject(path: string, key: string, value: string, hosts?: string[] | 'config'): Promise<Record<string, {
|
|
244
|
+
'result': boolean;
|
|
245
|
+
'return': string;
|
|
246
|
+
}>>;
|
|
226
247
|
/**
|
|
227
248
|
* --- 向本机或局域网 RPC 发送 package.json 更新操作 ---
|
|
228
249
|
* @param content package.json 文件内容
|
|
229
250
|
* @param hosts 局域网列表
|
|
230
251
|
*/
|
|
231
|
-
export declare function sendPackage(content: string, hosts?: string[] | 'config'): Promise<string
|
|
252
|
+
export declare function sendPackage(content: string, hosts?: string[] | 'config'): Promise<Record<string, {
|
|
253
|
+
'result': boolean;
|
|
254
|
+
'return': string;
|
|
255
|
+
}>>;
|
|
232
256
|
/** --- log 设置的选项 --- */
|
|
233
257
|
export interface ILogOptions {
|
|
234
258
|
'path'?: string;
|
package/lib/core.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Project: Kebab, User: JianSuoQiYue
|
|
3
3
|
* Date: 2019-5-3 23:54
|
|
4
|
-
* Last: 2020-4-11 22:34:58, 2022-10-2 14:13:06, 2022-12-28 20:33:24, 2023-12-15 11:49:02, 2024-7-2 15:23:35, 2025-6-13 19:45:53
|
|
4
|
+
* Last: 2020-4-11 22:34:58, 2022-10-2 14:13:06, 2022-12-28 20:33:24, 2023-12-15 11:49:02, 2024-7-2 15:23:35, 2025-6-13 19:45:53, 2026-05-20 09:50:00
|
|
5
5
|
*/
|
|
6
6
|
import * as cp from 'child_process';
|
|
7
7
|
import * as http2 from 'http2';
|
|
@@ -464,7 +464,9 @@ export async function sendReload(hosts) {
|
|
|
464
464
|
process.send({
|
|
465
465
|
'action': 'reload'
|
|
466
466
|
});
|
|
467
|
-
return
|
|
467
|
+
return {
|
|
468
|
+
'127.0.0.1': { 'result': true, 'return': 'Done' }
|
|
469
|
+
};
|
|
468
470
|
}
|
|
469
471
|
if (hosts === 'config') {
|
|
470
472
|
hosts = globalConfig.hosts;
|
|
@@ -472,7 +474,7 @@ export async function sendReload(hosts) {
|
|
|
472
474
|
// --- 局域网模式 ---
|
|
473
475
|
const time = lTime.stamp();
|
|
474
476
|
/** --- 返回成功的 host --- */
|
|
475
|
-
const rtn =
|
|
477
|
+
const rtn = {};
|
|
476
478
|
for (const host of hosts) {
|
|
477
479
|
const res = await lUndici.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
478
480
|
'action': 'reload',
|
|
@@ -486,7 +488,10 @@ export async function sendReload(hosts) {
|
|
|
486
488
|
}
|
|
487
489
|
const str = content.toString();
|
|
488
490
|
if (str === 'Done') {
|
|
489
|
-
rtn
|
|
491
|
+
rtn[host] = { 'result': true, 'return': 'Done' };
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
rtn[host] = { 'result': false, 'return': str };
|
|
490
495
|
}
|
|
491
496
|
}
|
|
492
497
|
return rtn;
|
|
@@ -503,7 +508,9 @@ export async function sendRestart(hosts) {
|
|
|
503
508
|
process.send({
|
|
504
509
|
'action': 'restart'
|
|
505
510
|
});
|
|
506
|
-
return
|
|
511
|
+
return {
|
|
512
|
+
'127.0.0.1': { 'result': true, 'return': 'Done' }
|
|
513
|
+
};
|
|
507
514
|
}
|
|
508
515
|
if (hosts === 'config') {
|
|
509
516
|
hosts = globalConfig.hosts;
|
|
@@ -511,7 +518,7 @@ export async function sendRestart(hosts) {
|
|
|
511
518
|
// --- 局域网模式 ---
|
|
512
519
|
const time = lTime.stamp();
|
|
513
520
|
/** --- 返回成功的 host --- */
|
|
514
|
-
const rtn =
|
|
521
|
+
const rtn = {};
|
|
515
522
|
for (const host of hosts) {
|
|
516
523
|
const res = await lUndici.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
517
524
|
'action': 'restart',
|
|
@@ -525,7 +532,10 @@ export async function sendRestart(hosts) {
|
|
|
525
532
|
}
|
|
526
533
|
const str = content.toString();
|
|
527
534
|
if (str === 'Done') {
|
|
528
|
-
rtn
|
|
535
|
+
rtn[host] = { 'result': true, 'return': 'Done' };
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
rtn[host] = { 'result': false, 'return': str };
|
|
529
539
|
}
|
|
530
540
|
}
|
|
531
541
|
return rtn;
|
|
@@ -547,7 +557,7 @@ export async function sendPm2(name, action = 'restart', hosts) {
|
|
|
547
557
|
// --- 局域网模式 ---
|
|
548
558
|
const time = lTime.stamp();
|
|
549
559
|
/** --- 返回成功的 host --- */
|
|
550
|
-
const rtn =
|
|
560
|
+
const rtn = {};
|
|
551
561
|
for (const host of hosts) {
|
|
552
562
|
const res = await lUndici.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
553
563
|
'action': 'pm2',
|
|
@@ -563,9 +573,10 @@ export async function sendPm2(name, action = 'restart', hosts) {
|
|
|
563
573
|
}
|
|
564
574
|
const str = content.toString();
|
|
565
575
|
if (str === 'Done') {
|
|
566
|
-
rtn
|
|
576
|
+
rtn[host] = { 'result': true, 'return': 'Done' };
|
|
567
577
|
}
|
|
568
578
|
else {
|
|
579
|
+
rtn[host] = { 'result': false, 'return': str };
|
|
569
580
|
debug('[CORE][sendPm2] rpc server content error:', str);
|
|
570
581
|
}
|
|
571
582
|
}
|
|
@@ -574,7 +585,7 @@ export async function sendPm2(name, action = 'restart', hosts) {
|
|
|
574
585
|
/**
|
|
575
586
|
* --- 向本机或局域网 RPC 发送 npm install 操作 ---
|
|
576
587
|
* @param path 路径,如 /home/kebab/
|
|
577
|
-
* @param hosts
|
|
588
|
+
* @param hosts 局域网列表,不填则代表本机
|
|
578
589
|
*/
|
|
579
590
|
export async function sendNpm(path, hosts) {
|
|
580
591
|
if (hosts === 'config') {
|
|
@@ -587,7 +598,7 @@ export async function sendNpm(path, hosts) {
|
|
|
587
598
|
// --- 局域网模式 ---
|
|
588
599
|
const time = lTime.stamp();
|
|
589
600
|
/** --- 返回成功的 host --- */
|
|
590
|
-
const rtn =
|
|
601
|
+
const rtn = {};
|
|
591
602
|
for (const host of hosts) {
|
|
592
603
|
const res = await lUndici.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
593
604
|
'action': 'npm',
|
|
@@ -602,9 +613,10 @@ export async function sendNpm(path, hosts) {
|
|
|
602
613
|
}
|
|
603
614
|
const str = content.toString();
|
|
604
615
|
if (str === 'Done') {
|
|
605
|
-
rtn
|
|
616
|
+
rtn[host] = { 'result': true, 'return': 'Done' };
|
|
606
617
|
}
|
|
607
618
|
else {
|
|
619
|
+
rtn[host] = { 'result': false, 'return': str };
|
|
608
620
|
debug('[CORE][sendNpmInstall] rpc server content error:', str);
|
|
609
621
|
}
|
|
610
622
|
}
|
|
@@ -626,7 +638,9 @@ export async function setGlobal(key, data, hosts) {
|
|
|
626
638
|
'key': key,
|
|
627
639
|
'data': data
|
|
628
640
|
});
|
|
629
|
-
return
|
|
641
|
+
return {
|
|
642
|
+
'127.0.0.1': { 'result': true, 'return': 'Done' }
|
|
643
|
+
};
|
|
630
644
|
}
|
|
631
645
|
if (hosts === 'config') {
|
|
632
646
|
hosts = globalConfig.hosts;
|
|
@@ -634,7 +648,7 @@ export async function setGlobal(key, data, hosts) {
|
|
|
634
648
|
// --- 局域网模式 ---
|
|
635
649
|
const time = lTime.stamp();
|
|
636
650
|
/** --- 返回成功的 host --- */
|
|
637
|
-
const rtn =
|
|
651
|
+
const rtn = {};
|
|
638
652
|
for (const host of hosts) {
|
|
639
653
|
const res = await lUndici.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
640
654
|
'action': 'global',
|
|
@@ -648,7 +662,10 @@ export async function setGlobal(key, data, hosts) {
|
|
|
648
662
|
}
|
|
649
663
|
const str = content.toString();
|
|
650
664
|
if (str === 'Done') {
|
|
651
|
-
rtn
|
|
665
|
+
rtn[host] = { 'result': true, 'return': 'Done' };
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
rtn[host] = { 'result': false, 'return': str };
|
|
652
669
|
}
|
|
653
670
|
}
|
|
654
671
|
return rtn;
|
|
@@ -730,7 +747,7 @@ export async function sendProject(path, key, value, hosts) {
|
|
|
730
747
|
// --- 局域网模式 ---
|
|
731
748
|
const time = lTime.stamp();
|
|
732
749
|
/** --- 返回成功的 host --- */
|
|
733
|
-
const rtn =
|
|
750
|
+
const rtn = {};
|
|
734
751
|
for (const host of hosts) {
|
|
735
752
|
const res = await lUndici.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
736
753
|
'action': 'project',
|
|
@@ -746,9 +763,10 @@ export async function sendProject(path, key, value, hosts) {
|
|
|
746
763
|
}
|
|
747
764
|
const str = content.toString();
|
|
748
765
|
if (str === 'Done') {
|
|
749
|
-
rtn
|
|
766
|
+
rtn[host] = { 'result': true, 'return': 'Done' };
|
|
750
767
|
}
|
|
751
768
|
else {
|
|
769
|
+
rtn[host] = { 'result': false, 'return': str };
|
|
752
770
|
debug('[CORE][sendProject] rpc server content error:', str);
|
|
753
771
|
}
|
|
754
772
|
}
|
|
@@ -770,7 +788,7 @@ export async function sendPackage(content, hosts) {
|
|
|
770
788
|
// --- 局域网模式 ---
|
|
771
789
|
const time = lTime.stamp();
|
|
772
790
|
/** --- 返回成功的 host --- */
|
|
773
|
-
const rtn =
|
|
791
|
+
const rtn = {};
|
|
774
792
|
for (const host of hosts) {
|
|
775
793
|
const res = await lUndici.get('http://' + host + ':' + globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
776
794
|
'action': 'package',
|
|
@@ -785,9 +803,10 @@ export async function sendPackage(content, hosts) {
|
|
|
785
803
|
}
|
|
786
804
|
const str = resContent.toString();
|
|
787
805
|
if (str === 'Done') {
|
|
788
|
-
rtn
|
|
806
|
+
rtn[host] = { 'result': true, 'return': 'Done' };
|
|
789
807
|
}
|
|
790
808
|
else {
|
|
809
|
+
rtn[host] = { 'result': false, 'return': str };
|
|
791
810
|
debug('[CORE][sendPackage] rpc server content error:', str);
|
|
792
811
|
}
|
|
793
812
|
}
|
package/package.json
CHANGED
package/sys/master.js
CHANGED
|
@@ -404,7 +404,7 @@ function createRpcListener() {
|
|
|
404
404
|
// --- 特殊文件不能覆盖 ---
|
|
405
405
|
continue;
|
|
406
406
|
}
|
|
407
|
-
if (fname.endsWith('.js.map') || fname.endsWith('.ts') || fname.endsWith('.scss') || fname.endsWith('.gitignore') || fname.endsWith('.DS_Store')) {
|
|
407
|
+
if (fname.endsWith('.js.map') || fname.endsWith('.ts') || fname.endsWith('.tsx') || fname.endsWith('.scss') || fname.endsWith('.gitignore') || fname.endsWith('.DS_Store')) {
|
|
408
408
|
// --- 测试或开发文件不覆盖 ---
|
|
409
409
|
continue;
|
|
410
410
|
}
|
package/sys/mod.d.ts
CHANGED
|
@@ -180,8 +180,10 @@ export default class Mod {
|
|
|
180
180
|
/**
|
|
181
181
|
* --- 批量更新数据 ---
|
|
182
182
|
* @param db 数据库对象
|
|
183
|
-
* @param data
|
|
184
|
-
*
|
|
183
|
+
* @param data 数据列表,每个元素必须包含 key 字段,其余字段为要更新的列;
|
|
184
|
+
* 支持稀疏数据(不同元素可以拥有不同的列集合),内部会自动按列集合分组批量执行
|
|
185
|
+
* @param key 用于定位记录的字段名(主键或唯一键),该字段仅用于 WHERE 条件匹配,不会被更新;
|
|
186
|
+
* data 中每个元素都必须包含此字段,否则该元素会被跳过
|
|
185
187
|
* @param opt 选项(opt.pre: MySQL 表前缀/PostgreSQL Schema 名)
|
|
186
188
|
*/
|
|
187
189
|
static updateList(db: lDb.Pool | lDb.Transaction, data: Array<Record<string, any>>, key: string, opt?: {
|
package/sys/mod.js
CHANGED
|
@@ -305,8 +305,10 @@ export default class Mod {
|
|
|
305
305
|
/**
|
|
306
306
|
* --- 批量更新数据 ---
|
|
307
307
|
* @param db 数据库对象
|
|
308
|
-
* @param data
|
|
309
|
-
*
|
|
308
|
+
* @param data 数据列表,每个元素必须包含 key 字段,其余字段为要更新的列;
|
|
309
|
+
* 支持稀疏数据(不同元素可以拥有不同的列集合),内部会自动按列集合分组批量执行
|
|
310
|
+
* @param key 用于定位记录的字段名(主键或唯一键),该字段仅用于 WHERE 条件匹配,不会被更新;
|
|
311
|
+
* data 中每个元素都必须包含此字段,否则该元素会被跳过
|
|
310
312
|
* @param opt 选项(opt.pre: MySQL 表前缀/PostgreSQL Schema 名)
|
|
311
313
|
*/
|
|
312
314
|
static async updateList(db, data, key, opt = {}) {
|
package/www/example/ctr/test.js
CHANGED
|
@@ -1407,7 +1407,10 @@ for (let i = 0; i < 30000; ++i) {
|
|
|
1407
1407
|
else {
|
|
1408
1408
|
// --- jsonl 格式:object ---
|
|
1409
1409
|
const r = row;
|
|
1410
|
-
for (const val of [
|
|
1410
|
+
for (const val of [
|
|
1411
|
+
r.time, r.unix, r.url,
|
|
1412
|
+
r.cookie, r.session, r.userAgent, r.realIp, r.cfIp, r.xIp, r.osMem, r.procMem, r.message
|
|
1413
|
+
]) {
|
|
1411
1414
|
echo.push('<td>' + lText.htmlescape(typeof val === 'string' ? val : lText.stringifyJson(val) ?? '') + '</td>');
|
|
1412
1415
|
}
|
|
1413
1416
|
}
|
|
@@ -1466,12 +1469,12 @@ to: ${to}`
|
|
|
1466
1469
|
return echo.join('') + '<br><br>' + this._getEnd();
|
|
1467
1470
|
}
|
|
1468
1471
|
async coreReload() {
|
|
1469
|
-
await lCore.sendReload();
|
|
1470
|
-
return
|
|
1472
|
+
const list = await lCore.sendReload();
|
|
1473
|
+
return `The reload request has been sent, please review the console.<br>Hosts: ${JSON.stringify(list)}<br><br>` + this._getEnd();
|
|
1471
1474
|
}
|
|
1472
1475
|
async coreRestart() {
|
|
1473
|
-
await lCore.sendRestart();
|
|
1474
|
-
return
|
|
1476
|
+
const list = await lCore.sendRestart();
|
|
1477
|
+
return `The restart request has been sent, please review the console.<br>Hosts: ${JSON.stringify(list)}<br><br>` + this._getEnd();
|
|
1475
1478
|
}
|
|
1476
1479
|
async corePm2() {
|
|
1477
1480
|
const name = this._get['name'] ?? '';
|
|
@@ -1483,7 +1486,7 @@ to: ${to}`
|
|
|
1483
1486
|
return 'Invalid action. Must be: start, stop, restart<br><br>' + this._getEnd();
|
|
1484
1487
|
}
|
|
1485
1488
|
const list = await lCore.sendPm2(name, action);
|
|
1486
|
-
return `PM2 ${action} request has been sent for "${name}".<br>
|
|
1489
|
+
return `PM2 ${action} request has been sent for "${name}".<br>Hosts: ${JSON.stringify(list)}<br><br>` + this._getEnd();
|
|
1487
1490
|
}
|
|
1488
1491
|
async coreNpm() {
|
|
1489
1492
|
// --- 创建一个临时目录 ---
|
|
@@ -1498,7 +1501,7 @@ to: ${to}`
|
|
|
1498
1501
|
}
|
|
1499
1502
|
}));
|
|
1500
1503
|
const list = await lCore.sendNpm(path);
|
|
1501
|
-
return `NPM request has been sent.<br>
|
|
1504
|
+
return `NPM request has been sent.<br>Hosts: ${JSON.stringify(list)}<br><br>` + this._getEnd();
|
|
1502
1505
|
}
|
|
1503
1506
|
async coreGlobal() {
|
|
1504
1507
|
const ts = lTime.stamp().toString();
|