sa2kit 1.2.0 → 1.3.0

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.
Files changed (49) hide show
  1. package/dist/{UniversalFileService-CEZRJ87g.d.mts → UniversalFileService-BuHN-jrR.d.ts} +47 -259
  2. package/dist/{UniversalFileService-CEZRJ87g.d.ts → UniversalFileService-CGGzYeeF.d.mts} +47 -259
  3. package/dist/{chunk-3XG5OHFD.mjs → chunk-CIVO4R6N.mjs} +2 -2
  4. package/dist/{chunk-3XG5OHFD.mjs.map → chunk-CIVO4R6N.mjs.map} +1 -1
  5. package/dist/chunk-EV6BCVOQ.mjs +204 -0
  6. package/dist/chunk-EV6BCVOQ.mjs.map +1 -0
  7. package/dist/chunk-W35VTQAW.js +211 -0
  8. package/dist/chunk-W35VTQAW.js.map +1 -0
  9. package/dist/{chunk-HWJ34NL6.js → chunk-ZRAW3HXA.js} +2 -2
  10. package/dist/{chunk-HWJ34NL6.js.map → chunk-ZRAW3HXA.js.map} +1 -1
  11. package/dist/drizzle-schema-BNhqj2AZ.d.mts +1114 -0
  12. package/dist/drizzle-schema-BNhqj2AZ.d.ts +1114 -0
  13. package/dist/mmd/admin/index.d.mts +487 -0
  14. package/dist/mmd/admin/index.d.ts +487 -0
  15. package/dist/mmd/admin/index.js +871 -0
  16. package/dist/mmd/admin/index.js.map +1 -0
  17. package/dist/mmd/admin/index.mjs +822 -0
  18. package/dist/mmd/admin/index.mjs.map +1 -0
  19. package/dist/mmd/index.d.mts +4 -193
  20. package/dist/mmd/index.d.ts +4 -193
  21. package/dist/mmd/server/index.d.mts +138 -0
  22. package/dist/mmd/server/index.d.ts +138 -0
  23. package/dist/mmd/server/index.js +245 -0
  24. package/dist/mmd/server/index.js.map +1 -0
  25. package/dist/mmd/server/index.mjs +207 -0
  26. package/dist/mmd/server/index.mjs.map +1 -0
  27. package/dist/testYourself/index.d.mts +145 -0
  28. package/dist/testYourself/index.d.ts +145 -0
  29. package/dist/testYourself/index.js +1004 -0
  30. package/dist/testYourself/index.js.map +1 -0
  31. package/dist/testYourself/index.mjs +993 -0
  32. package/dist/testYourself/index.mjs.map +1 -0
  33. package/dist/types-Bc_p-zAR.d.mts +194 -0
  34. package/dist/types-Bc_p-zAR.d.ts +194 -0
  35. package/dist/types-CK4We_aI.d.mts +270 -0
  36. package/dist/types-CK4We_aI.d.ts +270 -0
  37. package/dist/universalFile/index.d.mts +3 -2
  38. package/dist/universalFile/index.d.ts +3 -2
  39. package/dist/universalFile/index.js +48 -10
  40. package/dist/universalFile/index.js.map +1 -1
  41. package/dist/universalFile/index.mjs +43 -5
  42. package/dist/universalFile/index.mjs.map +1 -1
  43. package/dist/universalFile/server/index.d.mts +3 -2
  44. package/dist/universalFile/server/index.d.ts +3 -2
  45. package/dist/universalFile/server/index.js +239 -7
  46. package/dist/universalFile/server/index.js.map +1 -1
  47. package/dist/universalFile/server/index.mjs +234 -2
  48. package/dist/universalFile/server/index.mjs.map +1 -1
  49. package/package.json +19 -1
@@ -4,7 +4,7 @@ var chunkTKCYPDWU_js = require('../../chunk-TKCYPDWU.js');
4
4
  var chunk3RFBUDRA_js = require('../../chunk-3RFBUDRA.js');
5
5
  var chunkKH6RQ4J5_js = require('../../chunk-KH6RQ4J5.js');
6
6
  var chunk6PRFP5EG_js = require('../../chunk-6PRFP5EG.js');
