@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/dns.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Project: Kebab, User: JianSuoQiYue
|
|
4
|
+
* Date: 2019-6-19
|
|
5
|
+
* Last: 2022-09-12 20:58:07, 2024-2-21 17:55:54, 2025-6-13 19:08:56
|
|
6
|
+
*/
|
|
2
7
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
8
|
if (k2 === undefined) k2 = k;
|
|
4
9
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -35,16 +40,25 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
41
|
exports.Dns = exports.ERecordLine = exports.RECORD_TYPE = exports.ESERVICE = void 0;
|
|
37
42
|
exports.get = get;
|
|
43
|
+
// --- 库和定义 ---
|
|
38
44
|
const net = __importStar(require("../lib/net"));
|
|
39
45
|
const core = __importStar(require("../lib/core"));
|
|
40
46
|
const text = __importStar(require("../lib/text"));
|
|
41
47
|
const crypto = __importStar(require("../lib/crypto"));
|
|
42
48
|
const response = __importStar(require("../lib/net/response"));
|
|
49
|
+
/**
|
|
50
|
+
* 0.DNSPod:https://www.dnspod.cn/docs/index.html(腾讯云也请使用 DNSPod 的 API)
|
|
51
|
+
* 1.阿里云:https://help.aliyun.com/document_detail/29745.html
|
|
52
|
+
*/
|
|
53
|
+
/** --- 服务商定义 --- */
|
|
43
54
|
var ESERVICE;
|
|
44
55
|
(function (ESERVICE) {
|
|
45
56
|
ESERVICE[ESERVICE["DNSPOD"] = 0] = "DNSPOD";
|
|
46
57
|
ESERVICE[ESERVICE["ALIBABA"] = 1] = "ALIBABA";
|
|
47
58
|
})(ESERVICE || (exports.ESERVICE = ESERVICE = {}));
|
|
59
|
+
/**
|
|
60
|
+
* --- 记录值类型 ---
|
|
61
|
+
*/
|
|
48
62
|
exports.RECORD_TYPE = {
|
|
49
63
|
'A': 'A',
|
|
50
64
|
'NS': 'NS',
|
|
@@ -54,6 +68,9 @@ exports.RECORD_TYPE = {
|
|
|
54
68
|
'SRV': 'SRV',
|
|
55
69
|
'AAAA': 'AAAA'
|
|
56
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* --- 记录值线路 ---
|
|
73
|
+
*/
|
|
57
74
|
var ERecordLine;
|
|
58
75
|
(function (ERecordLine) {
|
|
59
76
|
ERecordLine[ERecordLine["DEFAULT"] = 0] = "DEFAULT";
|
|
@@ -88,6 +105,10 @@ class Dns {
|
|
|
88
105
|
opt.secretKey ??= config.dns?.[ESERVICE[opt.service]].skey;
|
|
89
106
|
this._opt = opt;
|
|
90
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* --- 最终发送 ---
|
|
110
|
+
* @param obj 要发送的信息
|
|
111
|
+
*/
|
|
91
112
|
async _send(obj) {
|
|
92
113
|
for (const key in obj) {
|
|
93
114
|
if (obj[key] === null || obj[key] === undefined) {
|
|
@@ -95,6 +116,7 @@ class Dns {
|
|
|
95
116
|
}
|
|
96
117
|
}
|
|
97
118
|
switch (this._opt.service) {
|
|
119
|
+
// --- DNSPod ---
|
|
98
120
|
case ESERVICE.DNSPOD: {
|
|
99
121
|
const data = Object.assign({
|
|
100
122
|
'login_token': (this._opt.secretId ?? '') + '.' + (this._opt.secretKey ?? ''),
|
|
@@ -102,8 +124,9 @@ class Dns {
|
|
|
102
124
|
}, obj);
|
|
103
125
|
const path = data['_path'];
|
|
104
126
|
delete data['_path'];
|
|
105
|
-
return net.post('https://dnsapi.cn/' + path, data);
|
|
127
|
+
return net.post('https://dnsapi.cn/' + path, data); // 境外 api 会自动调度到香港服务器
|
|
106
128
|
}
|
|
129
|
+
// --- 阿里云 ---
|
|
107
130
|
case ESERVICE.ALIBABA: {
|
|
108
131
|
const getData = core.objectSort(Object.assign({
|
|
109
132
|
'Format': 'JSON',
|
|
@@ -116,13 +139,18 @@ class Dns {
|
|
|
116
139
|
}, obj));
|
|
117
140
|
const urlRight = text.queryStringify(getData);
|
|
118
141
|
const signature = crypto.hashHmac('sha1', `GET&${encodeURIComponent('/')}&${encodeURIComponent(urlRight)}`, (this._opt.secretKey ?? '') + '&', 'base64');
|
|
119
|
-
return net.get(`https://alidns.aliyuncs.com/?${urlRight}&Signature=${encodeURIComponent(signature)}`);
|
|
142
|
+
return net.get(`https://alidns.aliyuncs.com/?${urlRight}&Signature=${encodeURIComponent(signature)}`); // 境外 api 会自动调度到新加坡服务器
|
|
120
143
|
}
|
|
121
144
|
}
|
|
122
145
|
return new response.Response(null);
|
|
123
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* --- 获取域名列表 ---
|
|
149
|
+
* @param opt 参数
|
|
150
|
+
*/
|
|
124
151
|
async getDomainList(opt) {
|
|
125
152
|
switch (this._opt.service) {
|
|
153
|
+
// --- DNSPod ---
|
|
126
154
|
case ESERVICE.DNSPOD: {
|
|
127
155
|
const rtn = await this._send({
|
|
128
156
|
'_path': 'Domain.List',
|
|
@@ -148,6 +176,7 @@ class Dns {
|
|
|
148
176
|
}
|
|
149
177
|
return r;
|
|
150
178
|
}
|
|
179
|
+
// --- 阿里云 ---
|
|
151
180
|
case ESERVICE.ALIBABA: {
|
|
152
181
|
const length = opt.length ?? 20;
|
|
153
182
|
const rtn = await this._send({
|
|
@@ -177,10 +206,15 @@ class Dns {
|
|
|
177
206
|
}
|
|
178
207
|
return null;
|
|
179
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* --- 添加记录 ---
|
|
211
|
+
* @param opt 参数
|
|
212
|
+
*/
|
|
180
213
|
async addDomainRecord(opt) {
|
|
181
214
|
const line = opt.line ?? ERecordLine.DEFAULT;
|
|
182
215
|
const ttl = opt.ttl ?? 600;
|
|
183
216
|
switch (this._opt.service) {
|
|
217
|
+
// --- DNSPod ---
|
|
184
218
|
case ESERVICE.DNSPOD: {
|
|
185
219
|
const rtn = await this._send({
|
|
186
220
|
'_path': 'Record.Create',
|
|
@@ -203,6 +237,7 @@ class Dns {
|
|
|
203
237
|
};
|
|
204
238
|
return r;
|
|
205
239
|
}
|
|
240
|
+
// --- 阿里云 ---
|
|
206
241
|
case ESERVICE.ALIBABA: {
|
|
207
242
|
const rtn = await this._send({
|
|
208
243
|
'Action': 'AddDomainRecord',
|
|
@@ -228,11 +263,17 @@ class Dns {
|
|
|
228
263
|
}
|
|
229
264
|
return null;
|
|
230
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* --- 修改记录 ---
|
|
268
|
+
* @param opt 参数
|
|
269
|
+
*/
|
|
231
270
|
async updateDomainRecord(opt) {
|
|
232
271
|
const line = opt.line ?? ERecordLine.DEFAULT;
|
|
233
272
|
const ttl = opt.ttl ?? 600;
|
|
234
273
|
switch (this._opt.service) {
|
|
274
|
+
// --- DNSPod ---
|
|
235
275
|
case ESERVICE.DNSPOD: {
|
|
276
|
+
// --- DNSPod 必须传 domain ---
|
|
236
277
|
const rtn = await this._send({
|
|
237
278
|
'_path': 'Record.Modify',
|
|
238
279
|
'domain': opt.domain,
|
|
@@ -255,6 +296,7 @@ class Dns {
|
|
|
255
296
|
};
|
|
256
297
|
return r;
|
|
257
298
|
}
|
|
299
|
+
// --- 阿里云 ---
|
|
258
300
|
case ESERVICE.ALIBABA: {
|
|
259
301
|
const rtn = await this._send({
|
|
260
302
|
'Action': 'UpdateDomainRecord',
|
|
@@ -280,8 +322,13 @@ class Dns {
|
|
|
280
322
|
}
|
|
281
323
|
return null;
|
|
282
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* --- 删除记录 ---
|
|
327
|
+
* @param opt 参数
|
|
328
|
+
*/
|
|
283
329
|
async deleteDomainRecord(opt) {
|
|
284
330
|
switch (this._opt.service) {
|
|
331
|
+
// --- DNSPod ---
|
|
285
332
|
case ESERVICE.DNSPOD: {
|
|
286
333
|
const rtn = await this._send({
|
|
287
334
|
'_path': 'Record.Remove',
|
|
@@ -297,6 +344,7 @@ class Dns {
|
|
|
297
344
|
'success': json.status.code === '1' ? true : false
|
|
298
345
|
};
|
|
299
346
|
}
|
|
347
|
+
// --- 阿里云 ---
|
|
300
348
|
case ESERVICE.ALIBABA: {
|
|
301
349
|
const rtn = await this._send({
|
|
302
350
|
'Action': 'DeleteDomainRecord',
|
|
@@ -316,6 +364,10 @@ class Dns {
|
|
|
316
364
|
}
|
|
317
365
|
}
|
|
318
366
|
exports.Dns = Dns;
|
|
367
|
+
/**
|
|
368
|
+
* --- 创建一个第三方 Dns 对象 ---
|
|
369
|
+
* @param opt 选项
|
|
370
|
+
*/
|
|
319
371
|
function get(ctr, opt) {
|
|
320
372
|
return new Dns(ctr, opt);
|
|
321
373
|
}
|
package/lib/fs.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project: Kebab, User: JianSuoQiYue
|
|
3
|
+
* Date: 2019-3-29 23:03:07
|
|
4
|
+
* Last: 2020-3-11 22:21:51, 2022-12-29 01:18:25, 2023-12-13 20:50:09
|
|
5
|
+
*/
|
|
1
6
|
import * as fs from 'fs';
|
|
2
7
|
import * as http from 'http';
|
|
3
8
|
import * as http2 from 'http2';
|
|
@@ -10,25 +15,102 @@ export declare function getContent(path: string, options: BufferEncoding | {
|
|
|
10
15
|
'start'?: number;
|
|
11
16
|
'end'?: number;
|
|
12
17
|
}): Promise<string | null>;
|
|
18
|
+
/**
|
|
19
|
+
* --- 写入文件内容 ---
|
|
20
|
+
* @param path 文件路径
|
|
21
|
+
* @param data 要写入的内容
|
|
22
|
+
* @param options 选项
|
|
23
|
+
*/
|
|
13
24
|
export declare function putContent(path: string, data: string | Buffer, options?: {
|
|
14
25
|
'encoding'?: BufferEncoding;
|
|
15
26
|
'mode'?: number;
|
|
16
27
|
'flag'?: string;
|
|
17
28
|
}): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* --- 读取链接的 target ---
|
|
31
|
+
* @param path 要读取的路径
|
|
32
|
+
* @param encoding 编码
|
|
33
|
+
*/
|
|
18
34
|
export declare function readLink(path: string, encoding?: BufferEncoding): Promise<string | null>;
|
|
35
|
+
/**
|
|
36
|
+
* --- 把源文件创建一个 link ---
|
|
37
|
+
* @param filePath 源文件
|
|
38
|
+
* @param linkPath 连接路径
|
|
39
|
+
* @param type 仅 Windows,类型,默认 file
|
|
40
|
+
*/
|
|
19
41
|
export declare function symlink(filePath: string, linkPath: string, type?: 'dir' | 'file' | 'junction'): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* --- 删除一个文件 ---
|
|
44
|
+
* @param path 要删除的文件路径
|
|
45
|
+
*/
|
|
20
46
|
export declare function unlink(path: string): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* --- 获取对象是否存在,存在则返回 stats 对象,否则返回 null ---
|
|
49
|
+
* @param path 对象路径
|
|
50
|
+
*/
|
|
21
51
|
export declare function stats(path: string): Promise<fs.Stats | null>;
|
|
52
|
+
/**
|
|
53
|
+
* --- 判断是否是目录或目录是否存在,是的话返回 stats ---
|
|
54
|
+
* @param path 判断路径
|
|
55
|
+
*/
|
|
22
56
|
export declare function isDir(path: string): Promise<fs.Stats | false>;
|
|
57
|
+
/**
|
|
58
|
+
* --- 判断是否是文件或文件是否存在,是的话返回 stats ---
|
|
59
|
+
* @param path 判断路径
|
|
60
|
+
*/
|
|
23
61
|
export declare function isFile(path: string): Promise<fs.Stats | false>;
|
|
62
|
+
/**
|
|
63
|
+
* --- 深度创建目录,如果最末目录存在,则自动创建成功 ---
|
|
64
|
+
* @param path 要创建的路径,如 /a/b/c/
|
|
65
|
+
* @param mode 权限
|
|
66
|
+
*/
|
|
24
67
|
export declare function mkdir(path: string, mode?: number): Promise<boolean>;
|
|
68
|
+
/**
|
|
69
|
+
* --- 删除空目录 ---
|
|
70
|
+
* @param path 要删除的目录
|
|
71
|
+
*/
|
|
25
72
|
export declare function rmdir(path: string): Promise<boolean>;
|
|
73
|
+
/**
|
|
74
|
+
* --- Danger 危险:危险函数,尽量不要使用 ---
|
|
75
|
+
* --- This f**king is a danger function, please don't use it ---
|
|
76
|
+
* --- 删除一个非空目录 ---
|
|
77
|
+
*/
|
|
26
78
|
export declare function rmdirDeep(path: string): Promise<boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* --- 修改权限
|
|
81
|
+
* @param path 要修改的路径
|
|
82
|
+
* @param mod 权限
|
|
83
|
+
*/
|
|
27
84
|
export declare function chmod(path: string, mod: string | number): Promise<boolean>;
|
|
85
|
+
/**
|
|
86
|
+
* --- 重命名/移动 文件文件夹 ---
|
|
87
|
+
* @param oldPath 老名
|
|
88
|
+
* @param newPath 新名
|
|
89
|
+
*/
|
|
28
90
|
export declare function rename(oldPath: string, newPath: string): Promise<boolean>;
|
|
91
|
+
/**
|
|
92
|
+
* --- 获取文件夹下文件列表 ---
|
|
93
|
+
* @param path 文件夹路径
|
|
94
|
+
*/
|
|
29
95
|
export declare function readDir(path: string, encoding?: BufferEncoding): Promise<fs.Dirent[]>;
|
|
96
|
+
/**
|
|
97
|
+
* --- 复制文件夹里的内容到另一个地方,失败不会回滚 ---
|
|
98
|
+
* @param from 源,末尾加 /
|
|
99
|
+
* @param to 目标,末尾加 /
|
|
100
|
+
* @param ignore 忽略的文件
|
|
101
|
+
*/
|
|
30
102
|
export declare function copyFolder(from: string, to: string, ignore?: RegExp[]): Promise<number>;
|
|
103
|
+
/**
|
|
104
|
+
* --- 复制文件 ---
|
|
105
|
+
* @param src 源文件
|
|
106
|
+
* @param dest 目标文件
|
|
107
|
+
*/
|
|
31
108
|
export declare function copyFile(src: string, dest: string): Promise<boolean>;
|
|
109
|
+
/**
|
|
110
|
+
* --- 创建读取文件的流 ---
|
|
111
|
+
* @param path 文件地址
|
|
112
|
+
* @param options 编码或配置
|
|
113
|
+
*/
|
|
32
114
|
export declare function createReadStream(path: string, options?: BufferEncoding | {
|
|
33
115
|
'flags'?: string;
|
|
34
116
|
'encoding'?: BufferEncoding;
|
|
@@ -36,9 +118,20 @@ export declare function createReadStream(path: string, options?: BufferEncoding
|
|
|
36
118
|
'start'?: number;
|
|
37
119
|
'end'?: number;
|
|
38
120
|
}): fs.ReadStream;
|
|
121
|
+
/**
|
|
122
|
+
* --- 读取文件写入到流,并等待写入完成 ---
|
|
123
|
+
* @param path 文件地址
|
|
124
|
+
* @param destination 要写入的流
|
|
125
|
+
* @param options 写入后是否终止写入流,默认终止
|
|
126
|
+
*/
|
|
39
127
|
export declare function pipe(path: string, destination: NodeJS.WritableStream, options?: {
|
|
40
128
|
'end'?: boolean;
|
|
41
129
|
}): Promise<boolean>;
|
|
130
|
+
/**
|
|
131
|
+
* --- 创建写入文件的流 ---
|
|
132
|
+
* @param path 文件地址
|
|
133
|
+
* @param options 编码或配置
|
|
134
|
+
*/
|
|
42
135
|
export declare function createWriteStream(path: string, options?: BufferEncoding | {
|
|
43
136
|
'flags'?: string;
|
|
44
137
|
'encoding'?: BufferEncoding;
|
|
@@ -46,4 +139,11 @@ export declare function createWriteStream(path: string, options?: BufferEncoding
|
|
|
46
139
|
'autoClose'?: boolean;
|
|
47
140
|
'start'?: number;
|
|
48
141
|
}): fs.WriteStream;
|
|
142
|
+
/**
|
|
143
|
+
* --- 读取文件并输出到 http 的 response ---
|
|
144
|
+
* @param path 文件绝对路径
|
|
145
|
+
* @param req http 请求对象
|
|
146
|
+
* @param res http 响应对象
|
|
147
|
+
* @param stat 文件的 stat(如果有)
|
|
148
|
+
*/
|
|
49
149
|
export declare function readToResponse(path: string, req: http2.Http2ServerRequest | http.IncomingMessage, res: http2.Http2ServerResponse | http.ServerResponse, stat?: fs.Stats | null): Promise<void>;
|
package/lib/fs.js
CHANGED
|
@@ -53,12 +53,22 @@ exports.createReadStream = createReadStream;
|
|
|
53
53
|
exports.pipe = pipe;
|
|
54
54
|
exports.createWriteStream = createWriteStream;
|
|
55
55
|
exports.readToResponse = readToResponse;
|
|
56
|
+
/**
|
|
57
|
+
* Project: Kebab, User: JianSuoQiYue
|
|
58
|
+
* Date: 2019-3-29 23:03:07
|
|
59
|
+
* Last: 2020-3-11 22:21:51, 2022-12-29 01:18:25, 2023-12-13 20:50:09
|
|
60
|
+
*/
|
|
56
61
|
const fs = __importStar(require("fs"));
|
|
57
62
|
const http2 = __importStar(require("http2"));
|
|
58
63
|
const mime = __importStar(require("@litert/mime"));
|
|
59
64
|
const text = __importStar(require("./text"));
|
|
60
65
|
const core = __importStar(require("./core"));
|
|
61
66
|
const zlib = __importStar(require("./zlib"));
|
|
67
|
+
/**
|
|
68
|
+
* --- 读取完整文件或一段 ---
|
|
69
|
+
* @param path 文件路径
|
|
70
|
+
* @param options 编码或选项
|
|
71
|
+
*/
|
|
62
72
|
async function getContent(path, options) {
|
|
63
73
|
if (typeof options === 'string') {
|
|
64
74
|
options = {
|
|
@@ -113,6 +123,12 @@ async function getContent(path, options) {
|
|
|
113
123
|
}
|
|
114
124
|
}
|
|
115
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* --- 写入文件内容 ---
|
|
128
|
+
* @param path 文件路径
|
|
129
|
+
* @param data 要写入的内容
|
|
130
|
+
* @param options 选项
|
|
131
|
+
*/
|
|
116
132
|
async function putContent(path, data, options = {}) {
|
|
117
133
|
try {
|
|
118
134
|
await fs.promises.writeFile(path, data, options);
|
|
@@ -122,6 +138,11 @@ async function putContent(path, data, options = {}) {
|
|
|
122
138
|
return false;
|
|
123
139
|
}
|
|
124
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* --- 读取链接的 target ---
|
|
143
|
+
* @param path 要读取的路径
|
|
144
|
+
* @param encoding 编码
|
|
145
|
+
*/
|
|
125
146
|
async function readLink(path, encoding) {
|
|
126
147
|
try {
|
|
127
148
|
return await fs.promises.readlink(path, {
|
|
@@ -132,6 +153,12 @@ async function readLink(path, encoding) {
|
|
|
132
153
|
return null;
|
|
133
154
|
}
|
|
134
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* --- 把源文件创建一个 link ---
|
|
158
|
+
* @param filePath 源文件
|
|
159
|
+
* @param linkPath 连接路径
|
|
160
|
+
* @param type 仅 Windows,类型,默认 file
|
|
161
|
+
*/
|
|
135
162
|
async function symlink(filePath, linkPath, type) {
|
|
136
163
|
try {
|
|
137
164
|
await fs.promises.symlink(filePath, linkPath, type);
|
|
@@ -141,6 +168,10 @@ async function symlink(filePath, linkPath, type) {
|
|
|
141
168
|
return false;
|
|
142
169
|
}
|
|
143
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* --- 删除一个文件 ---
|
|
173
|
+
* @param path 要删除的文件路径
|
|
174
|
+
*/
|
|
144
175
|
async function unlink(path) {
|
|
145
176
|
for (let i = 0; i <= 2; ++i) {
|
|
146
177
|
try {
|
|
@@ -159,6 +190,10 @@ async function unlink(path) {
|
|
|
159
190
|
return false;
|
|
160
191
|
}
|
|
161
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* --- 获取对象是否存在,存在则返回 stats 对象,否则返回 null ---
|
|
195
|
+
* @param path 对象路径
|
|
196
|
+
*/
|
|
162
197
|
async function stats(path) {
|
|
163
198
|
try {
|
|
164
199
|
return await fs.promises.lstat(path);
|
|
@@ -167,6 +202,10 @@ async function stats(path) {
|
|
|
167
202
|
return null;
|
|
168
203
|
}
|
|
169
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* --- 判断是否是目录或目录是否存在,是的话返回 stats ---
|
|
207
|
+
* @param path 判断路径
|
|
208
|
+
*/
|
|
170
209
|
async function isDir(path) {
|
|
171
210
|
const pstats = await stats(path);
|
|
172
211
|
if (!pstats?.isDirectory()) {
|
|
@@ -174,6 +213,10 @@ async function isDir(path) {
|
|
|
174
213
|
}
|
|
175
214
|
return pstats;
|
|
176
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* --- 判断是否是文件或文件是否存在,是的话返回 stats ---
|
|
218
|
+
* @param path 判断路径
|
|
219
|
+
*/
|
|
177
220
|
async function isFile(path) {
|
|
178
221
|
const pstats = await stats(path);
|
|
179
222
|
if (!pstats?.isFile()) {
|
|
@@ -181,10 +224,16 @@ async function isFile(path) {
|
|
|
181
224
|
}
|
|
182
225
|
return pstats;
|
|
183
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* --- 深度创建目录,如果最末目录存在,则自动创建成功 ---
|
|
229
|
+
* @param path 要创建的路径,如 /a/b/c/
|
|
230
|
+
* @param mode 权限
|
|
231
|
+
*/
|
|
184
232
|
async function mkdir(path, mode = 0o755) {
|
|
185
233
|
if (await isDir(path)) {
|
|
186
234
|
return true;
|
|
187
235
|
}
|
|
236
|
+
// --- 深度创建目录 ---
|
|
188
237
|
try {
|
|
189
238
|
await fs.promises.mkdir(path, {
|
|
190
239
|
'recursive': true,
|
|
@@ -196,6 +245,10 @@ async function mkdir(path, mode = 0o755) {
|
|
|
196
245
|
return false;
|
|
197
246
|
}
|
|
198
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* --- 删除空目录 ---
|
|
250
|
+
* @param path 要删除的目录
|
|
251
|
+
*/
|
|
199
252
|
async function rmdir(path) {
|
|
200
253
|
if (!(await isDir(path))) {
|
|
201
254
|
return true;
|
|
@@ -208,6 +261,11 @@ async function rmdir(path) {
|
|
|
208
261
|
return false;
|
|
209
262
|
}
|
|
210
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* --- Danger 危险:危险函数,尽量不要使用 ---
|
|
266
|
+
* --- This f**king is a danger function, please don't use it ---
|
|
267
|
+
* --- 删除一个非空目录 ---
|
|
268
|
+
*/
|
|
211
269
|
async function rmdirDeep(path) {
|
|
212
270
|
if (!path.endsWith('/')) {
|
|
213
271
|
path += '/';
|
|
@@ -219,6 +277,7 @@ async function rmdirDeep(path) {
|
|
|
219
277
|
return false;
|
|
220
278
|
}
|
|
221
279
|
if (stat.isDirectory()) {
|
|
280
|
+
// --- 目录 ---
|
|
222
281
|
const rtn = await rmdirDeep(path + item.name);
|
|
223
282
|
if (!rtn) {
|
|
224
283
|
return false;
|
|
@@ -233,6 +292,11 @@ async function rmdirDeep(path) {
|
|
|
233
292
|
}
|
|
234
293
|
return rmdir(path);
|
|
235
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* --- 修改权限
|
|
297
|
+
* @param path 要修改的路径
|
|
298
|
+
* @param mod 权限
|
|
299
|
+
*/
|
|
236
300
|
async function chmod(path, mod) {
|
|
237
301
|
try {
|
|
238
302
|
await fs.promises.chmod(path, mod);
|
|
@@ -242,6 +306,11 @@ async function chmod(path, mod) {
|
|
|
242
306
|
return false;
|
|
243
307
|
}
|
|
244
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* --- 重命名/移动 文件文件夹 ---
|
|
311
|
+
* @param oldPath 老名
|
|
312
|
+
* @param newPath 新名
|
|
313
|
+
*/
|
|
245
314
|
async function rename(oldPath, newPath) {
|
|
246
315
|
try {
|
|
247
316
|
await fs.promises.rename(oldPath, newPath);
|
|
@@ -251,6 +320,10 @@ async function rename(oldPath, newPath) {
|
|
|
251
320
|
return false;
|
|
252
321
|
}
|
|
253
322
|
}
|
|
323
|
+
/**
|
|
324
|
+
* --- 获取文件夹下文件列表 ---
|
|
325
|
+
* @param path 文件夹路径
|
|
326
|
+
*/
|
|
254
327
|
async function readDir(path, encoding) {
|
|
255
328
|
try {
|
|
256
329
|
const list = [];
|
|
@@ -270,12 +343,21 @@ async function readDir(path, encoding) {
|
|
|
270
343
|
return [];
|
|
271
344
|
}
|
|
272
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* --- 复制文件夹里的内容到另一个地方,失败不会回滚 ---
|
|
348
|
+
* @param from 源,末尾加 /
|
|
349
|
+
* @param to 目标,末尾加 /
|
|
350
|
+
* @param ignore 忽略的文件
|
|
351
|
+
*/
|
|
273
352
|
async function copyFolder(from, to, ignore = []) {
|
|
274
353
|
let num = 0;
|
|
354
|
+
// --- 如果源目录不存在或不是目录,则直接成功 :) ---
|
|
275
355
|
if (!await isDir(from)) {
|
|
276
356
|
return 0;
|
|
277
357
|
}
|
|
358
|
+
// --- 遍历源目录文件和文件夹,准备复制 ---
|
|
278
359
|
const flist = await readDir(from);
|
|
360
|
+
/** --- to 目录是否检查是否存在,空目录不复制,所以确定有 item file 的时候才创建 --- */
|
|
279
361
|
let checkTo = false;
|
|
280
362
|
for (const item of flist) {
|
|
281
363
|
if (item.isDirectory()) {
|
|
@@ -288,6 +370,7 @@ async function copyFolder(from, to, ignore = []) {
|
|
|
288
370
|
}
|
|
289
371
|
}
|
|
290
372
|
else if (item.isFile()) {
|
|
373
|
+
// --- 先判断本文件是否被排除 ---
|
|
291
374
|
if (ignore.length > 0 && text.match(item.name, ignore)) {
|
|
292
375
|
continue;
|
|
293
376
|
}
|
|
@@ -305,6 +388,11 @@ async function copyFolder(from, to, ignore = []) {
|
|
|
305
388
|
}
|
|
306
389
|
return num;
|
|
307
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* --- 复制文件 ---
|
|
393
|
+
* @param src 源文件
|
|
394
|
+
* @param dest 目标文件
|
|
395
|
+
*/
|
|
308
396
|
async function copyFile(src, dest) {
|
|
309
397
|
try {
|
|
310
398
|
await fs.promises.copyFile(src, dest);
|
|
@@ -314,6 +402,11 @@ async function copyFile(src, dest) {
|
|
|
314
402
|
return false;
|
|
315
403
|
}
|
|
316
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* --- 创建读取文件的流 ---
|
|
407
|
+
* @param path 文件地址
|
|
408
|
+
* @param options 编码或配置
|
|
409
|
+
*/
|
|
317
410
|
function createReadStream(path, options) {
|
|
318
411
|
if (typeof options === 'string') {
|
|
319
412
|
options = {
|
|
@@ -331,6 +424,12 @@ function createReadStream(path, options) {
|
|
|
331
424
|
'end': options.end
|
|
332
425
|
});
|
|
333
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* --- 读取文件写入到流,并等待写入完成 ---
|
|
429
|
+
* @param path 文件地址
|
|
430
|
+
* @param destination 要写入的流
|
|
431
|
+
* @param options 写入后是否终止写入流,默认终止
|
|
432
|
+
*/
|
|
334
433
|
function pipe(path, destination, options) {
|
|
335
434
|
return new Promise((resolve) => {
|
|
336
435
|
createReadStream(path).on('error', function () {
|
|
@@ -340,6 +439,11 @@ function pipe(path, destination, options) {
|
|
|
340
439
|
}).pipe(destination, options);
|
|
341
440
|
});
|
|
342
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* --- 创建写入文件的流 ---
|
|
444
|
+
* @param path 文件地址
|
|
445
|
+
* @param options 编码或配置
|
|
446
|
+
*/
|
|
343
447
|
function createWriteStream(path, options) {
|
|
344
448
|
if (typeof options === 'string') {
|
|
345
449
|
options = {
|
|
@@ -357,6 +461,13 @@ function createWriteStream(path, options) {
|
|
|
357
461
|
'start': options.start
|
|
358
462
|
});
|
|
359
463
|
}
|
|
464
|
+
/**
|
|
465
|
+
* --- 读取文件并输出到 http 的 response ---
|
|
466
|
+
* @param path 文件绝对路径
|
|
467
|
+
* @param req http 请求对象
|
|
468
|
+
* @param res http 响应对象
|
|
469
|
+
* @param stat 文件的 stat(如果有)
|
|
470
|
+
*/
|
|
360
471
|
async function readToResponse(path, req, res, stat) {
|
|
361
472
|
if (!stat) {
|
|
362
473
|
stat = await stats(path);
|
|
@@ -367,14 +478,17 @@ async function readToResponse(path, req, res, stat) {
|
|
|
367
478
|
res.end('<h1>404 Not found</h1><hr>Kebab');
|
|
368
479
|
return;
|
|
369
480
|
}
|
|
481
|
+
// --- 判断缓存以及 MIME 和编码 ---
|
|
370
482
|
let charset = '';
|
|
371
483
|
const mimeData = mime.getData(path);
|
|
372
484
|
if (['htm', 'html', 'css', 'js', 'xml', 'jpg', 'jpeg', 'svg', 'gif', 'png'].includes(mimeData.extension)) {
|
|
373
485
|
charset = '; charset=utf-8';
|
|
486
|
+
// --- 这些文件可能需要缓存 ---
|
|
374
487
|
const hash = `W/"${stat.size.toString(16)}-${stat.mtime.getTime().toString(16)}"`;
|
|
375
488
|
const lastModified = stat.mtime.toUTCString();
|
|
376
489
|
res.setHeader('etag', hash);
|
|
377
490
|
res.setHeader('cache-control', 'public, max-age=600');
|
|
491
|
+
// --- 判断返回 304 吗 ---
|
|
378
492
|
const noneMatch = req.headers['if-none-match'];
|
|
379
493
|
const modifiedSince = req.headers['if-modified-since'];
|
|
380
494
|
if ((hash === noneMatch) && (lastModified === modifiedSince)) {
|
|
@@ -387,9 +501,12 @@ async function readToResponse(path, req, res, stat) {
|
|
|
387
501
|
else {
|
|
388
502
|
res.setHeader('cache-control', 'no-cache, must-revalidate');
|
|
389
503
|
}
|
|
504
|
+
// --- 设置 type ---
|
|
390
505
|
res.setHeader('content-type', mimeData.mime + charset);
|
|
506
|
+
// --- 判断客户端支持的压缩模式 ---
|
|
391
507
|
const encoding = req.headers['accept-encoding'] ?? '';
|
|
392
508
|
if (mimeData.compressible && (stat.size >= 1024)) {
|
|
509
|
+
// --- 压缩 ---
|
|
393
510
|
const compress = await zlib.compress(encoding, await getContent(path));
|
|
394
511
|
if (compress) {
|
|
395
512
|
res.setHeader('content-encoding', compress.type);
|
|
@@ -399,6 +516,7 @@ async function readToResponse(path, req, res, stat) {
|
|
|
399
516
|
return;
|
|
400
517
|
}
|
|
401
518
|
}
|
|
519
|
+
// --- 不压缩 ---
|
|
402
520
|
res.setHeader('content-length', stat.size);
|
|
403
521
|
res.writeHead(200);
|
|
404
522
|
await pipe(path, res instanceof http2.Http2ServerResponse ? (res.stream ?? res) : res);
|
package/lib/jwt.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project: Kebab, User: JianSuoQiYue
|
|
3
|
+
* Date: 2023-1-31 20:34:47
|
|
4
|
+
* Last: 2023-1-31 20:34:47, 2023-12-8 13:55:09
|
|
5
|
+
*/
|
|
1
6
|
import * as kv from '../lib/kv';
|
|
2
7
|
import * as ctr from '../sys/ctr';
|
|
3
8
|
import * as types from '../types';
|
|
@@ -9,22 +14,60 @@ export interface IOptions {
|
|
|
9
14
|
'auth'?: boolean;
|
|
10
15
|
}
|
|
11
16
|
export declare class Jwt {
|
|
17
|
+
/** --- Kv --- */
|
|
12
18
|
private _link?;
|
|
19
|
+
/** --- 在前端或 Kv 中储存的名前缀 --- */
|
|
13
20
|
private _name;
|
|
21
|
+
/** --- 有效期 --- */
|
|
14
22
|
private _ttl;
|
|
23
|
+
/** --- cookie 模式时是否仅支持 SSL --- */
|
|
15
24
|
private _ssl;
|
|
25
|
+
/** --- 验证密钥 --- */
|
|
16
26
|
private _secret;
|
|
27
|
+
/** --- 是否从头部读取 --- */
|
|
17
28
|
private _auth;
|
|
29
|
+
/** --- ctr 对象 --- */
|
|
18
30
|
private _ctr;
|
|
31
|
+
/**
|
|
32
|
+
* --- 初始化函数,相当于 construct ---
|
|
33
|
+
* @param ctr 模型实例
|
|
34
|
+
* @param link Kv 或 Db 实例
|
|
35
|
+
* @param auth 设为 true 则优先从头 Authorization 或 post _auth 值读取 token
|
|
36
|
+
* @param opt 选项
|
|
37
|
+
*/
|
|
19
38
|
init(ctr: ctr.Ctr, opt?: IOptions, link?: kv.Pool): Promise<boolean>;
|
|
39
|
+
/**
|
|
40
|
+
* --- 将 _jwt 数据封装并返回(创建新的或者续期老的 token),默认会同时设置一个 cookie(data 值会自动设置 token、exp) ---
|
|
41
|
+
*/
|
|
20
42
|
renew(): string;
|
|
43
|
+
/**
|
|
44
|
+
* --- 清除 cookie,仅仅清除 cookie,jwt 并不会失效 ---
|
|
45
|
+
*/
|
|
21
46
|
clearCookie(): void;
|
|
47
|
+
/**
|
|
48
|
+
* --- 销毁 jwt,其实就是将 token block 信息写入 redis,如果没有 redis 则不能销毁,返回数组代表销毁成功的 token 和原 exp,否则失败返回 false ---
|
|
49
|
+
*/
|
|
22
50
|
destory(): Promise<{
|
|
23
51
|
token: string;
|
|
24
52
|
exp: number;
|
|
25
53
|
} | boolean>;
|
|
26
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* --- 获取 jwt 原始字符串,不保证有效 ---
|
|
57
|
+
*/
|
|
27
58
|
export declare function getOrigin(ctr: ctr.Ctr, name?: string, auth?: boolean): string;
|
|
59
|
+
/**
|
|
60
|
+
* --- decode ---
|
|
61
|
+
* 不传入 link 的话,将不做 block 有效校验,只做本身的 exp 有效校验
|
|
62
|
+
*/
|
|
28
63
|
export declare function decode(ctr: ctr.Ctr, val: string, link?: kv.Pool, name?: string, secret?: string): Promise<Record<string, types.DbValue> | false>;
|
|
64
|
+
/**
|
|
65
|
+
* --- 仅往 redis 写禁止相关 token 的数据,一般用于异步通知时在异处的服务器来调用的 ---
|
|
66
|
+
*/
|
|
29
67
|
export declare function block(ctr: ctr.Ctr, token: string, exp: number, link: kv.Pool, name?: string): Promise<boolean>;
|
|
68
|
+
/**
|
|
69
|
+
* @param ctr 模型实例
|
|
70
|
+
* @param opt name, ttl, ssl, secret, auth: false, true 则优先从头 Authorization 或 post _auth 值读取 token
|
|
71
|
+
* @param link 实例
|
|
72
|
+
*/
|
|
30
73
|
export declare function get(ctr: ctr.Ctr, opt?: IOptions, link?: kv.Pool): Promise<Jwt>;
|