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
@@ -2,7 +2,7 @@ export { LocalStorageProvider } from '../../chunk-GSTLV3MB.mjs';
2
2
  export { AliyunOSSProvider } from '../../chunk-YVBU7QDJ.mjs';
3
3
  import { CDNProviderError } from '../../chunk-ZGVB35L2.mjs';
4
4
  import { createLogger } from '../../chunk-KQGP6BTS.mjs';
5
- import { StorageProviderError, FileUploadError, FileProcessingError } from '../../chunk-3XG5OHFD.mjs';
5
+ import { StorageProviderError, FileUploadError, FileProcessingError } from '../../chunk-CIVO4R6N.mjs';
6
6
  import { __require } from '../../chunk-BJTO5JO5.mjs';
7
7
  import { createHash } from 'crypto';
8
8
  import * as path3 from 'path';
@@ -3126,6 +3126,174 @@ var UniversalFileService = class extends EventEmitter {
3126
3126
  );
3127
3127
  }
3128
3128
  }
3129
+ /**
3130
+ * 下载文件
3131
+ */
3132
+ async downloadFile(fileId, userId) {
3133
+ logger6.info(`\u{1F4E5} [UniversalFileService] \u5F00\u59CB\u4E0B\u8F7D\u6587\u4EF6: ${fileId}`);
3134
+ try {
3135
+ this.emitFileEvent("download:start", fileId);
3136
+ const metadata = await this.getFileMetadata(fileId);
3137
+ if (!metadata) {
3138
+ throw new FileUploadError(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${fileId}`);
3139
+ }
3140
+ await this.checkFileAccess(metadata, userId);
3141
+ const storageProvider = this.storageProviders.get(metadata.storageProvider);
3142
+ if (!storageProvider) {
3143
+ throw new StorageProviderError(`\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: ${metadata.storageProvider}`);
3144
+ }
3145
+ const fileBuffer = await storageProvider.download(metadata.storagePath);
3146
+ if (this.config.persistence?.enabled) {
3147
+ await this.updateAccessStats(fileId);
3148
+ }
3149
+ logger6.info(`\u2705 [UniversalFileService] \u6587\u4EF6\u4E0B\u8F7D\u5B8C\u6210: ${fileId}`);
3150
+ this.emitFileEvent("download:complete", fileId, { size: fileBuffer.length });
3151
+ return fileBuffer;
3152
+ } catch (error) {
3153
+ console.error(`\u274C [UniversalFileService] \u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25: ${fileId}:`, error);
3154
+ this.emitFileEvent("download:error", fileId, void 0, error instanceof Error ? error.message : "\u4E0B\u8F7D\u5931\u8D25");
3155
+ throw error;
3156
+ }
3157
+ }
3158
+ /**
3159
+ * 删除文件
3160
+ */
3161
+ async deleteFile(fileId, userId) {
3162
+ logger6.info(`\u{1F5D1}\uFE0F [UniversalFileService] \u5F00\u59CB\u5220\u9664\u6587\u4EF6: ${fileId}`);
3163
+ try {
3164
+ const metadata = await this.getFileMetadata(fileId);
3165
+ if (!metadata) {
3166
+ throw new FileUploadError(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${fileId}`);
3167
+ }
3168
+ await this.checkFileDeleteAccess(metadata, userId);
3169
+ const storageProvider = this.storageProviders.get(metadata.storageProvider);
3170
+ if (!storageProvider) {
3171
+ throw new StorageProviderError(`\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: ${metadata.storageProvider}`);
3172
+ }
3173
+ const deleteResult = await storageProvider.delete(metadata.storagePath);
3174
+ if (!deleteResult.success) {
3175
+ console.warn(`\u26A0\uFE0F [UniversalFileService] \u5B58\u50A8\u6587\u4EF6\u5220\u9664\u5931\u8D25: ${deleteResult.error}`);
3176
+ }
3177
+ if (this.config.persistence?.enabled) {
3178
+ await this.deleteFileMetadata(fileId);
3179
+ }
3180
+ this.clearMetadataCache(fileId);
3181
+ logger6.info(`\u2705 [UniversalFileService] \u6587\u4EF6\u5220\u9664\u5B8C\u6210: ${fileId}`);
3182
+ this.emitFileEvent("delete:complete", fileId);
3183
+ this.emit("file:deleted", fileId);
3184
+ } catch (error) {
3185
+ console.error(`\u274C [UniversalFileService] \u6587\u4EF6\u5220\u9664\u5931\u8D25: ${fileId}:`, error);
3186
+ this.emitFileEvent("delete:error", fileId, void 0, error instanceof Error ? error.message : "\u5220\u9664\u5931\u8D25");
3187
+ throw error;
3188
+ }
3189
+ }
3190
+ /**
3191
+ * 获取文件访问URL
3192
+ */
3193
+ async getFileUrl(fileId, userId, expiresIn) {
3194
+ const cacheKey = `${fileId}_${userId || "public"}_${expiresIn || 0}`;
3195
+ const cached = this.urlCache.get(cacheKey);
3196
+ if (cached && cached.expires > Date.now()) {
3197
+ return cached.url;
3198
+ }
3199
+ const metadata = await this.getFileMetadata(fileId);
3200
+ if (!metadata) {
3201
+ throw new FileUploadError(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${fileId}`);
3202
+ }
3203
+ await this.checkFileAccess(metadata, userId);
3204
+ let url;
3205
+ if (metadata.cdnUrl) {
3206
+ url = metadata.cdnUrl;
3207
+ } else {
3208
+ const storageProvider = this.storageProviders.get(metadata.storageProvider);
3209
+ if (!storageProvider) {
3210
+ throw new StorageProviderError(`\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: ${metadata.storageProvider}`);
3211
+ }
3212
+ url = await storageProvider.getAccessUrl(metadata.storagePath, expiresIn);
3213
+ }
3214
+ const cacheExpires = Date.now() + (this.config.cache?.urlTTL || 1800) * 1e3;
3215
+ this.urlCache.set(cacheKey, { url, expires: cacheExpires });
3216
+ return url;
3217
+ }
3218
+ /**
3219
+ * 获取文件元数据
3220
+ */
3221
+ async getFileMetadata(fileId) {
3222
+ const cached = this.metadataCache.get(fileId);
3223
+ if (cached && cached.expires > Date.now()) {
3224
+ return cached.data;
3225
+ }
3226
+ if (this.config.persistence?.enabled && this.config.persistence.repository) {
3227
+ try {
3228
+ const metadata = await this.config.persistence.repository.get(fileId);
3229
+ if (metadata) {
3230
+ this.cacheMetadata(metadata);
3231
+ }
3232
+ return metadata;
3233
+ } catch (error) {
3234
+ console.error("\u274C [UniversalFileService] \u67E5\u8BE2\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
3235
+ return null;
3236
+ }
3237
+ }
3238
+ logger6.warn(`\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u65E0\u6CD5\u67E5\u8BE2\u6587\u4EF6\u5143\u6570\u636E: ${fileId}`);
3239
+ return null;
3240
+ }
3241
+ /**
3242
+ * 查询文件列表
3243
+ */
3244
+ async queryFiles(options) {
3245
+ if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
3246
+ logger6.warn("\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u65E0\u6CD5\u67E5\u8BE2\u6587\u4EF6\u5217\u8868");
3247
+ return {
3248
+ items: [],
3249
+ total: 0,
3250
+ page: options.page || 1,
3251
+ pageSize: options.pageSize || 20,
3252
+ totalPages: 0,
3253
+ hasNext: false,
3254
+ hasPrev: false
3255
+ };
3256
+ }
3257
+ try {
3258
+ const result = await this.config.persistence.repository.query(options);
3259
+ const hasNext = result.page < result.totalPages;
3260
+ const hasPrev = result.page > 1;
3261
+ return {
3262
+ ...result,
3263
+ hasNext,
3264
+ hasPrev
3265
+ };
3266
+ } catch (error) {
3267
+ console.error("\u274C [UniversalFileService] \u67E5\u8BE2\u6587\u4EF6\u5217\u8868\u5931\u8D25:", error);
3268
+ throw error;
3269
+ }
3270
+ }
3271
+ /**
3272
+ * 批量删除文件
3273
+ */
3274
+ async batchDeleteFiles(fileIds, userId) {
3275
+ const result = {
3276
+ successCount: 0,
3277
+ failureCount: 0,
3278
+ failures: []
3279
+ };
3280
+ for (const fileId of fileIds) {
3281
+ try {
3282
+ await this.deleteFile(fileId, userId);
3283
+ result.successCount++;
3284
+ } catch (error) {
3285
+ result.failureCount++;
3286
+ result.failures.push({
3287
+ fileId,
3288
+ error: error instanceof Error ? error.message : "\u5220\u9664\u5931\u8D25"
3289
+ });
3290
+ }
3291
+ }
3292
+ if (result.successCount > 0) {
3293
+ this.emit("files:batch-deleted", fileIds.filter((_, i) => i < result.successCount));
3294
+ }
3295
+ return result;
3296
+ }
3129
3297
  /**
3130
3298
  * 获取上传进度
3131
3299
  */
@@ -3314,7 +3482,7 @@ var UniversalFileService = class extends EventEmitter {
3314
3482
  const expires = Date.now() + (this.config.cache?.metadataTTL || 3600) * 1e3;
3315
3483
  this.metadataCache.set(metadata.id, { data: metadata, expires });
3316
3484
  }
3317
- _clearMetadataCache2(fileId) {
3485
+ clearMetadataCache(fileId) {
3318
3486
  this.metadataCache.delete(fileId);
3319
3487
  }
3320
3488
  emitFileEvent(type, fileId, data, error) {
@@ -3328,6 +3496,70 @@ var UniversalFileService = class extends EventEmitter {
3328
3496
  this.emit(type, event);
3329
3497
  this.emit("*", event);
3330
3498
  }
3499
+ // ============= 数据库操作私有方法 =============
3500
+ /**
3501
+ * 保存文件元数据到数据库 (通过持久化仓储)
3502
+ */
3503
+ async saveFileMetadata(metadata) {
3504
+ if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
3505
+ logger6.warn("\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u8DF3\u8FC7\u4FDD\u5B58\u5143\u6570\u636E");
3506
+ return;
3507
+ }
3508
+ try {
3509
+ await this.config.persistence.repository.save(metadata);
3510
+ logger6.info("\u{1F4BE} [UniversalFileService] \u6587\u4EF6\u5143\u6570\u636E\u4FDD\u5B58\u6210\u529F:", metadata.id);
3511
+ } catch (error) {
3512
+ console.error("\u274C [UniversalFileService] \u4FDD\u5B58\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
3513
+ throw new FileUploadError(
3514
+ `\u4FDD\u5B58\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25: ${error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"}`
3515
+ );
3516
+ }
3517
+ }
3518
+ /**
3519
+ * 从数据库删除文件元数据 (通过持久化仓储)
3520
+ */
3521
+ async deleteFileMetadata(fileId) {
3522
+ if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
3523
+ return;
3524
+ }
3525
+ try {
3526
+ await this.config.persistence.repository.delete(fileId);
3527
+ logger6.info("\u{1F5D1}\uFE0F [UniversalFileService] \u6587\u4EF6\u5143\u6570\u636E\u5220\u9664\u6210\u529F:", fileId);
3528
+ } catch (error) {
3529
+ console.error("\u274C [UniversalFileService] \u5220\u9664\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
3530
+ throw new FileUploadError(
3531
+ `\u5220\u9664\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25: ${error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF"}`
3532
+ );
3533
+ }
3534
+ }
3535
+ /**
3536
+ * 更新访问统计
3537
+ */
3538
+ async updateAccessStats(fileId) {
3539
+ logger6.info("\u{1F4CA} [UniversalFileService] \u9700\u8981\u66F4\u65B0\u8BBF\u95EE\u7EDF\u8BA1:", fileId);
3540
+ }
3541
+ /**
3542
+ * 检查文件访问权限
3543
+ */
3544
+ async checkFileAccess(metadata, userId) {
3545
+ if (metadata.permission === "public") {
3546
+ return;
3547
+ }
3548
+ if (metadata.permission === "private" && metadata.uploaderId !== userId) {
3549
+ throw new FileUploadError("\u65E0\u6743\u9650\u8BBF\u95EE\u6B64\u6587\u4EF6");
3550
+ }
3551
+ if (metadata.permission === "authenticated" && !userId) {
3552
+ throw new FileUploadError("\u9700\u8981\u767B\u5F55\u624D\u80FD\u8BBF\u95EE\u6B64\u6587\u4EF6");
3553
+ }
3554
+ }
3555
+ /**
3556
+ * 检查文件删除权限
3557
+ */
3558
+ async checkFileDeleteAccess(metadata, userId) {
3559
+ if (metadata.uploaderId !== userId) {
3560
+ throw new FileUploadError("\u65E0\u6743\u9650\u5220\u9664\u6B64\u6587\u4EF6");
3561
+ }
3562
+ }
3331
3563
  };
3332
3564
  var logger7 = createLogger("CacheManager");
3333
3565
  var CacheManager = class {