@be-link/cos 1.12.0-beta.2 → 1.12.0-beta.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.
package/bin/cos.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { staticUploadToCos } = require('./upload');
5
+ function main() {
6
+ staticUploadToCos();
7
+ }
8
+
9
+ main();
package/bin/upload.js ADDED
@@ -0,0 +1,359 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const https = require('https');
7
+ const COS = require('cos-nodejs-sdk-v5');
8
+ const { getBucketConfig, getRegion } = require('../dist/index.cjs.js');
9
+
10
+ // 解析命令行参数
11
+ const argv = process.argv.slice(2);
12
+ let mode = 'development';
13
+ let projectName = undefined;
14
+
15
+ // 支持两种方式传递参数:
16
+ // 方式1: node_modules/.bin/cos production --project be-link-live-h5
17
+ // 方式2: node_modules/.bin/cos production -p be-link-live-h5
18
+ // 方式3: node_modules/.bin/cos production (使用默认配置)
19
+ for (let i = 0; i < argv.length; i++) {
20
+ const arg = argv[i];
21
+ if (arg === '--project' || arg === '-p') {
22
+ projectName = argv[i + 1];
23
+ i++; // 跳过下一个参数(项目名称)
24
+ } else if (arg === '--mode' || arg === '-m') {
25
+ mode = argv[i + 1];
26
+ i++;
27
+ } else if (!arg.startsWith('-') && ['development', 'test', 'production'].includes(arg)) {
28
+ // 兼容旧版本:第一个参数是 mode
29
+ mode = arg;
30
+ }
31
+ }
32
+
33
+ console.log('🚀 上传模式:', mode);
34
+ if (projectName) {
35
+ console.log('📦 项目标识:', projectName);
36
+ }
37
+
38
+ // 获取项目名称(用于远程路径)
39
+ const baseUrl = mode === 'production' ? 'project/prod/' : 'project/dev/';
40
+ const packageUrl = path.resolve(process.cwd(), './package.json');
41
+ const projectPackage = fs.readFileSync(packageUrl, { encoding: 'utf-8' });
42
+ const packageProjectName = JSON.parse(projectPackage).name;
43
+ const projectRemoteUrl = baseUrl + packageProjectName;
44
+
45
+ // 获取桶配置和地域
46
+ const bucketConfig = getBucketConfig(mode, projectName);
47
+ const region = getRegion(bucketConfig);
48
+
49
+ // 构建参数输出的地址
50
+ const distDirUrl = process.cwd() + '/dist';
51
+
52
+ // COS 实例(延迟初始化)
53
+ let cos = null;
54
+
55
+ /**
56
+ * 通过云函数获取临时密钥(参照浏览器端实现)
57
+ */
58
+ function getTempCredentials(mode) {
59
+ return new Promise((resolve, reject) => {
60
+ const url =
61
+ mode === 'production'
62
+ ? 'https://shield-60660-10-1304510571.sh.run.tcloudbase.com/config/get-cos-temp-secret'
63
+ : 'https://shield-74680-5-1304510571.sh.run.tcloudbase.com/config/get-cos-temp-secret';
64
+
65
+ const urlObj = new URL(url);
66
+ const options = {
67
+ hostname: urlObj.hostname,
68
+ path: urlObj.pathname,
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ },
73
+ };
74
+
75
+ const req = https.request(options, (res) => {
76
+ let data = '';
77
+
78
+ res.on('data', (chunk) => {
79
+ data += chunk;
80
+ });
81
+
82
+ res.on('end', () => {
83
+ try {
84
+ const result = JSON.parse(data);
85
+ const credentials = result?.data?.credentials;
86
+
87
+ if (!credentials) {
88
+ reject(new Error('获取临时密钥失败:返回数据格式错误'));
89
+ return;
90
+ }
91
+
92
+ resolve({
93
+ TmpSecretId: credentials.tmpSecretId,
94
+ TmpSecretKey: credentials.tmpSecretKey,
95
+ SecurityToken: credentials.sessionToken,
96
+ StartTime: result.data.startTime,
97
+ ExpiredTime: result.data.expiredTime,
98
+ });
99
+ } catch (err) {
100
+ reject(new Error('解析临时密钥响应失败:' + err.message));
101
+ }
102
+ });
103
+ });
104
+
105
+ req.on('error', (err) => {
106
+ reject(new Error('请求临时密钥失败:' + err.message));
107
+ });
108
+
109
+ req.end();
110
+ });
111
+ }
112
+
113
+ /**
114
+ * 初始化 COS 实例
115
+ * 优先使用云函数临时密钥,降级到环境变量
116
+ */
117
+ async function initCOS() {
118
+ if (cos) {
119
+ return cos;
120
+ }
121
+
122
+ try {
123
+ // 方式1:尝试通过云函数获取临时密钥(推荐)
124
+ console.log('🔐 正在获取临时密钥...');
125
+ const credentials = await getTempCredentials(mode || 'development');
126
+ console.log('✅ 临时密钥获取成功,有效期至:', new Date(credentials.ExpiredTime * 1000).toLocaleString());
127
+
128
+ cos = new COS({
129
+ getAuthorization: (options, callback) => {
130
+ callback({
131
+ TmpSecretId: credentials.TmpSecretId,
132
+ TmpSecretKey: credentials.TmpSecretKey,
133
+ SecurityToken: credentials.SecurityToken,
134
+ StartTime: credentials.StartTime,
135
+ ExpiredTime: credentials.ExpiredTime,
136
+ });
137
+ },
138
+ });
139
+
140
+ return cos;
141
+ } catch (err) {
142
+ // 方式2:降级到环境变量(用于本地开发或特殊情况)
143
+ console.warn('⚠️ 临时密钥获取失败:', err.message);
144
+ console.warn('⚠️ 尝试使用环境变量 COS_SECRET_ID 和 COS_SECRET_KEY');
145
+
146
+ const secretId = process.env.COS_SECRET_ID;
147
+ const secretKey = process.env.COS_SECRET_KEY;
148
+
149
+ if (!secretId || !secretKey) {
150
+ console.error('❌ 错误:未找到 COS 密钥配置');
151
+ console.error(' 请设置环境变量:');
152
+ console.error(' - COS_SECRET_ID');
153
+ console.error(' - COS_SECRET_KEY');
154
+ process.exit(1);
155
+ }
156
+
157
+ console.log('✅ 使用环境变量中的密钥');
158
+ cos = new COS({
159
+ SecretId: secretId,
160
+ SecretKey: secretKey,
161
+ });
162
+
163
+ return cos;
164
+ }
165
+ }
166
+
167
+ /**
168
+ * 上传单个文件(支持 Promise 和重试)
169
+ */
170
+ function upload(url, filename, retryCount = 0, maxRetries = 3) {
171
+ return new Promise((resolve, reject) => {
172
+ if (!url || !filename) {
173
+ reject(new Error('上传参数错误:url 和 filename 不能为空'));
174
+ return;
175
+ }
176
+
177
+ cos.putObject(
178
+ {
179
+ Bucket: bucketConfig.name,
180
+ Region: region,
181
+ Key: projectRemoteUrl + filename /* 必须 */,
182
+ StorageClass: 'STANDARD',
183
+ ACL: 'public-read', // 设置为公开读,确保文件可访问
184
+ Body: fs.createReadStream(url), // 上传文件对象
185
+ // onProgress: function (progressData) {
186
+ // // 可选:显示上传进度
187
+ // // console.log('上传进度:', JSON.stringify(progressData))
188
+ // },
189
+ },
190
+ function (err, data) {
191
+ if (err) {
192
+ // 重试逻辑
193
+ if (retryCount < maxRetries) {
194
+ console.log(` ⚠️ 上传失败,正在重试 (${retryCount + 1}/${maxRetries}): ${filename}`);
195
+ setTimeout(() => {
196
+ upload(url, filename, retryCount + 1, maxRetries)
197
+ .then(resolve)
198
+ .catch(reject);
199
+ }, 1000 * (retryCount + 1)); // 递增延迟
200
+ } else {
201
+ console.error(` ❌ 上传失败(已重试 ${maxRetries} 次): ${filename}`, err.message);
202
+ reject(err);
203
+ }
204
+ } else {
205
+ console.log(` ✅ 上传成功: ${filename}`);
206
+ resolve(data);
207
+ }
208
+ },
209
+ );
210
+ });
211
+ }
212
+
213
+ function getAllFiles(directoryPath) {
214
+ const files = fs.readdirSync(directoryPath, { withFileTypes: true });
215
+ const fileNamesAndPaths = [];
216
+
217
+ files.forEach((file) => {
218
+ const filePath = path.join(directoryPath, file.name);
219
+
220
+ if (file.isFile()) {
221
+ fileNamesAndPaths.push({
222
+ fileName: file.name,
223
+ filePath: filePath,
224
+ });
225
+ } else if (file.isDirectory()) {
226
+ const subDirectoryFiles = getAllFiles(filePath);
227
+ fileNamesAndPaths.push(...subDirectoryFiles);
228
+ }
229
+ });
230
+
231
+ return fileNamesAndPaths;
232
+ }
233
+
234
+ /**
235
+ * 删除远程项目目录
236
+ * 注意:deleteObject 只能删除单个文件,不能删除目录
237
+ * 如需删除整个目录,需要先列出所有文件再逐个删除
238
+ */
239
+ function deleteProject() {
240
+ return new Promise((resolve, reject) => {
241
+ // 先获取目录下的所有文件
242
+ cos.getBucket(
243
+ {
244
+ Bucket: bucketConfig.name,
245
+ Region: region,
246
+ Prefix: projectRemoteUrl,
247
+ },
248
+ function (err, data) {
249
+ if (err) {
250
+ console.log('⚠️ 获取远程文件列表失败(可能目录不存在,继续上传)');
251
+ resolve([]); // 目录不存在时继续执行
252
+ return;
253
+ }
254
+
255
+ const files = data.Contents || [];
256
+ if (files.length === 0) {
257
+ console.log('📁 远程目录为空,无需删除');
258
+ resolve([]);
259
+ return;
260
+ }
261
+
262
+ console.log(`🗑️ 正在删除 ${files.length} 个旧文件...`);
263
+
264
+ // 批量删除文件
265
+ cos.deleteMultipleObject(
266
+ {
267
+ Bucket: bucketConfig.name,
268
+ Region: region,
269
+ Objects: files.map((file) => ({ Key: file.Key })),
270
+ },
271
+ function (err, data) {
272
+ if (err) {
273
+ console.error('❌ 删除失败:', err.message);
274
+ reject(err);
275
+ } else {
276
+ console.log(`✅ 成功删除 ${files.length} 个旧文件`);
277
+ resolve(data);
278
+ }
279
+ },
280
+ );
281
+ },
282
+ );
283
+ });
284
+ }
285
+
286
+ /**
287
+ * 主函数:上传静态资源到 COS
288
+ */
289
+ async function staticUploadToCos() {
290
+ const startTime = Date.now();
291
+ console.log('\n' + '='.repeat(60));
292
+ console.log('📦 开始上传静态资源到 COS');
293
+ console.log('='.repeat(60));
294
+ console.log(`📂 项目名称: ${packageProjectName}`);
295
+ console.log(`🌍 环境模式: ${mode}`);
296
+ console.log(`🪣 存储桶: ${bucketConfig.name} (${region})`);
297
+ if (projectName) {
298
+ console.log(`🎯 项目标识: ${projectName}`);
299
+ }
300
+ console.log(`📍 远程路径: ${projectRemoteUrl}`);
301
+ console.log(`📁 本地目录: ${distDirUrl}`);
302
+ console.log('='.repeat(60) + '\n');
303
+
304
+ try {
305
+ // 1. 初始化 COS
306
+ await initCOS();
307
+
308
+ // 2. 检查本地文件
309
+ if (!fs.existsSync(distDirUrl)) {
310
+ throw new Error(`本地目录不存在: ${distDirUrl}`);
311
+ }
312
+
313
+ const files = getAllFiles(distDirUrl);
314
+ if (files.length === 0) {
315
+ console.log('⚠️ 警告:没有找到需要上传的文件');
316
+ return;
317
+ }
318
+
319
+ console.log(`📋 找到 ${files.length} 个文件待上传\n`);
320
+
321
+ // 3. 删除远程旧文件
322
+ await deleteProject();
323
+
324
+ // 4. 上传所有文件
325
+ console.log('\n📤 开始上传文件...\n');
326
+ const uploadPromises = files.map((file) => {
327
+ const filename = file.filePath.replace(distDirUrl, '');
328
+ return upload(file.filePath, filename);
329
+ });
330
+
331
+ // 等待所有文件上传完成
332
+ const results = await Promise.all(uploadPromises);
333
+
334
+ // 5. 输出结果
335
+ const endTime = Date.now();
336
+ const duration = ((endTime - startTime) / 1000).toFixed(2);
337
+
338
+ console.log('\n' + '='.repeat(60));
339
+ console.log('🎉 上传完成!');
340
+ console.log('='.repeat(60));
341
+ console.log(`✅ 成功上传: ${results.length} 个文件`);
342
+ console.log(`⏱️ 耗时: ${duration} 秒`);
343
+ console.log(`🔗 访问地址: https://${bucketConfig.host}/${projectRemoteUrl}`);
344
+ console.log('='.repeat(60) + '\n');
345
+
346
+ process.exit(0);
347
+ } catch (err) {
348
+ console.error('\n' + '='.repeat(60));
349
+ console.error('💥 上传失败!');
350
+ console.error('='.repeat(60));
351
+ console.error('❌ 错误信息:', err.message);
352
+ console.error('='.repeat(60) + '\n');
353
+ process.exit(1);
354
+ }
355
+ }
356
+
357
+ module.exports = {
358
+ staticUploadToCos,
359
+ };
@@ -27,6 +27,8 @@ export declare class BeLinkCOS {
27
27
  headers: Record<string, any>;
28
28
  /** 当前环境模式 */
29
29
  mode: EnvMode | null;
30
+ /** 项目名称 */
31
+ projectName: string | undefined;
30
32
  /** 是否限制临时密钥的使用范围 */
31
33
  private scopeLimit;
32
34
  /** 生命周期状态 */
@@ -85,11 +87,16 @@ export declare class BeLinkCOS {
85
87
  * 验证配置
86
88
  */
87
89
  protected validateConfig(config: InitConfig): boolean;
90
+ /**
91
+ * 获取当前使用的存储桶配置
92
+ */
93
+ private getCurrentBucketConfig;
88
94
  /**
89
95
  * 获取配置
90
96
  */
91
97
  getConfig(): {
92
98
  mode: EnvMode | null;
99
+ projectName: string | undefined;
93
100
  headers: Record<string, any>;
94
101
  scopeLimit: boolean;
95
102
  } | null;
@@ -1 +1 @@
1
- {"version":3,"file":"beLinkCos.d.ts","sourceRoot":"","sources":["../src/beLinkCos.ts"],"names":[],"mappings":"AAIA,OAAO,EAA0B,KAAK,OAAO,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEtE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SAAS;IACpB,iBAAiB;IACjB,OAAO,CAAC,GAAG,CAAa;IACxB,kBAAkB;IAClB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,aAAa;IACN,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAM;IACzC,aAAa;IACN,IAAI,EAAE,OAAO,GAAG,IAAI,CAAQ;IACnC,oBAAoB;IACpB,OAAO,CAAC,UAAU,CAAkB;IACpC,aAAa;IACb,SAAS,CAAC,aAAa,EAAE,OAAO,CAAS;IACzC,SAAS,CAAC,WAAW,EAAE,OAAO,CAAS;IACvC,WAAW;IACX,OAAO,CAAC,KAAK,CAAkB;IAE/B;;;;;;;;;;;;;;;;;;;;OAoBG;gBACS,MAAM,CAAC,EAAE,UAAU;IAO/B;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAyB9B;;;;;;;OAOG;YACW,OAAO;IAqCrB;;OAEG;IACH,SAAS,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAYjD;;OAEG;IACH,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMvC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMxC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMzC;;OAEG;IACH,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAmBrD;;OAEG;IACH,SAAS,IAAI;QAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAY/F;;;;;;;;;;;;;;OAcG;IACI,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,GAAE,MAAwB,GAAG,OAAO,CAAC,MAAM,CAAC;IA+DtF;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;IASnB;;;;;;;;;;;OAWG;IACU,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAS7D;;;;;;;;;;;;;;;;;;;;OAoBG;IACU,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAsCjF;;OAEG;IACH,OAAO,IAAI,IAAI;CAsBhB"}
1
+ {"version":3,"file":"beLinkCos.d.ts","sourceRoot":"","sources":["../src/beLinkCos.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,OAAO,EAA8B,MAAM,UAAU,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEtE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SAAS;IACpB,iBAAiB;IACjB,OAAO,CAAC,GAAG,CAAa;IACxB,kBAAkB;IAClB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,aAAa;IACN,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAM;IACzC,aAAa;IACN,IAAI,EAAE,OAAO,GAAG,IAAI,CAAQ;IACnC,WAAW;IACJ,WAAW,EAAE,MAAM,GAAG,SAAS,CAAa;IACnD,oBAAoB;IACpB,OAAO,CAAC,UAAU,CAAkB;IACpC,aAAa;IACb,SAAS,CAAC,aAAa,EAAE,OAAO,CAAS;IACzC,SAAS,CAAC,WAAW,EAAE,OAAO,CAAS;IACvC,WAAW;IACX,OAAO,CAAC,KAAK,CAAkB;IAE/B;;;;;;;;;;;;;;;;;;;;OAoBG;gBACS,MAAM,CAAC,EAAE,UAAU;IAO/B;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IA0B9B;;;;;;;OAOG;YACW,OAAO;IAqCrB;;OAEG;IACH,SAAS,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAYjD;;OAEG;IACH,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMvC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMxC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMzC;;OAEG;IACH,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAmBrD;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,SAAS,IAAI;QACX,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;QACrB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;QAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC7B,UAAU,EAAE,OAAO,CAAC;KACrB,GAAG,IAAI;IAaR;;;;;;;;;;;;;;OAcG;IACI,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,GAAE,MAAwB,GAAG,OAAO,CAAC,MAAM,CAAC;IA+DtF;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;IASnB;;;;;;;;;;;OAWG;IACU,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAU7D;;;;;;;;;;;;;;;;;;;;OAoBG;IACU,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAwCjF;;OAEG;IACH,OAAO,IAAI,IAAI;CAuBhB"}
package/dist/config.d.ts CHANGED
@@ -21,6 +21,21 @@ export interface BucketConfig {
21
21
  * 根据环境自动切换到对应的存储桶
22
22
  */
23
23
  export declare const BUCKETS_CONFIG: Record<EnvMode, BucketConfig>;
24
+ /**
25
+ * 特定项目的自定义存储桶配置
26
+ * 优先级高于默认配置
27
+ */
28
+ export declare const PROJECT_BUCKETS_CONFIG: Record<string, Partial<Record<EnvMode, BucketConfig>>>;
29
+ /**
30
+ * 获取存储桶配置
31
+ * 优先使用项目特定配置,如果没有则使用默认配置
32
+ */
33
+ export declare function getBucketConfig(mode: EnvMode, projectName?: string): BucketConfig;
34
+ /**
35
+ * 获取存储桶所在地域
36
+ * 根据桶配置动态判断地域
37
+ */
38
+ export declare function getRegion(bucketConfig: BucketConfig): string;
24
39
  /** COS 存储桶所在地域(南京) */
25
40
  export declare const REGION: "ap-nanjing";
26
41
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,YAAY;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,cAAc;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,CAgBxD,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,MAAM,EAAG,YAAqB,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,YAAY;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,cAAc;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,CAgBxD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAQzF,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,CAKjF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,CAM5D;AAED,sBAAsB;AACtB,eAAO,MAAM,MAAM,EAAG,YAAqB,CAAC"}
package/dist/index.cjs.js CHANGED
@@ -24,6 +24,40 @@ const BUCKETS_CONFIG = {
24
24
  protocol: 'https',
25
25
  },
26
26
  };
27
+ /**
28
+ * 特定项目的自定义存储桶配置
29
+ * 优先级高于默认配置
30
+ */
31
+ const PROJECT_BUCKETS_CONFIG = {
32
+ 'be-link-live-h5': {
33
+ production: {
34
+ name: 'release-belink-1304510571',
35
+ host: 'release-belink-1304510571.cos.ap-shanghai.myqcloud.com',
36
+ protocol: 'https',
37
+ },
38
+ },
39
+ };
40
+ /**
41
+ * 获取存储桶配置
42
+ * 优先使用项目特定配置,如果没有则使用默认配置
43
+ */
44
+ function getBucketConfig(mode, projectName) {
45
+ if (projectName && PROJECT_BUCKETS_CONFIG[projectName]?.[mode]) {
46
+ return PROJECT_BUCKETS_CONFIG[projectName][mode];
47
+ }
48
+ return BUCKETS_CONFIG[mode];
49
+ }
50
+ /**
51
+ * 获取存储桶所在地域
52
+ * 根据桶配置动态判断地域
53
+ */
54
+ function getRegion(bucketConfig) {
55
+ // 根据 host 判断地域
56
+ if (bucketConfig.host.includes('ap-shanghai')) {
57
+ return 'ap-shanghai';
58
+ }
59
+ return 'ap-nanjing';
60
+ }
27
61
  /** COS 存储桶所在地域(南京) */
28
62
  const REGION = 'ap-nanjing';
29
63
 
@@ -76,6 +110,8 @@ class BeLinkCOS {
76
110
  this.headers = {};
77
111
  /** 当前环境模式 */
78
112
  this.mode = null;
113
+ /** 项目名称 */
114
+ this.projectName = undefined;
79
115
  /** 是否限制临时密钥的使用范围 */
80
116
  this.scopeLimit = false;
81
117
  /** 生命周期状态 */
@@ -107,11 +143,12 @@ class BeLinkCOS {
107
143
  }
108
144
  // 保存配置
109
145
  this.mode = config.mode;
146
+ this.projectName = config.projectName;
110
147
  this.headers = config.headers || {};
111
148
  this.scopeLimit = config.ScopeLimit || false;
112
149
  this.debug = config.debug || false;
113
150
  this.isInitialized = true;
114
- this.log('COS 实例初始化成功', { mode: this.mode });
151
+ this.log('COS 实例初始化成功', { mode: this.mode, projectName: this.projectName });
115
152
  }
116
153
  /**
117
154
  * 初始化 COS SDK 实例
@@ -204,6 +241,15 @@ class BeLinkCOS {
204
241
  }
205
242
  return true;
206
243
  }
244
+ /**
245
+ * 获取当前使用的存储桶配置
246
+ */
247
+ getCurrentBucketConfig() {
248
+ if (!this.mode) {
249
+ throw new Error('实例未初始化');
250
+ }
251
+ return getBucketConfig(this.mode, this.projectName);
252
+ }
207
253
  /**
208
254
  * 获取配置
209
255
  */
@@ -214,6 +260,7 @@ class BeLinkCOS {
214
260
  }
215
261
  return {
216
262
  mode: this.mode,
263
+ projectName: this.projectName,
217
264
  headers: this.headers,
218
265
  scopeLimit: this.scopeLimit,
219
266
  };
@@ -321,7 +368,8 @@ class BeLinkCOS {
321
368
  return null;
322
369
  }
323
370
  const path = this.getFilePath(file);
324
- return `https://${BUCKETS_CONFIG[this.mode].host}${path}`;
371
+ const bucketConfig = this.getCurrentBucketConfig();
372
+ return `https://${bucketConfig.host}${path}`;
325
373
  }
326
374
  /**
327
375
  * 上传文件到腾讯云 COS
@@ -353,11 +401,13 @@ class BeLinkCOS {
353
401
  await this.initCOS();
354
402
  }
355
403
  const key = this.getFilePath(file);
356
- this.log('开始上传文件:', { filename: file.name, key });
404
+ const bucketConfig = this.getCurrentBucketConfig();
405
+ const region = getRegion(bucketConfig);
406
+ this.log('开始上传文件:', { filename: file.name, key, bucket: bucketConfig.name, region });
357
407
  return new Promise((resolve, reject) => {
358
408
  this.cos?.putObject({
359
- Bucket: BUCKETS_CONFIG[this.mode].name,
360
- Region: REGION,
409
+ Bucket: bucketConfig.name,
410
+ Region: region,
361
411
  Key: key,
362
412
  Body: file,
363
413
  onProgress: config?.onProgressCallback,
@@ -391,6 +441,7 @@ class BeLinkCOS {
391
441
  this.isDestroyed = true;
392
442
  this.isInitialized = false;
393
443
  this.mode = null;
444
+ this.projectName = undefined;
394
445
  this.headers = {};
395
446
  this.scopeLimit = false;
396
447
  this.log('实例已销毁');
@@ -403,4 +454,7 @@ class BeLinkCOS {
403
454
 
404
455
  exports.BUCKETS_CONFIG = BUCKETS_CONFIG;
405
456
  exports.BeLinkCOS = BeLinkCOS;
457
+ exports.PROJECT_BUCKETS_CONFIG = PROJECT_BUCKETS_CONFIG;
406
458
  exports.REGION = REGION;
459
+ exports.getBucketConfig = getBucketConfig;
460
+ exports.getRegion = getRegion;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { BeLinkCOS } from './beLinkCos';
2
2
  export type { EnvMode, BucketConfig } from './config';
3
- export { BUCKETS_CONFIG, REGION } from './config';
3
+ export { BUCKETS_CONFIG, REGION, PROJECT_BUCKETS_CONFIG, getBucketConfig, getRegion } from './config';
4
4
  export type { InitConfig, UploadConfig, UploadResult } from './types';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,sBAAsB,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGtG,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.esm.js CHANGED
@@ -22,6 +22,40 @@ const BUCKETS_CONFIG = {
22
22
  protocol: 'https',
23
23
  },
24
24
  };
25
+ /**
26
+ * 特定项目的自定义存储桶配置
27
+ * 优先级高于默认配置
28
+ */
29
+ const PROJECT_BUCKETS_CONFIG = {
30
+ 'be-link-live-h5': {
31
+ production: {
32
+ name: 'release-belink-1304510571',
33
+ host: 'release-belink-1304510571.cos.ap-shanghai.myqcloud.com',
34
+ protocol: 'https',
35
+ },
36
+ },
37
+ };
38
+ /**
39
+ * 获取存储桶配置
40
+ * 优先使用项目特定配置,如果没有则使用默认配置
41
+ */
42
+ function getBucketConfig(mode, projectName) {
43
+ if (projectName && PROJECT_BUCKETS_CONFIG[projectName]?.[mode]) {
44
+ return PROJECT_BUCKETS_CONFIG[projectName][mode];
45
+ }
46
+ return BUCKETS_CONFIG[mode];
47
+ }
48
+ /**
49
+ * 获取存储桶所在地域
50
+ * 根据桶配置动态判断地域
51
+ */
52
+ function getRegion(bucketConfig) {
53
+ // 根据 host 判断地域
54
+ if (bucketConfig.host.includes('ap-shanghai')) {
55
+ return 'ap-shanghai';
56
+ }
57
+ return 'ap-nanjing';
58
+ }
25
59
  /** COS 存储桶所在地域(南京) */
26
60
  const REGION = 'ap-nanjing';
27
61
 
@@ -74,6 +108,8 @@ class BeLinkCOS {
74
108
  this.headers = {};
75
109
  /** 当前环境模式 */
76
110
  this.mode = null;
111
+ /** 项目名称 */
112
+ this.projectName = undefined;
77
113
  /** 是否限制临时密钥的使用范围 */
78
114
  this.scopeLimit = false;
79
115
  /** 生命周期状态 */
@@ -105,11 +141,12 @@ class BeLinkCOS {
105
141
  }
106
142
  // 保存配置
107
143
  this.mode = config.mode;
144
+ this.projectName = config.projectName;
108
145
  this.headers = config.headers || {};
109
146
  this.scopeLimit = config.ScopeLimit || false;
110
147
  this.debug = config.debug || false;
111
148
  this.isInitialized = true;
112
- this.log('COS 实例初始化成功', { mode: this.mode });
149
+ this.log('COS 实例初始化成功', { mode: this.mode, projectName: this.projectName });
113
150
  }
114
151
  /**
115
152
  * 初始化 COS SDK 实例
@@ -202,6 +239,15 @@ class BeLinkCOS {
202
239
  }
203
240
  return true;
204
241
  }
242
+ /**
243
+ * 获取当前使用的存储桶配置
244
+ */
245
+ getCurrentBucketConfig() {
246
+ if (!this.mode) {
247
+ throw new Error('实例未初始化');
248
+ }
249
+ return getBucketConfig(this.mode, this.projectName);
250
+ }
205
251
  /**
206
252
  * 获取配置
207
253
  */
@@ -212,6 +258,7 @@ class BeLinkCOS {
212
258
  }
213
259
  return {
214
260
  mode: this.mode,
261
+ projectName: this.projectName,
215
262
  headers: this.headers,
216
263
  scopeLimit: this.scopeLimit,
217
264
  };
@@ -319,7 +366,8 @@ class BeLinkCOS {
319
366
  return null;
320
367
  }
321
368
  const path = this.getFilePath(file);
322
- return `https://${BUCKETS_CONFIG[this.mode].host}${path}`;
369
+ const bucketConfig = this.getCurrentBucketConfig();
370
+ return `https://${bucketConfig.host}${path}`;
323
371
  }
324
372
  /**
325
373
  * 上传文件到腾讯云 COS
@@ -351,11 +399,13 @@ class BeLinkCOS {
351
399
  await this.initCOS();
352
400
  }
353
401
  const key = this.getFilePath(file);
354
- this.log('开始上传文件:', { filename: file.name, key });
402
+ const bucketConfig = this.getCurrentBucketConfig();
403
+ const region = getRegion(bucketConfig);
404
+ this.log('开始上传文件:', { filename: file.name, key, bucket: bucketConfig.name, region });
355
405
  return new Promise((resolve, reject) => {
356
406
  this.cos?.putObject({
357
- Bucket: BUCKETS_CONFIG[this.mode].name,
358
- Region: REGION,
407
+ Bucket: bucketConfig.name,
408
+ Region: region,
359
409
  Key: key,
360
410
  Body: file,
361
411
  onProgress: config?.onProgressCallback,
@@ -389,6 +439,7 @@ class BeLinkCOS {
389
439
  this.isDestroyed = true;
390
440
  this.isInitialized = false;
391
441
  this.mode = null;
442
+ this.projectName = undefined;
392
443
  this.headers = {};
393
444
  this.scopeLimit = false;
394
445
  this.log('实例已销毁');
@@ -399,4 +450,4 @@ class BeLinkCOS {
399
450
  }
400
451
  }
401
452
 
402
- export { BUCKETS_CONFIG, BeLinkCOS, REGION };
453
+ export { BUCKETS_CONFIG, BeLinkCOS, PROJECT_BUCKETS_CONFIG, REGION, getBucketConfig, getRegion };
package/dist/types.d.ts CHANGED
@@ -15,6 +15,8 @@ export interface InitConfig {
15
15
  * - production: 生产环境
16
16
  */
17
17
  mode: EnvMode;
18
+ /** 项目名称(可选),用于特定项目的桶配置 */
19
+ projectName?: string;
18
20
  /** 自定义请求头(可选) */
19
21
  headers?: Record<string, any>;
20
22
  /** 是否限制临时密钥的使用范围(可选,默认 false) */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;OAMG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd,iBAAiB;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE9B,iCAAiC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,aAAa;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,aAAa;IACb,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,KAAK,IAAI,CAAC;IACjD,uBAAuB;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,eAAe;IACf,IAAI,EAAE,MAAM,CAAC;IACb,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU;IACV,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,iBAAiB;IACjB,GAAG,EAAE,MAAM,CAAC;CACb"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;OAMG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,iBAAiB;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE9B,iCAAiC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,aAAa;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,aAAa;IACb,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,KAAK,IAAI,CAAC;IACjD,uBAAuB;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,eAAe;IACf,IAAI,EAAE,MAAM,CAAC;IACb,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU;IACV,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,iBAAiB;IACjB,GAAG,EAAE,MAAM,CAAC;CACb"}
