@maiyunnet/kebab 2.0.6 → 2.0.8

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.
Files changed (83) hide show
  1. package/index.d.ts +11 -1
  2. package/index.js +13 -1
  3. package/lib/buffer.d.ts +25 -0
  4. package/lib/buffer.js +30 -5
  5. package/lib/captcha.d.ts +15 -0
  6. package/lib/captcha.js +20 -0
  7. package/lib/consistent.d.ts +51 -0
  8. package/lib/consistent.js +59 -0
  9. package/lib/core.d.ts +134 -0
  10. package/lib/core.js +176 -0
  11. package/lib/crypto.d.ts +75 -6
  12. package/lib/crypto.js +206 -38
  13. package/lib/db.d.ts +104 -0
  14. package/lib/db.js +126 -0
  15. package/lib/dns.d.ts +51 -0
  16. package/lib/dns.js +54 -2
  17. package/lib/fs.d.ts +100 -0
  18. package/lib/fs.js +118 -0
  19. package/lib/jwt.d.ts +43 -0
  20. package/lib/jwt.js +45 -0
  21. package/lib/kv.d.ts +362 -0
  22. package/lib/kv.js +377 -0
  23. package/lib/lan.d.ts +6 -0
  24. package/lib/lan.js +7 -0
  25. package/lib/net/formdata.d.ts +38 -0
  26. package/lib/net/formdata.js +43 -0
  27. package/lib/net/request.d.ts +62 -0
  28. package/lib/net/request.js +57 -0
  29. package/lib/net/response.d.ts +21 -0
  30. package/lib/net/response.js +16 -0
  31. package/lib/net.d.ts +86 -0
  32. package/lib/net.js +140 -0
  33. package/lib/s3.d.ts +52 -0
  34. package/lib/s3.js +51 -0
  35. package/lib/scan.d.ts +52 -0
  36. package/lib/scan.js +84 -0
  37. package/lib/session.d.ts +31 -0
  38. package/lib/session.js +52 -1
  39. package/lib/sql.d.ts +176 -0
  40. package/lib/sql.js +287 -2
  41. package/lib/ssh/sftp.d.ts +106 -0
  42. package/lib/ssh/sftp.js +106 -0
  43. package/lib/ssh/shell.d.ts +37 -0
  44. package/lib/ssh/shell.js +31 -0
  45. package/lib/ssh.d.ts +32 -0
  46. package/lib/ssh.js +32 -0
  47. package/lib/text.d.ts +131 -0
  48. package/lib/text.js +188 -0
  49. package/lib/time.d.ts +53 -0
  50. package/lib/time.js +55 -0
  51. package/lib/ws.d.ts +68 -0
  52. package/lib/ws.js +74 -0
  53. package/lib/zip.d.ts +53 -0
  54. package/lib/zip.js +73 -0
  55. package/lib/zlib.d.ts +76 -0
  56. package/lib/zlib.js +78 -0
  57. package/main.d.ts +6 -1
  58. package/main.js +11 -1
  59. package/package.json +2 -2
  60. package/sys/child.js +104 -0
  61. package/sys/cmd.js +28 -0
  62. package/sys/ctr.d.ts +166 -0
  63. package/sys/ctr.js +177 -0
  64. package/sys/master.js +63 -0
  65. package/sys/mod.d.ts +266 -0
  66. package/sys/mod.js +335 -0
  67. package/sys/route.d.ts +34 -0
  68. package/sys/route.js +164 -0
  69. package/www/example/ctr/test.d.ts +3 -0
  70. package/www/example/ctr/test.js +63 -1
  71. package/www/example/mod/test.js +14 -0
  72. package/www/example/mod/testdata.js +9 -0
  73. package/www/example/ws/test.js +1 -0
  74. package/.VSCodeCounter/2025-02-14_14-46-44/details.md +0 -82
  75. package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +0 -15
  76. package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +0 -2
  77. package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +0 -19
  78. package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +0 -22
  79. package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +0 -69
  80. package/.VSCodeCounter/2025-02-14_14-46-44/results.json +0 -1
  81. package/.VSCodeCounter/2025-02-14_14-46-44/results.md +0 -48
  82. package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +0 -118
  83. package/.vscode/tasks.json +0 -15
package/lib/net.js CHANGED
@@ -47,16 +47,27 @@ exports.filterProxyHeaders = filterProxyHeaders;
47
47
  exports.mproxy = mproxy;
