@maiyunnet/kebab 2.0.2 → 2.0.4

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 (49) hide show
  1. package/index.js +1 -1
  2. package/lib/sql.js +1 -3
  3. package/lib/text.js +5 -1
  4. package/package.json +1 -1
  5. package/tsconfig.json +1 -1
  6. package/index.ts +0 -33
  7. package/lib/buffer.ts +0 -152
  8. package/lib/captcha.ts +0 -63
  9. package/lib/consistent.ts +0 -219
  10. package/lib/core.ts +0 -880
  11. package/lib/crypto.ts +0 -384
  12. package/lib/db.ts +0 -719
  13. package/lib/dns.ts +0 -405
  14. package/lib/fs.ts +0 -527
  15. package/lib/jwt.ts +0 -276
  16. package/lib/kv.ts +0 -1489
  17. package/lib/lan.ts +0 -87
  18. package/lib/net/formdata.ts +0 -166
  19. package/lib/net/request.ts +0 -150
  20. package/lib/net/response.ts +0 -59
  21. package/lib/net.ts +0 -662
  22. package/lib/s3.ts +0 -235
  23. package/lib/scan.ts +0 -364
  24. package/lib/session.ts +0 -230
  25. package/lib/sql.ts +0 -1151
  26. package/lib/ssh/sftp.ts +0 -508
  27. package/lib/ssh/shell.ts +0 -123
  28. package/lib/ssh.ts +0 -191
  29. package/lib/text.ts +0 -615
  30. package/lib/time.ts +0 -254
  31. package/lib/ws.ts +0 -523
  32. package/lib/zip.ts +0 -447
  33. package/lib/zlib.ts +0 -350
  34. package/main.ts +0 -27
  35. package/sys/child.ts +0 -678
  36. package/sys/cmd.ts +0 -225
  37. package/sys/ctr.ts +0 -904
  38. package/sys/master.ts +0 -355
  39. package/sys/mod.ts +0 -1871
  40. package/sys/route.ts +0 -1113
  41. package/types/index.d.ts +0 -283
  42. package/www/example/ctr/main.ts +0 -9
  43. package/www/example/ctr/middle.ts +0 -26
  44. package/www/example/ctr/test.ts +0 -3218
  45. package/www/example/mod/test.ts +0 -47
  46. package/www/example/mod/testdata.ts +0 -30
  47. package/www/example/ws/mproxy.ts +0 -16
  48. package/www/example/ws/rproxy.ts +0 -14
  49. package/www/example/ws/test.ts +0 -36