package/package.json CHANGED
@@ -1,16 +1,10 @@
1
1
  {
2
2
  "name": "@be-link/cos",
3
- "version": "1.12.0-beta.2",
3
+ "version": "1.12.0-beta.4",
4
4
  "description": "前端项目产物上传cos",
5
- "author": "zhuifeng <yangyiboys@163.com>",
6
5
  "homepage": "https://github.com/snowmountain-top/be-link#readme",
6
+ "author": "zhuiyi",
7
7
  "license": "ISC",
8
- "main": "dist/index.cjs.js",
9
- "module": "dist/index.esm.js",
10
- "types": "dist/index.d.ts",
11
- "files": [
12
- "dist"
13
- ],
14
8
  "repository": {
15
9
  "type": "git",
16
10
  "url": "git+https://github.com/snowmountain-top/be-link.git"
@@ -18,17 +12,28 @@
18
12
  "bugs": {
19
13
  "url": "https://github.com/snowmountain-top/be-link/issues"
20
14
  },
15
+ "main": "dist/index.cjs.js",
16
+ "module": "dist/index.esm.js",
17
+ "types": "dist/index.d.ts",
18
+ "files": [
19
+ "dist",
20
+ "bin"
21
+ ],
22
+ "bin": {
23
+ "cos": "./bin/cos.js"
24
+ },
21
25
  "peerDependencies": {
22
26
  "cos-js-sdk-v5": "^1.8.6",
23
27
  "crypto-js": "^4.2.0"
24
28
  },
25
29
  "devDependencies": {
26
- "@types/crypto-js": "^4.2.2"
30
+ "@types/crypto-js": "^4.2.2",
31
+ "cos-js-sdk-v5": "^1.8.6",
32
+ "crypto-js": "^4.2.0"
27
33
  },
28
34
  "publishConfig": {
29
35
  "access": "public"
30
36
  },
31
- "gitHead": "76b71bb6850e5f57f1a1ba4bd17f2ae0f603b67e",
32
37
  "scripts": {
33
38
  "clean": "rimraf ./dist && rimraf .rollup.cache",
34
39
  "build:js": "rollup --config rollup.config.ts --configPlugin typescript",