@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/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.MOD_CWD = exports.FTMP_CWD = exports.IND_CWD = exports.WWW_CWD = exports.LOG_CWD = exports.LIB_CWD = exports.VHOST_CWD = exports.CERT_CWD = exports.CONF_CWD = exports.ROOT_CWD = exports.SYS_PATH = exports.LIB_PATH = exports.ROOT_PATH = exports.VER = void 0;
|
|
13
13
|
/** --- 当前系统版本号 --- */
|
|
14
|
-
exports.VER = '2.0.
|
|
14
|
+
exports.VER = '2.0.15';
|
|
15
15
|
// --- 服务端用的路径 ---
|
|
16
16
|
/** --- /xxx/xxx --- */
|
|
17
17
|
const dirname = __dirname.replace(/\\/g, '/');
|
package/lib/core.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare const globalConfig: types.IConfig & {
|
|
|
12
12
|
'rpcSecret': string;
|
|
13
13
|
'debug': boolean;
|
|
14
14
|
'max': number;
|
|
15
|
+
'hosts': string[];
|
|
15
16
|
};
|
|
16
17
|
/** --- Cookie 设置的选项 --- */
|
|
17
18
|
export interface ICookieOptions {
|
|
@@ -133,23 +134,23 @@ export declare function exec(command: string): Promise<string | false>;
|
|
|
133
134
|
* --- 向主进程(或局域网同代码机子)发送广播将进行 reload 操作,等待回传 ---
|
|
134
135
|
* --- 主要作用除代码热更新以外的其他情况 ---
|
|
135
136
|
*/
|
|
136
|
-
export declare function sendReload(hosts?: string[]): Promise<string[]>;
|
|
137
|
+
export declare function sendReload(hosts?: string[] | 'config'): Promise<string[]>;
|
|
137
138
|
/**
|
|
138
139
|
* --- 向主进程(或局域网同代码机子)发送广播将进行 restart 操作,停止监听并启动新进程,老进程在连接全部断开后自行销毁 ---
|
|
139
140
|
* --- 主要用作不间断的代码热更新 ---
|
|
140
141
|
*/
|
|
141
|
-
export declare function sendRestart(hosts?: string[]): Promise<string[]>;
|
|
142
|
+
export declare function sendRestart(hosts?: string[] | 'config'): Promise<string[]>;
|
|
142
143
|
/** --- 跨进程全局变量 --- */
|
|
143
144
|
export declare const global: Record<string, any>;
|
|
144
145
|
/**
|
|
145
|
-
* ---
|
|
146
|
+
* --- 设置跨线程/跨内网服务器的全局变量 ---
|
|
146
147
|
* @param key 变量名
|
|
147
148
|
* @param data 变量值
|
|
148
149
|
* @param hosts 局域网列表
|
|
149
150
|
*/
|
|
150
|
-
export declare function setGlobal(key: string, data: types.Json, hosts?: string[]): Promise<string[]>;
|
|
151
|
+
export declare function setGlobal(key: string, data: types.Json, hosts?: string[] | 'config'): Promise<string[]>;
|
|
151
152
|
/**
|
|
152
|
-
* ---
|
|
153
|
+
* --- 移除某个跨线程/跨内网服务器全局变量 ---
|
|
153
154
|
* @param key 变量名
|
|
154
155
|
* @param hosts 局域网列表
|
|
155
156
|
*/
|
|
@@ -160,20 +161,23 @@ export declare function removeGlobal(key: string, hosts?: string[]): Promise<str
|
|
|
160
161
|
* @param path 要覆盖到的路径,无所谓是否 / 开头 / 结尾,是对方 kebab 的根据路开始算起
|
|
161
162
|
* @param hosts 局域网多机部署,不设置默认本机部署
|
|
162
163
|
* @param config 是否自动更新 config 的 set.staticVer 为最新,默认更新
|
|
164
|
+
* @param strict 严格模式,只有存在的文件才会被覆盖,不存在则中途直接报错,默认为 true
|
|
163
165
|
*/
|
|
164
|
-
export declare function updateCode(sourcePath: string, path: string, hosts?: string[], config?: boolean): Promise<Record<string, {
|
|
166
|
+
export declare function updateCode(sourcePath: string, path: string, hosts?: string[] | 'config', config?: boolean, strict?: boolean): Promise<Record<string, {
|
|
165
167
|
'result': boolean;
|
|
166
168
|
'return': string;
|
|
167
169
|
}>>;
|
|
168
170
|
/** --- log 设置的选项 --- */
|
|
169
171
|
export interface ILogOptions {
|
|
170
|
-
'path'
|
|
171
|
-
'urlFull'
|
|
172
|
-
'hostname'
|
|
173
|
-
'req'
|
|
174
|
-
'get'
|
|
175
|
-
'cookie'
|
|
176
|
-
'
|
|
172
|
+
'path'?: string;
|
|
173
|
+
'urlFull'?: string;
|
|
174
|
+
'hostname'?: string;
|
|
175
|
+
'req'?: http2.Http2ServerRequest | http.IncomingMessage | null;
|
|
176
|
+
'get'?: Record<string, types.Json>;
|
|
177
|
+
'cookie'?: Record<string, string>;
|
|
178
|
+
'jwt'?: Record<string, any>;
|
|
179
|
+
'session'?: Record<string, any>;
|
|
180
|
+
'headers'?: http.IncomingHttpHeaders;
|
|
177
181
|
}
|
|
178
182
|
/**
|
|
179
183
|
* --- 写入文件日志 ---
|
|
@@ -181,25 +185,45 @@ export interface ILogOptions {
|
|
|
181
185
|
* @param fend 文件名追加
|
|
182
186
|
* @param opt 选项
|
|
183
187
|
*/
|
|
184
|
-
export declare function log(opt: sCtr.Ctr | ILogOptions, msg: string, fend?: string):
|
|
188
|
+
export declare function log(opt: sCtr.Ctr | ILogOptions, msg: string, fend?: string): void;
|
|
185
189
|
/**
|
|
186
190
|
* --- 获取日志内容为一个数组 ---
|
|
187
191
|
* @param opt 参数
|
|
188
192
|
*/
|
|
189
193
|
export declare function getLog(opt: {
|
|
190
194
|
/** --- 如 127.0.0.1 --- */
|
|
191
|
-
'
|
|
195
|
+
'hostname': string;
|
|
192
196
|
/** --- 如 2024/08/01/22 --- */
|
|
193
197
|
'path': string;
|
|
194
198
|
/** --- 如 -error --- */
|
|
195
199
|
'fend'?: string;
|
|
196
200
|
/** --- 仅显示被搜索到的行 --- */
|
|
197
201
|
'search'?: string;
|
|
202
|
+
/** --- 跳过的字节数,默认不跳过 --- */
|
|
203
|
+
'start'?: number;
|
|
198
204
|
/** --- 跳过条数 --- */
|
|
199
205
|
'offset'?: number;
|
|
200
206
|
/** --- 最大限制,默认 100 --- */
|
|
201
207
|
'limit'?: number;
|
|
208
|
+
/** --- 获取局域网服务器的日志,为空代表获取本机的 --- */
|
|
209
|
+
'host'?: string;
|
|
202
210
|
}): Promise<string[][] | null | false>;
|
|
211
|
+
/**
|
|
212
|
+
* --- 获取目录内文件/文件夹列表 ---
|
|
213
|
+
* @param opt 参数
|
|
214
|
+
*/
|
|
215
|
+
export declare function ls(opt: {
|
|
216
|
+
/** --- 如 2024/08/01/22,无所谓开头结尾 --- */
|
|
217
|
+
'path': string;
|
|
218
|
+
'encoding'?: BufferEncoding;
|
|
219
|
+
/** --- 获取局域网服务器的目录列表,为空代表获取本机的 --- */
|
|
220
|
+
'host'?: string;
|
|
221
|
+
}): Promise<Array<{
|
|
222
|
+
'isFile': boolean;
|
|
223
|
+
'isDirectory': boolean;
|
|
224
|
+
'isSymbolicLink': boolean;
|
|
225
|
+
'name': string;
|
|
226
|
+
}>>;
|
|
203
227
|
/**
|
|
204
228
|
* --- 完整的克隆一份数组/对象,Kebab: yes, Mutton: no ---
|
|
205
229
|
* @param obj 要克隆的对象
|
package/lib/core.js
CHANGED
|
@@ -56,6 +56,7 @@ exports.removeGlobal = removeGlobal;
|
|
|
56
56
|
exports.updateCode = updateCode;
|
|
57
57
|
exports.log = log;
|
|
58
58
|
exports.getLog = getLog;
|
|
59
|
+
exports.ls = ls;
|
|
59
60
|
exports.clone = clone;
|
|
60
61
|
exports.debug = debug;
|
|
61
62
|
exports.display = display;
|
|
@@ -457,6 +458,9 @@ async function sendReload(hosts) {
|
|
|
457
458
|
});
|
|
458
459
|
return [];
|
|
459
460
|
}
|
|
461
|
+
if (hosts === 'config') {
|
|
462
|
+
hosts = exports.globalConfig.hosts;
|
|
463
|
+
}
|
|
460
464
|
// --- 局域网模式 ---
|
|
461
465
|
const time = lTime.stamp();
|
|
462
466
|
/** --- 返回成功的 host --- */
|
|
@@ -493,6 +497,9 @@ async function sendRestart(hosts) {
|
|
|
493
497
|
});
|
|
494
498
|
return [];
|
|
495
499
|
}
|
|
500
|
+
if (hosts === 'config') {
|
|
501
|
+
hosts = exports.globalConfig.hosts;
|
|
502
|
+
}
|
|
496
503
|
// --- 局域网模式 ---
|
|
497
504
|
const time = lTime.stamp();
|
|
498
505
|
/** --- 返回成功的 host --- */
|
|
@@ -518,7 +525,7 @@ async function sendRestart(hosts) {
|
|
|
518
525
|
/** --- 跨进程全局变量 --- */
|
|
519
526
|
exports.global = {};
|
|
520
527
|
/**
|
|
521
|
-
* ---
|
|
528
|
+
* --- 设置跨线程/跨内网服务器的全局变量 ---
|
|
522
529
|
* @param key 变量名
|
|
523
530
|
* @param data 变量值
|
|
524
531
|
* @param hosts 局域网列表
|
|
@@ -533,6 +540,9 @@ async function setGlobal(key, data, hosts) {
|
|
|
533
540
|
});
|
|
534
541
|
return [];
|
|
535
542
|
}
|
|
543
|
+
if (hosts === 'config') {
|
|
544
|
+
hosts = exports.globalConfig.hosts;
|
|
545
|
+
}
|
|
536
546
|
// --- 局域网模式 ---
|
|
537
547
|
const time = lTime.stamp();
|
|
538
548
|
/** --- 返回成功的 host --- */
|
|
@@ -556,7 +566,7 @@ async function setGlobal(key, data, hosts) {
|
|
|
556
566
|
return rtn;
|
|
557
567
|
}
|
|
558
568
|
/**
|
|
559
|
-
* ---
|
|
569
|
+
* --- 移除某个跨线程/跨内网服务器全局变量 ---
|
|
560
570
|
* @param key 变量名
|
|
561
571
|
* @param hosts 局域网列表
|
|
562
572
|
*/
|
|
@@ -569,8 +579,12 @@ async function removeGlobal(key, hosts) {
|
|
|
569
579
|
* @param path 要覆盖到的路径,无所谓是否 / 开头 / 结尾,是对方 kebab 的根据路开始算起
|
|
570
580
|
* @param hosts 局域网多机部署,不设置默认本机部署
|
|
571
581
|
* @param config 是否自动更新 config 的 set.staticVer 为最新,默认更新
|
|
582
|
+
* @param strict 严格模式,只有存在的文件才会被覆盖,不存在则中途直接报错,默认为 true
|
|
572
583
|
*/
|
|
573
|
-
async function updateCode(sourcePath, path, hosts, config = true) {
|
|
584
|
+
async function updateCode(sourcePath, path, hosts, config = true, strict = true) {
|
|
585
|
+
if (hosts === 'config') {
|
|
586
|
+
hosts = exports.globalConfig.hosts;
|
|
587
|
+
}
|
|
574
588
|
hosts ??= ['127.0.0.1'];
|
|
575
589
|
/** --- 返回成功的 host --- */
|
|
576
590
|
const rtn = {};
|
|
@@ -581,6 +595,7 @@ async function updateCode(sourcePath, path, hosts, config = true) {
|
|
|
581
595
|
}
|
|
582
596
|
fd.putString('path', path);
|
|
583
597
|
fd.putString('config', config ? '1' : '0');
|
|
598
|
+
fd.putString('strict', strict ? '1' : '0');
|
|
584
599
|
const res = await lNet.post('http://' + host + ':' + exports.globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
585
600
|
'action': 'code',
|
|
586
601
|
'time': lTime.stamp()
|
|
@@ -609,65 +624,77 @@ async function updateCode(sourcePath, path, hosts, config = true) {
|
|
|
609
624
|
* @param fend 文件名追加
|
|
610
625
|
* @param opt 选项
|
|
611
626
|
*/
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
})) {
|
|
627
|
+
function log(opt, msg, fend = '') {
|
|
628
|
+
(async () => {
|
|
629
|
+
let req;
|
|
630
|
+
let headers;
|
|
631
|
+
let get;
|
|
632
|
+
let cookie;
|
|
633
|
+
let jwt;
|
|
634
|
+
let session;
|
|
635
|
+
let wpath;
|
|
636
|
+
let urlFull;
|
|
637
|
+
let hostname;
|
|
638
|
+
if (opt instanceof sCtr.Ctr) {
|
|
639
|
+
req = opt.getPrototype('_req');
|
|
640
|
+
headers = opt.getPrototype('_headers');
|
|
641
|
+
get = opt.getPrototype('_get');
|
|
642
|
+
cookie = opt.getPrototype('_cookie');
|
|
643
|
+
jwt = opt.getPrototype('_jwt');
|
|
644
|
+
session = opt.getPrototype('_session');
|
|
645
|
+
const config = opt.getPrototype('_config');
|
|
646
|
+
wpath = config.const.path;
|
|
647
|
+
urlFull = config.const.urlFull;
|
|
648
|
+
hostname = config.const.hostname;
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
req = opt.req ?? null;
|
|
652
|
+
headers = opt.headers ?? {};
|
|
653
|
+
get = opt.get ?? {};
|
|
654
|
+
cookie = opt.cookie ?? {};
|
|
655
|
+
jwt = opt.jwt ?? {};
|
|
656
|
+
session = opt.session ?? {};
|
|
657
|
+
wpath = opt.path ?? '';
|
|
658
|
+
urlFull = opt.urlFull ?? '';
|
|
659
|
+
hostname = opt.hostname ?? '';
|
|
660
|
+
}
|
|
661
|
+
if (hostname === '') {
|
|
662
|
+
hostname = 'system';
|
|
663
|
+
}
|
|
664
|
+
const realIp = req?.socket.remoteAddress ?? '';
|
|
665
|
+
const clientIp = req ? ip(headers, req) : '';
|
|
666
|
+
const [y, m, d, h] = lTime.format(null, 'Y-m-d-H').split('-');
|
|
667
|
+
let path = kebab.LOG_CWD + hostname + fend + '/' + y + '/' + m + '/' + d + '/';
|
|
668
|
+
const rtn = await lFs.mkdir(path, 0o777);
|
|
669
|
+
if (!rtn) {
|
|
656
670
|
return;
|
|
657
671
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
672
|
+
path += h + '.csv';
|
|
673
|
+
if (!await lFs.isFile(path)) {
|
|
674
|
+
if (!await lFs.putContent(path, 'TIME,UNIX,URL,COOKIE,SESSION,JWT,USER_AGENT,REALIP,CLIENTIP,MESSAGE\n', {
|
|
675
|
+
'encoding': 'utf8',
|
|
676
|
+
'mode': 0o777
|
|
677
|
+
})) {
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
await lFs.putContent(path, '"' +
|
|
682
|
+
lTime.format(null, 'H:i:s') + '","' +
|
|
683
|
+
lTime.stamp().toString() + '","' +
|
|
684
|
+
urlFull + wpath + (Object.keys(get).length ? '?' + lText.queryStringify(get).replace(/"/g, '""') : '') + '","' +
|
|
685
|
+
lText.queryStringify(cookie).replace(/"/g, '""') + '","' +
|
|
686
|
+
lText.stringifyJson(jwt).replace(/"/g, '""') + '","' +
|
|
687
|
+
lText.stringifyJson(session).replace(/"/g, '""') + '","' +
|
|
688
|
+
(headers['user-agent']?.replace(/"/g, '""') ?? 'No HTTP_USER_AGENT') + '","' +
|
|
689
|
+
realIp.replace(/"/g, '""') + '","' +
|
|
690
|
+
clientIp.replace(/"/g, '""') + '","' +
|
|
691
|
+
JSON.stringify(msg).slice(1, -1).replace(/"/g, '""') + '"\n', {
|
|
692
|
+
'encoding': 'utf8',
|
|
693
|
+
'mode': 0o777,
|
|
694
|
+
'flag': 'a'
|
|
695
|
+
});
|
|
696
|
+
})().catch((e) => {
|
|
697
|
+
display('[CORE] [log]', e);
|
|
671
698
|
});
|
|
672
699
|
}
|
|
673
700
|
/**
|
|
@@ -675,91 +702,59 @@ async function log(opt, msg, fend = '') {
|
|
|
675
702
|
* @param opt 参数
|
|
676
703
|
*/
|
|
677
704
|
async function getLog(opt) {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
'encoding': 'utf8'
|
|
694
|
-
}).on('data', (buf) => {
|
|
695
|
-
if (typeof buf !== 'string') {
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
while (true) {
|
|
699
|
-
// --- 分包 ---
|
|
700
|
-
const index = buf.indexOf('\n');
|
|
701
|
-
if (index === -1) {
|
|
702
|
-
// --- 本次包还没有结束 ---
|
|
703
|
-
packet += buf;
|
|
704
|
-
break;
|
|
705
|
-
}
|
|
706
|
-
// --- 本次行结束了 ---
|
|
707
|
-
if (limit === 0) {
|
|
708
|
-
break;
|
|
709
|
-
}
|
|
710
|
-
packet += buf.slice(0, index);
|
|
711
|
-
buf = buf.slice(index + 1);
|
|
712
|
-
++line;
|
|
713
|
-
// --- 先执行下本次完成的 ---
|
|
714
|
-
if (line > 1) {
|
|
715
|
-
if (offset === 0) {
|
|
716
|
-
if (!opt.search || packet.includes(opt.search)) {
|
|
717
|
-
const result = [];
|
|
718
|
-
let currentField = '';
|
|
719
|
-
let inQuotes = false;
|
|
720
|
-
for (let i = 0; i < packet.length; ++i) {
|
|
721
|
-
const char = packet[i];
|
|
722
|
-
if (char === '"') {
|
|
723
|
-
if (inQuotes && packet[i + 1] === '"') {
|
|
724
|
-
currentField += '"';
|
|
725
|
-
++i;
|
|
726
|
-
}
|
|
727
|
-
else {
|
|
728
|
-
inQuotes = !inQuotes;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
else if (char === ',' && !inQuotes) {
|
|
732
|
-
result.push(currentField);
|
|
733
|
-
currentField = '';
|
|
734
|
-
}
|
|
735
|
-
else {
|
|
736
|
-
currentField += char;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
result.push(currentField);
|
|
740
|
-
list.push(result);
|
|
741
|
-
--limit;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
else {
|
|
745
|
-
--offset;
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
// --- 处理结束 ---
|
|
749
|
-
packet = '';
|
|
750
|
-
// --- 看看还有没有后面的粘连包 ---
|
|
751
|
-
if (!buf.length) {
|
|
752
|
-
// --- 没粘连包 ---
|
|
753
|
-
break;
|
|
754
|
-
}
|
|
755
|
-
// --- 有粘连包 ---
|
|
756
|
-
}
|
|
757
|
-
}).on('end', () => {
|
|
758
|
-
resolve(list);
|
|
759
|
-
}).on('error', () => {
|
|
760
|
-
resolve(false);
|
|
761
|
-
});
|
|
705
|
+
opt.host ??= '127.0.0.1';
|
|
706
|
+
// --- 局域网模式 ---
|
|
707
|
+
const time = lTime.stamp();
|
|
708
|
+
const res = await lNet.get('http://' + opt.host + ':' + exports.globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
709
|
+
'action': 'log',
|
|
710
|
+
'time': time,
|
|
711
|
+
'hostname': opt.hostname,
|
|
712
|
+
'path': opt.path,
|
|
713
|
+
'fend': opt.fend,
|
|
714
|
+
'search': opt.search,
|
|
715
|
+
'start': opt.start,
|
|
716
|
+
'offset': opt.offset,
|
|
717
|
+
'limit': opt.limit,
|
|
718
|
+
}), exports.globalConfig.rpcSecret), {
|
|
719
|
+
'timeout': 2
|
|
762
720
|
});
|
|
721
|
+
const content = await res.getContent();
|
|
722
|
+
if (!content) {
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
const str = content.toString();
|
|
726
|
+
const j = lText.parseJson(str);
|
|
727
|
+
if (!j) {
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
return j.data;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* --- 获取目录内文件/文件夹列表 ---
|
|
734
|
+
* @param opt 参数
|
|
735
|
+
*/
|
|
736
|
+
async function ls(opt) {
|
|
737
|
+
opt.host ??= '127.0.0.1';
|
|
738
|
+
// --- 局域网模式 ---
|
|
739
|
+
const time = lTime.stamp();
|
|
740
|
+
const res = await lNet.get('http://' + opt.host + ':' + exports.globalConfig.rpcPort.toString() + '/' + lCrypto.aesEncrypt(lText.stringifyJson({
|
|
741
|
+
'action': 'ls',
|
|
742
|
+
'time': time,
|
|
743
|
+
'path': opt.path,
|
|
744
|
+
'encoding': opt.encoding,
|
|
745
|
+
}), exports.globalConfig.rpcSecret), {
|
|
746
|
+
'timeout': 2
|
|
747
|
+
});
|
|
748
|
+
const content = await res.getContent();
|
|
749
|
+
if (!content) {
|
|
750
|
+
return [];
|
|
751
|
+
}
|
|
752
|
+
const str = content.toString();
|
|
753
|
+
const j = lText.parseJson(str);
|
|
754
|
+
if (!j) {
|
|
755
|
+
return [];
|
|
756
|
+
}
|
|
757
|
+
return j.data;
|
|
763
758
|
}
|
|
764
759
|
/**
|
|
765
760
|
* --- 完整的克隆一份数组/对象,Kebab: yes, Mutton: no ---
|
package/lib/db.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Project: Kebab, User: JianSuoQiYue
|
|
3
3
|
* Date: 2019-4-15 13:40
|
|
4
|
-
* 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
|
|
4
|
+
* 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
|
|
5
5
|
*/
|
|
6
6
|
import * as mysql2 from 'mysql2/promise';
|
|
7
7
|
import * as ctr from '~/sys/ctr';
|