package/lib/s3.ts DELETED
@@ -1,235 +0,0 @@
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.ts DELETED
@@ -1,364 +0,0 @@
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
- */
6
-
7
- /*
8
- CREATE TABLE IF NOT EXISTS `scan` (
9
- `id` bigint NOT NULL AUTO_INCREMENT,
10
- `token` char (32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
11
- `data` text NOT NULL,
12
- `time_update` bigint NOT NULL,
13
- `time_add` bigint NOT NULL,
14
- `time_exp` bigint NOT NULL,
15
- PRIMARY KEY (`id`),
16
- UNIQUE KEY `token` (`token`) USING btree
17
- KEY `time_update` (`time_update`),
18
- KEY `time_exp` (`time_exp`)
19
- ) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
20
- */
21
- import * as lCore from '~/lib/core';
22
- import * as lDb from '~/lib/db';
23
- import * as lKv from '~/lib/kv';
24
- import * as lSql from '~/lib/sql';
25
- import * as lTime from '~/lib/time';
26
- import * as lText from '~/lib/text';
27
- import * as sCtr from '~/sys/ctr';
28
-
29
- /** --- Scan 设置的选项 --- */
30
- export interface IOptions {
31
- 'ttl'?: number;
32
- 'sqlPre'?: sCtr.Ctr | string;
33
- 'name'?: string;
34
- }
35
-
36
- /** --- scanned 函数的选项 --- */
37
- export interface IStaticOptions {
38
- 'sqlPre'?: sCtr.Ctr | string;
39
- 'name'?: string;
40
- }
41
-
42
- export class Scan {
43
-
44
- private readonly _link: lDb.Pool | lKv.Pool;
45
-
46
- private readonly _sql: lSql.Sql | null = null;
47
-
48
- /** --- 表名或者 kv 里 key 的前缀 --- */
49
- private readonly _name: string = 'scan';
50
-
51
- private _token: string | null = null;
52
-
53
- /** --- 有效期,默认 5 分钟 --- */
54
- private _ttl = 60 * 5;
55
-
56
- public constructor(link: lDb.Pool | lKv.Pool, token?: string, opt: IOptions = {}) {
57
- if (opt.ttl !== undefined) {
58
- this._ttl = opt.ttl;
59
- }
60
- if (opt.name) {
61
- this._name = opt.name;
62
- }
63
- this._link = link;
64
- if (link instanceof lDb.Pool) {
65
- this._sql = lSql.get(opt.sqlPre);
66
- }
67
- if (token) {
68
- this._token = token;
69
- }
70
- }
71
-
72
- /** --- 二维码剩余有效时间 --- */
73
- private _timeLeft: number | null = null;
74
-
75
- /**
76
- * --- 生成二维码处的轮询,检查是否被扫码、被录入数据 ---
77
- * @returns -3 系统错误 -2 token 不存在或已过期 -1 无操作, 0 已扫码, 其他返回为存的数据并结束轮询
78
- */
79
- public async poll(): Promise<any> {
80
- if (!this._token) {
81
- return -3;
82
- }
83
- const time = lTime.stamp();
84
- if (this._link instanceof lDb.Pool) {
85
- // --- Db ---
86
- this._sql!.select('*', this._name).where([
87
- { 'token': this._token },
88
- ['time_exp', '>', time]
89
- ]);
90
- const r = await this._link.query(this._sql!.getSql(), this._sql!.getData());
91
- if (r.error) {
92
- // --- 出错 ---
93
- return -3;
94
- }
95
- const data = r.rows?.[0];
96
- if (!data) {
97
- // --- 不存在或过期 ---
98
- return -2;
99
- }
100
- // --- 存在,判断是否被扫码,以及是否被写入数据 ---
101
- this._timeLeft = data['time_exp'] - time;
102
- if (data['data'] !== '') {
103
- // --- 已经写入数据了,删除数据库条目并返回写入的数据内容 ---
104
- this._sql!.delete(this._name).where({
105
- 'id': data['id']
106
- });
107
- const r = lText.parseJson(data['data']);
108
- return r === false ? -3 : r;
109
- }
110
- else if (data['time_update'] > 0) {
111
- // --- 已被扫描 ---
112
- return 0;
113
- }
114
- else {
115
- // --- 未扫描 ---
116
- return -1;
117
- }
118
- }
119
- else {
120
- // --- Kv ---
121
- const data = await this._link.getJson('scan-' + this._name + '_' + this._token);
122
- if (data === null) {
123
- // --- 不存在或过期 ---
124
- return -2;
125
- }
126
- const ttl = await this._link.ttl('scan-' + this._name + '_' + this._token);
127
- if (ttl === null) {
128
- return -3;
129
- }
130
- this._timeLeft = ttl;
131
- if (data['data'] !== null) {
132
- // --- 已经写入数据了,删除数据库条目并返回写入的数据内容 ---
133
- await this._link.del('scan-' + this._name + '_' + this._token);
134
- return data;
135
- }
136
- else if (data['time_update'] > 0) {
137
- // --- 已被扫描 ---
138
- return 0;
139
- }
140
- else {
141
- // --- 未扫描 ---
142
- return -1;
143
- }
144
- }
145
- }
146
-
147
- /**
148
- * --- 创建 token,直接应用到本类 ---
149
- */
150
- public async createToken(): Promise<boolean> {
151
- await this._gc();
152
- const time = lTime.stamp();
153
- let count = 0;
154
- while (true) {
155
- if (count === 5) {
156
- return false;
157
- }
158
- this._token = lCore.random(32, lCore.RANDOM_LUN);
159
- if (this._link instanceof lDb.Pool) {
160
- // --- Db ---
161
- this._sql!.insert(this._name).values({
162
- 'token': this._token,
163
- 'data': '',
164
- 'time_update': '0',
165
- 'time_add': time,
166
- 'time_exp': time + this._ttl
167
- });
168
- const r = await this._link.execute(this._sql!.getSql(), this._sql!.getData());
169
- if (r.error) {
170
- if (r.error.errno !== 1062) {
171
- return false;
172
- }
173
- }
174
- else {
175
- break;
176
- }
177
- }
178
- else {
179
- // --- Kv ---
180
- if (await this._link.set('scan-' + this._name + '_' + this._token, {
181
- 'time_update': 0,
182
- 'data': null
183
- }, this._ttl, 'nx')) {
184
- break;
185
- }
186
- }
187
- ++count;
188
- }
189
- return true;
190
- }
191
-
192
- /**
193
- * --- 获取当前 token ---
194
- */
195
- public getToken(): string | null {
196
- return this._token;
197
- }
198
-
199
- /**
200
- * --- 设置有效期,设置后的新 token 被创建有效 ---
201
- * @param ttl
202
- */
203
- public setTTL(ttl: number): void {
204
- this._ttl = ttl;
205
- }
206
-
207
- /**
208
- * --- 获取设置的有效期 ---
209
- */
210
- public getTTL(): number {
211
- return this._ttl;
212
- }
213
-
214
- /**
215
- * --- 获取当前 token 可扫剩余有效期 ---
216
- */
217
- public getTimeLeft(): number | null {
218
- return this._timeLeft;
219
- }
220
-
221
- /**
222
- * --- 根据情况清空 Db 状态下的 scan 表垃圾数据 ---
223
- */
224
- private async _gc(): Promise<void> {
225
- if (this._link instanceof lKv.Pool) {
226
- return;
227
- }
228
- if (lCore.rand(0, 10) !== 5) {
229
- return;
230
- }
231
- this._sql!.delete(this._name).where([
232
- ['time_exp', '<', lTime.stamp()]
233
- ]);
234
- await this._link.execute(this._sql!.getSql(), this._sql!.getData());
235
- }
236
-
237
- }
238
-
239
- /**
240
- * -- 创建 Scan 对象 ---
241
- * @param link
242
- * @param token Token
243
- * @param opt
244
- */
245
- export async function get(link: lDb.Pool | lKv.Pool, token?: string, opt: IOptions = {}): Promise<Scan> {
246
- const scan = new Scan(link, token, opt);
247
- if (!token) {
248
- await scan.createToken();
249
- }
250
- return scan;
251
- }
252
-
253
- /**
254
- * --- 对 token 执行访问操作,通常用户扫码后展示的网页所调用,代表已扫码 ---
255
- * @param link
256
- * @patam token 必填
257
- * @param opt
258
- */
259
- export async function scanned(
260
- link: lDb.Pool | lKv.Pool,
261
- token: string,
262
- opt: IStaticOptions = {}
263
- ): Promise<boolean> {
264
- const time = lTime.stamp();
265
- const name = opt.name ?? 'scan';
266
- if (link instanceof lDb.Pool) {
267
- // --- Db ---
268
- const sql = lSql.get(opt.sqlPre);
269
- sql.update(name, {
270
- 'time_update': time
271
- }).where([
272
- {
273
- 'token': token,
274
- 'time_update': '0'
275
- },
276
- ['time_exp', '>', time]
277
- ]);
278
- const r = await link.execute(sql.getSql(), sql.getData());
279
- if (r.error) {
280
- return false;
281
- }
282
- if (r.packet?.affectedRows && r.packet.affectedRows > 0) {
283
- return true;
284
- }
285
- }
286
- else {
287
- // --- Kv ---
288
- const ldata = await link.getJson('scan-' + name + '_' + token);
289
- if (ldata === null) {
290
- return false;
291
- }
292
- if (ldata['time_update'] > 0) {
293
- // --- 已经被扫码过了 ---
294
- return false;
295
- }
296
- ldata['time_update'] = time;
297
- const ttl = await link.ttl('scan-' + name + '_' + token);
298
- if (ttl === null) {
299
- return false;
300
- }
301
- return link.set('scan-' + name + '_' + token, ldata, ttl + 1, 'xx');
302
- }
303
- return false;
304
- }
305
-
306
- /**
307
- * --- 将数据写入 token,通常在客户的逻辑下去写,服务器会 poll 到 ---
308
- * @param link
309
- * @param token
310
- * @param data
311
- * @param opt
312
- */
313
- export async function setData(
314
- link: lDb.Pool | lKv.Pool,
315
- token: string,
316
- data: Record<string, any> | string | number,
317
- opt: IStaticOptions = {}
318
- ): Promise<boolean> {
319
- if (typeof data === 'number' && Number.isInteger(data)) {
320
- if (data >= -3 && data <= 1) {
321
- return false;
322
- }
323
- }
324
- const time = lTime.stamp();
325
- const name = opt.name ?? 'scan';
326
- if (link instanceof lDb.Pool) {
327
- // --- Db ---
328
- const sql = lSql.get(opt.sqlPre);
329
- sql.update(name, {
330
- 'data': lText.stringifyJson(data)
331
- }).where([
332
- {
333
- 'token': token,
334
- },
335
- ['time_update', '>', '0'],
336
- ['time_exp', '>', time]
337
- ]);
338
- const r = await link.execute(sql.getSql(), sql.getData());
339
- if (r.error) {
340
- return false;
341
- }
342
- if (r.packet?.affectedRows && r.packet?.affectedRows > 0) {
343
- return true;
344
- }
345
- }
346
- else {
347
- // --- Kv ---
348
- const ldata = await link.getJson('scan-' + name + '_' + token);
349
- if (ldata === null) {
350
- return false;
351
- }
352
- if (ldata['time_update'] === 0) {
353
- // --- 还未被扫码,无法操作 ---
354
- return false;
355
- }
356
- const ttl = await link.ttl('scan-' + name + '_' + token);
357
- if (ttl === null) {
358
- return false;
359
- }
360
- ldata['data'] = data;
361
- return link.set('scan-' + name + '_' + token, ldata, ttl + 1, 'xx');
362
- }
363
- return false;
364
- }