7
- var chunkHWJ34NL6_js = require('../../chunk-HWJ34NL6.js');
7
+ var chunkZRAW3HXA_js = require('../../chunk-ZRAW3HXA.js');
8
8
  var chunkDGUM43GV_js = require('../../chunk-DGUM43GV.js');
9
9
  var crypto = require('crypto');
10
10
  var path3 = require('path');
@@ -3083,7 +3083,7 @@ var UniversalFileService = class extends events.EventEmitter {
3083
3083
  }
3084
3084
  }
3085
3085
  if (!storageProvider) {
3086
- throw new chunkHWJ34NL6_js.StorageProviderError(`\u6CA1\u6709\u53EF\u7528\u7684\u5B58\u50A8\u63D0\u4F9B\u8005`);
3086
+ throw new chunkZRAW3HXA_js.StorageProviderError(`\u6CA1\u6709\u53EF\u7528\u7684\u5B58\u50A8\u63D0\u4F9B\u8005`);
3087
3087
  }
3088
3088
  const storagePath = this.generateStoragePath(metadata);
3089
3089
  progress.status = "uploading";
@@ -3093,7 +3093,7 @@ var UniversalFileService = class extends events.EventEmitter {
3093
3093
  this.emitFileEvent("upload:progress", fileId, { progress: progress.progress });
3094
3094
  const uploadResult = await storageProvider.upload(fileInfo, storagePath);
3095
3095
  if (!uploadResult.success) {
3096
- throw new chunkHWJ34NL6_js.FileUploadError(`\u4E0A\u4F20\u5931\u8D25: ${uploadResult.error}`);
3096
+ throw new chunkZRAW3HXA_js.FileUploadError(`\u4E0A\u4F20\u5931\u8D25: ${uploadResult.error}`);
3097
3097
  }
3098
3098
  metadata.storagePath = uploadResult.path || storagePath;
3099
3099
  metadata.storageProvider = selectedStorageType;
@@ -3148,6 +3148,174 @@ var UniversalFileService = class extends events.EventEmitter {
3148
3148
  );
3149
3149
  }
3150
3150
  }
