ai-yuca 1.2.4 → 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 +1 -1
- package/dist/src/upload.js +58 -44
- package/dist/src/uploadWithConfig.js +29 -6
- package/package.json +4 -2
- package/src/deploy.ts +1 -2
- package/src/upload.ts +55 -45
- package/src/uploadWithConfig.ts +29 -8
- 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
|
@@ -285,7 +285,7 @@ async function deployFiles(options) {
|
|
|
285
285
|
const uploadPromises = htmlFiles.map(file => {
|
|
286
286
|
const relativePath = path.relative(sourcePath, file);
|
|
287
287
|
const destination = `${prefix}/${cdnKey}/${relativePath}`;
|
|
288
|
-
console.log(`
|
|
288
|
+
console.log(`HTML上传: ${destination}`);
|
|
289
289
|
return (0, upload_1.uploadFile)({
|
|
290
290
|
bucketName: uploadConfig.bucketName,
|
|
291
291
|
filePath: file,
|
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
|
* 基于配置文件批量上传文件
|
|
@@ -149,8 +174,6 @@ async function uploadFilesWithConfig(options = {}) {
|
|
|
149
174
|
const allFiles = await getFilesToProcess(sourcePath, recursive);
|
|
150
175
|
for (const filePath of allFiles) {
|
|
151
176
|
if (cacheManager.isFileUploaded(filePath)) {
|
|
152
|
-
const cachedUrl = cacheManager.getUploadedUrl(filePath);
|
|
153
|
-
console.log(`跳过已上传文件: ${filePath} -> ${cachedUrl}`);
|
|
154
177
|
skippedFiles.push(filePath);
|
|
155
178
|
}
|
|
156
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
|
@@ -304,8 +304,7 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
|
|
|
304
304
|
const uploadPromises = htmlFiles.map(file => {
|
|
305
305
|
const relativePath = path.relative(sourcePath, file);
|
|
306
306
|
const destination = `${prefix}/${cdnKey}/${relativePath}`;
|
|
307
|
-
|
|
308
|
-
console.log(` 上传: ${relativePath}`);
|
|
307
|
+
console.log(`HTML上传: ${destination}`);
|
|
309
308
|
return uploadFile({
|
|
310
309
|
bucketName: uploadConfig.bucketName,
|
|
311
310
|
filePath: file,
|
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);
|
|
@@ -158,8 +181,6 @@ export async function uploadFilesWithConfig(options: UploadWithConfigOptions = {
|
|
|
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
|