ai-yuca 1.1.7 → 1.1.8

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/cli.ts CHANGED
@@ -97,7 +97,7 @@ program
97
97
  console.log('开始上传文件...');
98
98
 
99
99
  // 处理多个源路径
100
- let allResults: UploadFilesResult = { success: [], failed: [] };
100
+ let allResults: UploadFilesResult = { success: [], failed: [], files: [] };
101
101
 
102
102
  for (const sourcePath of source) {
103
103
  console.log(`\n处理路径: ${sourcePath}`);
@@ -134,6 +134,9 @@ program
134
134
  // 合并结果
135
135
  allResults.success = allResults.success.concat(results.success);
136
136
  allResults.failed = allResults.failed.concat(results.failed);
137
+ if (results.files) {
138
+ allResults.files = allResults.files!.concat(results.files);
139
+ }
137
140
  }
138
141
 
139
142
  const results = allResults;
@@ -156,6 +159,14 @@ program
156
159
  console.log(`- ${file.file}: ${file.error}`);
157
160
  });
158
161
  }
162
+
163
+ // 如果有files字段,显示目录下的所有文件
164
+ if (results.files && results.files.length > 0) {
165
+ console.log('\n目录下的所有文件:');
166
+ results.files.forEach(file => {
167
+ console.log(`- ${file}`);
168
+ });
169
+ }
159
170
  } catch (err) {
160
171
  console.error(`上传错误: ${err instanceof Error ? err.message : String(err)}`);
161
172
  process.exit(1);
@@ -289,6 +300,14 @@ program
289
300
  console.log(` ✗ ${file.file}: ${file.error}`);
290
301
  });
291
302
  }
303
+
304
+ // 显示目录下的所有文件
305
+ if (result.files && result.files.length > 0) {
306
+ console.log('\n目录下的所有文件:');
307
+ result.files.forEach((file) => {
308
+ console.log(`- ${file}`);
309
+ });
310
+ }
292
311
 
293
312
  } catch (err) {
294
313
  console.error(`上传错误: ${err instanceof Error ? err.message : String(err)}`);
package/dist/bin/cli.js CHANGED
@@ -120,7 +120,7 @@ program
120
120
  : (0, upload_1.createStorageClient)(); // 使用应用默认凭证
121
121
  console.log('开始上传文件...');
122
122
  // 处理多个源路径
123
- let allResults = { success: [], failed: [] };
123
+ let allResults = { success: [], failed: [], files: [] };
124
124
  for (const sourcePath of source) {
125
125
  console.log(`\n处理路径: ${sourcePath}`);
126
126
  // 检查路径是否存在
@@ -153,6 +153,9 @@ program
153
153
  // 合并结果
154
154
  allResults.success = allResults.success.concat(results.success);
155
155
  allResults.failed = allResults.failed.concat(results.failed);
156
+ if (results.files) {
157
+ allResults.files = allResults.files.concat(results.files);
158
+ }
156
159
  }
157
160
  const results = allResults;
158
161
  // 输出结果
@@ -171,6 +174,13 @@ program
171
174
  console.log(`- ${file.file}: ${file.error}`);
172
175
  });
173
176
  }
177
+ // 如果有files字段,显示目录下的所有文件
178
+ if (results.files && results.files.length > 0) {
179
+ console.log('\n目录下的所有文件:');
180
+ results.files.forEach(file => {
181
+ console.log(`- ${file}`);
182
+ });
183
+ }
174
184
  }
175
185
  catch (err) {
176
186
  console.error(`上传错误: ${err instanceof Error ? err.message : String(err)}`);
@@ -283,6 +293,13 @@ program
283
293
  console.log(` ✗ ${file.file}: ${file.error}`);
284
294
  });
285
295
  }
296
+ // 显示目录下的所有文件
297
+ if (result.files && result.files.length > 0) {
298
+ console.log('\n目录下的所有文件:');
299
+ result.files.forEach((file) => {
300
+ console.log(`- ${file}`);
301
+ });
302
+ }
286
303
  }
