@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/lib/time.js
CHANGED
|
@@ -38,20 +38,35 @@ exports.get = get;
|
|
|
38
38
|
exports.stamp = stamp;
|
|
39
39
|
exports.isMs = isMs;
|
|
40
40
|
exports.format = format;
|
|
41
|
+
/**
|
|
42
|
+
* Project: Kebab, User: JianSuoQiYue
|
|
43
|
+
* Date: 2019-6-6 12:04:15
|
|
44
|
+
* Last: 2020-3-29 23:41:21, 2024-1-18 17:16:50, 2024-8-5 10:55:21
|
|
45
|
+
*/
|
|
41
46
|
const sCtr = __importStar(require("../sys/ctr"));
|
|
47
|
+
/** --- 一小时的秒数 --- */
|
|
42
48
|
exports.HOUR = 3600;
|
|
49
|
+
/** --- 一天的秒数 --- */
|
|
43
50
|
exports.DAY = 86400;
|
|
51
|
+
/** --- 一年(365 天) */
|
|
44
52
|
exports.YEAR = 31536000;
|
|
53
|
+
/** --- 星期名 --- */
|
|
45
54
|
const dayNames = [
|
|
46
55
|
['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
|
47
56
|
['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
|
|
48
57
|
];
|
|
58
|
+
/** --- 月份名 --- */
|
|
49
59
|
const monthNames = [
|
|
50
60
|
['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
|
51
61
|
['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
|
52
62
|
];
|
|
53
63
|
class Time {
|
|
64
|
+
/**
|
|
65
|
+
* --- 构造函数 ---
|
|
66
|
+
* @param opt
|
|
67
|
+
*/
|
|
54
68
|
constructor(ctr, opt) {
|
|
69
|
+
/** --- 当前时区 --- */
|
|
55
70
|
this._zone = 0;
|
|
56
71
|
this._zone = opt.zone ?? ctr.getPrototype('_config').set.timezone ?? 0;
|
|
57
72
|
if (opt.data) {
|
|
@@ -65,6 +80,7 @@ class Time {
|
|
|
65
80
|
}
|
|
66
81
|
else if (typeof opt.data === 'string') {
|
|
67
82
|
this._date = new Date(opt.data);
|
|
83
|
+
/** --- 与当前设定时区的差小时 --- */
|
|
68
84
|
const offset = this._date.getTimezoneOffset() / 60 + this._zone;
|
|
69
85
|
if (offset !== 0) {
|
|
70
86
|
this._date.setUTCHours(this._date.getUTCHours() - offset);
|
|
@@ -75,26 +91,53 @@ class Time {
|
|
|
75
91
|
this._date = new Date();
|
|
76
92
|
}
|
|
77
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* --- 设置时区 ---
|
|
96
|
+
* @param zone 北京时间如 8
|
|
97
|
+
*/
|
|
78
98
|
setZone(zone) {
|
|
79
99
|
this._zone = zone;
|
|
80
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* --- 获取时区 ---
|
|
103
|
+
*/
|
|
81
104
|
getZone() {
|
|
82
105
|
return this._zone;
|
|
83
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* --- 获取 UTC 字符串 ---
|
|
109
|
+
*/
|
|
84
110
|
toUTCString() {
|
|
85
111
|
return this._date.toUTCString();
|
|
86
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* --- 获取格式化的字符串 ---
|
|
115
|
+
* @param f 格式化字符串
|
|
116
|
+
* @param zone 时区小时,如 8
|
|
117
|
+
*/
|
|
87
118
|
format(f, zone) {
|
|
88
119
|
return format(zone ?? 0, f, this._date);
|
|
89
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* --- 获取秒级时间戳 ---
|
|
123
|
+
*/
|
|
90
124
|
stamp() {
|
|
91
125
|
return stamp(this._date);
|
|
92
126
|
}
|
|
93
127
|
}
|
|
94
128
|
exports.Time = Time;
|
|
129
|
+
/**
|
|
130
|
+
* --- 创建获取一个时间对象 ---
|
|
131
|
+
* @param opt
|
|
132
|
+
*/
|
|
95
133
|
function get(ctr, opt = {}) {
|
|
96
134
|
return new Time(ctr, opt);
|
|
97
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* --- 获取秒级时间戳 ---
|
|
138
|
+
* @param date Date 对象可选
|
|
139
|
+
* @param zone 时区小时或 ctr 对象,如 8,设置 null 则以系统时区为准
|
|
140
|
+
*/
|
|
98
141
|
function stamp(date, zone) {
|
|
99
142
|
if (date) {
|
|
100
143
|
if (date instanceof Date) {
|
|
@@ -109,7 +152,9 @@ function stamp(date, zone) {
|
|
|
109
152
|
else {
|
|
110
153
|
zone *= 60;
|
|
111
154
|
}
|
|
155
|
+
/** --- 时区是否是负数 --- */
|
|
112
156
|
const negative = zone < 0;
|
|
157
|
+
/** --- 时区绝对值 --- */
|
|
113
158
|
const zoneabs = Math.abs(zone);
|
|
114
159
|
return Math.floor((new Date(`${date} ${negative ? '-' : '+'}${Math.floor(zoneabs / 60)}:${zoneabs % 60}`)).getTime() / 1000);
|
|
115
160
|
}
|
|
@@ -117,9 +162,19 @@ function stamp(date, zone) {
|
|
|
117
162
|
return Math.floor(Date.now() / 1000);
|
|
118
163
|
}
|
|
119
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* --- 是否是毫秒 ---
|
|
167
|
+
* @param time 要判断的时间戳
|
|
168
|
+
*/
|
|
120
169
|
function isMs(time) {
|
|
121
170
|
return time > 1000000000000 ? true : false;
|
|
122
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* --- 将时间对象转换为时间字符串 ---
|
|
174
|
+
* @param zone 时区小时或 ctr 对象,如 8,设置 null 则以系统时区为准
|
|
175
|
+
* @param f 转换格式
|
|
176
|
+
* @param date 时间对象或秒/毫秒级数字,如果是秒请乘以 1000
|
|
177
|
+
*/
|
|
123
178
|
function format(zone, f, date) {
|
|
124
179
|
const over = [];
|
|
125
180
|
if (date === undefined) {
|
package/lib/ws.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project: Kebab, User: JianSuoQiYue
|
|
3
|
+
* Date: 2019-6-2 20:42
|
|
4
|
+
* Last: 2020-4-9 22:33:11, 2022-09-13 13:32:01, 2022-12-30 19:13:07, 2024-2-6 23:53:45, 2024-12-23 01:33:16, 2025-1-28 21:05:51
|
|
5
|
+
*/
|
|
1
6
|
import * as http from 'http';
|
|
2
7
|
import * as net from 'net';
|
|
3
8
|
import * as types from '../types';
|
|
4
9
|
import * as sCtr from '../sys/ctr';
|
|
10
|
+
/** --- 一般用 SIMPLE --- */
|
|
5
11
|
export declare enum EFrameReceiveMode {
|
|
6
12
|
STANDARD = 0,
|
|
7
13
|
LITE = 1,
|
|
8
14
|
SIMPLE = 2
|
|
9
15
|
}
|
|
16
|
+
/** --- OPCODE --- */
|
|
10
17
|
export declare enum EOpcode {
|
|
11
18
|
CONTINUATION = 0,
|
|
12
19
|
TEXT = 1,
|
|
@@ -15,51 +22,78 @@ export declare enum EOpcode {
|
|
|
15
22
|
PING = 9,
|
|
16
23
|
PONG = 10
|
|
17
24
|
}
|
|
25
|
+
/** --- 请求的传入参数选项 --- */
|
|
18
26
|
export interface IConnectOptions {
|
|
27
|
+
/** --- 秒数 --- */
|
|
19
28
|
'timeout'?: number;
|
|
20
29
|
'hosts'?: Record<string, string>;
|
|
21
30
|
'local'?: string;
|
|
22
31
|
'headers'?: types.THttpHeaders;
|
|
32
|
+
/** --- cookie 托管对象 --- */
|
|
23
33
|
'cookie'?: Record<string, types.ICookie>;
|
|
34
|
+
/** --- 小帧模式,默认 false --- */
|
|
24
35
|
'mode'?: EFrameReceiveMode;
|
|
36
|
+
/** --- 加密模式,默认 true --- */
|
|
25
37
|
'masking'?: boolean;
|
|
38
|
+
/** --- 正向 mproxy 代理,url 如 wss://xxx/abc --- */
|
|
26
39
|
'mproxy'?: {
|
|
27
40
|
'url': string;
|
|
28
41
|
'auth': string;
|
|
29
42
|
};
|
|
30
43
|
}
|
|
44
|
+
/** --- 正向代理请求的传入参数选项 --- */
|
|
31
45
|
export interface IMproxyOptions {
|
|
46
|
+
/** --- 秒数 --- */
|
|
32
47
|
'timeout'?: number;
|
|
33
48
|
'hosts'?: Record<string, string>;
|
|
34
49
|
'local'?: string;
|
|
35
50
|
'headers'?: types.THttpHeaders;
|
|
51
|
+
/** --- 小帧模式,默认 false --- */
|
|
36
52
|
'mode'?: EFrameReceiveMode;
|
|
53
|
+
/** --- 加密模式,默认 true --- */
|
|
37
54
|
'masking'?: boolean;
|
|
38
55
|
}
|
|
56
|
+
/** --- 反向代理请求的传入参数选项 --- */
|
|
39
57
|
export interface IRproxyOptions {
|
|
58
|
+
/** --- 秒数 --- */
|
|
40
59
|
'timeout'?: number;
|
|
41
60
|
'hosts'?: Record<string, string>;
|
|
42
61
|
'local'?: string;
|
|
43
62
|
'headers'?: types.THttpHeaders;
|
|
63
|
+
/** --- 小帧模式,默认 false --- */
|
|
44
64
|
'mode'?: EFrameReceiveMode;
|
|
65
|
+
/** --- 加密模式,默认 true --- */
|
|
45
66
|
'masking'?: boolean;
|
|
67
|
+
/** --- 正向 mproxy 代理,url 如 wss://xxx/abc --- */
|
|
46
68
|
'mproxy'?: {
|
|
47
69
|
'url': string;
|
|
48
70
|
'auth': string;
|
|
49
71
|
};
|
|
50
72
|
}
|
|
51
73
|
export declare class Socket {
|
|
74
|
+
/** --- 当前的 ws 对象 --- */
|
|
52
75
|
private _ws;
|
|
53
76
|
constructor(request?: http.IncomingMessage, socket?: net.Socket, options?: {
|
|
54
77
|
'headers'?: http.OutgoingHttpHeaders;
|
|
55
78
|
'timeout'?: number;
|
|
56
79
|
});
|
|
80
|
+
/**
|
|
81
|
+
* --- 以客户端形式发起链接 ---
|
|
82
|
+
* @param u 以 ws, wss 开头的地址
|
|
83
|
+
* @param opt 参数
|
|
84
|
+
*/
|
|
57
85
|
connect(u: string, opt?: IConnectOptions): Promise<this | null>;
|
|
86
|
+
/** --- 创建成功后第一时间绑定事件 --- */
|
|
58
87
|
private _bindEvent;
|
|
88
|
+
/** --- 还未开启监听时来的数据将存在这里 --- */
|
|
59
89
|
private readonly _waitMsg;
|
|
90
|
+
/** --- 还未开启 error 监听时产生的 error 错误对象 --- */
|
|
60
91
|
private _error;
|
|
92
|
+
/** --- 还未开启 close 监听时是不是就已经 close --- */
|
|
61
93
|
private _close;
|
|
94
|
+
/** --- 未绑定自定义监听事件的默认执行函数 --- */
|
|
62
95
|
private _on;
|
|
96
|
+
/** --- 绑定监听 --- */
|
|
63
97
|
on(event: 'message', cb: (msg: {
|
|
64
98
|
'opcode': EOpcode;
|
|
65
99
|
'data': Buffer | string;
|
|
@@ -68,20 +102,54 @@ export declare class Socket {
|
|
|
68
102
|
on(event: 'drain' | 'close' | 'end', cb: () => void | Promise<void>): this;
|
|
69
103
|
end(): void;
|
|
70
104
|
destroy(): void;
|
|
105
|
+
/** --- 发送文本 --- */
|
|
71
106
|
writeText(data: string): boolean;
|
|
107
|
+
/** --- 发送结果对象字符串 --- */
|
|
72
108
|
writeResult(data: types.Json): boolean;
|
|
109
|
+
/** --- 发送二进制 --- */
|
|
73
110
|
writeBinary(data: string | Buffer | Array<string | Buffer>): boolean;
|
|
111
|
+
/** --- 当前是否是可写状态 --- */
|
|
74
112
|
get writable(): boolean;
|
|
113
|
+
/** --- 当前是否已经结束读取,并且无法继续读取 --- */
|
|
75
114
|
get ended(): boolean;
|
|
115
|
+
/** --- 当前是否已经结束写入,并且无法继续写入 --- */
|
|
76
116
|
get finished(): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* --- 当前连接是不是服务器连接 ---
|
|
119
|
+
*/
|
|
77
120
|
get isServer(): boolean;
|
|
121
|
+
/** --- 发送 ping --- */
|
|
78
122
|
ping(data?: Buffer | string): boolean;
|
|
123
|
+
/** --- 发送 ping --- */
|
|
79
124
|
pong(data?: Buffer | string): boolean;
|
|
80
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* --- 创建一个 ws 客户端发起 ws 请求 ---
|
|
128
|
+
* @param u 以 ws, wss 开头的地址
|
|
129
|
+
* @param opt 参数
|
|
130
|
+
*/
|
|
81
131
|
export declare function connect(u: string, opt?: IConnectOptions): Promise<Socket | null>;
|
|
132
|
+
/**
|
|
133
|
+
* --- 创建一个 ws 服务器接收处理器 ---
|
|
134
|
+
* @param request Http 请求端
|
|
135
|
+
* @param socket 响应双向 socket
|
|
136
|
+
*/
|
|
82
137
|
export declare function createServer(request: http.IncomingMessage, socket: net.Socket, options?: {
|
|
83
138
|
'headers'?: http.OutgoingHttpHeaders;
|
|
84
139
|
'timeout'?: number;
|
|
85
140
|
}): Socket;
|
|
141
|
+
/**
|
|
142
|
+
* --- 正向 mproxy 代理,读取 get 的 url 为实际请求地址 ---
|
|
143
|
+
* --- get: url, auth ---
|
|
144
|
+
* @param ctr 当前控制器
|
|
145
|
+
* @param auth 校验字符串,读取 get 的 auth 和本参数做比对
|
|
146
|
+
* @param opt 参数
|
|
147
|
+
*/
|
|
86
148
|
export declare function mproxy(ctr: sCtr.Ctr, auth: string, opt?: IMproxyOptions): Promise<number>;
|
|
149
|
+
/**
|
|
150
|
+
* --- 反向代理,将本 socket 连接反代到其他网址,在 ws 的 onLoad 事件中使用 ---
|
|
151
|
+
* @param ctr 当前控制器
|
|
152
|
+
* @param url 反代真实请求地址,如有 get 需要自行添加
|
|
153
|
+
* @param opt 参数
|
|
154
|
+
*/
|
|
87
155
|
export declare function rproxy(ctr: sCtr.Ctr, url: string, opt?: IRproxyOptions): Promise<boolean>;
|
package/lib/ws.js
CHANGED
|
@@ -38,15 +38,19 @@ exports.connect = connect;
|
|
|
38
38
|
exports.createServer = createServer;
|
|
39
39
|
exports.mproxy = mproxy;
|
|
40
40
|
exports.rproxy = rproxy;
|
|
41
|
+
// --- 第三方 ---
|
|
41
42
|
const liws = __importStar(require("@litert/websocket"));
|
|
43
|
+
// --- 库 ---
|
|
42
44
|
const lText = __importStar(require("../lib/text"));
|
|
43
45
|
const lNet = __importStar(require("../lib/net"));
|
|
46
|
+
/** --- 一般用 SIMPLE --- */
|
|
44
47
|
var EFrameReceiveMode;
|
|
45
48
|
(function (EFrameReceiveMode) {
|
|
46
49
|
EFrameReceiveMode[EFrameReceiveMode["STANDARD"] = 0] = "STANDARD";
|
|
47
50
|
EFrameReceiveMode[EFrameReceiveMode["LITE"] = 1] = "LITE";
|
|
48
51
|
EFrameReceiveMode[EFrameReceiveMode["SIMPLE"] = 2] = "SIMPLE";
|
|
49
52
|
})(EFrameReceiveMode || (exports.EFrameReceiveMode = EFrameReceiveMode = {}));
|
|
53
|
+
/** --- OPCODE --- */
|
|
50
54
|
var EOpcode;
|
|
51
55
|
(function (EOpcode) {
|
|
52
56
|
EOpcode[EOpcode["CONTINUATION"] = 0] = "CONTINUATION";
|
|
@@ -59,14 +63,19 @@ var EOpcode;
|
|
|
59
63
|
const liwsServer = liws.createServer();
|
|
60
64
|
class Socket {
|
|
61
65
|
constructor(request, socket, options = {}) {
|
|
66
|
+
/** --- 还未开启监听时来的数据将存在这里 --- */
|
|
62
67
|
this._waitMsg = [];
|
|
68
|
+
/** --- 还未开启 error 监听时产生的 error 错误对象 --- */
|
|
63
69
|
this._error = null;
|
|
70
|
+
/** --- 还未开启 close 监听时是不是就已经 close --- */
|
|
64
71
|
this._close = false;
|
|
72
|
+
/** --- 未绑定自定义监听事件的默认执行函数 --- */
|
|
65
73
|
this._on = {
|
|
66
74
|
message: (msg) => {
|
|
67
75
|
this._waitMsg.push(msg);
|
|
68
76
|
},
|
|
69
77
|
drain: () => {
|
|
78
|
+
// --- nothing ---
|
|
70
79
|
},
|
|
71
80
|
error: (e) => {
|
|
72
81
|
this._error = e;
|
|
@@ -75,11 +84,13 @@ class Socket {
|
|
|
75
84
|
this._close = true;
|
|
76
85
|
},
|
|
77
86
|
end: () => {
|
|
87
|
+
// --- nothing ---
|
|
78
88
|
}
|
|
79
89
|
};
|
|
80
90
|
if (!request || !socket) {
|
|
81
91
|
return;
|
|
82
92
|
}
|
|
93
|
+
// --- 一定是 server 模式 ---
|
|
83
94
|
this._ws = liwsServer.accept({
|
|
84
95
|
'request': request,
|
|
85
96
|
'socket': socket,
|
|
@@ -88,11 +99,17 @@ class Socket {
|
|
|
88
99
|
});
|
|
89
100
|
this._bindEvent();
|
|
90
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* --- 以客户端形式发起链接 ---
|
|
104
|
+
* @param u 以 ws, wss 开头的地址
|
|
105
|
+
* @param opt 参数
|
|
106
|
+
*/
|
|
91
107
|
async connect(u, opt = {}) {
|
|
92
108
|
const uri = lText.parseUrl(u);
|
|
93
109
|
if (!uri.hostname) {
|
|
94
110
|
return null;
|
|
95
111
|
}
|
|
112
|
+
/** --- 正向代理的地址 --- */
|
|
96
113
|
const puri = opt.mproxy ? lText.parseUrl(opt.mproxy.url) : null;
|
|
97
114
|
const timeout = opt.timeout ?? 10;
|
|
98
115
|
const hosts = opt.hosts ?? {};
|
|
@@ -106,16 +123,20 @@ class Socket {
|
|
|
106
123
|
}
|
|
107
124
|
}
|
|
108
125
|
headers['user-agent'] ??= 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36';
|
|
126
|
+
// --- cookie 托管 ---
|
|
109
127
|
if (opt.cookie) {
|
|
110
128
|
headers['cookie'] = lNet.buildCookieQuery(opt.cookie, uri);
|
|
111
129
|
}
|
|
130
|
+
// --- ssl ---
|
|
112
131
|
const ca = puri ?
|
|
113
132
|
puri.protocol === 'wss:' ? await lNet.getCa() : null :
|
|
114
133
|
uri.protocol === 'wss:' ? await lNet.getCa() : null;
|
|
115
134
|
if (!ca && hosts[uri.hostname]) {
|
|
135
|
+
// --- 没有 ca,但是要设置 额外的 host ---
|
|
116
136
|
headers['host'] = uri.hostname + (uri.port ? ':' + uri.port : '');
|
|
117
137
|
}
|
|
118
138
|
try {
|
|
139
|
+
// --- 重定义 IP ---
|
|
119
140
|
const host = puri?.hostname ?? uri.hostname ?? '';
|
|
120
141
|
const port = (puri ? puri.port : uri.port) ?? 443;
|
|
121
142
|
const path = puri ? puri.path + (puri.path?.includes('?') ? '&' : '?') + lText.queryStringify({
|
|
@@ -152,6 +173,7 @@ class Socket {
|
|
|
152
173
|
return null;
|
|
153
174
|
}
|
|
154
175
|
}
|
|
176
|
+
/** --- 创建成功后第一时间绑定事件 --- */
|
|
155
177
|
_bindEvent() {
|
|
156
178
|
this._ws.on('message', (msg) => {
|
|
157
179
|
(async () => {
|
|
@@ -173,6 +195,7 @@ class Socket {
|
|
|
173
195
|
'data': data
|
|
174
196
|
});
|
|
175
197
|
})().catch(() => {
|
|
198
|
+
// --- nothing ---
|
|
176
199
|
});
|
|
177
200
|
}).on('drain', () => {
|
|
178
201
|
this._on.drain();
|
|
@@ -205,6 +228,7 @@ class Socket {
|
|
|
205
228
|
break;
|
|
206
229
|
}
|
|
207
230
|
default: {
|
|
231
|
+
// --- close ---
|
|
208
232
|
if (!this._close) {
|
|
209
233
|
break;
|
|
210
234
|
}
|
|
@@ -219,36 +243,46 @@ class Socket {
|
|
|
219
243
|
destroy() {
|
|
220
244
|
this._ws.destroy();
|
|
221
245
|
}
|
|
246
|
+
/** --- 发送文本 --- */
|
|
222
247
|
writeText(data) {
|
|
223
248
|
if (!this._ws.writable) {
|
|
224
249
|
return false;
|
|
225
250
|
}
|
|
226
251
|
return this._ws.writeText(data);
|
|
227
252
|
}
|
|
253
|
+
/** --- 发送结果对象字符串 --- */
|
|
228
254
|
writeResult(data) {
|
|
229
255
|
if (!this._ws.writable) {
|
|
230
256
|
return false;
|
|
231
257
|
}
|
|
232
258
|
return this._ws.writeText(lText.stringifyResult(data));
|
|
233
259
|
}
|
|
260
|
+
/** --- 发送二进制 --- */
|
|
234
261
|
writeBinary(data) {
|
|
235
262
|
if (!this._ws.writable) {
|
|
236
263
|
return false;
|
|
237
264
|
}
|
|
238
265
|
return this._ws.writeBinary(data);
|
|
239
266
|
}
|
|
267
|
+
/** --- 当前是否是可写状态 --- */
|
|
240
268
|
get writable() {
|
|
241
269
|
return this._ws.writable;
|
|
242
270
|
}
|
|
271
|
+
/** --- 当前是否已经结束读取,并且无法继续读取 --- */
|
|
243
272
|
get ended() {
|
|
244
273
|
return this._ws.ended;
|
|
245
274
|
}
|
|
275
|
+
/** --- 当前是否已经结束写入,并且无法继续写入 --- */
|
|
246
276
|
get finished() {
|
|
247
277
|
return this._ws.finished;
|
|
248
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* --- 当前连接是不是服务器连接 ---
|
|
281
|
+
*/
|
|
249
282
|
get isServer() {
|
|
250
283
|
return this._ws.isServer;
|
|
251
284
|
}
|
|
285
|
+
/** --- 发送 ping --- */
|
|
252
286
|
ping(data) {
|
|
253
287
|
try {
|
|
254
288
|
this._ws.ping(data);
|
|
@@ -258,6 +292,7 @@ class Socket {
|
|
|
258
292
|
return false;
|
|
259
293
|
}
|
|
260
294
|
}
|
|
295
|
+
/** --- 发送 ping --- */
|
|
261
296
|
pong(data) {
|
|
262
297
|
try {
|
|
263
298
|
this._ws.pong(data);
|
|
@@ -269,15 +304,31 @@ class Socket {
|
|
|
269
304
|
}
|
|
270
305
|
}
|
|
271
306
|
exports.Socket = Socket;
|
|
307
|
+
/**
|
|
308
|
+
* --- 创建一个 ws 客户端发起 ws 请求 ---
|
|
309
|
+
* @param u 以 ws, wss 开头的地址
|
|
310
|
+
* @param opt 参数
|
|
311
|
+
*/
|
|
272
312
|
function connect(u, opt = {}) {
|
|
273
313
|
const s = new Socket();
|
|
274
314
|
return s.connect(u, opt);
|
|
275
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* --- 创建一个 ws 服务器接收处理器 ---
|
|
318
|
+
* @param request Http 请求端
|
|
319
|
+
* @param socket 响应双向 socket
|
|
320
|
+
*/
|
|
276
321
|
function createServer(request, socket, options = {}) {
|
|
277
322
|
return new Socket(request, socket, options);
|
|
278
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* --- 绑定 socket 管道 ---
|
|
326
|
+
* @param s1 第一个 socket
|
|
327
|
+
* @param s2 第二个 socket
|
|
328
|
+
*/
|
|
279
329
|
function bindPipe(s1, s2) {
|
|
280
330
|
return new Promise((resolve) => {
|
|
331
|
+
// --- 监听发送端的 ---
|
|
281
332
|
s1.on('message', (msg) => {
|
|
282
333
|
switch (msg.opcode) {
|
|
283
334
|
case EOpcode.TEXT:
|
|
@@ -303,11 +354,13 @@ function bindPipe(s1, s2) {
|
|
|
303
354
|
break;
|
|
304
355
|
}
|
|
305
356
|
default: {
|
|
357
|
+
// --- EOpcode.CONTINUATION ---
|
|
306
358
|
}
|
|
307
359
|
}
|
|
308
360
|
}).on('close', () => {
|
|
309
361
|
resolve();
|
|
310
362
|
});
|
|
363
|
+
// --- 监听远程端的 ---
|
|
311
364
|
s2.on('message', (msg) => {
|
|
312
365
|
switch (msg.opcode) {
|
|
313
366
|
case EOpcode.TEXT:
|
|
@@ -333,6 +386,7 @@ function bindPipe(s1, s2) {
|
|
|
333
386
|
break;
|
|
334
387
|
}
|
|
335
388
|
default: {
|
|
389
|
+
// --- EOpcode.CONTINUATION ---
|
|
336
390
|
}
|
|
337
391
|
}
|
|
338
392
|
}).on('close', () => {
|
|
@@ -340,9 +394,18 @@ function bindPipe(s1, s2) {
|
|
|
340
394
|
});
|
|
341
395
|
});
|
|
342
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* --- 正向 mproxy 代理,读取 get 的 url 为实际请求地址 ---
|
|
399
|
+
* --- get: url, auth ---
|
|
400
|
+
* @param ctr 当前控制器
|
|
401
|
+
* @param auth 校验字符串,读取 get 的 auth 和本参数做比对
|
|
402
|
+
* @param opt 参数
|
|
403
|
+
*/
|
|
343
404
|
async function mproxy(ctr, auth, opt = {}) {
|
|
344
405
|
const req = ctr.getPrototype('_req');
|
|
406
|
+
/** --- 请求端产生的双向 socket --- */
|
|
345
407
|
const socket = ctr.getPrototype('_socket');
|
|
408
|
+
/** --- 客户端请求中的 get 的数据 --- */
|
|
346
409
|
const get = ctr.getPrototype('_get');
|
|
347
410
|
if (get['auth'] !== auth) {
|
|
348
411
|
return 0;
|
|
@@ -352,6 +415,8 @@ async function mproxy(ctr, auth, opt = {}) {
|
|
|
352
415
|
}
|
|
353
416
|
opt.headers ??= {};
|
|
354
417
|
Object.assign(opt.headers, lNet.filterProxyHeaders(req.headers));
|
|
418
|
+
// --- 发起请求 ---
|
|
419
|
+
/** --- 远程端的双向 socket --- */
|
|
355
420
|
const rsocket = await connect(get['url'], opt);
|
|
356
421
|
if (!rsocket) {
|
|
357
422
|
return -2;
|
|
@@ -359,11 +424,20 @@ async function mproxy(ctr, auth, opt = {}) {
|
|
|
359
424
|
await bindPipe(socket, rsocket);
|
|
360
425
|
return 1;
|
|
361
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* --- 反向代理,将本 socket 连接反代到其他网址,在 ws 的 onLoad 事件中使用 ---
|
|
429
|
+
* @param ctr 当前控制器
|
|
430
|
+
* @param url 反代真实请求地址,如有 get 需要自行添加
|
|
431
|
+
* @param opt 参数
|
|
432
|
+
*/
|
|
362
433
|
async function rproxy(ctr, url, opt = {}) {
|
|
363
434
|
const req = ctr.getPrototype('_req');
|
|
435
|
+
/** --- 请求端产生的双向 socket --- */
|
|
364
436
|
const socket = ctr.getPrototype('_socket');
|
|
365
437
|
opt.headers ??= {};
|
|
366
438
|
Object.assign(opt.headers, lNet.filterProxyHeaders(req.headers));
|
|
439
|
+
// --- 发起请求 ---
|
|
440
|
+
/** --- 远程端的双向 socket --- */
|
|
367
441
|
const rsocket = await connect(url, opt);
|
|
368
442
|
if (!rsocket) {
|
|
369
443
|
return false;
|
package/lib/zip.d.ts
CHANGED
|
@@ -1,20 +1,49 @@
|
|
|
1
1
|
import jszip from 'jszip';
|
|
2
2
|
import * as types from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* --- 本库主要用于读取 zip,请尽量不要用来写入 zip,尤其是大文件 zip ---
|
|
5
|
+
*/
|
|
3
6
|
export declare class Zip {
|
|
7
|
+
/** --- zip 对象 --- */
|
|
4
8
|
private readonly _zip;
|
|
9
|
+
/** --- 当前路径,以 / 开头以 / 结尾 --- */
|
|
5
10
|
private _path;
|
|
6
11
|
constructor(zip: jszip);
|
|
7
12
|
getContent(path: string): Promise<string | null>;
|
|
8
13
|
getContent<T extends types.TZipOutputType>(path: string, type: T): Promise<types.IZipOutputByType[T] | null>;
|
|
14
|
+
/**
|
|
15
|
+
* --- 写入文件内容 ---
|
|
16
|
+
* @param path 文件路径
|
|
17
|
+
* @param data 要写入的内容
|
|
18
|
+
* @param options 选项
|
|
19
|
+
*/
|
|
9
20
|
putContent<T extends types.TZipInputType>(path: string, data: types.IZipInputByType[T], options?: {
|
|
10
21
|
'base64'?: boolean;
|
|
11
22
|
'binary'?: boolean;
|
|
12
23
|
'date'?: Date;
|
|
13
24
|
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* --- 删除一个文件/文件夹(深度删除) ---
|
|
27
|
+
* @param path 要删除的文件路径
|
|
28
|
+
*/
|
|
14
29
|
unlink(path: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* --- 获取对象是否存在,存在则返回 stats 对象,否则返回 null ---
|
|
32
|
+
* @param path 对象路径
|
|
33
|
+
* @param options 选项
|
|
34
|
+
*/
|
|
15
35
|
stats(path: string): types.IZipStats | null;
|
|
36
|
+
/**
|
|
37
|
+
* --- 判断是否是目录或目录是否存在,是的话返回 stats ---
|
|
38
|
+
* @param path 判断路径
|
|
39
|
+
*/
|
|
16
40
|
isDir(path: string): types.IZipStats | false;
|
|
41
|
+
/**
|
|
42
|
+
* --- 判断是否是文件或文件是否存在,是的话返回 stats ---
|
|
43
|
+
* @param path 判断路径
|
|
44
|
+
*/
|
|
17
45
|
isFile(path: string): types.IZipStats | false;
|
|
46
|
+
/** --- 读取目录,hasChildren: false, hasDir: true, pathAsKey: false --- */
|
|
18
47
|
readDir(path?: string, opt?: {
|
|
19
48
|
'hasChildren'?: boolean;
|
|
20
49
|
'hasDir'?: boolean;
|
|
@@ -26,15 +55,39 @@ export declare class Zip {
|
|
|
26
55
|
'pathAsKey': true;
|
|
27
56
|
}): Record<string, types.IZipItem>;
|
|
28
57
|
private _readDir;
|
|
58
|
+
/** --- 目录列表缓存 --- */
|
|
29
59
|
private _list;
|
|
60
|
+
/**
|
|
61
|
+
* --- 重建目录列表缓存 ---
|
|
62
|
+
*/
|
|
30
63
|
private _refreshList;
|
|
64
|
+
/**
|
|
65
|
+
* --- 获取当前目录,末尾不带 / ---
|
|
66
|
+
* @return string
|
|
67
|
+
*/
|
|
31
68
|
pwd(): string;
|
|
69
|
+
/**
|
|
70
|
+
* --- 进入一个目录(不存在也能进入,需要自行判断) ---
|
|
71
|
+
* --- 返回进入后的路径值 ---
|
|
72
|
+
* @param dir 相对路径或绝对路径
|
|
73
|
+
*/
|
|
32
74
|
cd(dir: string): string;
|
|
75
|
+
/**
|
|
76
|
+
* --- 打包 zip ---
|
|
77
|
+
* @param options 选项
|
|
78
|
+
*/
|
|
33
79
|
generate<T extends types.TZipOutputType>(options?: {
|
|
34
80
|
'type'?: T;
|
|
35
81
|
'level'?: number;
|
|
36
82
|
'onUpdate'?: (percent: number, currentFile: string | null) => void;
|
|
37
83
|
}): Promise<types.IZipOutputByType[T]>;
|
|
84
|
+
/**
|
|
85
|
+
* --- 获取 path 和 string/Buffer 对应的文件列表 ---
|
|
86
|
+
*/
|
|
38
87
|
getList(): Promise<Record<string, Buffer | string>>;
|
|
39
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* --- 获取 zip 对象 ---
|
|
91
|
+
* @param data 对象数据
|
|
92
|
+
*/
|
|
40
93
|
export declare function get(data?: types.TZipInputFileFormat): Promise<Zip | null>;
|