48
48
  exports.mproxyData = mproxyData;
49
49
  exports.rproxy = rproxy;
50
+ /**
51
+ * Project: Kebab, User: JianSuoQiYue
52
+ * Date: 2019-5-15 22:47
53
+ * CA: https://curl.haxx.se/ca/cacert.pem
54
+ * Last: 2020-4-9 20:11:02, 2022-09-22 14:30:13, 2024-1-1 21:32:26, 2024-1-12 13:01:54, 2025-6-13 13:20:52
55
+ */
50
56
  const stream = __importStar(require("stream"));
57
+ // --- 第三方 ---
51
58
  const hc = __importStar(require("@litert/http-client"));
59
+ // --- 库和定义 ---
52
60
  const fs = __importStar(require("../lib/fs"));
53
61
  const text = __importStar(require("../lib/text"));
54
62
  const time = __importStar(require("../lib/time"));
55
63
  const kebab = __importStar(require("../index"));
64
+ // --- 自己 ---
56
65
  const fd = __importStar(require("./net/formdata"));
57
66
  const lRequest = __importStar(require("./net/request"));
58
67
  const response = __importStar(require("./net/response"));
68
+ /** --- ca 根证书内容 --- */
59
69
  let ca = '';
70
+ /** --- 获取 CA 证书 --- */
60
71
  async function getCa() {
61
72
  if (ca) {
62
73
  return ca;
@@ -64,26 +75,53 @@ async function getCa() {
64
75
  ca = (await fs.getContent(kebab.LIB_PATH + 'net/cacert.pem', 'utf8')) ?? '';
65
76
  return ca;
66
77
  }
78
+ /** --- 复用的 hc 对象列表 --- */
67
79
  const reuses = {
68
80
  'default': hc.createHttpClient()
69
81
  };
82
+ /**
83
+ * --- 创建一个请求对象 ---
84
+ * @param u
85
+ */
70
86
  function open(u) {
71
87
  return new lRequest.Request(u);
72
88
  }
89
+ /**
90
+ * --- 发起一个 get 请求 ---
91
+ * @param u 请求的 URL
92
+ * @param opt 参数
93
+ */
73
94
  async function get(u, opt = {}) {
74
95
  return request(u, undefined, opt);
75
96
  }
97
+ /**
98
+ * --- 发起一个 post 请求 ---
99
+ * @param u 请求的 URL
100
+ * @param data 要发送的数据
101
+ * @param opt 参数
102
+ */
76
103
  async function post(u, data, opt = {}) {
77
104
  opt.method = 'POST';
78
105
  return request(u, data, opt);
79
106
  }
107
+ /**
108
+ * --- 发起 JSON 请求 ---
109
+ * @param u
110
+ * @param data
111
+ * @param opt
112
+ */
80
113
  async function postJson(u, data, opt = {}) {
81
114
  opt.method = 'POST';
82
115
  opt.type = 'json';
83
116
  return request(u, data, opt);
84
117
  }
118
+ /**
119
+ * --- 发起一个请求 ---
120
+ * @param opt 配置项
121
+ */
85
122
  async function request(u, data, opt = {}) {
86
123
  const uri = text.parseUrl(u);
124
+ /** --- 正向代理的地址 --- */
87
125
  const puri = opt.mproxy ? text.parseUrl(opt.mproxy.url) : null;
88
126
  const method = opt.method ?? 'GET';
89
127
  const type = opt.type ?? 'form';
@@ -100,6 +138,7 @@ async function request(u, data, opt = {}) {
100
138
  }
101
139
  }
102
140
  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';
141
+ // --- DATA ---
103
142
  if (method === 'GET') {
104
143
  if (data && !(data instanceof stream.Readable) && !Buffer.isBuffer(data)) {
105
144
  u += (u.includes('?') ? '&' : '?') +
@@ -108,6 +147,7 @@ async function request(u, data, opt = {}) {
108
147
  }
109
148
  }
110
149
  else {
150
+ // --- POST ---
111
151
  if (data && !(data instanceof stream.Readable) && !Buffer.isBuffer(data) && typeof data !== 'string') {
112
152
  if (type === 'form') {
113
153
  data = text.queryStringify(data);
@@ -124,14 +164,18 @@ async function request(u, data, opt = {}) {
124
164
  }
125
165
  }
126
166
  headers['accept-encoding'] = 'gzip, deflate';
167
+ // --- ssl ---
127
168
  if (uri.protocol === 'https:') {
128
169
  await getCa();
129
170
  }
171
+ // --- cookie 托管 ---
130
172
  if (opt.cookie) {
131
173
  headers['cookie'] = buildCookieQuery(opt.cookie, uri);
132
174
  }
175
+ // --- 发起请求 ---
133
176
  let req;
134
177
  try {
178
+ // --- 重定义 IP ---
135
179
  const host = (puri ? puri.hostname : uri.hostname) ?? '';
136
180
  if (!host) {
137
181
  const res = new response.Response(null);
@@ -174,9 +218,14 @@ async function request(u, data, opt = {}) {
174
218
  res.error = err;
175
219
  return res;
176
220
  }
221
+ // --- 处理返回值 ---
222
+ // --- 是否追踪 cookie ---
177
223
  if (opt.cookie) {
224
+ // --- 提取 cookie ---
178
225
  await buildCookieObject(opt.cookie, (req.headers['set-cookie'] ?? []), uri);
179
226
  }
227
+ // --- 直接下载到文件 ---
228
+ /** --- 已下载文件的 size --- */
180
229
  let total = 0;
181
230
  if (save && (!req.headers['location'] || follow === 0)) {
182
231
  await new Promise(function (resolve) {
@@ -192,6 +241,7 @@ async function request(u, data, opt = {}) {
192
241
  }).pipe(fs.createWriteStream(save));
193
242
  });
194
243
  }
244
+ // --- 创建 Response 对象 ---
195
245
  const res = new response.Response(req);
196
246
  if (total) {
197
247
  res.setContent(total.toString());
@@ -209,12 +259,14 @@ async function request(u, data, opt = {}) {
209
259
  }
210
260
  res.headers['http-code'] = req.statusCode;
211
261
  res.headers['http-url'] = u;
262
+ // --- 判断 follow 追踪 ---
212
263
  if (follow === 0) {
213
264
  return res;
214
265
  }
215
266
  if (!res.headers['location']) {
216
267
  return res;
217
268
  }
269
+ // --- 哦,要追踪 ---
218
270
  headers['referer'] = u;
219
271
  return request(text.urlResolve(u, req.headers['location']), data, {
220
272
  'method': method,
@@ -229,6 +281,14 @@ async function request(u, data, opt = {}) {
229
281
  'reuse': reuse
230
282
  });
231
283
  }
284
+ /**
285
+ * --- 对 cookie 对象进行操作 ---
286
+ * @param cookie 要操作的对象
287
+ * @param name 名
288
+ * @param value 值
289
+ * @param domain 应用网址,如 .xxx.com
290
+ * @param opt 选项 ttl, path, ssl, httponly
291
+ */
232
292
  function setCookie(cookie, name, value, domain, opt = {}) {
233
293
  const tim = time.stamp();
234
294
  const ttl = opt.ttl ?? 0;
@@ -248,25 +308,35 @@ function setCookie(cookie, name, value, domain, opt = {}) {
248
308
  'httponly': opt['httponly'] ? true : false
249
309
  };
250
310
  }
311
+ /**
312
+ * --- 根据 Set-Cookie 头部转换到 cookie 对象 ---
313
+ * @param cookie cookie 对象
314
+ * @param setCookies 头部的 set-cookie 数组
315
+ * @param uri 请求的 URI 对象
316
+ */
251
317
  async function buildCookieObject(cookie, setCookies, uri) {
252
318
  const tim = time.stamp();
253
319
  uri.path ??= '/';
254
320
  for (const setCookie of setCookies) {
255
321
  const cookieTmp = {};
256
322
  const list = setCookie.split(';');
323
+ // --- 提取 set-cookie 中的定义信息 ---
257
324
  for (let index = 0; index < list.length; ++index) {
258
325
  const item = list[index];
259
326
  const arr = item.split('=');
260
327
  const key = arr[0].trim();
261
328
  const val = arr[1] ?? '';
262
329
  if (index === 0) {
330
+ // --- 用户定义的信息 ---
263
331
  cookieTmp['name'] = key;
264
332
  cookieTmp['value'] = decodeURIComponent(val);
265
333
  }
266
334
  else {
335
+ // --- cookie 配置信息,可转小写方便读取 ---
267
336
  cookieTmp[key.toLowerCase()] = val;
268
337
  }
269
338
  }
339
+ // --- 获取定义的 domain ---
270
340
  let domain = '', domainN = '';
271
341
  if (cookieTmp['domain']) {
272
342
  cookieTmp['domain'] = cookieTmp['domain'].split(':')[0];
@@ -283,15 +353,28 @@ async function buildCookieObject(cookie, setCookies, uri) {
283
353
  domain = '.' + (uri.hostname ?? '');
284
354
  domainN = uri.hostname ?? '';
285
355
  }
356
+ // --- 判断有没有设置 domain 的权限 ---
357
+ // --- uri.hostname vs domain(domainN) ---
358
+ // --- ok.xxx.com vs .ok.xxx.com: true ---
359
+ // --- ok.xxx.com vs .xxx.com: true ---
360
+ // --- z.ok.xxx.com vs .xxx.com: true ---
361
+ // --- ok.xxx.com vs .zz.ok.xxx.com: false ---
286
362
  if (uri.hostname !== domainN) {
363
+ // --- 设置的域名和当前 host 不相等,如果是 IP、无 . 域名,则直接失败 ---
287
364
  if (!text.isDomain(uri.hostname ?? '')) {
288
365
  continue;
289
366
  }
290
367
  const parseDomain = await text.parseDomain(domainN);
291
368
  if (parseDomain.tld === domainN.toLowerCase()) {
369
+ // --- 不能给 tld 设置 cookie ---
292
370
  continue;
293
371
  }
372
+ // --- 判断访问路径 (uri['host']) 是不是设置域名 (domain) 的孩子,domain 必须是 uriHost 的同级或者父辈 ---
294
373
  if (!((uri.hostname ?? '').endsWith(domain))) {
374
+ // --- false 代表进入了,代表失败 ---
375
+ // --- ok.xxx.com, .xxx.com: true ---
376
+ // --- ok.xxx.com, .ppp.com: false ---
377
+ // --- ok.xxx.com, .p.ok.xxx.com: false ---
295
378
  continue;
296
379
  }
297
380
  }
@@ -306,6 +389,7 @@ async function buildCookieObject(cookie, setCookies, uri) {
306
389
  if (cookieTmp['max-age']) {
307
390
  exp = tim + Number(cookieTmp['max-age']);
308
391
  }
392
+ // --- path ---
309
393
  let path = cookieTmp['path'] ?? '';
310
394
  if (path === '') {
311
395
  const srp = (uri.pathname ?? '').lastIndexOf('/');
@@ -325,6 +409,11 @@ async function buildCookieObject(cookie, setCookies, uri) {
325
409
  };
326
410
  }
327
411
  }
412
+ /**
413
+ * --- 对象转换为 Cookie 拼接字符串(会自动筛掉不能发送的 cookie) ---
414
+ * @param cookie cookie 对象
415
+ * @param uri 请求的 URI 对象
416
+ */
328
417
  function buildCookieQuery(cookie, uri) {
329
418
  const tim = time.stamp();
330
419
  let cookieStr = '';
@@ -338,12 +427,26 @@ function buildCookieQuery(cookie, uri) {
338
427
  if (item.secure && (uri.protocol === 'https')) {
339
428
  continue;
340
429
  }
430
+ // --- 判断 path 是否匹配 ---
341
431
  if (!uri.path.startsWith(item.path)) {
342
432
  continue;
343
433
  }
344
434
  const domain = '.' + item.domain;
435
+ // --- 判断 $uri['host'] 必须是 $domain 的同级或子级 ---
436
+ // --- $uri['host'] vs $domain ---
437
+ // --- ok.xxx.com vs .ok.xxx.com: true ---
438
+ // --- ok.xxx.com vs .xxx.com: true ---
439
+ // --- z.ok.xxx.com vs .xxx.com: true ---
440
+ // --- ok.xxx.com vs .zz.ok.xxx.com: false ---
345
441
  if ('.' + (uri.hostname ?? '') !== domain) {
442
+ // --- 域名不相等,那么判断当前域名 host 是不是 domain 的孩子 ---
346
443
  if (!(uri.hostname.endsWith(domain))) {
444
+ // --- false 代表进入,被排除了,因为 cookie 的 domain 和当前 host 后半部分,代表不是 domain 的孩子 ---
445
+ // --- ok.xxx.com, .zz.ok.xxx.com: false ---
446
+ // --- pp.ok.xxx.com, .zz.ok.xxx.com: false ---
447
+ // --- q.b.ok.xx.com, .zz.ok.xxx.com: false ---
448
+ // --- z.ok.xxx.com, .xxx.com: true ---
449
+ // --- xx.xxx.com, .ok.xxx.com: false ---
347
450
  continue;
348
451
  }
349
452
  }
@@ -356,6 +459,10 @@ function buildCookieQuery(cookie, uri) {
356
459
  return '';
357
460
  }
358
461
  }
462
+ /**
463
+ * --- 模拟重启浏览器后的状态 ---
464
+ * @param cookie cookie 对象
465
+ */
359
466
  function resetCookieSession(cookie) {
360
467
  for (const key in cookie) {
361
468
  const item = cookie[key];
@@ -364,10 +471,19 @@ function resetCookieSession(cookie) {
364
471
  }
365
472
  }
366
473
  }
474
+ /**
475
+ * --- 创建 FormData 对象, Mutton: false, Kebab: true ---
476
+ */
367
477
  function getFormData() {
368
478
  return new fd.FormData();
369
479
  }
480
+ /** --- proxy 要剔除的基础头部 --- */
370
481
  const proxyContinueHeaders = ['host', 'connection', 'http-version', 'http-code', 'http-url'];
482
+ /**
483
+ * --- 剔除不代理的 header ---
484
+ * @param headers 剔除前的 header
485
+ * @param res 直接设置头部而不返回,可置空
486
+ */
371
487
  function filterProxyHeaders(headers, res) {
372
488
  const heads = {};
373
489
  for (const h in headers) {
@@ -389,10 +505,18 @@ function filterProxyHeaders(headers, res) {
389
505
  }
390
506
  return heads;
391
507
  }
508
+ /**
509
+ * --- 正向 mproxy 代理,读取 get 的 url 为实际请求地址 ---
510
+ * --- get: url, auth ---
511
+ * @param ctr 当前控制器
512
+ * @param auth 校验字符串,读取 get 的 auth 和本参数做比对
513
+ * @param opt 参数
514
+ */
392
515
  async function mproxy(ctr, auth, opt = {}) {
393
516
  const req = ctr.getPrototype('_req');
394
517
  const res = ctr.getPrototype('_res');
395
518
  const input = ctr.getPrototype('_input');
519
+ /** --- 客户端请求中的 get 的数据 --- */
396
520
  const get = ctr.getPrototype('_get');
397
521
  if (get['auth'] !== auth) {
398
522
  return 0;
@@ -403,6 +527,7 @@ async function mproxy(ctr, auth, opt = {}) {
403
527
  opt.method = req.method ?? 'GET';
404
528
  opt.headers ??= {};
405
529
  Object.assign(opt.headers, filterProxyHeaders(req.headers));
530
+ // --- 发起请求 ---
406
531
  const rres = await request(get['url'], req.headers['content-type']?.includes('form-data') ? req : input, opt);
407
532
  if (rres.error) {
408
533
  return -2;
@@ -418,6 +543,10 @@ async function mproxy(ctr, auth, opt = {}) {
418
543
  });
419
544
  return 1;
420
545
  }
546
+ /**
547
+ * --- 获取 mproxy 的附加数据 ---
548
+ * @param ctr 当前控制器
549
+ */
421
550
  function mproxyData(ctr) {
422
551
  const get = ctr.getPrototype('_get');
423
552
  if (!get['data']) {
@@ -429,6 +558,12 @@ function mproxyData(ctr) {
429
558
  }
430
559
  return data;
431
560
  }
561
+ /**
562
+ * --- 反向代理,将本服务器的某个路由反代到其他网址 ---
563
+ * @param ctr 当前控制器
564
+ * @param route 要反代的路由
565
+ * @param opt 参数
566
+ */
432
567
  async function rproxy(ctr, route, opt = {}) {
433
568
  const req = ctr.getPrototype('_req');
434
569
  const res = ctr.getPrototype('_res');
@@ -439,10 +574,15 @@ async function rproxy(ctr, route, opt = {}) {
439
574
  if (!path.startsWith(key)) {
440
575
  continue;
441
576
  }
577
+ // --- 找到了,做转发 ---
578
+ // --- key 类似:test/net-rproxy/ ---
579
+ // --- 值类似:https://cdn.jsdelivr.net/npm/deskrt@2.0.10/ ---
580
+ /** --- 要拼接的地址 --- */
442
581
  const lpath = path.slice(key.length);
443
582
  opt.method = req.method ?? 'GET';
444
583
  opt.headers ??= {};
445
584
  Object.assign(opt.headers, filterProxyHeaders(req.headers));
585
+ // --- 发起请求 ---
446
586
  const rres = await request(route[key] + lpath, req.headers['content-type']?.includes('form-data') ? req : input, opt);
447
587
  if (rres.error) {
448
588
  return false;
package/lib/s3.d.ts CHANGED
@@ -1,35 +1,87 @@
1
+ /**
2
+ * Project: Kebab, User: Tang Rukun, JianSuoQiYue
3
+ * Date: 2024-2-18 18:32:45
4
+ * Last: 2024-2-18 18:32:47, 2024-3-16 16:42:27, 2024-5-31 21:36:26, 2024-7-8 00:28:42, 2024-7-19 11:32:43, 2025-6-10 21:45:34
5
+ */
1
6
  import * as s3 from '@aws-sdk/client-s3';
2
7
  import * as stream from 'stream';
3
8
  import * as sCtr from '../sys/ctr';
9
+ /**
10
+ * s3 文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
11
+ */
12
+ /** --- 服务商定义 --- */
4
13
  export declare enum ESERVICE {
5
14
  'AMAZON' = 0,
6
15
  'TENCENT' = 1,
7
16
  'ALIBABA' = 2,
8
17
  'CF' = 3
9
18
  }
19
+ /** --- 选项 --- */
10
20
  export interface IOptions {
21
+ /** --- 服务商 ---- */
11
22
  'service': ESERVICE;
23
+ /** --- cf r2 使用 --- */
12
24
  'account'?: string;
25
+ /** --- 密钥键 --- */
13
26
  'secretId'?: string;
27
+ /** --- 密钥值 --- */
14
28
  'secretKey'?: string;
29
+ /** --- 区域 --- */
15
30
  'region'?: string;
31
+ /** --- 预定义 bucket --- */
16
32
  'bucket'?: string;
17
33
  }
18
34
  export declare class S3 {
19
35
  private readonly _link;
36
+ /** --- bucket 名 --- */
20
37
  private _bucket;
21
38
  private readonly _ctr;
22
39
  constructor(ctr: sCtr.Ctr, opt: IOptions);
40
+ /**
41
+ * --- 修改预定义 bucket ---
42
+ * @param bucket bucket 名
43
+ */
23
44
  setBucket(bucket: string): void;
45
+ /**
46
+ * --- 上传对象(可传流且也可无需设置 length) --
47
+ * @param key 对象路径
48
+ * @param content 内容
49
+ * @param length 设置 contentLength,如果是流模式则需要设置此项,也可以设置为对象参数
50
+ * @param bucket bucket 名
51
+ */
24
52
  putObject(key: string, content: string | Buffer | stream.Readable, length?: number | {
25
53
  'length'?: number;
26
54
  'type'?: string;
27
55
  'disposition'?: string;
28
56
  'bucket'?: string;
29
57
  }, bucket?: string): Promise<s3.CompleteMultipartUploadCommandOutput | false>;
58
+ /**
59
+ * --- 获取对象流,可通过流获取 buffer 或 text ---
60
+ * @param key 对象路径
61
+ * @param bucket bucket 名
62
+ */
30
63
  getObject(key: string, bucket?: string): Promise<false | (stream.Readable & import("@smithy/types").SdkStreamMixin) | (Blob & import("@smithy/types").SdkStreamMixin) | (ReadableStream<any> & import("@smithy/types").SdkStreamMixin) | undefined>;
64
+ /**
65
+ * --- 删除对象 ---
66
+ * @param key 对象路径
67
+ * @param bucket bucket 名
68
+ */
31
69
  deleteObject(key: string, bucket?: string): Promise<boolean>;
70
+ /**
71
+ * --- 批量删除对象 ---
72
+ * @param keys 批量对象路径
73
+ * @param bucket bucket 名
74
+ */
32
75
  deleteObjects(keys: string[], bucket?: string): Promise<boolean>;
76
+ /**
77
+ * --- 检测对象是否存在 ---
78
+ * @param key 对象路径
79
+ * @param bucket bucket 名
80
+ */
33
81
  headObject(key: string, bucket?: string): Promise<s3.HeadObjectCommandOutput | false>;
34
82
  }
83
+ /**
84
+ * --- 创建一个对象存储对象 ---
85
+ * @param opt 选项
86
+ */
35
87
  export declare function get(ctr: sCtr.Ctr, opt: IOptions): S3;
package/lib/s3.js CHANGED
@@ -1,4 +1,9 @@
1
1
  "use strict";
2
+ /**
3
+ * Project: Kebab, User: Tang Rukun, JianSuoQiYue
4
+ * Date: 2024-2-18 18:32:45
5
+ * Last: 2024-2-18 18:32:47, 2024-3-16 16:42:27, 2024-5-31 21:36:26, 2024-7-8 00:28:42, 2024-7-19 11:32:43, 2025-6-10 21:45:34
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,10 +40,15 @@ var __importStar = (this && this.__importStar) || (function () {
35
40
  Object.defineProperty(exports, "__esModule", { value: true });
36
41
  exports.S3 = exports.ESERVICE = void 0;
37
42
  exports.get = get;
43
+ // --- 库和定义 ---
38
44
  const s3 = __importStar(require("@aws-sdk/client-s3"));
39
45
  const ls = __importStar(require("@aws-sdk/lib-storage"));
40
46
  const lCore = __importStar(require("../lib/core"));
41
47
  const lText = __importStar(require("../lib/text"));
48
+ /**
49
+ * s3 文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
50
+ */
51
+ /** --- 服务商定义 --- */
42
52
  var ESERVICE;
43
53
  (function (ESERVICE) {
44
54
  ESERVICE[ESERVICE["AMAZON"] = 0] = "AMAZON";
@@ -48,6 +58,7 @@ var ESERVICE;
48
58
  })(ESERVICE || (exports.ESERVICE = ESERVICE = {}));
49
59
  class S3 {
50
60
  constructor(ctr, opt) {
61
+ /** --- bucket 名 --- */
51
62
  this._bucket = '';
52
63
  this._ctr = ctr;
53
64
  const config = ctr.getPrototype('_config');
@@ -84,12 +95,25 @@ class S3 {
84
95
  'endpoint': endpoint
85
96
  });
86
97
  }
98
+ /**
99
+ * --- 修改预定义 bucket ---
100
+ * @param bucket bucket 名
101
+ */
87
102
  setBucket(bucket) {
88
103
  this._bucket = bucket;
89
104
  }
105
+ /**
106
+ * --- 上传对象(可传流且也可无需设置 length) --
107
+ * @param key 对象路径
108
+ * @param content 内容
109
+ * @param length 设置 contentLength,如果是流模式则需要设置此项,也可以设置为对象参数
110
+ * @param bucket bucket 名
111
+ */
90
112
  async putObject(key, content, length, bucket) {
91
113
  try {
114
+ /** --- content type --- */
92
115
  let type = undefined;
116
+ /** --- content disposition --- */
93
117
  let disposition = undefined;
94
118
  if (typeof length !== 'number') {
95
119
  type = length?.type;
@@ -116,6 +140,12 @@ class S3 {
116
140
  return false;
117
141
  }
118
142
  }
143
+ /**
144
+ * --- 获取对象流,可通过流获取 buffer 或 text ---
145
+ * @param key 对象路径
146
+ * @param bucket bucket 名
147
+ */
148
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
119
149
  async getObject(key, bucket) {
120
150
  try {
121
151
  const go = new s3.GetObjectCommand({
@@ -126,9 +156,15 @@ class S3 {
126
156
  return r.Body;
127
157
  }
128
158
  catch {
159
+ // await lCore.log(this._ctr, '[getObject, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
129
160
  return false;
130
161
  }
131
162
  }
163
+ /**
164
+ * --- 删除对象 ---
165
+ * @param key 对象路径
166
+ * @param bucket bucket 名
167
+ */
132
168
  async deleteObject(key, bucket) {
133
169
  try {
134
170
  const doc = new s3.DeleteObjectCommand({
@@ -139,9 +175,15 @@ class S3 {
139
175
  return true;
140
176
  }
141
177
  catch {
178
+ // await lCore.log(this._ctr, '[deleteObject, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
142
179
  return false;
143
180
  }
144
181
  }
182
+ /**
183
+ * --- 批量删除对象 ---
184
+ * @param keys 批量对象路径
185
+ * @param bucket bucket 名
186
+ */
145
187
  async deleteObjects(keys, bucket) {
146
188
  try {
147
189
  const doc = new s3.DeleteObjectsCommand({
@@ -158,6 +200,11 @@ class S3 {
158
200
  return false;
159
201
  }
160
202
  }
203
+ /**
204
+ * --- 检测对象是否存在 ---
205
+ * @param key 对象路径
206
+ * @param bucket bucket 名
207
+ */
161
208
  async headObject(key, bucket) {
162
209
  try {
163
210
  const ho = new s3.HeadObjectCommand({
@@ -175,6 +222,10 @@ class S3 {
175
222
  }
176
223
  }
177
224
  exports.S3 = S3;
225
+ /**
226
+ * --- 创建一个对象存储对象 ---
227
+ * @param opt 选项
228
+ */
178
229
  function get(ctr, opt) {
179
230
  return new S3(ctr, opt);
180
231
  }
package/lib/scan.d.ts CHANGED
@@ -1,11 +1,18 @@
1
+ /**
2
+ * Project: Kebab, User: JianSuoQiYue
3
+ * Date: 2022-09-24 15:23:25
4
+ * Last: 2022-09-24 15:23:25, 2022-9-26 12:37:01, 2022-12-29 00:11:16
5
+ */
1
6
  import * as lDb from '../lib/db';
2
7
  import * as lKv from '../lib/kv';
3
8
  import * as sCtr from '../sys/ctr';
9
+ /** --- Scan 设置的选项 --- */
4
10
  export interface IOptions {
5
11
  'ttl'?: number;
6
12
  'sqlPre'?: sCtr.Ctr | string;
7
13
  'name'?: string;
8
14
  }
15
+ /** --- scanned 函数的选项 --- */
9
16
  export interface IStaticOptions {
10
17
  'sqlPre'?: sCtr.Ctr | string;
11
18
  'name'?: string;
@@ -13,19 +20,64 @@ export interface IStaticOptions {
13
20
  export declare class Scan {
14
21
  private readonly _link;
15
22
  private readonly _sql;
23
+ /** --- 表名或者 kv 里 key 的前缀 --- */
16
24
  private readonly _name;
17
25
  private _token;
26
+ /** --- 有效期,默认 5 分钟 --- */
18
27
  private _ttl;
19
28
  constructor(link: lDb.Pool | lKv.Pool, token?: string, opt?: IOptions);
29
+ /** --- 二维码剩余有效时间 --- */
20
30
  private _timeLeft;
31
+ /**
32
+ * --- 生成二维码处的轮询,检查是否被扫码、被录入数据 ---
33
+ * @returns -3 系统错误 -2 token 不存在或已过期 -1 无操作, 0 已扫码, 其他返回为存的数据并结束轮询
34
+ */
21
35
  poll(): Promise<any>;
36
+ /**
37
+ * --- 创建 token,直接应用到本类 ---
38
+ */
22
39
  createToken(): Promise<boolean>;
40
+ /**
41
+ * --- 获取当前 token ---
42
+ */
23
43
  getToken(): string | null;
44
+ /**
45
+ * --- 设置有效期,设置后的新 token 被创建有效 ---
46
+ * @param ttl
47
+ */
24
48
  setTTL(ttl: number): void;
49
+ /**
50
+ * --- 获取设置的有效期 ---
51
+ */
25
52
  getTTL(): number;
53
+ /**
54
+ * --- 获取当前 token 可扫剩余有效期 ---
55
+ */
26
56
  getTimeLeft(): number | null;
57
+ /**
58
+ * --- 根据情况清空 Db 状态下的 scan 表垃圾数据 ---
59
+ */
27
60
  private _gc;
28
61
  }
62
+ /**
63
+ * -- 创建 Scan 对象 ---
64
+ * @param link
65
+ * @param token Token
66
+ * @param opt
67
+ */
29
68
  export declare function get(link: lDb.Pool | lKv.Pool, token?: string, opt?: IOptions): Promise<Scan>;
69
+ /**
70
+ * --- 对 token 执行访问操作,通常用户扫码后展示的网页所调用,代表已扫码 ---
71
+ * @param link
72
+ * @patam token 必填
73
+ * @param opt
74
+ */
30
75
  export declare function scanned(link: lDb.Pool | lKv.Pool, token: string, opt?: IStaticOptions): Promise<boolean>;
76
+ /**
77
+ * --- 将数据写入 token,通常在客户的逻辑下去写,服务器会 poll 到 ---
78
+ * @param link
79
+ * @param token
80
+ * @param data
81
+ * @param opt
82
+ */
31
83
  export declare function setData(link: lDb.Pool | lKv.Pool, token: string, data: Record<string, any> | string | number, opt?: IStaticOptions): Promise<boolean>;