3151
+ /**
3152
+ * 下载文件
3153
+ */
3154
+ async downloadFile(fileId, userId) {
3155
+ logger6.info(`\u{1F4E5} [UniversalFileService] \u5F00\u59CB\u4E0B\u8F7D\u6587\u4EF6: ${fileId}`);
3156
+ try {
3157
+ this.emitFileEvent("download:start", fileId);
3158
+ const metadata = await this.getFileMetadata(fileId);
3159
+ if (!metadata) {
3160
+ throw new chunkZRAW3HXA_js.FileUploadError(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${fileId}`);
3161
+ }
3162
+ await this.checkFileAccess(metadata, userId);
3163
+ const storageProvider = this.storageProviders.get(metadata.storageProvider);
3164
+ if (!storageProvider) {
3165
+ throw new chunkZRAW3HXA_js.StorageProviderError(`\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: ${metadata.storageProvider}`);
3166
+ }
3167
+ const fileBuffer = await storageProvider.download(metadata.storagePath);
3168
+ if (this.config.persistence?.enabled) {
3169
+ await this.updateAccessStats(fileId);
3170
+ }
3171
+ logger6.info(`\u2705 [UniversalFileService] \u6587\u4EF6\u4E0B\u8F7D\u5B8C\u6210: ${fileId}`);
3172
+ this.emitFileEvent("download:complete", fileId, { size: fileBuffer.length });
3173
+ return fileBuffer;
3174
+ } catch (error) {
3175
+ console.error(`\u274C [UniversalFileService] \u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25: ${fileId}:`, error);
3176
+ this.emitFileEvent("download:error", fileId, void 0, error instanceof Error ? error.message : "\u4E0B\u8F7D\u5931\u8D25");
3177
+ throw error;
3178
+ }
3179
+ }
3180
+ /**
3181
+ * 删除文件
3182
+ */
3183
+ async deleteFile(fileId, userId) {
3184
+ logger6.info(`\u{1F5D1}\uFE0F [UniversalFileService] \u5F00\u59CB\u5220\u9664\u6587\u4EF6: ${fileId}`);
3185
+ try {
3186
+ const metadata = await this.getFileMetadata(fileId);
3187
+ if (!metadata) {
3188
+ throw new chunkZRAW3HXA_js.FileUploadError(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${fileId}`);
3189
+ }
3190
+ await this.checkFileDeleteAccess(metadata, userId);
3191
+ const storageProvider = this.storageProviders.get(metadata.storageProvider);
3192
+ if (!storageProvider) {
3193
+ throw new chunkZRAW3HXA_js.StorageProviderError(`\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: ${metadata.storageProvider}`);
3194
+ }
3195
+ const deleteResult = await storageProvider.delete(metadata.storagePath);
3196
+ if (!deleteResult.success) {
3197
+ console.warn(`\u26A0\uFE0F [UniversalFileService] \u5B58\u50A8\u6587\u4EF6\u5220\u9664\u5931\u8D25: ${deleteResult.error}`);
3198
+ }
3199
+ if (this.config.persistence?.enabled) {
3200
+ await this.deleteFileMetadata(fileId);
3201
+ }
3202
+ this.clearMetadataCache(fileId);
3203
+ logger6.info(`\u2705 [UniversalFileService] \u6587\u4EF6\u5220\u9664\u5B8C\u6210: ${fileId}`);
3204
+ this.emitFileEvent("delete:complete", fileId);
3205
+ this.emit("file:deleted", fileId);
3206
+ } catch (error) {
3207
+ console.error(`\u274C [UniversalFileService] \u6587\u4EF6\u5220\u9664\u5931\u8D25: ${fileId}:`, error);
3208
+ this.emitFileEvent("delete:error", fileId, void 0, error instanceof Error ? error.message : "\u5220\u9664\u5931\u8D25");
3209
+ throw error;
3210
+ }
3211
+ }
3212
+ /**
3213
+ * 获取文件访问URL
3214
+ */
3215
+ async getFileUrl(fileId, userId, expiresIn) {
3216
+ const cacheKey = `${fileId}_${userId || "public"}_${expiresIn || 0}`;
3217
+ const cached = this.urlCache.get(cacheKey);
3218
+ if (cached && cached.expires > Date.now()) {
3219
+ return cached.url;
3220
+ }
3221
+ const metadata = await this.getFileMetadata(fileId);
3222
+ if (!metadata) {
3223
+ throw new chunkZRAW3HXA_js.FileUploadError(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${fileId}`);
3224
+ }
3225
+ await this.checkFileAccess(metadata, userId);
3226
+ let url;
3227
+ if (metadata.cdnUrl) {
3228
+ url = metadata.cdnUrl;
3229
+ } else {
3230
+ const storageProvider = this.storageProviders.get(metadata.storageProvider);
3231
+ if (!storageProvider) {
3232
+ throw new chunkZRAW3HXA_js.StorageProviderError(`\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: ${metadata.storageProvider}`);
3233
+ }
3234
+ url = await storageProvider.getAccessUrl(metadata.storagePath, expiresIn);
3235
+ }
3236
+ const cacheExpires = Date.now() + (this.config.cache?.urlTTL || 1800) * 1e3;
3237
+ this.urlCache.set(cacheKey, { url, expires: cacheExpires });
3238
+ return url;
3239
+ }
3240
+ /**
3241
+ * 获取文件元数据
3242
+ */
3243
+ async getFileMetadata(fileId) {
3244
+ const cached = this.metadataCache.get(fileId);
3245
+ if (cached && cached.expires > Date.now()) {
3246
+ return cached.data;
3247
+ }
3248
+ if (this.config.persistence?.enabled && this.config.persistence.repository) {
3249
+ try {
3250
+ const metadata = await this.config.persistence.repository.get(fileId);
3251
+ if (metadata) {
3252
+ this.cacheMetadata(metadata);
3253
+ }
3254
+ return metadata;
3255
+ } catch (error) {
3256
+ console.error("\u274C [UniversalFileService] \u67E5\u8BE2\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
3257
+ return null;
3258
+ }
3259
+ }
3260
+ logger6.warn(`\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u65E0\u6CD5\u67E5\u8BE2\u6587\u4EF6\u5143\u6570\u636E: ${fileId}`);
3261
+ return null;
3262
+ }
3263
+ /**
3264
+ * 查询文件列表
3265
+ */
3266
+ async queryFiles(options) {
3267
+ if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
3268
+ logger6.warn("\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u65E0\u6CD5\u67E5\u8BE2\u6587\u4EF6\u5217\u8868");
3269
+ return {
3270
+ items: [],
3271
+ total: 0,
3272
+ page: options.page || 1,
3273
+ pageSize: options.pageSize || 20,
3274
+ totalPages: 0,
3275
+ hasNext: false,
3276
+ hasPrev: false
3277
+ };
3278
+ }
3279
+ try {
3280
+ const result = await this.config.persistence.repository.query(options);
3281
+ const hasNext = result.page < result.totalPages;
3282
+ const hasPrev = result.page > 1;
3283
+ return {
3284
+ ...result,
3285
+ hasNext,
3286
+ hasPrev
3287
+ };
3288
+ } catch (error) {
3289
+ console.error("\u274C [UniversalFileService] \u67E5\u8BE2\u6587\u4EF6\u5217\u8868\u5931\u8D25:", error);
3290
+ throw error;
3291
+ }
3292
+ }
3293
+ /**
3294
+ * 批量删除文件
3295
+ */
3296
+ async batchDeleteFiles(fileIds, userId) {
3297
+ const result = {
3298
+ successCount: 0,
3299
+ failureCount: 0,
3300
+ failures: []
3301
+ };
3302
+ for (const fileId of fileIds) {
3303
+ try {
3304
+ await this.deleteFile(fileId, userId);
3305
+ result.successCount++;
3306
+ } catch (error) {
3307
+ result.failureCount++;
3308
+ result.failures.push({
3309
+ fileId,
3310
+ error: error instanceof Error ? error.message : "\u5220\u9664\u5931\u8D25"
3311
+ });
3312
+ }
3313
+ }
3314
+ if (result.successCount > 0) {
3315
+ this.emit("files:batch-deleted", fileIds.filter((_, i) => i < result.successCount));
3316
+ }
3317
+ return result;
3318
+ }
3151
3319
  /**
3152
3320
  * 获取上传进度
3153
3321
  */
@@ -3231,11 +3399,11 @@ var UniversalFileService = class extends events.EventEmitter {
3231
3399
  }
3232
3400
  async validateFile(file) {
3233
3401
  if (this.config.maxFileSize && file.size > this.config.maxFileSize) {
3234
- throw new chunkHWJ34NL6_js.FileUploadError(`\u6587\u4EF6\u5927\u5C0F\u8D85\u8FC7\u9650\u5236: ${file.size} > ${this.config.maxFileSize}`);
3402
+ throw new chunkZRAW3HXA_js.FileUploadError(`\u6587\u4EF6\u5927\u5C0F\u8D85\u8FC7\u9650\u5236: ${file.size} > ${this.config.maxFileSize}`);
3235
3403
  }
3236
3404
  const mimeType = file.type || getMimeType(file.name);
3237
3405
  if (this.config.allowedMimeTypes && this.config.allowedMimeTypes.length > 0 && !this.config.allowedMimeTypes.includes(mimeType)) {
3238
- throw new chunkHWJ34NL6_js.FileUploadError(`\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B: ${mimeType}`);
3406
+ throw new chunkZRAW3HXA_js.FileUploadError(`\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B: ${mimeType}`);
3239
3407
  }
3240
3408
  }
3241
3409
  async generateFileMetadata(fileId, fileInfo) {
@@ -3285,7 +3453,7 @@ var UniversalFileService = class extends events.EventEmitter {
3285
3453
  return;
3286
3454
  }
3287
3455
  if (this.processingQueue.length >= 1e3) {
3288
- throw new chunkHWJ34NL6_js.FileProcessingError("\u5904\u7406\u961F\u5217\u5DF2\u6EE1");
3456
+ throw new chunkZRAW3HXA_js.FileProcessingError("\u5904\u7406\u961F\u5217\u5DF2\u6EE1");
3289
3457
  }
3290
3458
  this.processingQueue.push({
3291
3459
  fileId: metadata.id,
@@ -3336,7 +3504,7 @@ var UniversalFileService = class extends events.EventEmitter {
3336
3504
  const expires = Date.now() + (this.config.cache?.metadataTTL || 3600) * 1e3;
3337
3505
  this.metadataCache.set(metadata.id, { data: metadata, expires });
3338
3506
  }
3339
- _clearMetadataCache2(fileId) {
3507
+ clearMetadataCache(fileId) {
3340
3508
  this.metadataCache.delete(fileId);
3341
3509
  }
3342
3510
  emitFileEvent(type, fileId, data, error) {
@@ -3350,6 +3518,70 @@ var UniversalFileService = class extends events.EventEmitter {
3350
3518
  this.emit(type, event);
3351
3519
  this.emit("*", event);
3352
3520
  }
3521
+ // ============= 数据库操作私有方法 =============
3522
+ /**
3523
+ * 保存文件元数据到数据库 (通过持久化仓储)
3524
+ */
3525
+ async saveFileMetadata(metadata) {
3526
+ if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
3527
+ logger6.warn("\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u8DF3\u8FC7\u4FDD\u5B58\u5143\u6570\u636E");
3528
+ return;
3529
+ }
3530
+ try {
3531
+ await this.config.persistence.repository.save(metadata);
3532
+ logger6.info("\u{1F4BE} [UniversalFileService] \u6587\u4EF6\u5143\u6570\u636E\u4FDD\u5B58\u6210\u529F:", metadata.id);
3533
+ } catch (error) {
3534
+ console.error("\u274C [UniversalFileService] \u4FDD\u5B58\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
3535
+ throw new chunkZRAW3HXA_js.FileUploadError(
3536
+ `\u4FDD\u5B58\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25: ${error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"}`
3537
+ );
3538
+ }
3539
+ }
3540
+ /**
3541
+ * 从数据库删除文件元数据 (通过持久化仓储)
3542
+ */
3543
+ async deleteFileMetadata(fileId) {
3544
+ if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
3545
+ return;
3546
+ }
3547
+ try {
3548
+ await this.config.persistence.repository.delete(fileId);
3549
+ logger6.info("\u{1F5D1}\uFE0F [UniversalFileService] \u6587\u4EF6\u5143\u6570\u636E\u5220\u9664\u6210\u529F:", fileId);
3550
+ } catch (error) {
3551
+ console.error("\u274C [UniversalFileService] \u5220\u9664\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
3552
+ throw new chunkZRAW3HXA_js.FileUploadError(
3553
+ `\u5220\u9664\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25: ${error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"}`
3554
+ );
3555
+ }
3556
+ }
3557
+ /**
3558
+ * 更新访问统计
3559
+ */
3560
+ async updateAccessStats(fileId) {
3561
+ logger6.info("\u{1F4CA} [UniversalFileService] \u9700\u8981\u66F4\u65B0\u8BBF\u95EE\u7EDF\u8BA1:", fileId);
3562
+ }
3563
+ /**
3564
+ * 检查文件访问权限
3565
+ */
3566
+ async checkFileAccess(metadata, userId) {
3567
+ if (metadata.permission === "public") {
3568
+ return;
3569
+ }
3570
+ if (metadata.permission === "private" && metadata.uploaderId !== userId) {
3571
+ throw new chunkZRAW3HXA_js.FileUploadError("\u65E0\u6743\u9650\u8BBF\u95EE\u6B64\u6587\u4EF6");
3572
+ }
3573
+ if (metadata.permission === "authenticated" && !userId) {
3574
+ throw new chunkZRAW3HXA_js.FileUploadError("\u9700\u8981\u767B\u5F55\u624D\u80FD\u8BBF\u95EE\u6B64\u6587\u4EF6");
3575
+ }
3576
+ }
3577
+ /**
3578
+ * 检查文件删除权限
3579
+ */
3580
+ async checkFileDeleteAccess(metadata, userId) {
3581
+ if (metadata.uploaderId !== userId) {
3582
+ throw new chunkZRAW3HXA_js.FileUploadError("\u65E0\u6743\u9650\u5220\u9664\u6B64\u6587\u4EF6");
3583
+ }
3584
+ }
3353
3585
  };
3354
3586
  var logger7 = chunk6PRFP5EG_js.createLogger("CacheManager");
3355
3587
  var CacheManager = class {