ai-yuca 1.2.3 → 1.2.5

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/.cdn.cache.json CHANGED
@@ -1,7 +0,0 @@
1
- {
2
- "8d687e843e19199df437e245ee166123": "https://storage.googleapis.com/decom-cdn-test/fed/static/china2u/about.html",
3
- "f7c4edbaf98ece51425d5a7bc7d92d8f": "https://storage.googleapis.com/decom-cdn-test/fed/static/china2u/index.html",
4
- "55e8513f7e9e0a36434a1d5fa2613537": "https://storage.googleapis.com/decom-cdn-test/fed/static/china2u/ss/dd/index.js",
5
- "dc89e4b5e72eed0053323bbd39852234": "https://storage.googleapis.com/decom-cdn-test/fed/static/china2u/ss/dd.js",
6
- "d41d8cd98f00b204e9800998ecf8427e": "https://storage.googleapis.com/decom-cdn-test/fed/static/china2u/test.json"
7
- }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-yuca",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "一个用AI生成的开发辅助工具",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -36,12 +36,14 @@
36
36
  "commander": "^10.0.0",
37
37
  "fast-glob": "^3.3.3",
38
38
  "inquirer": "^12.9.4",
39
- "md5-file": "^5.0.0"
39
+ "md5-file": "^5.0.0",
40
+ "mime-types": "^3.0.1"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@types/chai": "^5.2.2",
43
44
  "@types/google-cloud__storage": "^2.3.1",
44
45
  "@types/inquirer": "^9.0.9",
46
+ "@types/mime-types": "^3.0.1",
45
47
  "@types/mocha": "^10.0.10",
46
48
  "@types/node": "^24.3.1",
47
49
  "@types/sinon": "^17.0.4",
@@ -272,6 +272,7 @@ async function deployFiles(options) {
272
272
  const sourcePath = options.source || uploadConfig.sourcePath;
273
273
  const htmlFiles = filterHtmlFiles(sourcePath);
274
274
  const cdnFiles = htmlFiles.map(file => ({ key: path.relative(sourcePath, file) }));
275
+ const storageClient = (0, upload_1.createStorageClient)(options.keyFile ? { keyFilename: options.keyFile } : {});
275
276
  console.log('📁 定义基础路径...');
276
277
  const prefix = `${config.aws.prefix}/${config.upload.s3Static}`;
277
278
  if (htmlFiles.length === 0) {
@@ -284,12 +285,12 @@ async function deployFiles(options) {
284
285
  const uploadPromises = htmlFiles.map(file => {
285
286
  const relativePath = path.relative(sourcePath, file);
286
287
  const destination = `${prefix}/${cdnKey}/${relativePath}`;
287
- console.log(` 上传: ${relativePath}`);
288
+ console.log(`HTML上传: ${destination}`);
288
289
  return (0, upload_1.uploadFile)({
289
290
  bucketName: uploadConfig.bucketName,
290
291
  filePath: file,
291
292
  destination,
292
- storageClient: (0, upload_1.createStorageClient)(options.keyFile ? { keyFilename: options.keyFile } : {}),
293
+ storageClient,
293
294
  enableCompression: true
294
295
  }).then(result => ({ result, relativePath, destination }));
295
296
  });
@@ -326,7 +327,7 @@ async function deployFiles(options) {
326
327
  bucketName: uploadConfig.bucketName,
327
328
  filePath: tempVersionFile,
328
329
  destination: versionConfigPath,
329
- storageClient: (0, upload_1.createStorageClient)(options.keyFile ? { keyFilename: options.keyFile } : {}),
330
+ storageClient,
330
331
  enableCompression: false
331
332
  });
332
333
  }
@@ -358,7 +359,7 @@ async function deployFiles(options) {
358
359
  bucketName: uploadConfig.bucketName,
359
360
  filePath: tempVersionListFile,
360
361
  destination: versionListPath,
361
- storageClient: (0, upload_1.createStorageClient)(options.keyFile ? { keyFilename: options.keyFile } : {}),
362
+ storageClient,
362
363
  enableCompression: false
363
364
  });
364
365
  }
@@ -46,6 +46,7 @@ const path = __importStar(require("path"));
46
46
  const util = __importStar(require("util"));
47
47
  const compression_1 = require("./utils/compression");
48
48
  const config_1 = require("./config");
49
+ const mime = __importStar(require("mime-types"));
49
50
  const readdir = util.promisify(fs.readdir);
