@maiyunnet/kebab 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.VSCodeCounter/2025-02-14_14-46-44/details.md +82 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +15 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +2 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +19 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +22 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +69 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/results.json +1 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/results.md +48 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +118 -0
- package/.vscode/tasks.json +15 -0
- package/LICENSE +201 -0
- package/README.md +201 -0
- package/bin/kebab.js +2 -0
- package/eslint.config.js +22 -0
- package/index.js +19 -0
- package/index.ts +33 -0
- package/lib/buffer.js +108 -0
- package/lib/buffer.ts +152 -0
- package/lib/captcha/zcool-addict-italic.ttf +0 -0
- package/lib/captcha.js +71 -0
- package/lib/captcha.ts +63 -0
- package/lib/consistent.js +171 -0
- package/lib/consistent.ts +219 -0
- package/lib/core.js +663 -0
- package/lib/core.ts +880 -0
- package/lib/crypto.js +256 -0
- package/lib/crypto.ts +384 -0
- package/lib/db.js +521 -0
- package/lib/db.ts +719 -0
- package/lib/dns.js +321 -0
- package/lib/dns.ts +405 -0
- package/lib/fs.js +405 -0
- package/lib/fs.ts +527 -0
- package/lib/jwt.js +223 -0
- package/lib/jwt.ts +276 -0
- package/lib/kv.js +1004 -0
- package/lib/kv.ts +1489 -0
- package/lib/lan.js +99 -0
- package/lib/lan.ts +87 -0
- package/lib/net/cacert.pem +3480 -0
- package/lib/net/formdata.js +137 -0
- package/lib/net/formdata.ts +166 -0
- package/lib/net/request.js +102 -0
- package/lib/net/request.ts +150 -0
- package/lib/net/response.js +28 -0
- package/lib/net/response.ts +59 -0
- package/lib/net.js +462 -0
- package/lib/net.ts +662 -0
- package/lib/s3.js +180 -0
- package/lib/s3.ts +235 -0
- package/lib/scan.js +276 -0
- package/lib/scan.ts +364 -0
- package/lib/session.js +177 -0
- package/lib/session.ts +230 -0
- package/lib/sql.js +818 -0
- package/lib/sql.ts +1151 -0
- package/lib/ssh/sftp.js +373 -0
- package/lib/ssh/sftp.ts +508 -0
- package/lib/ssh/shell.js +109 -0
- package/lib/ssh/shell.ts +123 -0
- package/lib/ssh.js +171 -0
- package/lib/ssh.ts +191 -0
- package/lib/text/tld.json +1 -0
- package/lib/text.js +452 -0
- package/lib/text.ts +607 -0
- package/lib/time.js +216 -0
- package/lib/time.ts +254 -0
- package/lib/ws.js +373 -0
- package/lib/ws.ts +523 -0
- package/lib/zip.js +381 -0
- package/lib/zip.ts +447 -0
- package/lib/zlib.js +289 -0
- package/lib/zlib.ts +350 -0
- package/main.js +51 -0
- package/main.ts +27 -0
- package/package.json +37 -0
- package/sys/child.js +585 -0
- package/sys/child.ts +678 -0
- package/sys/cmd.js +226 -0
- package/sys/cmd.ts +225 -0
- package/sys/ctr.js +608 -0
- package/sys/ctr.ts +904 -0
- package/sys/master.js +314 -0
- package/sys/master.ts +355 -0
- package/sys/mod.js +1273 -0
- package/sys/mod.ts +1871 -0
- package/sys/route.js +922 -0
- package/sys/route.ts +1113 -0
- package/types/index.d.ts +283 -0
- package/www/example/ctr/main.js +42 -0
- package/www/example/ctr/main.ts +9 -0
- package/www/example/ctr/middle.js +57 -0
- package/www/example/ctr/middle.ts +26 -0
- package/www/example/ctr/test.js +2818 -0
- package/www/example/ctr/test.ts +3218 -0
- package/www/example/data/locale/en.test.json +8 -0
- package/www/example/data/locale/index.html +1 -0
- package/www/example/data/locale/ja.test.json +8 -0
- package/www/example/data/locale/sc.test.json +8 -0
- package/www/example/data/locale/tc.test.json +8 -0
- package/www/example/data/test.zip +0 -0
- package/www/example/kebab.json +24 -0
- package/www/example/mod/test.js +49 -0
- package/www/example/mod/test.ts +47 -0
- package/www/example/mod/testdata.js +11 -0
- package/www/example/mod/testdata.ts +30 -0
- package/www/example/route.json +6 -0
- package/www/example/view/test.ejs +11 -0
- package/www/example/ws/mproxy.js +49 -0
- package/www/example/ws/mproxy.ts +16 -0
- package/www/example/ws/rproxy.js +47 -0
- package/www/example/ws/rproxy.ts +14 -0
- package/www/example/ws/test.js +68 -0
- package/www/example/ws/test.ts +36 -0
package/lib/s3.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.S3 = exports.ESERVICE = void 0;
|
|
37
|
+
exports.get = get;
|
|
38
|
+
const s3 = __importStar(require("@aws-sdk/client-s3"));
|
|
39
|
+
const ls = __importStar(require("@aws-sdk/lib-storage"));
|
|
40
|
+
const lCore = __importStar(require("~/lib/core"));
|
|
41
|
+
const lText = __importStar(require("~/lib/text"));
|
|
42
|
+
var ESERVICE;
|
|
43
|
+
(function (ESERVICE) {
|
|
44
|
+
ESERVICE[ESERVICE["AMAZON"] = 0] = "AMAZON";
|
|
45
|
+
ESERVICE[ESERVICE["TENCENT"] = 1] = "TENCENT";
|
|
46
|
+
ESERVICE[ESERVICE["ALIBABA"] = 2] = "ALIBABA";
|
|
47
|
+
ESERVICE[ESERVICE["CF"] = 3] = "CF";
|
|
48
|
+
})(ESERVICE || (exports.ESERVICE = ESERVICE = {}));
|
|
49
|
+
class S3 {
|
|
50
|
+
constructor(ctr, opt) {
|
|
51
|
+
this._bucket = '';
|
|
52
|
+
this._ctr = ctr;
|
|
53
|
+
const config = ctr.getPrototype('_config');
|
|
54
|
+
opt.account ??= config.s3?.[ESERVICE[opt.service]]?.account ?? '';
|
|
55
|
+
opt.secretId ??= config.s3?.[ESERVICE[opt.service]]?.sid ?? '';
|
|
56
|
+
opt.secretKey ??= config.s3?.[ESERVICE[opt.service]]?.skey ?? '';
|
|
57
|
+
opt.region ??= config.s3?.[ESERVICE[opt.service]]?.region ?? '';
|
|
58
|
+
opt.bucket ??= config.s3?.[ESERVICE[opt.service]]?.bucket ?? '';
|
|
59
|
+
this._bucket = opt.bucket;
|
|
60
|
+
let endpoint;
|
|
61
|
+
switch (opt.service) {
|
|
62
|
+
case ESERVICE.TENCENT: {
|
|
63
|
+
endpoint = `https://cos.${opt.region}.myqcloud.com`;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case ESERVICE.ALIBABA: {
|
|
67
|
+
endpoint = `https://oss-${opt.region}.aliyuncs.com`;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case ESERVICE.CF: {
|
|
71
|
+
endpoint = `https://${opt.account}.r2.cloudflarestorage.com`;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
default: {
|
|
75
|
+
endpoint = undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
this._link = new s3.S3Client({
|
|
79
|
+
'region': opt.region,
|
|
80
|
+
'credentials': {
|
|
81
|
+
'accessKeyId': opt.secretId,
|
|
82
|
+
'secretAccessKey': opt.secretKey
|
|
83
|
+
},
|
|
84
|
+
'endpoint': endpoint
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
setBucket(bucket) {
|
|
88
|
+
this._bucket = bucket;
|
|
89
|
+
}
|
|
90
|
+
async putObject(key, content, length, bucket) {
|
|
91
|
+
try {
|
|
92
|
+
let type = undefined;
|
|
93
|
+
let disposition = undefined;
|
|
94
|
+
if (typeof length !== 'number') {
|
|
95
|
+
type = length?.type;
|
|
96
|
+
disposition = length?.disposition;
|
|
97
|
+
bucket = length?.bucket;
|
|
98
|
+
length = length?.length;
|
|
99
|
+
}
|
|
100
|
+
const upload = new ls.Upload({
|
|
101
|
+
'client': this._link,
|
|
102
|
+
'params': {
|
|
103
|
+
'Bucket': bucket ?? this._bucket,
|
|
104
|
+
'Key': key,
|
|
105
|
+
'Body': content,
|
|
106
|
+
'ContentLength': length,
|
|
107
|
+
'ContentType': type,
|
|
108
|
+
'ContentDisposition': disposition
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const res = await upload.done();
|
|
112
|
+
return (res.Location && res.Bucket && res.Key) ? res : false;
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
await lCore.log(this._ctr, '[putObject, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async getObject(key, bucket) {
|
|
120
|
+
try {
|
|
121
|
+
const go = new s3.GetObjectCommand({
|
|
122
|
+
'Bucket': bucket ?? this._bucket,
|
|
123
|
+
'Key': key
|
|
124
|
+
});
|
|
125
|
+
const r = await this._link.send(go);
|
|
126
|
+
return r.Body;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async deleteObject(key, bucket) {
|
|
133
|
+
try {
|
|
134
|
+
const doc = new s3.DeleteObjectCommand({
|
|
135
|
+
'Bucket': bucket ?? this._bucket,
|
|
136
|
+
'Key': key
|
|
137
|
+
});
|
|
138
|
+
await this._link.send(doc);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async deleteObjects(keys, bucket) {
|
|
146
|
+
try {
|
|
147
|
+
const doc = new s3.DeleteObjectsCommand({
|
|
148
|
+
'Bucket': bucket ?? this._bucket,
|
|
149
|
+
'Delete': {
|
|
150
|
+
'Objects': keys.map((key) => ({ 'Key': key }))
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
await this._link.send(doc);
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
await lCore.log(this._ctr, '[deleteObjects, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async headObject(key, bucket) {
|
|
162
|
+
try {
|
|
163
|
+
const ho = new s3.HeadObjectCommand({
|
|
164
|
+
'Bucket': bucket ?? this._bucket,
|
|
165
|
+
'Key': key
|
|
166
|
+
});
|
|
167
|
+
return await this._link.send(ho);
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
if (e.$metadata?.httpStatusCode !== 404) {
|
|
171
|
+
await lCore.log(this._ctr, '[headObject, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
exports.S3 = S3;
|
|
178
|
+
function get(ctr, opt) {
|
|
179
|
+
return new S3(ctr, opt);
|
|
180
|
+
}
|
package/lib/s3.ts
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
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
|
+
*/
|
|
6
|
+
|
|
7
|
+
// --- 库和定义 ---
|
|
8
|
+
import * as s3 from '@aws-sdk/client-s3';
|
|
9
|
+
import * as ls from '@aws-sdk/lib-storage';
|
|
10
|
+
import * as stream from 'stream';
|
|
11
|
+
import * as sCtr from '~/sys/ctr';
|
|
12
|
+
import * as lCore from '~/lib/core';
|
|
13
|
+
import * as lText from '~/lib/text';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* s3 文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** --- 服务商定义 --- */
|
|
20
|
+
export enum ESERVICE {
|
|
21
|
+
'AMAZON',
|
|
22
|
+
'TENCENT',
|
|
23
|
+
'ALIBABA',
|
|
24
|
+
'CF'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** --- 选项 --- */
|
|
28
|
+
export interface IOptions {
|
|
29
|
+
/** --- 服务商 ---- */
|
|
30
|
+
'service': ESERVICE;
|
|
31
|
+
/** --- cf r2 使用 --- */
|
|
32
|
+
'account'?: string;
|
|
33
|
+
/** --- 密钥键 --- */
|
|
34
|
+
'secretId'?: string;
|
|
35
|
+
/** --- 密钥值 --- */
|
|
36
|
+
'secretKey'?: string;
|
|
37
|
+
/** --- 区域 --- */
|
|
38
|
+
'region'?: string;
|
|
39
|
+
/** --- 预定义 bucket --- */
|
|
40
|
+
'bucket'?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class S3 {
|
|
44
|
+
|
|
45
|
+
private readonly _link;
|
|
46
|
+
|
|
47
|
+
/** --- bucket 名 --- */
|
|
48
|
+
private _bucket: string = '';
|
|
49
|
+
|
|
50
|
+
private readonly _ctr: sCtr.Ctr;
|
|
51
|
+
|
|
52
|
+
public constructor(ctr: sCtr.Ctr, opt: IOptions) {
|
|
53
|
+
this._ctr = ctr;
|
|
54
|
+
const config = ctr.getPrototype('_config');
|
|
55
|
+
opt.account ??= config.s3?.[ESERVICE[opt.service]]?.account ?? '';
|
|
56
|
+
opt.secretId ??= config.s3?.[ESERVICE[opt.service]]?.sid ?? '';
|
|
57
|
+
opt.secretKey ??= config.s3?.[ESERVICE[opt.service]]?.skey ?? '';
|
|
58
|
+
opt.region ??= config.s3?.[ESERVICE[opt.service]]?.region ?? '';
|
|
59
|
+
opt.bucket ??= config.s3?.[ESERVICE[opt.service]]?.bucket ?? '';
|
|
60
|
+
this._bucket = opt.bucket;
|
|
61
|
+
let endpoint: string | undefined;
|
|
62
|
+
switch (opt.service) {
|
|
63
|
+
case ESERVICE.TENCENT: {
|
|
64
|
+
endpoint = `https://cos.${opt.region}.myqcloud.com`;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case ESERVICE.ALIBABA: {
|
|
68
|
+
endpoint = `https://oss-${opt.region}.aliyuncs.com`;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case ESERVICE.CF: {
|
|
72
|
+
endpoint = `https://${opt.account}.r2.cloudflarestorage.com`;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
default: {
|
|
76
|
+
endpoint = undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
this._link = new s3.S3Client({
|
|
80
|
+
'region': opt.region,
|
|
81
|
+
'credentials': {
|
|
82
|
+
'accessKeyId': opt.secretId,
|
|
83
|
+
'secretAccessKey': opt.secretKey
|
|
84
|
+
},
|
|
85
|
+
'endpoint': endpoint
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* --- 修改预定义 bucket ---
|
|
91
|
+
* @param bucket bucket 名
|
|
92
|
+
*/
|
|
93
|
+
public setBucket(bucket: string): void {
|
|
94
|
+
this._bucket = bucket;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* --- 上传对象(可传流且也可无需设置 length) --
|
|
99
|
+
* @param key 对象路径
|
|
100
|
+
* @param content 内容
|
|
101
|
+
* @param length 设置 contentLength,如果是流模式则需要设置此项,也可以设置为对象参数
|
|
102
|
+
* @param bucket bucket 名
|
|
103
|
+
*/
|
|
104
|
+
public async putObject(
|
|
105
|
+
key: string, content: string | Buffer | stream.Readable, length?: number | {
|
|
106
|
+
'length'?: number;
|
|
107
|
+
'type'?: string;
|
|
108
|
+
'disposition'?: string;
|
|
109
|
+
'bucket'?: string;
|
|
110
|
+
}, bucket?: string
|
|
111
|
+
): Promise<s3.CompleteMultipartUploadCommandOutput | false> {
|
|
112
|
+
try {
|
|
113
|
+
/** --- content type --- */
|
|
114
|
+
let type: string | undefined = undefined;
|
|
115
|
+
/** --- content disposition --- */
|
|
116
|
+
let disposition: string | undefined = undefined;
|
|
117
|
+
if (typeof length !== 'number') {
|
|
118
|
+
type = length?.type;
|
|
119
|
+
disposition = length?.disposition;
|
|
120
|
+
bucket = length?.bucket;
|
|
121
|
+
length = length?.length;
|
|
122
|
+
}
|
|
123
|
+
const upload = new ls.Upload({
|
|
124
|
+
'client': this._link,
|
|
125
|
+
'params': {
|
|
126
|
+
'Bucket': bucket ?? this._bucket,
|
|
127
|
+
'Key': key,
|
|
128
|
+
'Body': content,
|
|
129
|
+
'ContentLength': length,
|
|
130
|
+
'ContentType': type,
|
|
131
|
+
'ContentDisposition': disposition
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
const res = await upload.done();
|
|
135
|
+
return (res.Location && res.Bucket && res.Key) ? res : false;
|
|
136
|
+
}
|
|
137
|
+
catch (e: any) {
|
|
138
|
+
await lCore.log(this._ctr, '[putObject, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* --- 获取对象流,可通过流获取 buffer 或 text ---
|
|
145
|
+
* @param key 对象路径
|
|
146
|
+
* @param bucket bucket 名
|
|
147
|
+
*/
|
|
148
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
149
|
+
public async getObject(key: string, bucket?: string) {
|
|
150
|
+
try {
|
|
151
|
+
const go = new s3.GetObjectCommand({
|
|
152
|
+
'Bucket': bucket ?? this._bucket,
|
|
153
|
+
'Key': key
|
|
154
|
+
});
|
|
155
|
+
const r = await this._link.send(go);
|
|
156
|
+
return r.Body;
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// await lCore.log(this._ctr, '[getObject, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* --- 删除对象 ---
|
|
166
|
+
* @param key 对象路径
|
|
167
|
+
* @param bucket bucket 名
|
|
168
|
+
*/
|
|
169
|
+
public async deleteObject(key: string, bucket?: string): Promise<boolean> {
|
|
170
|
+
try {
|
|
171
|
+
const doc = new s3.DeleteObjectCommand({
|
|
172
|
+
'Bucket': bucket ?? this._bucket,
|
|
173
|
+
'Key': key
|
|
174
|
+
});
|
|
175
|
+
await this._link.send(doc);
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// await lCore.log(this._ctr, '[deleteObject, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* --- 批量删除对象 ---
|
|
186
|
+
* @param keys 批量对象路径
|
|
187
|
+
* @param bucket bucket 名
|
|
188
|
+
*/
|
|
189
|
+
public async deleteObjects(keys: string[], bucket?: string): Promise<boolean> {
|
|
190
|
+
try {
|
|
191
|
+
const doc = new s3.DeleteObjectsCommand({
|
|
192
|
+
'Bucket': bucket ?? this._bucket,
|
|
193
|
+
'Delete': {
|
|
194
|
+
'Objects': keys.map((key) => ({ 'Key': key }))
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
await this._link.send(doc);
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
catch (e: any) {
|
|
201
|
+
await lCore.log(this._ctr, '[deleteObjects, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* --- 检测对象是否存在 ---
|
|
208
|
+
* @param key 对象路径
|
|
209
|
+
* @param bucket bucket 名
|
|
210
|
+
*/
|
|
211
|
+
public async headObject(key: string, bucket?: string): Promise<s3.HeadObjectCommandOutput | false> {
|
|
212
|
+
try {
|
|
213
|
+
const ho = new s3.HeadObjectCommand({
|
|
214
|
+
'Bucket': bucket ?? this._bucket,
|
|
215
|
+
'Key': key
|
|
216
|
+
});
|
|
217
|
+
return await this._link.send(ho);
|
|
218
|
+
}
|
|
219
|
+
catch (e: any) {
|
|
220
|
+
if (e.$metadata?.httpStatusCode !== 404) {
|
|
221
|
+
await lCore.log(this._ctr, '[headObject, s3] ' + lText.stringifyJson(e.message ?? '').slice(1, -1).replace(/"/g, '""'), '-error');
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* --- 创建一个对象存储对象 ---
|
|
231
|
+
* @param opt 选项
|
|
232
|
+
*/
|
|
233
|
+
export function get(ctr: sCtr.Ctr, opt: IOptions): S3 {
|
|
234
|
+
return new S3(ctr, opt);
|
|
235
|
+
}
|
package/lib/scan.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Scan = void 0;
|
|
37
|
+
exports.get = get;
|
|
38
|
+
exports.scanned = scanned;
|
|
39
|
+
exports.setData = setData;
|
|
40
|
+
const lCore = __importStar(require("~/lib/core"));
|
|
41
|
+
const lDb = __importStar(require("~/lib/db"));
|
|
42
|
+
const lKv = __importStar(require("~/lib/kv"));
|
|
43
|
+
const lSql = __importStar(require("~/lib/sql"));
|
|
44
|
+
const lTime = __importStar(require("~/lib/time"));
|
|
45
|
+
const lText = __importStar(require("~/lib/text"));
|
|
46
|
+
class Scan {
|
|
47
|
+
constructor(link, token, opt = {}) {
|
|
48
|
+
this._sql = null;
|
|
49
|
+
this._name = 'scan';
|
|
50
|
+
this._token = null;
|
|
51
|
+
this._ttl = 60 * 5;
|
|
52
|
+
this._timeLeft = null;
|
|
53
|
+
if (opt.ttl !== undefined) {
|
|
54
|
+
this._ttl = opt.ttl;
|
|
55
|
+
}
|
|
56
|
+
if (opt.name) {
|
|
57
|
+
this._name = opt.name;
|
|
58
|
+
}
|
|
59
|
+
this._link = link;
|
|
60
|
+
if (link instanceof lDb.Pool) {
|
|
61
|
+
this._sql = lSql.get(opt.sqlPre);
|
|
62
|
+
}
|
|
63
|
+
if (token) {
|
|
64
|
+
this._token = token;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async poll() {
|
|
68
|
+
if (!this._token) {
|
|
69
|
+
return -3;
|
|
70
|
+
}
|
|
71
|
+
const time = lTime.stamp();
|
|
72
|
+
if (this._link instanceof lDb.Pool) {
|
|
73
|
+
this._sql.select('*', this._name).where([
|
|
74
|
+
{ 'token': this._token },
|
|
75
|
+
['time_exp', '>', time]
|
|
76
|
+
]);
|
|
77
|
+
const r = await this._link.query(this._sql.getSql(), this._sql.getData());
|
|
78
|
+
if (r.error) {
|
|
79
|
+
return -3;
|
|
80
|
+
}
|
|
81
|
+
const data = r.rows?.[0];
|
|
82
|
+
if (!data) {
|
|
83
|
+
return -2;
|
|
84
|
+
}
|
|
85
|
+
this._timeLeft = data['time_exp'] - time;
|
|
86
|
+
if (data['data'] !== '') {
|
|
87
|
+
this._sql.delete(this._name).where({
|
|
88
|
+
'id': data['id']
|
|
89
|
+
});
|
|
90
|
+
const r = lText.parseJson(data['data']);
|
|
91
|
+
return r === false ? -3 : r;
|
|
92
|
+
}
|
|
93
|
+
else if (data['time_update'] > 0) {
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
return -1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const data = await this._link.getJson('scan-' + this._name + '_' + this._token);
|
|
102
|
+
if (data === null) {
|
|
103
|
+
return -2;
|
|
104
|
+
}
|
|
105
|
+
const ttl = await this._link.ttl('scan-' + this._name + '_' + this._token);
|
|
106
|
+
if (ttl === null) {
|
|
107
|
+
return -3;
|
|
108
|
+
}
|
|
109
|
+
this._timeLeft = ttl;
|
|
110
|
+
if (data['data'] !== null) {
|
|
111
|
+
await this._link.del('scan-' + this._name + '_' + this._token);
|
|
112
|
+
return data;
|
|
113
|
+
}
|
|
114
|
+
else if (data['time_update'] > 0) {
|
|
115
|
+
return 0;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
return -1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async createToken() {
|
|
123
|
+
await this._gc();
|
|
124
|
+
const time = lTime.stamp();
|
|
125
|
+
let count = 0;
|
|
126
|
+
while (true) {
|
|
127
|
+
if (count === 5) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
this._token = lCore.random(32, lCore.RANDOM_LUN);
|
|
131
|
+
if (this._link instanceof lDb.Pool) {
|
|
132
|
+
this._sql.insert(this._name).values({
|
|
133
|
+
'token': this._token,
|
|
134
|
+
'data': '',
|
|
135
|
+
'time_update': '0',
|
|
136
|
+
'time_add': time,
|
|
137
|
+
'time_exp': time + this._ttl
|
|
138
|
+
});
|
|
139
|
+
const r = await this._link.execute(this._sql.getSql(), this._sql.getData());
|
|
140
|
+
if (r.error) {
|
|
141
|
+
if (r.error.errno !== 1062) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
if (await this._link.set('scan-' + this._name + '_' + this._token, {
|
|
151
|
+
'time_update': 0,
|
|
152
|
+
'data': null
|
|
153
|
+
}, this._ttl, 'nx')) {
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
++count;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
getToken() {
|
|
162
|
+
return this._token;
|
|
163
|
+
}
|
|
164
|
+
setTTL(ttl) {
|
|
165
|
+
this._ttl = ttl;
|
|
166
|
+
}
|
|
167
|
+
getTTL() {
|
|
168
|
+
return this._ttl;
|
|
169
|
+
}
|
|
170
|
+
getTimeLeft() {
|
|
171
|
+
return this._timeLeft;
|
|
172
|
+
}
|
|
173
|
+
async _gc() {
|
|
174
|
+
if (this._link instanceof lKv.Pool) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (lCore.rand(0, 10) !== 5) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
this._sql.delete(this._name).where([
|
|
181
|
+
['time_exp', '<', lTime.stamp()]
|
|
182
|
+
]);
|
|
183
|
+
await this._link.execute(this._sql.getSql(), this._sql.getData());
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
exports.Scan = Scan;
|
|
187
|
+
async function get(link, token, opt = {}) {
|
|
188
|
+
const scan = new Scan(link, token, opt);
|
|
189
|
+
if (!token) {
|
|
190
|
+
await scan.createToken();
|
|
191
|
+
}
|
|
192
|
+
return scan;
|
|
193
|
+
}
|
|
194
|
+
async function scanned(link, token, opt = {}) {
|
|
195
|
+
const time = lTime.stamp();
|
|
196
|
+
const name = opt.name ?? 'scan';
|
|
197
|
+
if (link instanceof lDb.Pool) {
|
|
198
|
+
const sql = lSql.get(opt.sqlPre);
|
|
199
|
+
sql.update(name, {
|
|
200
|
+
'time_update': time
|
|
201
|
+
}).where([
|
|
202
|
+
{
|
|
203
|
+
'token': token,
|
|
204
|
+
'time_update': '0'
|
|
205
|
+
},
|
|
206
|
+
['time_exp', '>', time]
|
|
207
|
+
]);
|
|
208
|
+
const r = await link.execute(sql.getSql(), sql.getData());
|
|
209
|
+
if (r.error) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
if (r.packet?.affectedRows && r.packet.affectedRows > 0) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
const ldata = await link.getJson('scan-' + name + '_' + token);
|
|
218
|
+
if (ldata === null) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
if (ldata['time_update'] > 0) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
ldata['time_update'] = time;
|
|
225
|
+
const ttl = await link.ttl('scan-' + name + '_' + token);
|
|
226
|
+
if (ttl === null) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
return link.set('scan-' + name + '_' + token, ldata, ttl + 1, 'xx');
|
|
230
|
+
}
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
async function setData(link, token, data, opt = {}) {
|
|
234
|
+
if (typeof data === 'number' && Number.isInteger(data)) {
|
|
235
|
+
if (data >= -3 && data <= 1) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const time = lTime.stamp();
|
|
240
|
+
const name = opt.name ?? 'scan';
|
|
241
|
+
if (link instanceof lDb.Pool) {
|
|
242
|
+
const sql = lSql.get(opt.sqlPre);
|
|
243
|
+
sql.update(name, {
|
|
244
|
+
'data': lText.stringifyJson(data)
|
|
245
|
+
}).where([
|
|
246
|
+
{
|
|
247
|
+
'token': token,
|
|
248
|
+
},
|
|
249
|
+
['time_update', '>', '0'],
|
|
250
|
+
['time_exp', '>', time]
|
|
251
|
+
]);
|
|
252
|
+
const r = await link.execute(sql.getSql(), sql.getData());
|
|
253
|
+
if (r.error) {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
if (r.packet?.affectedRows && r.packet?.affectedRows > 0) {
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
const ldata = await link.getJson('scan-' + name + '_' + token);
|
|
262
|
+
if (ldata === null) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
if (ldata['time_update'] === 0) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
const ttl = await link.ttl('scan-' + name + '_' + token);
|
|
269
|
+
if (ttl === null) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
ldata['data'] = data;
|
|
273
|
+
return link.set('scan-' + name + '_' + token, ldata, ttl + 1, 'xx');
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
}
|