287
304
  catch (err) {
288
305
  console.error(`上传错误: ${err instanceof Error ? err.message : String(err)}`);
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-yuca",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "一个用AI生成的开发辅助工具",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -198,18 +198,26 @@ async function updateEnvironmentConfig(env, projectName, versionInfo, config, ke
198
198
  let projectConfig = envConfig.projects.find((p) => p.name === projectName);
199
199
  if (!projectConfig) {
200
200
  projectConfig = {
201
+ baseUrl: versionInfo.baseUrl,
202
+ s3Static: config.upload.s3Static,
203
+ branch: versionInfo.branch,
204
+ links: versionInfo.links,
201
205
  name: projectName,
202
206
  latestVersion: versionInfo.cdnKey,
203
- versions: [versionInfo]
207
+ cdnVersion: versionInfo.cdnKey,
204
208
  };
205
209
  envConfig.projects.push(projectConfig);
206
210
  }
207
211
  else {
208
- projectConfig.latestVersion = versionInfo.cdnKey;
209
- projectConfig.versions = projectConfig.versions || [];
210
- projectConfig.versions.push(versionInfo);
211
- // 保留最近50个版本
212
- projectConfig.versions = projectConfig.versions.slice(-50);
212
+ projectConfig = {
213
+ baseUrl: versionInfo.baseUrl,
214
+ s3Static: config.upload.s3Static,
215
+ branch: versionInfo.branch,
216
+ links: versionInfo.links,
217
+ name: projectName,
218
+ latestVersion: versionInfo.cdnKey,
219
+ cdnVersion: versionInfo.cdnKey,
220
+ };
213
221
  }
214
222
  // 上传更新后的环境配置
215
223
  const configPath = `${config.aws.prefix}/static/config/${env}.config.json`;
@@ -230,6 +238,7 @@ async function updateEnvironmentConfig(env, projectName, versionInfo, config, ke
230
238
  * 执行deploy命令
231
239
  */
232
240
  async function deployFiles(options) {
241
+ var _a;
233
242
  try {
234
243
  console.log('🚀 开始部署流程...');
235
244
  // 1. 配置校验阶段
@@ -237,12 +246,16 @@ async function deployFiles(options) {
237
246
  const config = validateConfig(options.config);
238
247
  // 2. 执行upload-config阶段
239
248
  console.log('📤 执行upload-config上传配置文件...');
249
+ let files = [];
240
250
  try {
241
- await (0, uploadWithConfig_1.uploadFilesWithConfig)({
251
+ const res = await (0, uploadWithConfig_1.uploadFilesWithConfig)({
242
252
  configPath: options.config,
243
253
  storageClientOptions: options.keyFile ? { keyFilename: options.keyFile } : {},
244
254
  enableCache: true
245
255
  });
256
+ if ((_a = res.files) === null || _a === void 0 ? void 0 : _a.length) {
257
+ files = res.files;
258
+ }
246
259
  }
247
260
  catch (error) {
248
261
  console.warn(`⚠️ upload-config执行失败: ${error instanceof Error ? error.message : String(error)}`);
@@ -258,18 +271,18 @@ async function deployFiles(options) {
258
271
  const projectInfo = getProjectInfo();
259
272
  console.log('🔍 筛选目标文件...');
260
273
  const sourcePath = options.source || uploadConfig.sourcePath;
261
- const files = filterHtmlFiles(sourcePath);
262
- const cdnFiles = files.map(file => ({ key: path.relative(sourcePath, file) }));
274
+ const htmlFiles = filterHtmlFiles(sourcePath);
275
+ const cdnFiles = htmlFiles.map(file => ({ key: path.relative(sourcePath, file) }));
263
276
  console.log('📁 定义基础路径...');
264
277
  const prefix = `${config.aws.prefix}/${config.upload.s3Static}`;
265
- if (files.length === 0) {
278
+ if (htmlFiles.length === 0) {
266
279
  throw new Error('未找到需要上传的HTML文件');
267
280
  }
268
281
  // 5. 文件处理与上传阶段
269
282
  console.log('📤 上传原始HTML文件...');
270
283
  const uploadedFiles = [];
271
284
  // 使用Promise.all并行上传文件
272
- const uploadPromises = files.map(file => {
285
+ const uploadPromises = htmlFiles.map(file => {
273
286
  const relativePath = path.relative(sourcePath, file);
274
287
  const destination = `${prefix}/${cdnKey}/${relativePath}`;
275
288
  console.log(` 上传: ${relativePath}`);
@@ -294,18 +307,18 @@ async function deployFiles(options) {
294
307
  }
295
308
  // 6. 发布配置文件上传阶段
296
309
  console.log('📝 生成发布信息对象...');
297
- const langCdnHtml = []; // 多语言HTML文件,暂时为空
298
310
  const obj = {
299
311
  cdnVersion: cdnKey,
300
312
  name: projectInfo.name,
301
313
  baseUrl: config.deploy.baseUrl,
302
- links: [...cdnFiles.map(v => v.key), ...langCdnHtml],
314
+ links: uploadedFiles,
303
315
  s3Static: config.upload.s3Static,
304
- branch: getBranchName()
316
+ branch: getBranchName(),
317
+ files
305
318
  };
306
319
  console.log('📤 上传版本配置文件...');
307
320
  const versionConfigPath = `${config.aws.prefix}/static/config/${options.env}/${projectInfo.name}/${cdnKey}.json`;
308
- const versionConfigContent = JSON.stringify({ obj, files: uploadedFiles }, null, 2);
321
+ const versionConfigContent = JSON.stringify(obj, null, 2);
309
322
  // 创建临时文件上传JSON内容
310
323
  const tempVersionFile = path.join(process.cwd(), `.temp-version-${cdnKey}.json`);
311
324
  fs.writeFileSync(tempVersionFile, versionConfigContent);
@@ -332,7 +345,7 @@ async function deployFiles(options) {
332
345
  // 这里应该从GCP读取现有版本列表,暂时跳过
333
346
  versionList = [cdnKey]; // 简化处理
334
347
  }
335
- catch (_a) {
348
+ catch (_b) {
336
349
  versionList = [cdnKey];
337
350
  }
338
351
  // 保留最近50个版本
@@ -387,7 +400,7 @@ async function deployFiles(options) {
387
400
  baseUrl: Array.isArray(config.deploy.baseUrl) ? config.deploy.baseUrl[0] : config.deploy.baseUrl,
388
401
  branch: getBranchName(),
389
402
  timestamp: Date.now(),
390
- files: obj.links
403
+ links: obj.links
391
404
  };
392
405
  const projectConfigUpdate = await updateEnvironmentConfig(options.env, projectInfo.name, versionInfo, config, options.keyFile);
393
406
  console.log('项目配置信息上传结果:', JSON.stringify(projectConfigUpdate));
@@ -40,7 +40,7 @@ export interface DeployVersionInfo {
40
40
  baseUrl: string;
41
41
  branch?: string;
42
42
  timestamp: number;
43
- files: string[];
43
+ links: string[];
44
44
  }
45
45
  export interface EnvironmentConfig {
46
46
  projects: ProjectConfig[];
@@ -72,6 +72,10 @@ export type UploadResult = UploadSuccessResult | UploadFailedResult;
72
72
  export interface UploadFilesResult {
73
73
  success: UploadSuccessResult[];
74
74
  failed: UploadFailedResult[];
75
+ /**
76
+ * 当源路径为目录时,返回该目录下所有文件的相对路径
77
+ */
78
+ files?: string[];
75
79
  }
76
80
  /**
77
81
  * CLI上传命令选项接口
@@ -3,6 +3,14 @@
3
3
  */
4
4
  import { Storage } from '@google-cloud/storage';
5
5
  import { StorageClientOptions, UploadFileOptions, UploadFilesOptions, UploadResult, UploadFilesResult } from './types/upload';
6
+ /**
7
+ * 递归收集目录下所有文件的相对路径
8
+ * @param dirPath - 目录路径
9
+ * @param basePath - 基础路径,用于计算相对路径
10
+ * @param recursive - 是否递归
11
+ * @returns 文件相对路径数组
12
+ */
13
+ declare function collectFiles(dirPath: string, basePath: string, recursive?: boolean): Promise<string[]>;
6
14
  /**
7
15
  * 创建GCP存储客户端
8
16
  * @param options - 配置选项
@@ -21,4 +29,4 @@ declare function uploadFile(options: UploadFileOptions): Promise<UploadResult>;
21
29
  * @returns 上传结果
22
30
  */
23
31
  declare function uploadFiles(options: UploadFilesOptions): Promise<UploadFilesResult>;
24
- export { createStorageClient, uploadFile, uploadFiles };
32
+ export { createStorageClient, uploadFile, uploadFiles, collectFiles };
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.createStorageClient = createStorageClient;
37
37
  exports.uploadFile = uploadFile;
38
38
  exports.uploadFiles = uploadFiles;
39
+ exports.collectFiles = collectFiles;
39
40
  /**
40
41
  * GCP上传功能模块
41
42
  */
@@ -47,6 +48,32 @@ const compression_1 = require("./utils/compression");
47
48
  const config_1 = require("./config");
48
49
  const readdir = util.promisify(fs.readdir);
49
50
  const stat = util.promisify(fs.stat);
51
+ /**
52
+ * 递归收集目录下所有文件的相对路径
53
+ * @param dirPath - 目录路径
54
+ * @param basePath - 基础路径,用于计算相对路径
55
+ * @param recursive - 是否递归
56
+ * @returns 文件相对路径数组
57
+ */
58
+ async function collectFiles(dirPath, basePath, recursive = false) {
59
+ const files = [];
60
+ const items = await readdir(dirPath);
61
+ for (const item of items) {
62
+ const itemPath = path.join(dirPath, item);
63
+ const itemStats = await stat(itemPath);
64
+ if (itemStats.isFile()) {
65
+ // 计算相对于basePath的相对路径
66
+ const relativePath = path.relative(basePath, itemPath);
67
+ files.push(relativePath);
68
+ }
69
+ else if (recursive && itemStats.isDirectory()) {
70
+ // 递归收集子目录中的文件
71
+ const subFiles = await collectFiles(itemPath, basePath, recursive);
72
+ files.push(...subFiles);
73
+ }
74
+ }
75
+ return files;
76
+ }
50
77
  /**
51
78
  * 创建GCP存储客户端
52
79
  * @param options - 配置选项
@@ -186,11 +213,20 @@ async function uploadFiles(options) {
186
213
  }
187
214
  const results = {
188
215
  success: [],
189
- failed: []
216
+ failed: [],
217
+ files: []
190
218
  };
191
219
  try {
192
220
  // 如果sourcePath是数组,批量上传多个文件
193
221
  if (Array.isArray(sourcePath)) {
222
+ for (const filePath of sourcePath) {
223
+ const stats = await stat(filePath);
224
+ if (stats.isDirectory()) {
225
+ // 如果是目录,收集其中的文件
226
+ const dirFiles = await collectFiles(filePath, filePath, recursive);
227
+ results.files = results.files.concat(dirFiles);
228
+ }
229
+ }
194
230
  const uploadPromises = sourcePath.map(filePath => uploadFile({
195
231
  bucketName,
196
232
  filePath,
@@ -228,6 +264,9 @@ async function uploadFiles(options) {
228
264
  }
229
265
  }
230
266
  else if (stats.isDirectory()) {
267
+ // 收集目录下所有文件的相对路径
268
+ const allFiles = await collectFiles(sourcePath, sourcePath, recursive);
269
+ results.files = allFiles;
231
270
  // 上传目录中的文件
232
271
  const files = await readdir(sourcePath);
233
272
  // 分离文件和目录
@@ -278,6 +317,11 @@ async function uploadFiles(options) {
278
317
  for (const subResults of dirResults) {
279
318
  results.success = results.success.concat(subResults.success);
280
319
  results.failed = results.failed.concat(subResults.failed);
320
+ // 合并子目录的files字段
321
+ if (subResults.files) {
322
+ results.files = results.files || [];
323
+ results.files = results.files.concat(subResults.files);
324
+ }
281
325
  }
282
326
  }
283
327
  }
@@ -161,7 +161,7 @@ async function uploadFilesWithConfig(options = {}) {
161
161
  // 如果没有文件需要上传,直接返回
162
162
  if (filesToUpload.length === 0) {
163
163
  console.log('所有文件都已上传,无需重复上传。');
164
- return {
164
+ const result = {
165
165
  success: skippedFiles.map(file => ({
166
166
  success: true,
167
167
  file,
@@ -171,8 +171,21 @@ async function uploadFilesWithConfig(options = {}) {
171
171
  contentType: 'application/octet-stream',
172
172
  timeCreated: new Date().toISOString()
173
173
  })),
174
- failed: []
174
+ failed: [],
175
+ files: []
175
176
  };
177
+ // 收集目录下所有文件的相对路径
178
+ try {
179
+ const stats = await stat(sourcePath);
180
+ if (stats.isDirectory()) {
181
+ const allFiles = await (0, upload_1.collectFiles)(sourcePath, sourcePath, recursive);
182
+ result.files = allFiles;
183
+ }
184
+ }
185
+ catch (error) {
186
+ console.warn('收集文件列表时出错:', error);
187
+ }
188
+ return result;
176
189
  }
177
190
  }
178
191
  // 执行批量上传
@@ -221,6 +234,18 @@ async function uploadFilesWithConfig(options = {}) {
221
234
  }));
222
235
  result.success.push(...skippedResults);
223
236
  }
237
+ // 收集目录下所有文件的相对路径
238
+ try {
239
+ const stats = await stat(sourcePath);
240
+ if (stats.isDirectory()) {
241
+ const allFiles = await (0, upload_1.collectFiles)(sourcePath, sourcePath, recursive);
242
+ result.files = allFiles;
243
+ }
244
+ }
245
+ catch (error) {
246
+ // 如果收集文件失败,不影响主要功能
247
+ console.warn('收集文件列表时出错:', error);
248
+ }
224
249
  return result;
225
250
  }
226
251
  catch (error) {
File without changes
package/out/ss/dd.js ADDED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-yuca",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "一个用AI生成的开发辅助工具",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
package/src/deploy.ts CHANGED
@@ -205,17 +205,25 @@ async function updateEnvironmentConfig(
205
205
 
206
206
  if (!projectConfig) {
207
207
  projectConfig = {
208
+ baseUrl: versionInfo.baseUrl,
209
+ s3Static:config.upload.s3Static,
210
+ branch: versionInfo.branch,
211
+ links: versionInfo.links,
208
212
  name: projectName,
209
213
  latestVersion: versionInfo.cdnKey,
210
- versions: [versionInfo]
214
+ cdnVersion: versionInfo.cdnKey,
211
215
  };
212
216
  envConfig.projects.push(projectConfig);
213
217
  } else {
214
- projectConfig.latestVersion = versionInfo.cdnKey;
215
- projectConfig.versions = projectConfig.versions || [];
216
- projectConfig.versions.push(versionInfo);
217
- // 保留最近50个版本
218
- projectConfig.versions = projectConfig.versions.slice(-50);
218
+ projectConfig = {
219
+ baseUrl: versionInfo.baseUrl,
220
+ s3Static:config.upload.s3Static,
221
+ branch: versionInfo.branch,
222
+ links: versionInfo.links,
223
+ name: projectName,
224
+ latestVersion: versionInfo.cdnKey,
225
+ cdnVersion: versionInfo.cdnKey,
226
+ };
219
227
  }
220
228
 
221
229
  // 上传更新后的环境配置
@@ -252,12 +260,16 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
252
260
 
253
261
  // 2. 执行upload-config阶段
254
262
  console.log('📤 执行upload-config上传配置文件...');
263
+ let files: string[] = [];
255
264
  try {
256
- await uploadFilesWithConfig({
265
+ const res = await uploadFilesWithConfig({
257
266
  configPath: options.config,
258
267
  storageClientOptions: options.keyFile ? { keyFilename: options.keyFile } : {},
259
268
  enableCache: true
260
269
  });
270
+ if (res.files?.length){
271
+ files = res.files;
272
+ }
261
273
  } catch (error) {
262
274
  console.warn(`⚠️ upload-config执行失败: ${error instanceof Error ? error.message : String(error)}`);
263
275
  }
@@ -276,13 +288,13 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
276
288
 
277
289
  console.log('🔍 筛选目标文件...');
278
290
  const sourcePath = options.source || uploadConfig.sourcePath;
279
- const files = filterHtmlFiles(sourcePath);
280
- const cdnFiles = files.map(file => ({ key: path.relative(sourcePath, file) }));
291
+ const htmlFiles = filterHtmlFiles(sourcePath);
292
+ const cdnFiles = htmlFiles.map(file => ({ key: path.relative(sourcePath, file) }));
281
293
 
282
294
  console.log('📁 定义基础路径...');
283
295
  const prefix = `${config.aws.prefix}/${config.upload.s3Static}`;
284
296
 
285
- if (files.length === 0) {
297
+ if (htmlFiles.length === 0) {
286
298
  throw new Error('未找到需要上传的HTML文件');
287
299
  }
288
300
 
@@ -291,7 +303,7 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
291
303
  const uploadedFiles: string[] = [];
292
304
 
293
305
  // 使用Promise.all并行上传文件
294
- const uploadPromises = files.map(file => {
306
+ const uploadPromises = htmlFiles.map(file => {
295
307
  const relativePath = path.relative(sourcePath, file);
296
308
  const destination = `${prefix}/${cdnKey}/${relativePath}`;
297
309
 
@@ -319,19 +331,19 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
319
331
 
320
332
  // 6. 发布配置文件上传阶段
321
333
  console.log('📝 生成发布信息对象...');
322
- const langCdnHtml: string[] = []; // 多语言HTML文件,暂时为空
323
334
  const obj = {
324
335
  cdnVersion: cdnKey,
325
336
  name: projectInfo.name,
326
337
  baseUrl: config.deploy.baseUrl,
327
- links: [...cdnFiles.map(v => v.key), ...langCdnHtml],
338
+ links: uploadedFiles,
328
339
  s3Static: config.upload.s3Static,
329
- branch: getBranchName()
340
+ branch: getBranchName(),
341
+ files
330
342
  };
331
343
 
332
344
  console.log('📤 上传版本配置文件...');
333
345
  const versionConfigPath = `${config.aws.prefix}/static/config/${options.env}/${projectInfo.name}/${cdnKey}.json`;
334
- const versionConfigContent = JSON.stringify({ obj, files: uploadedFiles }, null, 2);
346
+ const versionConfigContent = JSON.stringify(obj, null, 2);
335
347
 
336
348
  // 创建临时文件上传JSON内容
337
349
  const tempVersionFile = path.join(process.cwd(), `.temp-version-${cdnKey}.json`);
@@ -422,7 +434,7 @@ export async function deployFiles(options: DeployCommandOptions): Promise<Deploy
422
434
  baseUrl: Array.isArray(config.deploy.baseUrl) ? config.deploy.baseUrl[0] : config.deploy.baseUrl,
423
435
  branch: getBranchName(),
424
436
  timestamp: Date.now(),
425
- files: obj.links
437
+ links: obj.links
426
438
  };
427
439
 
428
440
  const projectConfigUpdate = await updateEnvironmentConfig(options.env, projectInfo.name, versionInfo, config, options.keyFile);
@@ -45,7 +45,7 @@ export interface DeployVersionInfo {
45
45
  baseUrl: string;
46
46
  branch?: string;
47
47
  timestamp: number;
48
- files: string[];
48
+ links: string[];
49
49
  }
50
50
 
51
51
  export interface EnvironmentConfig {
@@ -79,6 +79,10 @@ export type UploadResult = UploadSuccessResult | UploadFailedResult;
79
79
  export interface UploadFilesResult {
80
80
  success: UploadSuccessResult[];
81
81
  failed: UploadFailedResult[];
82
+ /**
83
+ * 当源路径为目录时,返回该目录下所有文件的相对路径
84
+ */
85
+ files?: string[];
82
86
  }
83
87
 
84
88
  /**
package/src/upload.ts CHANGED
@@ -20,6 +20,35 @@ import { loadConfig } from './config';
20
20
  const readdir = util.promisify(fs.readdir);
21
21
  const stat = util.promisify(fs.stat);
22
22
 
23
+ /**
24
+ * 递归收集目录下所有文件的相对路径
25
+ * @param dirPath - 目录路径
26
+ * @param basePath - 基础路径,用于计算相对路径
27
+ * @param recursive - 是否递归
28
+ * @returns 文件相对路径数组
29
+ */
30
+ async function collectFiles(dirPath: string, basePath: string, recursive: boolean = false): Promise<string[]> {
31
+ const files: string[] = [];
32
+ const items = await readdir(dirPath);
33
+
34
+ for (const item of items) {
35
+ const itemPath = path.join(dirPath, item);
36
+ const itemStats = await stat(itemPath);
37
+
38
+ if (itemStats.isFile()) {
39
+ // 计算相对于basePath的相对路径
40
+ const relativePath = path.relative(basePath, itemPath);
41
+ files.push(relativePath);
42
+ } else if (recursive && itemStats.isDirectory()) {
43
+ // 递归收集子目录中的文件
44
+ const subFiles = await collectFiles(itemPath, basePath, recursive);
45
+ files.push(...subFiles);
46
+ }
47
+ }
48
+
49
+ return files;
50
+ }
51
+
23
52
  /**
24
53
  * 创建GCP存储客户端
25
54
  * @param options - 配置选项
@@ -177,12 +206,22 @@ async function uploadFiles(options: UploadFilesOptions): Promise<UploadFilesResu
177
206
 
178
207
  const results: UploadFilesResult = {
179
208
  success: [],
180
- failed: []
209
+ failed: [],
210
+ files: []
181
211
  };
182
212
 
183
213
  try {
184
214
  // 如果sourcePath是数组,批量上传多个文件
185
215
  if (Array.isArray(sourcePath)) {
216
+ for (const filePath of sourcePath) {
217
+ const stats = await stat(filePath);
218
+ if (stats.isDirectory()) {
219
+ // 如果是目录,收集其中的文件
220
+ const dirFiles = await collectFiles(filePath, filePath, recursive);
221
+ results.files = results.files!.concat(dirFiles);
222
+ }
223
+ }
224
+
186
225
  const uploadPromises = sourcePath.map(filePath =>
187
226
  uploadFile({
188
227
  bucketName,
@@ -224,6 +263,10 @@ async function uploadFiles(options: UploadFilesOptions): Promise<UploadFilesResu
224
263
  results.failed.push(result);
225
264
  }
226
265
  } else if (stats.isDirectory()) {
266
+ // 收集目录下所有文件的相对路径
267
+ const allFiles = await collectFiles(sourcePath, sourcePath, recursive);
268
+ results.files = allFiles;
269
+
227
270
  // 上传目录中的文件
228
271
  const files = await readdir(sourcePath);
229
272
 
@@ -283,6 +326,11 @@ async function uploadFiles(options: UploadFilesOptions): Promise<UploadFilesResu
283
326
  for (const subResults of dirResults) {
284
327
  results.success = results.success.concat(subResults.success);
285
328
  results.failed = results.failed.concat(subResults.failed);
329
+ // 合并子目录的files字段
330
+ if (subResults.files) {
331
+ results.files = results.files || [];
332
+ results.files = results.files.concat(subResults.files);
333
+ }
286
334
  }
287
335
  }
288
336
  }
@@ -296,5 +344,6 @@ async function uploadFiles(options: UploadFilesOptions): Promise<UploadFilesResu
296
344
  export {
297
345
  createStorageClient,
298
346
  uploadFile,
299
- uploadFiles
347
+ uploadFiles,
348
+ collectFiles
300
349
  };
@@ -6,7 +6,7 @@ import * as path from 'path';
6
6
  import * as fs from 'fs';
7
7
  import chalk from 'chalk';
8
8
  import { StorageClientOptions, UploadFilesResult } from './types/upload';
9
- import { uploadFiles } from './upload';
9
+ import { uploadFiles, collectFiles } from './upload';
10
10
  import { loadConfig, getBucketName, getUploadDestination, getUploadSourcePath, VSConfig } from './config';
11
11
  import { CacheManager, createCacheManager } from './cache';
12
12
 
@@ -171,7 +171,7 @@ export async function uploadFilesWithConfig(options: UploadWithConfigOptions = {
171
171
  // 如果没有文件需要上传,直接返回
172
172
  if (filesToUpload.length === 0) {
173
173
  console.log('所有文件都已上传,无需重复上传。');
174
- return {
174
+ const result = {
175
175
  success: skippedFiles.map(file => ({
176
176
  success: true as const,
177
177
  file,
@@ -181,8 +181,22 @@ export async function uploadFilesWithConfig(options: UploadWithConfigOptions = {
181
181
  contentType: 'application/octet-stream',
182
182
  timeCreated: new Date().toISOString()
183
183
  })),
184
- failed: []
184
+ failed: [],
185
+ files: [] as string[]
185
186
  };
187
+
188
+ // 收集目录下所有文件的相对路径
189
+ try {
190
+ const stats = await stat(sourcePath);
191
+ if (stats.isDirectory()) {
192
+ const allFiles = await collectFiles(sourcePath, sourcePath, recursive);
193
+ result.files = allFiles;
194
+ }
195
+ } catch (error) {
196
+ console.warn('收集文件列表时出错:', error);
197
+ }
198
+
199
+ return result;
186
200
  }
187
201
  }
188
202
 
@@ -236,6 +250,18 @@ export async function uploadFilesWithConfig(options: UploadWithConfigOptions = {
236
250
  result.success.push(...skippedResults);
237
251
  }
238
252
 
253
+ // 收集目录下所有文件的相对路径
254
+ try {
255
+ const stats = await stat(sourcePath);
256
+ if (stats.isDirectory()) {
257
+ const allFiles = await collectFiles(sourcePath, sourcePath, recursive);
258
+ result.files = allFiles;
259
+ }
260
+ } catch (error) {
261
+ // 如果收集文件失败,不影响主要功能
262
+ console.warn('收集文件列表时出错:', error);
263
+ }
264
+
239
265
  return result;
240
266
  } catch (error) {
241
267
  throw new Error(`基于配置文件的上传失败: ${error instanceof Error ? error.message : String(error)}`);