50
51
  const stat = util.promisify(fs.stat);
51
52
  /**
@@ -85,14 +86,27 @@ function createStorageClient(options = {}) {
85
86
  // 如果提供了keyFilename,使用密钥文件认证
86
87
  if (keyFilename) {
87
88
  return new storage_1.Storage({
88
- keyFilename
89
+ keyFilename,
90
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
91
+ // 重试策略配置
92
+ retryOptions: {
93
+ retryDelayMultiplier: 2, // 重试延迟倍数(指数退避)
94
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
95
+ maxRetries: 5, // 最大重试次数(根据需求调整)
96
+ },
89
97
  });
90
98
  }
91
99
  // 如果提供了credentials,使用凭证对象认证
92
100
  if (credentials) {
93
101
  return new storage_1.Storage({
94
102
  projectId,
95
- credentials
103
+ credentials,
104
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
105
+ retryOptions: {
106
+ retryDelayMultiplier: 2, // 重试延迟倍数
107
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
108
+ maxRetries: 5, // 最大重试次数
109
+ },
96
110
  });
97
111
  }
98
112
  // 尝试从vs.config.json读取aws.FileKey
@@ -101,7 +115,13 @@ function createStorageClient(options = {}) {
101
115
  if (((_a = config.aws) === null || _a === void 0 ? void 0 : _a.FileKey) && fs.existsSync(config.aws.FileKey)) {
102
116
  console.log(`使用配置文件中的密钥文件: ${config.aws.FileKey}`);
103
117
  return new storage_1.Storage({
104
- keyFilename: config.aws.FileKey
118
+ keyFilename: config.aws.FileKey,
119
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
120
+ retryOptions: {
121
+ retryDelayMultiplier: 2, // 重试延迟倍数
122
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
123
+ maxRetries: 5, // 最大重试次数
124
+ },
105
125
  });
106
126
  }
107
127
  }
@@ -112,7 +132,14 @@ function createStorageClient(options = {}) {
112
132
  // 使用应用默认凭证(ADC)进行免密认证
113
133
  // 这将使用环境变量 或默认服务账号
114
134
  console.log('使用应用默认凭证(免登方式)');
115
- return new storage_1.Storage();
135
+ return new storage_1.Storage({
136
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
137
+ retryOptions: {
138
+ retryDelayMultiplier: 2, // 重试延迟倍数
139
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
140
+ maxRetries: 5, // 最大重试次数
141
+ },
142
+ });
116
143
  }
117
144
  /**
118
145
  * 上传单个文件到GCP存储桶
@@ -134,39 +161,20 @@ async function uploadFile(options) {
134
161
  // 确定目标路径
135
162
  const destPath = destination || path.basename(filePath);
136
163
  // 检查是否需要压缩
137
- let fileToUpload = filePath;
138
164
  let contentEncoding;
139
- let contentType;
165
+ let contentType = '';
140
166
  if (enableCompression && (0, compression_1.shouldCompressFile)(filePath)) {
141
167
  // 压缩文件
142
- fileToUpload = await (0, compression_1.compressFile)(filePath);
143
168
  contentEncoding = 'gzip';
144
169
  // 根据文件扩展名设置正确的Content-Type
145
- const ext = path.extname(filePath).toLowerCase();
146
- switch (ext) {
147
- case '.js':
148
- contentType = 'application/javascript';
149
- break;
150
- case '.css':
151
- contentType = 'text/css';
152
- break;
153
- case '.json':
154
- contentType = 'application/json';
155
- break;
156
- case '.html':
157
- contentType = 'text/html';
158
- break;
159
- case '.woff':
160
- contentType = 'font/woff';
161
- break;
162
- default:
163
- contentType = 'application/octet-stream';
164
- }
170
+ const fileName = path.basename(filePath);
171
+ contentType = mime.contentType(fileName) || '';
165
172
  }
173
+ console.log('开始上传', filePath);
166
174
  // 上传文件
167
- // @ts-ignore
168
- const [file] = await bucket.upload(fileToUpload, {
175
+ const [file] = await bucket.upload(filePath, {
169
176
  destination: destPath,
177
+ gzip: contentEncoding === 'gzip',
170
178
  // 设置元数据
171
179
  metadata: {
172
180
  // 为.json文件设置缓存时间为0,其他文件保持一年缓存
@@ -175,24 +183,22 @@ async function uploadFile(options) {
175
183
  contentType
176
184
  }
177
185
  });
178
- // 如果上传了压缩文件,删除临时文件
179
- if (fileToUpload !== filePath && fs.existsSync(fileToUpload)) {
180
- fs.unlinkSync(fileToUpload);
181
- }
182
186
  // 获取文件公共URL
183
187
  const [metadata] = await file.getMetadata();
188
+ console.log('上传成功', filePath);
184
189
  return {
185
190
  success: true,
186
191
  file: metadata.name || path.basename(filePath),
192
+ // file: path.basename(filePath),
187
193
  filePath: filePath,
188
194
  size: metadata.size || 0,
189
- contentType: metadata.contentType || 'application/octet-stream',
195
+ contentType: metadata.contentType || contentType,
190
196
  timeCreated: metadata.timeCreated || new Date().toISOString(),
191
- url: `https://storage.googleapis.com/${bucketName}/${metadata.name || path.basename(filePath)}`
197
+ url: `https://storage.googleapis.com/${bucketName}/${metadata.name}`
192
198
  };
193
199
  }
194
200
  catch (error) {
195
- console.log('上传文件时出错:', filePath, JSON.stringify(error));
201
+ console.log(`${filePath}出错:`, JSON.stringify(error));
196
202
  return {
197
203
  success: false,
198
204
  file: filePath,
@@ -228,14 +234,22 @@ async function uploadFiles(options) {
228
234
  results.files = results.files.concat(dirFiles);
229
235
  }
230
236
  }
231
- const uploadPromises = sourcePath.map(filePath => uploadFile({
232
- bucketName,
233
- filePath,
234
- destination: destination ? `${destination}${filePath.replace(uploadDir || '', '')}` : undefined,
235
- storageClient,
236
- enableCompression
237
- }));
238
- const uploadResults = await Promise.all(uploadPromises);
237
+ const uploadPromises = [...sourcePath];
238
+ // 将上传任务按5个为一组进行分组处理
239
+ const batchSize = 5;
240
+ const uploadResults = [];
241
+ for (let i = 0; i < uploadPromises.length; i += batchSize) {
242
+ console.log('开始上传第', i, '-', i + batchSize, '文件');
243
+ const batch = uploadPromises.slice(i, i + batchSize);
244
+ const batchResults = await Promise.all(batch.map(filePath => uploadFile({
245
+ bucketName,
246
+ filePath,
247
+ destination: destination ? `${destination}${filePath.replace(uploadDir || '', '')}` : undefined,
248
+ storageClient,
249
+ enableCompression
250
+ })));
251
+ uploadResults.push(...batchResults);
252
+ }
239
253
  for (const result of uploadResults) {
240
254
  if (result.success) {
241
255
  results.success.push(result);
@@ -86,14 +86,26 @@ function createStorageClientFromConfig(options = {}) {
86
86
  // 如果提供了keyFilename,使用密钥文件认证
87
87
  if (keyFilename) {
88
88
  return new storage_1.Storage({
89
- keyFilename
89
+ keyFilename,
90
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
91
+ retryOptions: {
92
+ retryDelayMultiplier: 2, // 重试延迟倍数
93
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
94
+ maxRetries: 5, // 最大重试次数
95
+ },
90
96
  });
91
97
  }
92
98
  // 如果提供了credentials,使用凭证对象认证
93
99
  if (credentials) {
94
100
  return new storage_1.Storage({
95
101
  projectId,
96
- credentials
102
+ credentials,
103
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
104
+ retryOptions: {
105
+ retryDelayMultiplier: 2, // 重试延迟倍数
106
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
107
+ maxRetries: 5, // 最大重试次数
108
+ },
97
109
  });
98
110
  }
99
111
  // 尝试从vs.config.json读取aws.FileKey
@@ -102,7 +114,13 @@ function createStorageClientFromConfig(options = {}) {
102
114
  if (((_a = config.aws) === null || _a === void 0 ? void 0 : _a.FileKey) && fs.existsSync(config.aws.FileKey)) {
103
115
  console.log(`使用配置文件中的密钥文件: ${config.aws.FileKey}`);
104
116
  return new storage_1.Storage({
105
- keyFilename: config.aws.FileKey
117
+ keyFilename: config.aws.FileKey,
118
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
119
+ retryOptions: {
120
+ retryDelayMultiplier: 2, // 重试延迟倍数
121
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
122
+ maxRetries: 5, // 最大重试次数
123
+ },
106
124
  });
107
125
  }
108
126
  }
@@ -112,7 +130,14 @@ function createStorageClientFromConfig(options = {}) {
112
130
  }
113
131
  // 使用应用默认凭证(ADC)进行免密认证
114
132
  console.log('使用应用默认凭证(免登方式)');
115
- return new storage_1.Storage();
133
+ return new storage_1.Storage({
134
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
135
+ retryOptions: {
136
+ retryDelayMultiplier: 2, // 重试延迟倍数
137
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
138
+ maxRetries: 5, // 最大重试次数
139
+ }
140
+ });
116
141
  }
117
142
  /**
118
143
  * 基于配置文件批量上传文件
@@ -147,11 +172,8 @@ async function uploadFilesWithConfig(options = {}) {
147
172
  if (enableCache && cacheManager) {
148
173
  // 获取所有需要处理的文件
149
174
  const allFiles = await getFilesToProcess(sourcePath, recursive);
150
- console.log('allFiles', allFiles);
151
175
  for (const filePath of allFiles) {
152
176
  if (cacheManager.isFileUploaded(filePath)) {
153
- const cachedUrl = cacheManager.getUploadedUrl(filePath);
154
- console.log(`跳过已上传文件: ${filePath} -> ${cachedUrl}`);
155
177
  skippedFiles.push(filePath);
156
178
  }
157
179
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-yuca",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "一个用AI生成的开发辅助工具",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -36,12 +36,14 @@
36
36
  "commander": "^10.0.0",
37
37
  "fast-glob": "^3.3.3",
38
38
  "inquirer": "^12.9.4",
39
- "md5-file": "^5.0.0"
39
+ "md5-file": "^5.0.0",
40
+ "mime-types": "^3.0.1"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@types/chai": "^5.2.2",
43
44
  "@types/google-cloud__storage": "^2.3.1",
44
45
  "@types/inquirer": "^9.0.9",
46
+ "@types/mime-types": "^3.0.1",
45
47
  "@types/mocha": "^10.0.10",
46
48
  "@types/node": "^24.3.1",
47
49
  "@types/sinon": "^17.0.4",
package/src/deploy.ts CHANGED
@@ -256,7 +256,6 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
256
256
  // 1. 配置校验阶段
257
257
  console.log('📋 验证配置文件...');
258
258
  const config = validateConfig(options.config);
259
-
260
259
  // 2. 执行upload-config阶段
261
260
  console.log('📤 执行upload-config上传配置文件...');
262
261
  let files: string[] = [];
@@ -289,7 +288,7 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
289
288
  const sourcePath = options.source || uploadConfig.sourcePath;
290
289
  const htmlFiles = filterHtmlFiles(sourcePath);
291
290
  const cdnFiles = htmlFiles.map(file => ({ key: path.relative(sourcePath, file) }));
292
-
291
+ const storageClient = createStorageClient(options.keyFile ? { keyFilename: options.keyFile } : {});
293
292
  console.log('📁 定义基础路径...');
294
293
  const prefix = `${config.aws.prefix}/${config.upload.s3Static}`;
295
294
 
@@ -305,13 +304,12 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
305
304
  const uploadPromises = htmlFiles.map(file => {
306
305
  const relativePath = path.relative(sourcePath, file);
307
306
  const destination = `${prefix}/${cdnKey}/${relativePath}`;
308
-
309
- console.log(` 上传: ${relativePath}`);
307
+ console.log(`HTML上传: ${destination}`);
310
308
  return uploadFile({
311
309
  bucketName: uploadConfig.bucketName,
312
310
  filePath: file,
313
311
  destination,
314
- storageClient: createStorageClient(options.keyFile ? { keyFilename: options.keyFile } : {}),
312
+ storageClient,
315
313
  enableCompression: true
316
314
  }).then(result => ({ result, relativePath, destination }));
317
315
  });
@@ -353,7 +351,7 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
353
351
  bucketName: uploadConfig.bucketName,
354
352
  filePath: tempVersionFile,
355
353
  destination: versionConfigPath,
356
- storageClient: createStorageClient(options.keyFile ? { keyFilename: options.keyFile } : {}),
354
+ storageClient,
357
355
  enableCompression: false
358
356
  });
359
357
  } finally {
@@ -381,13 +379,13 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
381
379
 
382
380
  const tempVersionListFile = path.join(process.cwd(), `.temp-version-list-${cdnKey}.json`);
383
381
  fs.writeFileSync(tempVersionListFile, JSON.stringify(versionList, null, 2));
384
-
382
+
385
383
  try {
386
384
  await uploadFile({
387
385
  bucketName: uploadConfig.bucketName,
388
386
  filePath: tempVersionListFile,
389
387
  destination: versionListPath,
390
- storageClient: createStorageClient(options.keyFile ? { keyFilename: options.keyFile } : {}),
388
+ storageClient,
391
389
  enableCompression: false
392
390
  });
393
391
  } finally {
package/src/upload.ts CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  } from './types/upload';
17
17
  import { shouldCompressFile, compressFile } from './utils/compression';
18
18
  import { loadConfig } from './config';
19
-
19
+ import * as mime from 'mime-types';
20
20
  const readdir = util.promisify(fs.readdir);
21
21
  const stat = util.promisify(fs.stat);
22
22
 
@@ -60,7 +60,14 @@ function createStorageClient(options: Partial<StorageClientOptions> = {}): Stora
60
60
  // 如果提供了keyFilename,使用密钥文件认证
61
61
  if (keyFilename) {
62
62
  return new Storage({
63
- keyFilename
63
+ keyFilename,
64
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
65
+ // 重试策略配置
66
+ retryOptions: {
67
+ retryDelayMultiplier: 2, // 重试延迟倍数(指数退避)
68
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
69
+ maxRetries: 5, // 最大重试次数(根据需求调整)
70
+ },
64
71
  });
65
72
  }
66
73
 
@@ -68,7 +75,13 @@ function createStorageClient(options: Partial<StorageClientOptions> = {}): Stora
68
75
  if (credentials) {
69
76
  return new Storage({
70
77
  projectId,
71
- credentials
78
+ credentials,
79
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
80
+ retryOptions: {
81
+ retryDelayMultiplier: 2, // 重试延迟倍数
82
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
83
+ maxRetries: 5, // 最大重试次数
84
+ },
72
85
  });
73
86
  }
74
87
 
@@ -78,7 +91,13 @@ function createStorageClient(options: Partial<StorageClientOptions> = {}): Stora
78
91
  if (config.aws?.FileKey && fs.existsSync(config.aws.FileKey)) {
79
92
  console.log(`使用配置文件中的密钥文件: ${config.aws.FileKey}`);
80
93
  return new Storage({
81
- keyFilename: config.aws.FileKey
94
+ keyFilename: config.aws.FileKey,
95
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
96
+ retryOptions: {
97
+ retryDelayMultiplier: 2, // 重试延迟倍数
98
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
99
+ maxRetries: 5, // 最大重试次数
100
+ },
82
101
  });
83
102
  }
84
103
  } catch (error) {
@@ -89,7 +108,14 @@ function createStorageClient(options: Partial<StorageClientOptions> = {}): Stora
89
108
  // 使用应用默认凭证(ADC)进行免密认证
90
109
  // 这将使用环境变量 或默认服务账号
91
110
  console.log('使用应用默认凭证(免登方式)');
92
- return new Storage();
111
+ return new Storage({
112
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
113
+ retryOptions: {
114
+ retryDelayMultiplier: 2, // 重试延迟倍数
115
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
116
+ maxRetries: 5, // 最大重试次数
117
+ },
118
+ });
93
119
  }
94
120
 
95
121
  /**
@@ -117,42 +143,22 @@ async function uploadFile(options: UploadFileOptions): Promise<UploadResult> {
117
143
  const destPath = destination || path.basename(filePath);
118
144
 
119
145
  // 检查是否需要压缩
120
- let fileToUpload = filePath;
121
146
  let contentEncoding: string | undefined;
122
- let contentType: string | undefined;
147
+ let contentType: string = '';
123
148
 
124
149
  if (enableCompression && shouldCompressFile(filePath)) {
125
150
  // 压缩文件
126
- fileToUpload = await compressFile(filePath);
127
151
  contentEncoding = 'gzip';
128
-
129
152
  // 根据文件扩展名设置正确的Content-Type
130
- const ext = path.extname(filePath).toLowerCase();
131
- switch (ext) {
132
- case '.js':
133
- contentType = 'application/javascript';
134
- break;
135
- case '.css':
136
- contentType = 'text/css';
137
- break;
138
- case '.json':
139
- contentType = 'application/json';
140
- break;
141
- case '.html':
142
- contentType = 'text/html';
143
- break;
144
- case '.woff':
145
- contentType = 'font/woff';
146
- break;
147
- default:
148
- contentType = 'application/octet-stream';
149
- }
153
+ const fileName = path.basename(filePath);
154
+ contentType = mime.contentType(fileName) || '';
150
155
  }
151
156
 
157
+ console.log('开始上传', filePath)
152
158
  // 上传文件
153
- // @ts-ignore
154
- const [file] = await bucket.upload(fileToUpload, {
159
+ const [file] = await bucket.upload(filePath, {
155
160
  destination: destPath,
161
+ gzip: contentEncoding === 'gzip',
156
162
  // 设置元数据
157
163
  metadata: {
158
164
  // 为.json文件设置缓存时间为0,其他文件保持一年缓存
@@ -162,25 +168,21 @@ async function uploadFile(options: UploadFileOptions): Promise<UploadResult> {
162
168
  }
163
169
  });
164
170
 
165
- // 如果上传了压缩文件,删除临时文件
166
- if (fileToUpload !== filePath && fs.existsSync(fileToUpload)) {
167
- fs.unlinkSync(fileToUpload);
168
- }
169
-
170
171
  // 获取文件公共URL
171
172
  const [metadata] = await file.getMetadata();
172
-
173
+ console.log('上传成功', filePath)
173
174
  return {
174
175
  success: true,
175
176
  file: metadata.name || path.basename(filePath),
177
+ // file: path.basename(filePath),
176
178
  filePath: filePath,
177
179
  size: metadata.size || 0,
178
- contentType: metadata.contentType || 'application/octet-stream',
180
+ contentType: metadata.contentType || contentType,
179
181
  timeCreated: metadata.timeCreated || new Date().toISOString(),
180
- url: `https://storage.googleapis.com/${bucketName}/${metadata.name || path.basename(filePath)}`
182
+ url: `https://storage.googleapis.com/${bucketName}/${metadata.name}`
181
183
  };
182
184
  } catch (error) {
183
- console.log('上传文件时出错:', filePath, JSON.stringify(error));
185
+ console.log(`${ filePath }出错:`, JSON.stringify(error));
184
186
  return {
185
187
  success: false,
186
188
  file: filePath,
@@ -223,17 +225,25 @@ async function uploadFiles(options: UploadFilesOptions): Promise<UploadFilesResu
223
225
  }
224
226
  }
225
227
 
226
- const uploadPromises = sourcePath.map(filePath =>
228
+ const uploadPromises = [...sourcePath];
229
+
230
+ // 将上传任务按5个为一组进行分组处理
231
+ const batchSize = 5;
232
+ const uploadResults: UploadResult[] = [];
233
+
234
+ for (let i = 0; i < uploadPromises.length; i += batchSize) {
235
+ console.log('开始上传第', i, '-', i + batchSize, '文件');
236
+ const batch = uploadPromises.slice(i, i + batchSize);
237
+ const batchResults = await Promise.all(batch.map(filePath =>
227
238
  uploadFile({
228
239
  bucketName,
229
240
  filePath,
230
241
  destination: destination ? `${destination}${filePath.replace(uploadDir || '', '')}` : undefined,
231
242
  storageClient,
232
243
  enableCompression
233
- })
234
- );
235
-
236
- const uploadResults = await Promise.all(uploadPromises);
244
+ })));
245
+ uploadResults.push(...batchResults);
246
+ }
237
247
 
238
248
  for (const result of uploadResults) {
239
249
  if (result.success) {
@@ -75,7 +75,13 @@ function createStorageClientFromConfig(options: Partial<StorageClientOptions> =
75
75
  // 如果提供了keyFilename,使用密钥文件认证
76
76
  if (keyFilename) {
77
77
  return new Storage({
78
- keyFilename
78
+ keyFilename,
79
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
80
+ retryOptions: {
81
+ retryDelayMultiplier: 2, // 重试延迟倍数
82
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
83
+ maxRetries: 5, // 最大重试次数
84
+ },
79
85
  });
80
86
  }
81
87
 
@@ -83,7 +89,13 @@ function createStorageClientFromConfig(options: Partial<StorageClientOptions> =
83
89
  if (credentials) {
84
90
  return new Storage({
85
91
  projectId,
86
- credentials
92
+ credentials,
93
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
94
+ retryOptions: {
95
+ retryDelayMultiplier: 2, // 重试延迟倍数
96
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
97
+ maxRetries: 5, // 最大重试次数
98
+ },
87
99
  });
88
100
  }
89
101
 
@@ -93,7 +105,13 @@ function createStorageClientFromConfig(options: Partial<StorageClientOptions> =
93
105
  if (config.aws?.FileKey && fs.existsSync(config.aws.FileKey)) {
94
106
  console.log(`使用配置文件中的密钥文件: ${config.aws.FileKey}`);
95
107
  return new Storage({
96
- keyFilename: config.aws.FileKey
108
+ keyFilename: config.aws.FileKey,
109
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
110
+ retryOptions: {
111
+ retryDelayMultiplier: 2, // 重试延迟倍数
112
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
113
+ maxRetries: 5, // 最大重试次数
114
+ },
97
115
  });
98
116
  }
99
117
  } catch (error) {
@@ -103,7 +121,14 @@ function createStorageClientFromConfig(options: Partial<StorageClientOptions> =
103
121
 
104
122
  // 使用应用默认凭证(ADC)进行免密认证
105
123
  console.log('使用应用默认凭证(免登方式)');
106
- return new Storage();
124
+ return new Storage({
125
+ timeout: 300000, // 超时时间设为 5 分钟(300,000 毫秒)
126
+ retryOptions: {
127
+ retryDelayMultiplier: 2, // 重试延迟倍数
128
+ maxRetryDelay: 60000, // 最大重试延迟(毫秒),避免延迟过长
129
+ maxRetries: 5, // 最大重试次数
130
+ }
131
+ });
107
132
  }
108
133
 
109
134
  /**
@@ -126,10 +151,8 @@ export async function uploadFilesWithConfig(options: UploadWithConfigOptions = {
126
151
  try {
127
152
  // 加载配置文件
128
153
  const config: VSConfig = loadConfig(configPath);
129
-
130
154
  // 创建存储客户端
131
155
  const storageClient = createStorageClientFromConfig(storageClientOptions);
132
-
133
156
  // 获取配置信息
134
157
  const bucketName = getBucketName(config);
135
158
  const sourcePath = customSourcePath || getUploadSourcePath(config);
@@ -155,11 +178,9 @@ export async function uploadFilesWithConfig(options: UploadWithConfigOptions = {
155
178
  if (enableCache && cacheManager) {
156
179
  // 获取所有需要处理的文件
157
180
  const allFiles = await getFilesToProcess(sourcePath, recursive);
158
- console.log('allFiles', allFiles);
181
+
159
182
  for (const filePath of allFiles) {
160
183
  if (cacheManager.isFileUploaded(filePath)) {
161
- const cachedUrl = cacheManager.getUploadedUrl(filePath);
162
- console.log(`跳过已上传文件: ${filePath} -> ${cachedUrl}`);
163
184
  skippedFiles.push(filePath);
164
185
  } else {
165
186
  filesToUpload.push(filePath);
package/tsconfig.json CHANGED
@@ -13,5 +13,5 @@
13
13
  "resolveJsonModule": true
14
14
  },
15
15
  "include": ["src/**/*", "bin/**/*", "test/**/*"],
16
- "exclude": ["node_modules", "dist"]
16
+ "exclude": ["node_modules", "dist", "out", "i18n"]
17
17
  }
package/out/about.html DELETED
@@ -1,20 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>About - Test Deploy</title>
7
- </head>
8
- <body>
9
- <h1>About Page</h1>
10
- <p>This is the about page for deploy command testing.</p>
11
- <div id="content">
12
- <h2>Features</h2>
13
- <ul>
14
- <li>Deploy to multiple environments</li>
15
- <li>Version management</li>
16
- <li>File upload to GCP</li>
17
- </ul>
18
- </div>
19
- </body>
20
- </html>
package/out/index.html DELETED
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Test Deploy Page</title>
7
- </head>
8
- <body>
9
- <h1>Welcome to Test Deploy</h1>
10
- <p>This is a test HTML file for deploy command testing.</p>
11
- <script>
12
- console.log('Deploy test page loaded');
13
- </script>
14
- </body>
15
- </html>
@@ -1,2 +0,0 @@
1
- const a = 0;
2
- const b = 1;
package/out/ss/dd.js DELETED
@@ -1 +0,0 @@
1
- const a = 0;
package/out/test.json DELETED
File without changes