@dofe/infra-shared-services 0.1.1
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/dist/email/dto/email.dto.d.ts +70 -0
- package/dist/email/dto/email.dto.d.ts.map +1 -0
- package/dist/email/dto/email.dto.js +58 -0
- package/dist/email/dto/email.dto.js.map +1 -0
- package/dist/email/email.module.d.ts +3 -0
- package/dist/email/email.module.d.ts.map +1 -0
- package/dist/email/email.module.js +38 -0
- package/dist/email/email.module.js.map +1 -0
- package/dist/email/email.service.d.ts +61 -0
- package/dist/email/email.service.d.ts.map +1 -0
- package/dist/email/email.service.js +191 -0
- package/dist/email/email.service.js.map +1 -0
- package/dist/email/index.d.ts +5 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +26 -0
- package/dist/email/index.js.map +1 -0
- package/dist/file-storage/bucket-resolver.d.ts +174 -0
- package/dist/file-storage/bucket-resolver.d.ts.map +1 -0
- package/dist/file-storage/bucket-resolver.js +270 -0
- package/dist/file-storage/bucket-resolver.js.map +1 -0
- package/dist/file-storage/file-storage.factory.d.ts +183 -0
- package/dist/file-storage/file-storage.factory.d.ts.map +1 -0
- package/dist/file-storage/file-storage.factory.js +300 -0
- package/dist/file-storage/file-storage.factory.js.map +1 -0
- package/dist/file-storage/file-storage.module.d.ts +49 -0
- package/dist/file-storage/file-storage.module.d.ts.map +1 -0
- package/dist/file-storage/file-storage.module.js +74 -0
- package/dist/file-storage/file-storage.module.js.map +1 -0
- package/dist/file-storage/file-storage.service.d.ts +381 -0
- package/dist/file-storage/file-storage.service.d.ts.map +1 -0
- package/dist/file-storage/file-storage.service.js +598 -0
- package/dist/file-storage/file-storage.service.js.map +1 -0
- package/dist/file-storage/index.d.ts +43 -0
- package/dist/file-storage/index.d.ts.map +1 -0
- package/dist/file-storage/index.js +65 -0
- package/dist/file-storage/index.js.map +1 -0
- package/dist/file-storage/types.d.ts +187 -0
- package/dist/file-storage/types.d.ts.map +1 -0
- package/dist/file-storage/types.js +21 -0
- package/dist/file-storage/types.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/ip-geo/continent-mapping.d.ts +31 -0
- package/dist/ip-geo/continent-mapping.d.ts.map +1 -0
- package/dist/ip-geo/continent-mapping.js +246 -0
- package/dist/ip-geo/continent-mapping.js.map +1 -0
- package/dist/ip-geo/index.d.ts +33 -0
- package/dist/ip-geo/index.d.ts.map +1 -0
- package/dist/ip-geo/index.js +41 -0
- package/dist/ip-geo/index.js.map +1 -0
- package/dist/ip-geo/ip-geo.module.d.ts +8 -0
- package/dist/ip-geo/ip-geo.module.d.ts.map +1 -0
- package/dist/ip-geo/ip-geo.module.js +34 -0
- package/dist/ip-geo/ip-geo.module.js.map +1 -0
- package/dist/ip-geo/ip-geo.service.d.ts +43 -0
- package/dist/ip-geo/ip-geo.service.d.ts.map +1 -0
- package/dist/ip-geo/ip-geo.service.js +153 -0
- package/dist/ip-geo/ip-geo.service.js.map +1 -0
- package/dist/ip-info/index.d.ts +7 -0
- package/dist/ip-info/index.d.ts.map +1 -0
- package/dist/ip-info/index.js +13 -0
- package/dist/ip-info/index.js.map +1 -0
- package/dist/ip-info/ip-info.client.d.ts +32 -0
- package/dist/ip-info/ip-info.client.d.ts.map +1 -0
- package/dist/ip-info/ip-info.client.js +73 -0
- package/dist/ip-info/ip-info.client.js.map +1 -0
- package/dist/ip-info/ip-info.module.d.ts +3 -0
- package/dist/ip-info/ip-info.module.d.ts.map +1 -0
- package/dist/ip-info/ip-info.module.js +45 -0
- package/dist/ip-info/ip-info.module.js.map +1 -0
- package/dist/ip-info/ip-info.service.d.ts +50 -0
- package/dist/ip-info/ip-info.service.d.ts.map +1 -0
- package/dist/ip-info/ip-info.service.js +177 -0
- package/dist/ip-info/ip-info.service.js.map +1 -0
- package/dist/ocr/index.d.ts +33 -0
- package/dist/ocr/index.d.ts.map +1 -0
- package/dist/ocr/index.js +53 -0
- package/dist/ocr/index.js.map +1 -0
- package/dist/ocr/ocr.module.d.ts +41 -0
- package/dist/ocr/ocr.module.d.ts.map +1 -0
- package/dist/ocr/ocr.module.js +61 -0
- package/dist/ocr/ocr.module.js.map +1 -0
- package/dist/ocr/ocr.service.d.ts +111 -0
- package/dist/ocr/ocr.service.d.ts.map +1 -0
- package/dist/ocr/ocr.service.js +214 -0
- package/dist/ocr/ocr.service.js.map +1 -0
- package/dist/sms/index.d.ts +5 -0
- package/dist/sms/index.d.ts.map +1 -0
- package/dist/sms/index.js +29 -0
- package/dist/sms/index.js.map +1 -0
- package/dist/sms/sms.factory.d.ts +140 -0
- package/dist/sms/sms.factory.d.ts.map +1 -0
- package/dist/sms/sms.factory.js +276 -0
- package/dist/sms/sms.factory.js.map +1 -0
- package/dist/sms/sms.module.d.ts +3 -0
- package/dist/sms/sms.module.d.ts.map +1 -0
- package/dist/sms/sms.module.js +38 -0
- package/dist/sms/sms.module.js.map +1 -0
- package/dist/sms/sms.service.d.ts +139 -0
- package/dist/sms/sms.service.d.ts.map +1 -0
- package/dist/sms/sms.service.js +278 -0
- package/dist/sms/sms.service.js.map +1 -0
- package/dist/sms/types.d.ts +204 -0
- package/dist/sms/types.d.ts.map +1 -0
- package/dist/sms/types.js +44 -0
- package/dist/sms/types.js.map +1 -0
- package/dist/streaming-asr/index.d.ts +45 -0
- package/dist/streaming-asr/index.d.ts.map +1 -0
- package/dist/streaming-asr/index.js +66 -0
- package/dist/streaming-asr/index.js.map +1 -0
- package/dist/streaming-asr/streaming-asr.module.d.ts +37 -0
- package/dist/streaming-asr/streaming-asr.module.d.ts.map +1 -0
- package/dist/streaming-asr/streaming-asr.module.js +59 -0
- package/dist/streaming-asr/streaming-asr.module.js.map +1 -0
- package/dist/streaming-asr/streaming-asr.service.d.ts +276 -0
- package/dist/streaming-asr/streaming-asr.service.d.ts.map +1 -0
- package/dist/streaming-asr/streaming-asr.service.js +1120 -0
- package/dist/streaming-asr/streaming-asr.service.js.map +1 -0
- package/dist/streaming-asr/types.d.ts +194 -0
- package/dist/streaming-asr/types.d.ts.map +1 -0
- package/dist/streaming-asr/types.js +8 -0
- package/dist/streaming-asr/types.js.map +1 -0
- package/dist/system-health/index.d.ts +7 -0
- package/dist/system-health/index.d.ts.map +1 -0
- package/dist/system-health/index.js +25 -0
- package/dist/system-health/index.js.map +1 -0
- package/dist/system-health/system-health.controller.d.ts +43 -0
- package/dist/system-health/system-health.controller.d.ts.map +1 -0
- package/dist/system-health/system-health.controller.js +86 -0
- package/dist/system-health/system-health.controller.js.map +1 -0
- package/dist/system-health/system-health.module.d.ts +3 -0
- package/dist/system-health/system-health.module.d.ts.map +1 -0
- package/dist/system-health/system-health.module.js +29 -0
- package/dist/system-health/system-health.module.js.map +1 -0
- package/dist/system-health/system-health.service.d.ts +14 -0
- package/dist/system-health/system-health.service.d.ts.map +1 -0
- package/dist/system-health/system-health.service.js +87 -0
- package/dist/system-health/system-health.service.js.map +1 -0
- package/dist/uploader/index.d.ts +3 -0
- package/dist/uploader/index.d.ts.map +1 -0
- package/dist/uploader/index.js +8 -0
- package/dist/uploader/index.js.map +1 -0
- package/dist/uploader/uploader.module.d.ts +3 -0
- package/dist/uploader/uploader.module.d.ts.map +1 -0
- package/dist/uploader/uploader.module.js +25 -0
- package/dist/uploader/uploader.module.js.map +1 -0
- package/dist/uploader/uploader.service.d.ts +86 -0
- package/dist/uploader/uploader.service.d.ts.map +1 -0
- package/dist/uploader/uploader.service.js +188 -0
- package/dist/uploader/uploader.service.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview 存储桶解析器
|
|
3
|
+
*
|
|
4
|
+
* 本文件实现了存储桶的智能解析功能,负责:
|
|
5
|
+
* - 根据 IP 地址进行区域感知的存储桶选择
|
|
6
|
+
* - 根据公开/私有属性选择合适的存储桶
|
|
7
|
+
* - 验证存储桶配置的有效性
|
|
8
|
+
*
|
|
9
|
+
* @module file-storage/bucket-resolver
|
|
10
|
+
*/
|
|
11
|
+
import { ConfigService } from '@nestjs/config';
|
|
12
|
+
import { Logger } from 'winston';
|
|
13
|
+
import { FileBucketVendor } from '@prisma/client';
|
|
14
|
+
import { PardxUploader } from '@dofe/infra-clients';
|
|
15
|
+
import { IpGeoService } from '@dofe/infra-shared-services';
|
|
16
|
+
import { BucketLookupOptions } from './types';
|
|
17
|
+
/**
|
|
18
|
+
* 存储桶解析结果
|
|
19
|
+
*
|
|
20
|
+
* @interface BucketResolveResult
|
|
21
|
+
*/
|
|
22
|
+
export interface BucketResolveResult {
|
|
23
|
+
/** 解析后的存储桶名称 */
|
|
24
|
+
bucket: string;
|
|
25
|
+
/** 解析后的存储供应商 */
|
|
26
|
+
vendor: FileBucketVendor;
|
|
27
|
+
/** 存储桶配置(如果找到) */
|
|
28
|
+
config?: PardxUploader.Config;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 存储桶解析器
|
|
32
|
+
*
|
|
33
|
+
* @description 负责根据各种条件智能解析存储桶配置。
|
|
34
|
+
*
|
|
35
|
+
* 解析优先级:
|
|
36
|
+
* 1. 如果明确指定了 bucket,验证并使用
|
|
37
|
+
* 2. 根据 IP 地址推断区域(大洲)
|
|
38
|
+
* 3. 根据 isPublic 属性过滤
|
|
39
|
+
* 4. 选择默认存储桶
|
|
40
|
+
*
|
|
41
|
+
* @class BucketResolver
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* @Injectable()
|
|
46
|
+
* class MyService {
|
|
47
|
+
* constructor(private readonly resolver: BucketResolver) {}
|
|
48
|
+
*
|
|
49
|
+
* async getBucket(ip: string) {
|
|
50
|
+
* const result = await this.resolver.resolve({
|
|
51
|
+
* ip,
|
|
52
|
+
* isPublic: false,
|
|
53
|
+
* });
|
|
54
|
+
* console.log('Resolved bucket:', result.bucket);
|
|
55
|
+
* }
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare class BucketResolver {
|
|
60
|
+
private readonly ipGeoService;
|
|
61
|
+
private readonly logger;
|
|
62
|
+
/**
|
|
63
|
+
* 存储桶配置列表
|
|
64
|
+
* @private
|
|
65
|
+
*/
|
|
66
|
+
private readonly bucketConfigs;
|
|
67
|
+
/**
|
|
68
|
+
* 应用配置
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
private readonly appConfig;
|
|
72
|
+
/**
|
|
73
|
+
* 默认存储供应商
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
private readonly defaultVendor;
|
|
77
|
+
/**
|
|
78
|
+
* 构造函数
|
|
79
|
+
*
|
|
80
|
+
* @param {ConfigService} configService - NestJS 配置服务
|
|
81
|
+
* @param {IpGeoService} ipGeoService - IP 地理位置服务(infra 层)
|
|
82
|
+
* @param {Logger} logger - Winston 日志记录器
|
|
83
|
+
*/
|
|
84
|
+
constructor(configService: ConfigService, ipGeoService: IpGeoService, logger: Logger);
|
|
85
|
+
/**
|
|
86
|
+
* 解析存储桶
|
|
87
|
+
*
|
|
88
|
+
* @description 根据提供的选项智能解析出最合适的存储桶配置。
|
|
89
|
+
*
|
|
90
|
+
* @param {BucketLookupOptions} options - 查询选项
|
|
91
|
+
* @returns {Promise<BucketResolveResult>} 解析结果
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // 根据 IP 解析
|
|
96
|
+
* const result = await resolver.resolve({ ip: '8.8.8.8' });
|
|
97
|
+
*
|
|
98
|
+
* // 指定公开存储桶
|
|
99
|
+
* const result = await resolver.resolve({ isPublic: true });
|
|
100
|
+
*
|
|
101
|
+
* // 明确指定存储桶
|
|
102
|
+
* const result = await resolver.resolve({
|
|
103
|
+
* vendor: 'oss',
|
|
104
|
+
* bucket: 'my-bucket',
|
|
105
|
+
* });
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
resolve(options?: BucketLookupOptions): Promise<BucketResolveResult>;
|
|
109
|
+
/**
|
|
110
|
+
* 解析默认存储桶
|
|
111
|
+
*
|
|
112
|
+
* @description 根据公开属性、IP 和区域设置选择默认存储桶。
|
|
113
|
+
*
|
|
114
|
+
* @param {boolean} [isPublic] - 是否公开存储桶
|
|
115
|
+
* @param {string} [ip] - 客户端 IP 地址
|
|
116
|
+
* @param {string} [locale] - 区域设置
|
|
117
|
+
* @returns {Promise<string>} 默认存储桶名称
|
|
118
|
+
*/
|
|
119
|
+
resolveDefaultBucket(isPublic?: boolean, ip?: string, locale?: string): Promise<string>;
|
|
120
|
+
/**
|
|
121
|
+
* 验证存储桶是否有效
|
|
122
|
+
*
|
|
123
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
124
|
+
* @param {string} bucket - 存储桶名称
|
|
125
|
+
* @returns {boolean} 是否有效
|
|
126
|
+
*/
|
|
127
|
+
validateBucket(vendor: FileBucketVendor, bucket: string): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* 根据存储桶名称获取供应商
|
|
130
|
+
*
|
|
131
|
+
* @param {string} bucket - 存储桶名称
|
|
132
|
+
* @returns {FileBucketVendor | undefined} 供应商或 undefined
|
|
133
|
+
*/
|
|
134
|
+
getVendorForBucket(bucket: string): FileBucketVendor | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* 查找存储桶配置
|
|
137
|
+
*
|
|
138
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
139
|
+
* @param {string} bucket - 存储桶名称
|
|
140
|
+
* @returns {PardxUploader.Config | undefined} 配置或 undefined
|
|
141
|
+
*/
|
|
142
|
+
findBucketConfig(vendor: FileBucketVendor, bucket: string): PardxUploader.Config | undefined;
|
|
143
|
+
/**
|
|
144
|
+
* 获取所有存储桶配置
|
|
145
|
+
*
|
|
146
|
+
* @returns {PardxUploader.Config[]} 配置列表
|
|
147
|
+
*/
|
|
148
|
+
getAllConfigs(): PardxUploader.Config[];
|
|
149
|
+
/**
|
|
150
|
+
* 根据属性过滤存储桶
|
|
151
|
+
*
|
|
152
|
+
* @param {Partial<PardxUploader.Config>} filter - 过滤条件
|
|
153
|
+
* @returns {PardxUploader.Config[]} 匹配的配置列表
|
|
154
|
+
*/
|
|
155
|
+
filterBuckets(filter: Partial<PardxUploader.Config>): PardxUploader.Config[];
|
|
156
|
+
/**
|
|
157
|
+
* 生成新的文件键
|
|
158
|
+
*
|
|
159
|
+
* @description 根据根路径和扩展名生成唯一的文件键。
|
|
160
|
+
*
|
|
161
|
+
* @param {string} root - 根路径
|
|
162
|
+
* @param {string} ext - 文件扩展名
|
|
163
|
+
* @param {string} [bucket] - 存储桶名称
|
|
164
|
+
* @returns {string} 生成的文件键
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* const key = resolver.generateFileKey('uploads', 'jpg', 'my-bucket');
|
|
169
|
+
* // 返回: "my-bucket/dev/uploads/1704067200000-abc123.jpg"
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
generateFileKey(root: string, ext: string, bucket?: string): string;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=bucket-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bucket-resolver.d.ts","sourceRoot":"","sources":["../../src/file-storage/bucket-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAI3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,gBAAgB;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,MAAM,EAAE,gBAAgB,CAAC;IACzB,kBAAkB;IAClB,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBACa,cAAc;IA4BvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IACI,OAAO,CAAC,QAAQ,CAAC,MAAM;IA5B1D;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;IAEvD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IAEtC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IAEjD;;;;;;OAMG;gBAED,aAAa,EAAE,aAAa,EACX,YAAY,EAAE,YAAY,EACO,MAAM,EAAE,MAAM;IAQlE;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,OAAO,CACX,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,mBAAmB,CAAC;IAgC/B;;;;;;;;;OASG;IACG,oBAAoB,CACxB,QAAQ,CAAC,EAAE,OAAO,EAClB,EAAE,CAAC,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAkClB;;;;;;OAMG;IACH,cAAc,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAQjE;;;;;OAKG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAKhE;;;;;;OAMG;IACH,gBAAgB,CACd,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,aAAa,CAAC,MAAM,GAAG,SAAS;IAQnC;;;;OAIG;IACH,aAAa,IAAI,aAAa,CAAC,MAAM,EAAE;IAIvC;;;;;OAKG;IACH,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE;IAW5E;;;;;;;;;;;;;;;OAeG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;CASpE"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview 存储桶解析器
|
|
4
|
+
*
|
|
5
|
+
* 本文件实现了存储桶的智能解析功能,负责:
|
|
6
|
+
* - 根据 IP 地址进行区域感知的存储桶选择
|
|
7
|
+
* - 根据公开/私有属性选择合适的存储桶
|
|
8
|
+
* - 验证存储桶配置的有效性
|
|
9
|
+
*
|
|
10
|
+
* @module file-storage/bucket-resolver
|
|
11
|
+
*/
|
|
12
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
13
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
15
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
16
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
17
|
+
};
|
|
18
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
19
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
20
|
+
};
|
|
21
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
22
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
23
|
+
};
|
|
24
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
25
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.BucketResolver = void 0;
|
|
29
|
+
const common_1 = require("@nestjs/common");
|
|
30
|
+
const config_1 = require("@nestjs/config");
|
|
31
|
+
const nest_winston_1 = require("nest-winston");
|
|
32
|
+
const winston_1 = require("winston");
|
|
33
|
+
const infra_shared_services_1 = require("@dofe/infra-shared-services");
|
|
34
|
+
const array_util_1 = __importDefault(require("@dofe/infra-utils/array.util"));
|
|
35
|
+
const environment_util_1 = __importDefault(require("@dofe/infra-utils/environment.util"));
|
|
36
|
+
/**
|
|
37
|
+
* 存储桶解析器
|
|
38
|
+
*
|
|
39
|
+
* @description 负责根据各种条件智能解析存储桶配置。
|
|
40
|
+
*
|
|
41
|
+
* 解析优先级:
|
|
42
|
+
* 1. 如果明确指定了 bucket,验证并使用
|
|
43
|
+
* 2. 根据 IP 地址推断区域(大洲)
|
|
44
|
+
* 3. 根据 isPublic 属性过滤
|
|
45
|
+
* 4. 选择默认存储桶
|
|
46
|
+
*
|
|
47
|
+
* @class BucketResolver
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* @Injectable()
|
|
52
|
+
* class MyService {
|
|
53
|
+
* constructor(private readonly resolver: BucketResolver) {}
|
|
54
|
+
*
|
|
55
|
+
* async getBucket(ip: string) {
|
|
56
|
+
* const result = await this.resolver.resolve({
|
|
57
|
+
* ip,
|
|
58
|
+
* isPublic: false,
|
|
59
|
+
* });
|
|
60
|
+
* console.log('Resolved bucket:', result.bucket);
|
|
61
|
+
* }
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
let BucketResolver = class BucketResolver {
|
|
66
|
+
ipGeoService;
|
|
67
|
+
logger;
|
|
68
|
+
/**
|
|
69
|
+
* 存储桶配置列表
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
bucketConfigs;
|
|
73
|
+
/**
|
|
74
|
+
* 应用配置
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
appConfig;
|
|
78
|
+
/**
|
|
79
|
+
* 默认存储供应商
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
defaultVendor;
|
|
83
|
+
/**
|
|
84
|
+
* 构造函数
|
|
85
|
+
*
|
|
86
|
+
* @param {ConfigService} configService - NestJS 配置服务
|
|
87
|
+
* @param {IpGeoService} ipGeoService - IP 地理位置服务(infra 层)
|
|
88
|
+
* @param {Logger} logger - Winston 日志记录器
|
|
89
|
+
*/
|
|
90
|
+
constructor(configService, ipGeoService, logger) {
|
|
91
|
+
this.ipGeoService = ipGeoService;
|
|
92
|
+
this.logger = logger;
|
|
93
|
+
this.bucketConfigs =
|
|
94
|
+
configService.getOrThrow('buckets');
|
|
95
|
+
this.appConfig = configService.getOrThrow('app');
|
|
96
|
+
this.defaultVendor = this.appConfig.defaultVendor;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 解析存储桶
|
|
100
|
+
*
|
|
101
|
+
* @description 根据提供的选项智能解析出最合适的存储桶配置。
|
|
102
|
+
*
|
|
103
|
+
* @param {BucketLookupOptions} options - 查询选项
|
|
104
|
+
* @returns {Promise<BucketResolveResult>} 解析结果
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* // 根据 IP 解析
|
|
109
|
+
* const result = await resolver.resolve({ ip: '8.8.8.8' });
|
|
110
|
+
*
|
|
111
|
+
* // 指定公开存储桶
|
|
112
|
+
* const result = await resolver.resolve({ isPublic: true });
|
|
113
|
+
*
|
|
114
|
+
* // 明确指定存储桶
|
|
115
|
+
* const result = await resolver.resolve({
|
|
116
|
+
* vendor: 'oss',
|
|
117
|
+
* bucket: 'my-bucket',
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
async resolve(options = {}) {
|
|
122
|
+
const { bucket, ip, isPublic, locale, vendor } = options;
|
|
123
|
+
// 确定供应商
|
|
124
|
+
const finalVendor = vendor ?? this.defaultVendor;
|
|
125
|
+
// 如果明确指定了 bucket,验证并返回
|
|
126
|
+
if (bucket) {
|
|
127
|
+
if (this.validateBucket(finalVendor, bucket)) {
|
|
128
|
+
const config = this.findBucketConfig(finalVendor, bucket);
|
|
129
|
+
return { bucket, vendor: finalVendor, config };
|
|
130
|
+
}
|
|
131
|
+
// bucket 无效,继续使用默认逻辑
|
|
132
|
+
this.logger.warn('Invalid bucket specified, falling back to default', {
|
|
133
|
+
bucket,
|
|
134
|
+
vendor: finalVendor,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
// 解析默认存储桶
|
|
138
|
+
const defaultBucket = await this.resolveDefaultBucket(isPublic, ip, locale);
|
|
139
|
+
const resolvedVendor = this.getVendorForBucket(defaultBucket) ?? finalVendor;
|
|
140
|
+
const config = this.findBucketConfig(resolvedVendor, defaultBucket);
|
|
141
|
+
return {
|
|
142
|
+
bucket: defaultBucket,
|
|
143
|
+
vendor: resolvedVendor,
|
|
144
|
+
config,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* 解析默认存储桶
|
|
149
|
+
*
|
|
150
|
+
* @description 根据公开属性、IP 和区域设置选择默认存储桶。
|
|
151
|
+
*
|
|
152
|
+
* @param {boolean} [isPublic] - 是否公开存储桶
|
|
153
|
+
* @param {string} [ip] - 客户端 IP 地址
|
|
154
|
+
* @param {string} [locale] - 区域设置
|
|
155
|
+
* @returns {Promise<string>} 默认存储桶名称
|
|
156
|
+
*/
|
|
157
|
+
async resolveDefaultBucket(isPublic, ip, locale) {
|
|
158
|
+
// 确定区域
|
|
159
|
+
let zone = environment_util_1.default.getBaseZone();
|
|
160
|
+
if (ip) {
|
|
161
|
+
const continent = await this.ipGeoService.getContinent(ip);
|
|
162
|
+
zone = continent ?? zone;
|
|
163
|
+
}
|
|
164
|
+
locale = locale ?? zone;
|
|
165
|
+
// 确定公开属性
|
|
166
|
+
const finalIsPublic = isPublic ?? this.appConfig.defaultBucketPublic;
|
|
167
|
+
// 过滤存储桶
|
|
168
|
+
let buckets = array_util_1.default.filter(this.bucketConfigs, { isPublic: finalIsPublic }, this.appConfig.defaultBucketPublic);
|
|
169
|
+
buckets = array_util_1.default.filter(buckets, { locale: locale }, zone);
|
|
170
|
+
// 查找默认存储桶
|
|
171
|
+
const bucketConfig = array_util_1.default.findOne(buckets, { isDefault: true }, false);
|
|
172
|
+
if (bucketConfig?.bucket) {
|
|
173
|
+
return bucketConfig.bucket;
|
|
174
|
+
}
|
|
175
|
+
// 回退到区域配置的默认存储桶
|
|
176
|
+
const zoneConfig = this.appConfig.zones?.find((z) => z.zone === zone);
|
|
177
|
+
return finalIsPublic
|
|
178
|
+
? (zoneConfig?.defaultPublicBucket ?? '')
|
|
179
|
+
: (zoneConfig?.defaultPrivateBucket ?? '');
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* 验证存储桶是否有效
|
|
183
|
+
*
|
|
184
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
185
|
+
* @param {string} bucket - 存储桶名称
|
|
186
|
+
* @returns {boolean} 是否有效
|
|
187
|
+
*/
|
|
188
|
+
validateBucket(vendor, bucket) {
|
|
189
|
+
return this.bucketConfigs.some((config) => config.bucket === bucket &&
|
|
190
|
+
(config.vendor ?? this.defaultVendor) === vendor);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* 根据存储桶名称获取供应商
|
|
194
|
+
*
|
|
195
|
+
* @param {string} bucket - 存储桶名称
|
|
196
|
+
* @returns {FileBucketVendor | undefined} 供应商或 undefined
|
|
197
|
+
*/
|
|
198
|
+
getVendorForBucket(bucket) {
|
|
199
|
+
const config = this.bucketConfigs.find((c) => c.bucket === bucket);
|
|
200
|
+
return config?.vendor ?? this.defaultVendor;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* 查找存储桶配置
|
|
204
|
+
*
|
|
205
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
206
|
+
* @param {string} bucket - 存储桶名称
|
|
207
|
+
* @returns {PardxUploader.Config | undefined} 配置或 undefined
|
|
208
|
+
*/
|
|
209
|
+
findBucketConfig(vendor, bucket) {
|
|
210
|
+
return this.bucketConfigs.find((config) => config.bucket === bucket &&
|
|
211
|
+
(config.vendor ?? this.defaultVendor) === vendor);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* 获取所有存储桶配置
|
|
215
|
+
*
|
|
216
|
+
* @returns {PardxUploader.Config[]} 配置列表
|
|
217
|
+
*/
|
|
218
|
+
getAllConfigs() {
|
|
219
|
+
return [...this.bucketConfigs];
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 根据属性过滤存储桶
|
|
223
|
+
*
|
|
224
|
+
* @param {Partial<PardxUploader.Config>} filter - 过滤条件
|
|
225
|
+
* @returns {PardxUploader.Config[]} 匹配的配置列表
|
|
226
|
+
*/
|
|
227
|
+
filterBuckets(filter) {
|
|
228
|
+
return this.bucketConfigs.filter((config) => {
|
|
229
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
230
|
+
if (config[key] !== value) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* 生成新的文件键
|
|
239
|
+
*
|
|
240
|
+
* @description 根据根路径和扩展名生成唯一的文件键。
|
|
241
|
+
*
|
|
242
|
+
* @param {string} root - 根路径
|
|
243
|
+
* @param {string} ext - 文件扩展名
|
|
244
|
+
* @param {string} [bucket] - 存储桶名称
|
|
245
|
+
* @returns {string} 生成的文件键
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```typescript
|
|
249
|
+
* const key = resolver.generateFileKey('uploads', 'jpg', 'my-bucket');
|
|
250
|
+
* // 返回: "my-bucket/dev/uploads/1704067200000-abc123.jpg"
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
generateFileKey(root, ext, bucket) {
|
|
254
|
+
const prefix = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
|
|
255
|
+
const env = environment_util_1.default.getEnv();
|
|
256
|
+
if (bucket) {
|
|
257
|
+
return `${bucket}/${env}/${root}/${prefix}.${ext}`;
|
|
258
|
+
}
|
|
259
|
+
return `${env}/${root}/${prefix}.${ext}`;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
exports.BucketResolver = BucketResolver;
|
|
263
|
+
exports.BucketResolver = BucketResolver = __decorate([
|
|
264
|
+
(0, common_1.Injectable)(),
|
|
265
|
+
__param(2, (0, common_1.Inject)(nest_winston_1.WINSTON_MODULE_PROVIDER)),
|
|
266
|
+
__metadata("design:paramtypes", [config_1.ConfigService,
|
|
267
|
+
infra_shared_services_1.IpGeoService,
|
|
268
|
+
winston_1.Logger])
|
|
269
|
+
], BucketResolver);
|
|
270
|
+
//# sourceMappingURL=bucket-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bucket-resolver.js","sourceRoot":"","sources":["../../src/file-storage/bucket-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview 文件存储客户端工厂
|
|
3
|
+
*
|
|
4
|
+
* 本文件实现了文件存储客户端的工厂模式,负责:
|
|
5
|
+
* - 根据存储供应商类型创建对应的客户端实例
|
|
6
|
+
* - 管理客户端实例的生命周期(单例模式)
|
|
7
|
+
* - 提供统一的客户端获取接口
|
|
8
|
+
*
|
|
9
|
+
* @module file-storage/factory
|
|
10
|
+
*/
|
|
11
|
+
import { ConfigService } from '@nestjs/config';
|
|
12
|
+
import { HttpService } from '@nestjs/axios';
|
|
13
|
+
import { Logger } from 'winston';
|
|
14
|
+
import { FileBucketVendor } from '@prisma/client';
|
|
15
|
+
import { FileStorageInterface, PardxUploader } from '@dofe/infra-clients';
|
|
16
|
+
import { RedisService } from '@dofe/infra-redis';
|
|
17
|
+
import { AppConfig } from '@dofe/infra-common';
|
|
18
|
+
import { StorageClientKey } from './types';
|
|
19
|
+
/**
|
|
20
|
+
* 文件存储客户端工厂
|
|
21
|
+
*
|
|
22
|
+
* @description 使用工厂模式管理不同存储供应商的客户端实例。
|
|
23
|
+
*
|
|
24
|
+
* 主要职责:
|
|
25
|
+
* - 根据 vendor 和 bucket 创建对应的客户端实例
|
|
26
|
+
* - 使用单例模式缓存客户端实例,避免重复创建
|
|
27
|
+
* - 统一管理存储配置和凭证
|
|
28
|
+
*
|
|
29
|
+
* 支持的存储供应商:
|
|
30
|
+
* - 's3': AWS S3 兼容存储
|
|
31
|
+
* - 'oss': 阿里云 OSS
|
|
32
|
+
* - 'tos': 火山引擎 TOS
|
|
33
|
+
* - 'us3': UCloud US3
|
|
34
|
+
* - 'gcs': Google Cloud Storage
|
|
35
|
+
* - 'qiniu': 七牛云存储
|
|
36
|
+
*
|
|
37
|
+
* @class FileStorageClientFactory
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* @Injectable()
|
|
42
|
+
* class MyService {
|
|
43
|
+
* constructor(private readonly factory: FileStorageClientFactory) {}
|
|
44
|
+
*
|
|
45
|
+
* async uploadFile(vendor: FileBucketVendor, bucket: string, file: Buffer) {
|
|
46
|
+
* const client = this.factory.getClient(vendor, bucket);
|
|
47
|
+
* await client.fileUploader(file, { key: 'path/to/file', bucket });
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare class FileStorageClientFactory {
|
|
53
|
+
private readonly redis;
|
|
54
|
+
private readonly httpService;
|
|
55
|
+
private readonly logger;
|
|
56
|
+
/**
|
|
57
|
+
* 客户端实例缓存
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
private readonly clients;
|
|
61
|
+
/**
|
|
62
|
+
* 存储桶配置列表
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
private readonly bucketConfigs;
|
|
66
|
+
/**
|
|
67
|
+
* 存储凭证配置
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
private readonly storageCredentials;
|
|
71
|
+
/**
|
|
72
|
+
* 应用配置
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
private readonly appConfig;
|
|
76
|
+
/**
|
|
77
|
+
* 默认存储供应商
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
private readonly defaultVendor;
|
|
81
|
+
/**
|
|
82
|
+
* 构造函数
|
|
83
|
+
*
|
|
84
|
+
* @param {ConfigService} configService - NestJS 配置服务
|
|
85
|
+
* @param {RedisService} redis - Redis 服务
|
|
86
|
+
* @param {HttpService} httpService - HTTP 服务
|
|
87
|
+
* @param {Logger} logger - Winston 日志记录器
|
|
88
|
+
*/
|
|
89
|
+
constructor(configService: ConfigService, redis: RedisService, httpService: HttpService, logger: Logger);
|
|
90
|
+
/**
|
|
91
|
+
* 预初始化所有配置的存储客户端
|
|
92
|
+
*
|
|
93
|
+
* @private
|
|
94
|
+
*/
|
|
95
|
+
private initializeClients;
|
|
96
|
+
/**
|
|
97
|
+
* 创建存储客户端实例
|
|
98
|
+
*
|
|
99
|
+
* @private
|
|
100
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
101
|
+
* @param {PardxUploader.Config} config - 存储桶配置
|
|
102
|
+
* @returns {FileStorageInterface} 客户端实例
|
|
103
|
+
* @throws {Error} 不支持的供应商类型时抛出异常
|
|
104
|
+
*/
|
|
105
|
+
private createClient;
|
|
106
|
+
/**
|
|
107
|
+
* 获取存储客户端
|
|
108
|
+
*
|
|
109
|
+
* @description 根据供应商和存储桶获取对应的客户端实例。
|
|
110
|
+
* 如果客户端不存在,将返回 undefined。
|
|
111
|
+
*
|
|
112
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
113
|
+
* @param {string} bucket - 存储桶名称
|
|
114
|
+
* @returns {FileStorageInterface | undefined} 客户端实例或 undefined
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const client = factory.getClient('oss', 'my-bucket');
|
|
119
|
+
* if (client) {
|
|
120
|
+
* await client.uploadFile('/path/to/file', 'key', 'my-bucket');
|
|
121
|
+
* }
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
getClient(vendor: FileBucketVendor, bucket: string): FileStorageInterface | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* 获取存储客户端(必须存在)
|
|
127
|
+
*
|
|
128
|
+
* @description 获取客户端实例,如果不存在则抛出异常。
|
|
129
|
+
*
|
|
130
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
131
|
+
* @param {string} bucket - 存储桶名称
|
|
132
|
+
* @returns {FileStorageInterface} 客户端实例
|
|
133
|
+
* @throws {Error} 客户端不存在时抛出异常
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const client = factory.getClientOrThrow('oss', 'my-bucket');
|
|
138
|
+
* await client.uploadFile('/path/to/file', 'key', 'my-bucket');
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
getClientOrThrow(vendor: FileBucketVendor, bucket: string): FileStorageInterface;
|
|
142
|
+
/**
|
|
143
|
+
* 检查客户端是否存在
|
|
144
|
+
*
|
|
145
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
146
|
+
* @param {string} bucket - 存储桶名称
|
|
147
|
+
* @returns {boolean} 是否存在
|
|
148
|
+
*/
|
|
149
|
+
hasClient(vendor: FileBucketVendor, bucket: string): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* 获取存储桶配置
|
|
152
|
+
*
|
|
153
|
+
* @param {FileBucketVendor} vendor - 存储供应商
|
|
154
|
+
* @param {string} bucket - 存储桶名称
|
|
155
|
+
* @returns {PardxUploader.Config | undefined} 存储桶配置
|
|
156
|
+
*/
|
|
157
|
+
getBucketConfig(vendor: FileBucketVendor, bucket: string): PardxUploader.Config | undefined;
|
|
158
|
+
/**
|
|
159
|
+
* 获取所有存储桶配置
|
|
160
|
+
*
|
|
161
|
+
* @returns {PardxUploader.Config[]} 存储桶配置列表
|
|
162
|
+
*/
|
|
163
|
+
getAllBucketConfigs(): PardxUploader.Config[];
|
|
164
|
+
/**
|
|
165
|
+
* 获取默认存储供应商
|
|
166
|
+
*
|
|
167
|
+
* @returns {FileBucketVendor} 默认供应商
|
|
168
|
+
*/
|
|
169
|
+
getDefaultVendor(): FileBucketVendor;
|
|
170
|
+
/**
|
|
171
|
+
* 获取应用配置
|
|
172
|
+
*
|
|
173
|
+
* @returns {AppConfig} 应用配置
|
|
174
|
+
*/
|
|
175
|
+
getAppConfig(): AppConfig;
|
|
176
|
+
/**
|
|
177
|
+
* 获取所有已初始化的客户端键
|
|
178
|
+
*
|
|
179
|
+
* @returns {StorageClientKey[]} 客户端键列表
|
|
180
|
+
*/
|
|
181
|
+
getClientKeys(): StorageClientKey[];
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=file-storage.factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-storage.factory.d.ts","sourceRoot":"","sources":["../../src/file-storage/file-storage.factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EACL,oBAAoB,EAMpB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,SAAS,EAA4B,MAAM,oBAAoB,CAAC;AAGzE,OAAO,EACL,gBAAgB,EAGjB,MAAM,SAAS,CAAC;AAiCjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBACa,wBAAwB;IA0CjC,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IACK,OAAO,CAAC,QAAQ,CAAC,MAAM;IA3C1D;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CACZ;IAEZ;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;IAEvD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAwB;IAE3D;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IAEtC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IAEjD;;;;;;;OAOG;gBAED,aAAa,EAAE,aAAa,EACX,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,WAAW,EACS,MAAM,EAAE,MAAM;IAclE;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IA8BpB;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,CACP,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,oBAAoB,GAAG,SAAS;IAKnC;;;;;;;;;;;;;;;OAeG;IACH,gBAAgB,CACd,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,oBAAoB;IAYvB;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAK5D;;;;;;OAMG;IACH,eAAe,CACb,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,aAAa,CAAC,MAAM,GAAG,SAAS;IAQnC;;;;OAIG;IACH,mBAAmB,IAAI,aAAa,CAAC,MAAM,EAAE;IAI7C;;;;OAIG;IACH,gBAAgB,IAAI,gBAAgB;IAIpC;;;;OAIG;IACH,YAAY,IAAI,SAAS;IAIzB;;;;OAIG;IACH,aAAa,IAAI,gBAAgB,EAAE;CAGpC"}
|