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 +0 -7
- package/dist/package.json +4 -2
- package/dist/src/deploy.js +5 -4
- package/dist/src/upload.js +58 -44
- package/dist/src/uploadWithConfig.js +29 -7
- package/package.json +4 -2
- package/src/deploy.ts +6 -8
- package/src/upload.ts +55 -45
- package/src/uploadWithConfig.ts +30 -9
- package/tsconfig.json +1 -1
- package/out/about.html +0 -20
- package/out/index.html +0 -15
- package/out/ss/dd/index.js +0 -2
- package/out/ss/dd.js +0 -1
- package/out/test.json +0 -0
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
|
+
"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/dist/src/deploy.js
CHANGED
|
@@ -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(`
|
|
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
|
|
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
|
|
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
|
|
362
|
+
storageClient,
|
|
362
363
|
enableCompression: false
|
|
363
364
|
});
|
|
364
365
|
}
|
package/dist/src/upload.js
CHANGED
|
@@ -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
|
|
146
|
-
|
|
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
|
-
|
|
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 ||
|
|
195
|
+
contentType: metadata.contentType || contentType,
|
|
190
196
|
timeCreated: metadata.timeCreated || new Date().toISOString(),
|
|
191
|
-
url: `https://storage.googleapis.com/${bucketName}/${metadata.name
|
|
197
|
+
url: `https://storage.googleapis.com/${bucketName}/${metadata.name}`
|
|
192
198
|
};
|
|
193
199
|
}
|
|
194
200
|
catch (error) {
|
|
195
|
-
console.log(
|
|
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
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
+
"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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
131
|
-
|
|
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
|
-
|
|
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 ||
|
|
180
|
+
contentType: metadata.contentType || contentType,
|
|
179
181
|
timeCreated: metadata.timeCreated || new Date().toISOString(),
|
|
180
|
-
url: `https://storage.googleapis.com/${bucketName}/${metadata.name
|
|
182
|
+
url: `https://storage.googleapis.com/${bucketName}/${metadata.name}`
|
|
181
183
|
};
|
|
182
184
|
} catch (error) {
|
|
183
|
-
console.log(
|
|
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
|
|
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) {
|
package/src/uploadWithConfig.ts
CHANGED
|
@@ -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
|
-
|
|
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
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>
|
package/out/ss/dd/index.js
DELETED
package/out/ss/dd.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const a = 0;
|
package/out/test.json
DELETED
|
File without changes
|