sa2kit 1.6.57 → 1.6.58
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/dist/AliyunOSSProvider-KSYW2IOG.js +15 -0
- package/dist/{AliyunOSSProvider-2FARPAQD.js.map → AliyunOSSProvider-KSYW2IOG.js.map} +1 -1
- package/dist/AliyunOSSProvider-TBK3G7YK.mjs +6 -0
- package/dist/{AliyunOSSProvider-UMVGVBDJ.mjs.map → AliyunOSSProvider-TBK3G7YK.mjs.map} +1 -1
- package/dist/LocalStorageProvider-2DGYRQAB.mjs +6 -0
- package/dist/{LocalStorageProvider-PYOHETJV.mjs.map → LocalStorageProvider-2DGYRQAB.mjs.map} +1 -1
- package/dist/LocalStorageProvider-SSRW3ZJW.js +15 -0
- package/dist/{LocalStorageProvider-JQF5WK5H.js.map → LocalStorageProvider-SSRW3ZJW.js.map} +1 -1
- package/dist/UniversalFileService-336GFY6N.mjs +6 -0
- package/dist/{UniversalFileService-TNYKO6JN.mjs.map → UniversalFileService-336GFY6N.mjs.map} +1 -1
- package/dist/UniversalFileService-J6ET6KZK.js +15 -0
- package/dist/{UniversalFileService-RBV6EN5J.js.map → UniversalFileService-J6ET6KZK.js.map} +1 -1
- package/dist/calendar/index.js +11 -11
- package/dist/calendar/index.mjs +4 -4
- package/dist/chunk-25OFOKNF.js +171 -0
- package/dist/chunk-25OFOKNF.js.map +1 -0
- package/dist/chunk-3DXPQ4YV.mjs +165 -0
- package/dist/chunk-3DXPQ4YV.mjs.map +1 -0
- package/dist/{chunk-4VJQZSPU.mjs → chunk-3NHAT7D4.mjs} +3 -4
- package/dist/chunk-3NHAT7D4.mjs.map +1 -0
- package/dist/{chunk-3JW4X3AC.mjs → chunk-622Y6LTH.mjs} +3 -3
- package/dist/{chunk-3JW4X3AC.mjs.map → chunk-622Y6LTH.mjs.map} +1 -1
- package/dist/chunk-CIVO4R6N.mjs +37 -0
- package/dist/chunk-CIVO4R6N.mjs.map +1 -0
- package/dist/{chunk-6BJ76BYC.mjs → chunk-EGJPS7OL.mjs} +3 -3
- package/dist/{chunk-6BJ76BYC.mjs.map → chunk-EGJPS7OL.mjs.map} +1 -1
- package/dist/{chunk-U7AQC2Z7.js → chunk-EKIOJEJK.js} +1179 -2002
- package/dist/chunk-EKIOJEJK.js.map +1 -0
- package/dist/{chunk-53WLQ22S.js → chunk-EOWTOG7Y.js} +6 -6
- package/dist/{chunk-53WLQ22S.js.map → chunk-EOWTOG7Y.js.map} +1 -1
- package/dist/chunk-HDMIOOZY.mjs +546 -0
- package/dist/chunk-HDMIOOZY.mjs.map +1 -0
- package/dist/{chunk-MZKATHB7.js → chunk-HHVDOIPV.js} +4 -4
- package/dist/{chunk-MZKATHB7.js.map → chunk-HHVDOIPV.js.map} +1 -1
- package/dist/chunk-HJ6MH7J7.js +552 -0
- package/dist/chunk-HJ6MH7J7.js.map +1 -0
- package/dist/chunk-KH6RQ4J5.js +28 -0
- package/dist/chunk-KH6RQ4J5.js.map +1 -0
- package/dist/{chunk-35CXIK5Y.js → chunk-NCOXT7SK.js} +11 -11
- package/dist/{chunk-35CXIK5Y.js.map → chunk-NCOXT7SK.js.map} +1 -1
- package/dist/chunk-NZZZUMMX.mjs +784 -0
- package/dist/chunk-NZZZUMMX.mjs.map +1 -0
- package/dist/{chunk-OBIPI4GU.mjs → chunk-OFYBMMWT.mjs} +4 -4
- package/dist/{chunk-OBIPI4GU.mjs.map → chunk-OFYBMMWT.mjs.map} +1 -1
- package/dist/{chunk-W2NCOORK.js → chunk-PVLLRDUT.js} +951 -145
- package/dist/chunk-PVLLRDUT.js.map +1 -0
- package/dist/chunk-Q5EDCKQA.js +336 -0
- package/dist/chunk-Q5EDCKQA.js.map +1 -0
- package/dist/{chunk-6NMIKAE7.mjs → chunk-SNBILYSH.mjs} +5 -5
- package/dist/{chunk-6NMIKAE7.mjs.map → chunk-SNBILYSH.mjs.map} +1 -1
- package/dist/{chunk-IPY26RQH.js → chunk-UVHPCLP6.js} +5 -5
- package/dist/{chunk-IPY26RQH.js.map → chunk-UVHPCLP6.js.map} +1 -1
- package/dist/{chunk-V6BXO6ZS.mjs → chunk-WGD2NBVR.mjs} +835 -38
- package/dist/chunk-WGD2NBVR.mjs.map +1 -0
- package/dist/{chunk-HYZ5C6FY.mjs → chunk-WS3QZYBI.mjs} +1175 -1996
- package/dist/chunk-WS3QZYBI.mjs.map +1 -0
- package/dist/{chunk-UR5TU4MW.mjs → chunk-XLR6QUDR.mjs} +3 -3
- package/dist/{chunk-UR5TU4MW.mjs.map → chunk-XLR6QUDR.mjs.map} +1 -1
- package/dist/chunk-YMS6BPXS.js +807 -0
- package/dist/chunk-YMS6BPXS.js.map +1 -0
- package/dist/chunk-YOTQG4NP.mjs +314 -0
- package/dist/chunk-YOTQG4NP.mjs.map +1 -0
- package/dist/chunk-ZGVB35L2.mjs +25 -0
- package/dist/chunk-ZGVB35L2.mjs.map +1 -0
- package/dist/chunk-ZRAW3HXA.js +43 -0
- package/dist/chunk-ZRAW3HXA.js.map +1 -0
- package/dist/{chunk-4XXIBWCO.js → chunk-ZRWED7Q6.js} +66 -66
- package/dist/{chunk-4XXIBWCO.js.map → chunk-ZRWED7Q6.js.map} +1 -1
- package/dist/{chunk-DVENFCQY.js → chunk-ZWQJSZEY.js} +4 -5
- package/dist/chunk-ZWQJSZEY.js.map +1 -0
- package/dist/components/index.js +104 -104
- package/dist/components/index.mjs +4 -4
- package/dist/index.js +146 -148
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -11
- package/dist/index.mjs.map +1 -1
- package/dist/logger/index.js +7 -7
- package/dist/logger/index.mjs +1 -4
- package/dist/mikuFusionGame/index.js +4 -4
- package/dist/mikuFusionGame/index.mjs +3 -3
- package/dist/portfolio/index.js +10 -10
- package/dist/portfolio/index.mjs +5 -5
- package/dist/showmasterpiece/db/index.js +42 -42
- package/dist/showmasterpiece/db/index.mjs +1 -1
- package/dist/showmasterpiece/index.js +143 -144
- package/dist/showmasterpiece/index.js.map +1 -1
- package/dist/showmasterpiece/index.mjs +7 -9
- package/dist/showmasterpiece/index.mjs.map +1 -1
- package/dist/showmasterpiece/logic/index.js +19 -19
- package/dist/showmasterpiece/logic/index.mjs +2 -2
- package/dist/showmasterpiece/server/index.js +42 -42
- package/dist/showmasterpiece/server/index.mjs +1 -1
- package/dist/showmasterpiece/ui/web/index.js +34 -34
- package/dist/showmasterpiece/ui/web/index.mjs +6 -6
- package/dist/universalExport/server/index.js +2 -4
- package/dist/universalExport/server/index.js.map +1 -1
- package/dist/universalExport/server/index.mjs +1 -3
- package/dist/universalExport/server/index.mjs.map +1 -1
- package/dist/universalFile/index.js +6 -9
- package/dist/universalFile/index.js.map +1 -1
- package/dist/universalFile/index.mjs +1 -5
- package/dist/universalFile/index.mjs.map +1 -1
- package/dist/universalFile/server/index.js +31 -64
- package/dist/universalFile/server/index.js.map +1 -1
- package/dist/universalFile/server/index.mjs +7 -42
- package/dist/universalFile/server/index.mjs.map +1 -1
- package/dist/utils/index.js +11 -11
- package/dist/utils/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/AliyunOSSProvider-2FARPAQD.js +0 -15
- package/dist/AliyunOSSProvider-UMVGVBDJ.mjs +0 -9
- package/dist/LocalStorageProvider-JQF5WK5H.js +0 -15
- package/dist/LocalStorageProvider-PYOHETJV.mjs +0 -9
- package/dist/UniversalFileService-RBV6EN5J.js +0 -15
- package/dist/UniversalFileService-TNYKO6JN.mjs +0 -9
- package/dist/chunk-4NFOSCM6.js +0 -34
- package/dist/chunk-4NFOSCM6.js.map +0 -1
- package/dist/chunk-4VJQZSPU.mjs.map +0 -1
- package/dist/chunk-6AHYPPUP.js +0 -344
- package/dist/chunk-6AHYPPUP.js.map +0 -1
- package/dist/chunk-76V7EKBX.mjs +0 -796
- package/dist/chunk-76V7EKBX.mjs.map +0 -1
- package/dist/chunk-ACLOJXXE.js +0 -195
- package/dist/chunk-ACLOJXXE.js.map +0 -1
- package/dist/chunk-AEXPAH7Z.mjs +0 -32
- package/dist/chunk-AEXPAH7Z.mjs.map +0 -1
- package/dist/chunk-CFGX3EKK.js +0 -560
- package/dist/chunk-CFGX3EKK.js.map +0 -1
- package/dist/chunk-D2HXMGXS.js +0 -46
- package/dist/chunk-D2HXMGXS.js.map +0 -1
- package/dist/chunk-DVENFCQY.js.map +0 -1
- package/dist/chunk-HYZ5C6FY.mjs.map +0 -1
- package/dist/chunk-K7WNCB4V.mjs +0 -554
- package/dist/chunk-K7WNCB4V.mjs.map +0 -1
- package/dist/chunk-L4ZYBFB2.mjs +0 -44
- package/dist/chunk-L4ZYBFB2.mjs.map +0 -1
- package/dist/chunk-M4HGHTIC.js +0 -820
- package/dist/chunk-M4HGHTIC.js.map +0 -1
- package/dist/chunk-PXWDQFWV.mjs +0 -192
- package/dist/chunk-PXWDQFWV.mjs.map +0 -1
- package/dist/chunk-U7AQC2Z7.js.map +0 -1
- package/dist/chunk-V6BXO6ZS.mjs.map +0 -1
- package/dist/chunk-VTGPHE4Z.mjs +0 -322
- package/dist/chunk-VTGPHE4Z.mjs.map +0 -1
- package/dist/chunk-W2NCOORK.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/universalFile/server/utils/mime.ts","../src/universalFile/server/UniversalFileService.ts"],"names":["path","uuidv4"],"mappings":"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","file":"chunk-76V7EKBX.mjs","sourcesContent":["/**\n * MIME 类型工具函数\n */\n\nimport * as path from 'path';\n\n/** MIME 类型映射表 */\nconst MIME_TYPES: Record<string, string> = {\n // 图片\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.svg': 'image/svg+xml',\n '.bmp': 'image/bmp',\n '.ico': 'image/x-icon',\n\n // 视频\n '.mp4': 'video/mp4',\n '.avi': 'video/x-msvideo',\n '.mov': 'video/quicktime',\n '.wmv': 'video/x-ms-wmv',\n '.flv': 'video/x-flv',\n '.mkv': 'video/x-matroska',\n '.webm': 'video/webm',\n\n // 音频\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n '.m4a': 'audio/mp4',\n '.flac': 'audio/flac',\n '.aac': 'audio/aac',\n\n // 文档\n '.pdf': 'application/pdf',\n '.doc': 'application/msword',\n '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n '.xls': 'application/vnd.ms-excel',\n '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n '.ppt': 'application/vnd.ms-powerpoint',\n '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n '.txt': 'text/plain',\n '.rtf': 'application/rtf',\n\n // 压缩文件\n '.zip': 'application/zip',\n '.rar': 'application/x-rar-compressed',\n '.7z': 'application/x-7z-compressed',\n '.tar': 'application/x-tar',\n '.gz': 'application/gzip',\n\n // 代码文件\n '.js': 'application/javascript',\n '.json': 'application/json',\n '.xml': 'application/xml',\n '.html': 'text/html',\n '.css': 'text/css',\n '.ts': 'application/typescript',\n\n // 其他\n '.csv': 'text/csv',\n '.md': 'text/markdown',\n};\n\n/**\n * 根据文件名获取 MIME 类型\n *\n * @param filename 文件名\n * @returns MIME 类型\n *\n * @example\n * ```typescript\n * getMimeType('photo.jpg') // 'image/jpeg'\n * getMimeType('video.mp4') // 'video/mp4'\n * getMimeType('unknown.xyz') // 'application/octet-stream'\n * ```\n */\nexport function getMimeType(filename: string): string {\n const ext = path.extname(filename).toLowerCase();\n return MIME_TYPES[ext] || 'application/octet-stream';\n}\n\n/**\n * 根据 MIME 类型获取文件扩展名\n *\n * @param mimeType MIME 类型\n * @returns 文件扩展名(包含点号)\n *\n * @example\n * ```typescript\n * getExtensionFromMimeType('image/jpeg') // '.jpg'\n * getExtensionFromMimeType('video/mp4') // '.mp4'\n * ```\n */\nexport function getExtensionFromMimeType(mimeType: string): string | null {\n for (const [ext, mime] of Object.entries(MIME_TYPES)) {\n if (mime === mimeType) {\n return ext;\n }\n }\n return null;\n}\n\n/**\n * 检查是否为图片类型\n *\n * @param mimeType MIME 类型\n * @returns 是否为图片\n */\nexport function isImageType(mimeType: string): boolean {\n return mimeType.startsWith('image/');\n}\n\n/**\n * 检查是否为视频类型\n *\n * @param mimeType MIME 类型\n * @returns 是否为视频\n */\nexport function isVideoType(mimeType: string): boolean {\n return mimeType.startsWith('video/');\n}\n\n/**\n * 检查是否为音频类型\n *\n * @param mimeType MIME 类型\n * @returns 是否为音频\n */\nexport function isAudioType(mimeType: string): boolean {\n return mimeType.startsWith('audio/');\n}\n\n/**\n * 检查是否为文档类型\n *\n * @param mimeType MIME 类型\n * @returns 是否为文档\n */\nexport function isDocumentType(mimeType: string): boolean {\n const documentTypes = [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument',\n 'text/plain',\n 'application/rtf',\n ];\n return documentTypes.some(type => mimeType.includes(type));\n}\n\n/**\n * 验证 MIME 类型是否在允许列表中\n *\n * @param mimeType MIME 类型\n * @param allowedTypes 允许的类型列表(支持通配符)\n * @returns 是否允许\n *\n * @example\n * ```typescript\n * isAllowedMimeType('image/jpeg', ['image/*']) // true\n * isAllowedMimeType('video/mp4', ['image/*']) // false\n * isAllowedMimeType('image/png', ['image/jpeg']) // false\n * ```\n */\nexport function isAllowedMimeType(\n mimeType: string,\n allowedTypes: string[]\n): boolean {\n return allowedTypes.some(allowed => {\n if (allowed === '*/*') {\n return true;\n }\n if (allowed.endsWith('/*')) {\n const prefix = allowed.slice(0, -2);\n return mimeType.startsWith(prefix + '/');\n }\n return mimeType === allowed;\n });\n}\n\n","/**\n * 通用文件服务核心实现\n *\n * 提供统一的文件上传、下载、管理接口\n */\n\nimport { EventEmitter } from 'events';\nimport { v4 as uuidv4 } from 'uuid';\nimport { createHash } from 'crypto';\nimport * as path from 'path';\nimport { createLogger } from '../../logger';\nimport { getMimeType } from './utils/mime';\n\nconst logger = createLogger('UniversalFileService');\n\nimport type {\n StorageType,\n CDNType,\n ProcessorType,\n FileMetadata,\n UploadFileInfo,\n UploadProgress,\n FileQueryOptions,\n PaginatedResult,\n BatchOperationResult,\n FileEvent,\n FileEventListener,\n UploadStatus,\n} from '../types';\n\n// Backend specific types\nimport type {\n UniversalFileServiceConfig,\n IStorageProvider,\n ICDNProvider,\n IFileProcessor,\n} from './types';\n\nimport {\n FileUploadError,\n FileProcessingError,\n StorageProviderError,\n} from '../types';\n\n/**\n * 通用文件服务类\n */\nexport class UniversalFileService extends EventEmitter {\n private config: UniversalFileServiceConfig;\n private storageProviders = new Map<StorageType, IStorageProvider>();\n private cdnProviders = new Map<CDNType, ICDNProvider>();\n private fileProcessors = new Map<ProcessorType, IFileProcessor>();\n private uploadProgressMap = new Map<string, UploadProgress>();\n private metadataCache = new Map<string, { data: FileMetadata; expires: number }>();\n private urlCache = new Map<string, { url: string; expires: number }>();\n private processingQueue: Array<{\n fileId: string;\n processor: IFileProcessor;\n inputPath: string;\n outputPath: string;\n options: any;\n }> = [];\n private isProcessingQueueRunning = false;\n\n constructor(config: UniversalFileServiceConfig) {\n super();\n this.config = config;\n\n // 如果启用了持久化,设置自动监听器\n if (this.config.persistence?.enabled && this.config.persistence.repository) {\n this.setupPersistenceListeners();\n }\n }\n\n // ============= 持久化设置 =============\n\n /**\n * 设置数据库持久化监听器\n *\n * 当文件上传完成或删除时,自动触发数据库操作\n */\n private setupPersistenceListeners(): void {\n const { repository, autoPersist = true } = this.config.persistence!;\n\n if (!autoPersist) {\n logger.info('⚙️ [UniversalFileService] 自动持久化已禁用');\n return;\n }\n\n logger.info('✅ [UniversalFileService] 已启用数据库持久化,自动监听文件事件');\n\n // 监听文件上传完成事件\n this.on('upload:complete', async (fileId: string, data: any) => {\n try {\n const metadata = data.metadata || data;\n await repository.save(metadata);\n logger.info('💾 [Persistence] 文件元数据已自动保存: ' + (fileId));\n } catch (error) {\n logger.error('❌ [Persistence] 保存失败: ' + (fileId), error);\n // 不抛出错误,避免影响上传流程\n }\n });\n\n // 监听文件删除事件\n this.on('file:deleted', async (fileId: string) => {\n try {\n await repository.delete(fileId);\n logger.info('🗑️ [Persistence] 文件元数据已自动删除: ' + (fileId));\n } catch (error) {\n logger.error('❌ [Persistence] 删除失败: ' + (fileId), error);\n }\n });\n\n // 监听批量删除事件\n this.on('files:batch-deleted', async (fileIds: string[]) => {\n try {\n await repository.batchDelete(fileIds);\n logger.info('🗑️ [Persistence] 批量删除元数据: ' + (fileIds.length) + ' 个文件');\n } catch (error) {\n logger.error(`❌ [Persistence] 批量删除失败`, error);\n }\n });\n }\n\n // ============= 初始化方法 =============\n\n /**\n * 初始化文件服务\n */\n async initialize(): Promise<void> {\n logger.info('🚀 [UniversalFileService] 开始初始化文件服务...');\n\n try {\n // 验证配置是否完整\n await this.validateConfiguration();\n\n // 初始化存储提供者\n await this.initializeStorageProviders();\n\n // 初始化CDN提供者\n await this.initializeCDNProviders();\n\n // 初始化文件处理器\n await this.initializeFileProcessors();\n\n logger.info('✅ [UniversalFileService] 文件服务初始化完成');\n } catch (error) {\n console.error('❌ [UniversalFileService] 文件服务初始化失败:', error);\n throw error;\n }\n }\n\n /**\n * 重新初始化存储提供者(支持配置热更新)\n */\n async reinitializeStorageProviders(): Promise<void> {\n logger.info('🔄 [UniversalFileService] 重新初始化存储提供者...');\n\n try {\n // 重新初始化所有存储提供者\n for (const [type, provider] of this.storageProviders) {\n if ('reinitialize' in provider) {\n try {\n logger.info('🔄 [UniversalFileService] 重新初始化存储提供者: ' + (type) + '...');\n\n // 获取对应的配置(从原始配置中获取)\n const config = (this.config as any).storageProviders?.[type as string];\n if (config) {\n await (provider as any).reinitialize(config);\n logger.info('✅ [UniversalFileService] 存储提供者重新初始化完成: ' + (type));\n } else {\n logger.warn('⚠️ [UniversalFileService] 存储提供者配置不存在: ' + (type));\n }\n } catch (error) {\n logger.error('❌ [UniversalFileService] 存储提供者重新初始化失败: ' + (type), error);\n // 继续处理其他提供者\n }\n }\n }\n\n logger.info('✅ [UniversalFileService] 存储提供者重新初始化完成');\n } catch (error) {\n console.error('❌ [UniversalFileService] 存储提供者重新初始化失败:', error);\n throw error;\n }\n }\n\n /**\n * 注册存储提供者\n */\n registerStorageProvider(provider: IStorageProvider): void {\n this.storageProviders.set(provider.type, provider);\n logger.info('📦 [UniversalFileService] 注册存储提供者: ' + (provider.type));\n }\n\n /**\n * 注册CDN提供者\n */\n registerCDNProvider(provider: ICDNProvider): void {\n this.cdnProviders.set(provider.type, provider);\n logger.info('🌐 [UniversalFileService] 注册CDN提供者: ' + (provider.type));\n }\n\n /**\n * 注册文件处理器\n */\n registerFileProcessor(processor: IFileProcessor): void {\n this.fileProcessors.set(processor.type, processor);\n logger.info('⚙️ [UniversalFileService] 注册文件处理器: ' + (processor.type));\n }\n\n // ============= 核心文件操作方法 =============\n\n /**\n * 上传文件\n */\n async uploadFile(\n fileInfo: UploadFileInfo,\n storageType?: StorageType,\n onProgress?: (progress: UploadProgress) => void\n ): Promise<FileMetadata> {\n const fileId = uuidv4();\n const startTime = Date.now();\n\n logger.info('📤 [UniversalFileService] 开始上传文件: ' + (fileInfo.file.name) + ', ID: ' + (fileId));\n\n try {\n // 验证文件\n await this.validateFile(fileInfo.file);\n\n // 初始化上传进度\n const progress: UploadProgress = {\n fileId,\n status: 'pending',\n progress: 0,\n uploadedBytes: 0,\n totalBytes: fileInfo.file.size,\n speed: 0,\n remainingTime: 0,\n };\n\n this.uploadProgressMap.set(fileId, progress);\n this.emitFileEvent('upload:start', fileId, { fileName: fileInfo.file.name });\n\n // 生成文件元数据\n const metadata = await this.generateFileMetadata(fileId, fileInfo);\n\n // 选择存储提供者\n const selectedStorageType = storageType || this.config.defaultStorage;\n let storageProvider = this.storageProviders.get(selectedStorageType as StorageType);\n\n // 如果指定的存储提供者不可用,优先尝试OSS\n if (!storageProvider) {\n logger.info(\n '⚠️ [UniversalFileService] 存储提供者 ' + (selectedStorageType) + ' 不可用,尝试使用OSS'\n );\n storageProvider = this.storageProviders.get('aliyun-oss');\n\n // 如果OSS也不可用,回退到本地存储\n if (!storageProvider) {\n logger.info(`⚠️ [UniversalFileService] OSS不可用,回退到本地存储`);\n storageProvider = this.storageProviders.get('local');\n }\n }\n\n if (!storageProvider) {\n throw new StorageProviderError(`没有可用的存储提供者`);\n }\n\n // 生成存储路径\n const storagePath = this.generateStoragePath(metadata);\n\n // 更新上传状态\n progress.status = 'uploading';\n progress.progress = 10;\n this.uploadProgressMap.set(fileId, progress);\n onProgress?.(progress);\n this.emitFileEvent('upload:progress', fileId, { progress: progress.progress });\n\n // 执行上传\n const uploadResult = await storageProvider.upload(fileInfo, storagePath);\n\n if (!uploadResult.success) {\n throw new FileUploadError('上传失败: ' + (uploadResult.error));\n }\n\n // 更新元数据\n metadata.storagePath = uploadResult.path || storagePath;\n metadata.storageProvider = selectedStorageType as StorageType;\n\n // 生成CDN URL(如果启用)\n if (this.config.defaultCDN !== 'none') {\n const cdnProvider = this.cdnProviders.get(this.config.defaultCDN as CDNType);\n if (cdnProvider && uploadResult.url) {\n metadata.cdnUrl = await cdnProvider.generateUrl(uploadResult.url);\n }\n }\n\n // 更新上传进度\n progress.status = fileInfo.needsProcessing ? 'processing' : 'completed';\n progress.progress = fileInfo.needsProcessing ? 70 : 100;\n this.uploadProgressMap.set(fileId, progress);\n onProgress?.(progress);\n\n // 如果需要处理,添加到处理队列\n if (fileInfo.needsProcessing && fileInfo.processingOptions) {\n await this.queueFileProcessing(metadata, fileInfo.processingOptions);\n }\n\n // 缓存元数据\n this.cacheMetadata(metadata);\n\n // 保存到数据库通过事件触发(如果启用了持久化)\n // persistence.repository 会监听 'upload:complete' 事件自动保存\n\n // 完成上传\n progress.status = 'completed';\n progress.progress = 100;\n this.uploadProgressMap.set(fileId, progress);\n onProgress?.(progress);\n\n const uploadTime = Date.now() - startTime;\n logger.info('✅ [UniversalFileService] 文件上传完成: ' + (fileId) + ', 耗时: ' + (uploadTime) + 'ms');\n\n this.emitFileEvent('upload:complete', fileId, {\n fileName: fileInfo.file.name,\n size: fileInfo.file.size,\n uploadTime,\n });\n\n return metadata;\n } catch (error) {\n console.error('❌ [UniversalFileService] 文件上传失败: ' + (fileId) + ':', error);\n\n // 更新上传状态为失败\n const progress = this.uploadProgressMap.get(fileId);\n if (progress) {\n progress.status = 'failed';\n progress.error = error instanceof Error ? error.message : '上传失败';\n this.uploadProgressMap.set(fileId, progress);\n onProgress?.(progress);\n }\n\n this.emitFileEvent(\n 'upload:error',\n fileId,\n undefined,\n error instanceof Error ? error.message : '上传失败'\n );\n throw error;\n } finally {\n // 清理上传进度(可选,或设置过期时间)\n setTimeout(\n () => {\n this.uploadProgressMap.delete(fileId);\n },\n 5 * 60 * 1000\n ); // 5分钟后清理\n }\n }\n\n\n /**\n * 下载文件\n */\n async downloadFile(fileId: string, userId?: string): Promise<Buffer> {\n logger.info('📥 [UniversalFileService] 开始下载文件: ' + (fileId));\n\n try {\n this.emitFileEvent('download:start', fileId);\n\n // 获取文件元数据\n const metadata = await this.getFileMetadata(fileId);\n\n if (!metadata) {\n throw new FileUploadError('文件不存在: ' + (fileId));\n }\n\n // 检查权限\n await this.checkFileAccess(metadata, userId);\n\n // 获取存储提供者\n const storageProvider = this.storageProviders.get(metadata.storageProvider);\n\n if (!storageProvider) {\n throw new StorageProviderError('存储提供者不存在: ' + (metadata.storageProvider));\n }\n\n // 下载文件\n const fileBuffer = await storageProvider.download(metadata.storagePath);\n\n // 更新访问统计 (如果启用了持久化)\n if (this.config.persistence?.enabled) {\n await this.updateAccessStats(fileId);\n }\n\n logger.info('✅ [UniversalFileService] 文件下载完成: ' + (fileId));\n this.emitFileEvent('download:complete', fileId, { size: fileBuffer.length });\n\n return fileBuffer;\n } catch (error) {\n console.error('❌ [UniversalFileService] 文件下载失败: ' + (fileId) + ':', error);\n this.emitFileEvent('download:error', fileId, undefined, error instanceof Error ? error.message : '下载失败');\n throw error;\n }\n }\n\n /**\n * 删除文件\n */\n async deleteFile(fileId: string, userId?: string): Promise<void> {\n logger.info('🗑️ [UniversalFileService] 开始删除文件: ' + (fileId));\n\n try {\n // 获取文件元数据\n const metadata = await this.getFileMetadata(fileId);\n\n if (!metadata) {\n throw new FileUploadError('文件不存在: ' + (fileId));\n }\n\n // 检查删除权限\n await this.checkFileDeleteAccess(metadata, userId);\n\n // 获取存储提供者\n const storageProvider = this.storageProviders.get(metadata.storageProvider);\n\n if (!storageProvider) {\n throw new StorageProviderError('存储提供者不存在: ' + (metadata.storageProvider));\n }\n\n // 从存储中删除文件\n const deleteResult = await storageProvider.delete(metadata.storagePath);\n\n if (!deleteResult.success) {\n console.warn('⚠️ [UniversalFileService] 存储文件删除失败: ' + (deleteResult.error));\n }\n\n // 从数据库中删除元数据 (通过事件触发)\n if (this.config.persistence?.enabled) {\n await this.deleteFileMetadata(fileId);\n }\n\n // 清除缓存\n this.clearMetadataCache(fileId);\n\n logger.info('✅ [UniversalFileService] 文件删除完成: ' + (fileId));\n this.emitFileEvent('delete:complete', fileId);\n this.emit('file:deleted', fileId);\n } catch (error) {\n console.error('❌ [UniversalFileService] 文件删除失败: ' + (fileId) + ':', error);\n this.emitFileEvent('delete:error', fileId, undefined, error instanceof Error ? error.message : '删除失败');\n throw error;\n }\n }\n\n /**\n * 获取文件访问URL\n */\n async getFileUrl(fileId: string, userId?: string, expiresIn?: number): Promise<string> {\n // 检查缓存\n const cacheKey = (fileId) + '_' + (userId || 'public') + '_' + (expiresIn || 0);\n const cached = this.urlCache.get(cacheKey);\n\n if (cached && cached.expires > Date.now()) {\n return cached.url;\n }\n\n // 获取文件元数据\n const metadata = await this.getFileMetadata(fileId);\n\n if (!metadata) {\n throw new FileUploadError('文件不存在: ' + (fileId));\n }\n\n // 检查访问权限\n await this.checkFileAccess(metadata, userId);\n\n let url: string;\n\n // 优先使用CDN URL\n if (metadata.cdnUrl) {\n url = metadata.cdnUrl;\n } else {\n // 获取存储提供者访问URL\n const storageProvider = this.storageProviders.get(metadata.storageProvider);\n\n if (!storageProvider) {\n throw new StorageProviderError('存储提供者不存在: ' + (metadata.storageProvider));\n }\n\n url = await storageProvider.getAccessUrl(metadata.storagePath, expiresIn);\n }\n\n // 缓存URL\n const cacheExpires = Date.now() + (this.config.cache?.urlTTL || 1800) * 1000;\n this.urlCache.set(cacheKey, { url, expires: cacheExpires });\n\n return url;\n }\n\n /**\n * 获取文件元数据\n */\n async getFileMetadata(fileId: string): Promise<FileMetadata | null> {\n // 检查缓存\n const cached = this.metadataCache.get(fileId);\n if (cached && cached.expires > Date.now()) {\n return cached.data;\n }\n\n // 如果启用了持久化,从数据库查询\n if (this.config.persistence?.enabled && this.config.persistence.repository) {\n try {\n const metadata = await this.config.persistence.repository.get(fileId);\n if (metadata) {\n // 缓存结果\n this.cacheMetadata(metadata);\n }\n return metadata;\n } catch (error) {\n console.error('❌ [UniversalFileService] 查询文件元数据失败:', error);\n return null;\n }\n }\n\n // 如果没有启用持久化,返回 null\n logger.warn('⚠️ [UniversalFileService] 持久化未启用,无法查询文件元数据: ' + (fileId));\n return null;\n }\n\n /**\n * 查询文件列表\n */\n async queryFiles(options: FileQueryOptions): Promise<PaginatedResult<FileMetadata>> {\n if (!this.config.persistence?.enabled || !this.config.persistence.repository) {\n logger.warn('⚠️ [UniversalFileService] 持久化未启用,无法查询文件列表');\n return {\n items: [],\n total: 0,\n page: options.page || 1,\n pageSize: options.pageSize || 20,\n totalPages: 0,\n hasNext: false,\n hasPrev: false,\n };\n }\n\n try {\n const result = await this.config.persistence.repository.query(options);\n // 添加 hasNext 和 hasPrev\n const hasNext = result.page < result.totalPages;\n const hasPrev = result.page > 1;\n return {\n ...result,\n hasNext,\n hasPrev,\n };\n } catch (error) {\n console.error('❌ [UniversalFileService] 查询文件列表失败:', error);\n throw error;\n }\n }\n\n /**\n * 批量删除文件\n */\n async batchDeleteFiles(fileIds: string[], userId?: string): Promise<BatchOperationResult> {\n const result: BatchOperationResult = {\n successCount: 0,\n failureCount: 0,\n failures: [],\n };\n\n for (const fileId of fileIds) {\n try {\n await this.deleteFile(fileId, userId);\n result.successCount++;\n } catch (error) {\n result.failureCount++;\n result.failures.push({\n fileId,\n error: error instanceof Error ? error.message : '删除失败',\n });\n }\n }\n\n // 触发批量删除事件\n if (result.successCount > 0) {\n this.emit('files:batch-deleted', fileIds.filter((_, i) => i < result.successCount));\n }\n\n return result;\n }\n\n /**\n * 获取上传进度\n */\n getUploadProgress(fileId: string): UploadProgress | undefined {\n return this.uploadProgressMap.get(fileId);\n }\n\n // ============= 事件处理方法 =============\n\n /**\n * 监听文件事件\n */\n onFileEvent(eventType: string, listener: FileEventListener): void {\n this.on(eventType, listener);\n }\n\n /**\n * 移除文件事件监听器\n */\n offFileEvent(eventType: string, listener: FileEventListener): void {\n this.off(eventType, listener);\n }\n\n // ============= 私有方法 =============\n\n /**\n * 验证配置是否完整\n */\n private async validateConfiguration(): Promise<void> {\n logger.info('🔍 [UniversalFileService] 验证配置文件...');\n\n // 检查基础配置\n if (!this.config) {\n throw new Error('文件服务配置为空');\n }\n\n // 检查存储配置\n if (!this.config.storage) {\n throw new Error('存储配置为空');\n }\n\n // 检查存储提供者配置\n if (this.config.storage.type === 'aliyun-oss') {\n const ossConfig = this.config.storage as any;\n\n // 如果配置不完整,等待配置加载\n if (!ossConfig.accessKeyId || !ossConfig.accessKeySecret || !ossConfig.bucket || !ossConfig.region) {\n logger.warn('⚠️ [UniversalFileService] OSS配置不完整,等待配置加载...');\n\n // 轮询检查配置是否加载完成,最多等待30秒\n const maxRetries = 30;\n const retryInterval = 1000; // 1秒\n\n for (let i = 0; i < maxRetries; i++) {\n await new Promise(resolve => setTimeout(resolve, retryInterval));\n\n // 重新检查配置(这里假设配置可能会被外部更新)\n const updatedConfig = this.config.storage as any;\n if (updatedConfig.accessKeyId && updatedConfig.accessKeySecret && updatedConfig.bucket && updatedConfig.region) {\n logger.info('✅ [UniversalFileService] OSS配置加载完成');\n break;\n }\n\n if (i === maxRetries - 1) {\n throw new Error('OSS配置加载超时:缺少必需的配置项 (accessKeyId, accessKeySecret, bucket, region)');\n }\n\n logger.debug('等待OSS配置加载中... (' + (i + 1) + '/' + (maxRetries) + ')');\n }\n }\n }\n\n // 检查默认存储类型\n if (!this.config.defaultStorage) {\n this.config.defaultStorage = this.config.storage.type as any;\n }\n\n logger.info('✅ [UniversalFileService] 配置验证完成');\n }\n\n private async initializeStorageProviders(): Promise<void> {\n logger.info('📦 [UniversalFileService] 开始初始化存储提供者...');\n\n // 如果还没有注册任何存储提供者,先注册默认的\n if (this.storageProviders.size === 0) {\n await this.registerDefaultStorageProviders();\n }\n\n if (this.config.storageProviders) {\n for (const [type, config] of Object.entries(this.config.storageProviders)) {\n if (config && config.enabled) {\n const provider = this.storageProviders.get(type as StorageType);\n if (provider) {\n try {\n await provider.initialize(config);\n logger.info('✅ [UniversalFileService] 存储提供者初始化完成: ' + (type));\n } catch (error) {\n console.warn('⚠️ [UniversalFileService] 存储提供者初始化失败: ' + (type) + ':', error);\n // 如果默认存储提供者初始化失败,切换到本地存储\n // if (type === this.config.defaultStorage) {\n // console.warn('⚠️ [UniversalFileService] 默认存储提供者 ' + (type) + ' 初始化失败,切换到本地存储');\n // this.config.defaultStorage = 'local';\n // }\n }\n } else {\n console.warn('⚠️ [UniversalFileService] 存储提供者未注册: ' + (type));\n }\n }\n }\n }\n }\n\n private async registerDefaultStorageProviders(): Promise<void> {\n logger.info('📦 [UniversalFileService] 注册默认存储提供者...');\n\n // 根据配置注册相应的存储提供者\n try {\n if (this.config.storage) {\n if (this.config.storage.type === 'aliyun-oss' && this.config.storage.enabled) {\n const { AliyunOSSProvider } = await import('./providers/AliyunOSSProvider');\n const ossProvider = new AliyunOSSProvider();\n this.registerStorageProvider(ossProvider);\n logger.info('✅ [UniversalFileService] 阿里云OSS提供者注册成功');\n } else if (this.config.storage.type === 'local' && this.config.storage.enabled) {\n const { LocalStorageProvider } = await import('./providers/LocalStorageProvider');\n const localProvider = new LocalStorageProvider();\n this.registerStorageProvider(localProvider);\n logger.info('✅ [UniversalFileService] 本地存储提供者注册成功');\n }\n }\n\n // 如果没有注册任何提供者,注册本地存储作为后备\n if (this.storageProviders.size === 0) {\n const { LocalStorageProvider } = await import('./providers/LocalStorageProvider');\n const fallbackProvider = new LocalStorageProvider();\n this.registerStorageProvider(fallbackProvider);\n logger.info('✅ [UniversalFileService] 已注册备用本地存储提供者');\n }\n } catch (error) {\n console.warn('⚠️ [UniversalFileService] 注册默认存储提供者失败:', error);\n throw new Error('无法初始化存储提供者');\n }\n }\n\n private async initializeCDNProviders(): Promise<void> {\n // CDN 初始化暂时跳过,未来支持多个 CDN 提供者时实现\n if (this.config.cdn && this.config.cdn.enabled) {\n logger.info('✅ [UniversalFileService] CDN配置已启用: ' + (this.config.cdn.type));\n }\n }\n\n private async initializeFileProcessors(): Promise<void> {\n for (const processor of Array.from(this.fileProcessors.values())) {\n await processor.initialize();\n logger.info('✅ [UniversalFileService] 文件处理器初始化完成: ' + (processor.type));\n }\n }\n\n private async validateFile(file: File): Promise<void> {\n // 检查文件大小\n if (this.config.maxFileSize && file.size > this.config.maxFileSize) {\n throw new FileUploadError('文件大小超过限制: ' + (file.size) + ' > ' + (this.config.maxFileSize));\n }\n\n // 检查文件类型\n const mimeType = file.type || getMimeType(file.name);\n\n if (\n this.config.allowedMimeTypes &&\n this.config.allowedMimeTypes.length > 0 &&\n !this.config.allowedMimeTypes.includes(mimeType)\n ) {\n throw new FileUploadError('不支持的文件类型: ' + (mimeType));\n }\n }\n\n private async generateFileMetadata(\n fileId: string,\n fileInfo: UploadFileInfo\n ): Promise<FileMetadata> {\n const now = new Date();\n const mimeType = fileInfo.file.type || getMimeType(fileInfo.file.name);\n const extension = path.extname(fileInfo.file.name).toLowerCase();\n\n // 生成文件哈希(用于去重检测)\n const hash = await this.generateFileHash(fileInfo.file);\n\n return {\n id: fileId,\n originalName: fileInfo.file.name,\n storageName: (fileId) + (extension),\n size: fileInfo.file.size,\n mimeType,\n extension,\n hash,\n uploadTime: now,\n permission: fileInfo.permission || 'public',\n uploaderId: fileInfo.metadata?.uploadedBy || 'system',\n moduleId: fileInfo.moduleId,\n businessId: fileInfo.businessId,\n storageProvider: (this.config.defaultStorage || 'local') as StorageType,\n storagePath: '',\n accessCount: 0,\n metadata: fileInfo.metadata || {},\n };\n }\n\n private generateStoragePath(metadata: FileMetadata): string {\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return (metadata.moduleId) + '/' + (year) + '/' + (month) + '/' + (day) + '/' + (metadata.storageName);\n }\n\n private async generateFileHash(file: File): Promise<string> {\n const buffer = await file.arrayBuffer();\n const hash = createHash('sha256');\n hash.update(Buffer.from(buffer));\n return hash.digest('hex');\n }\n\n private async queueFileProcessing(metadata: FileMetadata, options: any): Promise<void> {\n if (!this.config.processors?.length || 0 > 0) {\n return;\n }\n\n const processor = this.fileProcessors.get(options.type);\n if (!processor) {\n console.warn('⚠️ [UniversalFileService] 文件处理器不存在: ' + (options.type));\n return;\n }\n\n if (this.processingQueue.length >= 1000) {\n throw new FileProcessingError('处理队列已满');\n }\n\n this.processingQueue.push({\n fileId: metadata.id,\n processor,\n inputPath: metadata.storagePath,\n outputPath: this.generateProcessedPath(metadata, options),\n options,\n });\n\n // 启动处理队列\n if (!this.isProcessingQueueRunning) {\n this.processFileQueue();\n }\n }\n\n private generateProcessedPath(metadata: FileMetadata, options: any): string {\n const basePath = metadata.storagePath;\n const extension = path.extname(basePath);\n const basename = basePath.replace(extension, '');\n\n return (basename) + '_processed' + (extension);\n }\n\n private async processFileQueue(): Promise<void> {\n if (this.isProcessingQueueRunning || this.processingQueue.length === 0) {\n return;\n }\n\n this.isProcessingQueueRunning = true;\n\n while (this.processingQueue.length > 0) {\n const task = this.processingQueue.shift();\n if (!task) break;\n\n try {\n this.emitFileEvent('processing:start', task.fileId);\n\n const result = await task.processor.process(task.inputPath, task.outputPath, task.options);\n\n if (result.success) {\n this.emitFileEvent('processing:complete', task.fileId, result);\n } else {\n this.emitFileEvent('processing:error', task.fileId, undefined, result.error);\n }\n } catch (error) {\n console.error('❌ [UniversalFileService] 文件处理失败: ' + (task.fileId) + ':', error);\n this.emitFileEvent(\n 'processing:error',\n task.fileId,\n undefined,\n error instanceof Error ? error.message : '处理失败'\n );\n }\n }\n\n this.isProcessingQueueRunning = false;\n }\n\n private cacheMetadata(metadata: FileMetadata): void {\n const expires = Date.now() + (this.config.cache?.metadataTTL || 3600) * 1000;\n this.metadataCache.set(metadata.id, { data: metadata, expires });\n }\n\n private clearMetadataCache(fileId: string): void {\n this.metadataCache.delete(fileId);\n }\n\n private emitFileEvent(type: string, fileId: string, data?: any, error?: string): void {\n const event: FileEvent = {\n type: type as any,\n fileId,\n timestamp: new Date(),\n data,\n error,\n };\n\n this.emit(type, event);\n this.emit('*', event); // 通用事件监听\n }\n\n // ============= 数据库操作私有方法 =============\n\n /**\n * 保存文件元数据到数据库 (通过持久化仓储)\n */\n private async saveFileMetadata(metadata: FileMetadata): Promise<void> {\n if (!this.config.persistence?.enabled || !this.config.persistence.repository) {\n logger.warn('⚠️ [UniversalFileService] 持久化未启用,跳过保存元数据');\n return;\n }\n\n try {\n await this.config.persistence.repository.save(metadata);\n logger.info('💾 [UniversalFileService] 文件元数据保存成功:', metadata.id);\n } catch (error) {\n console.error('❌ [UniversalFileService] 保存文件元数据失败:', error);\n throw new FileUploadError(\n '保存文件元数据失败: ' + (error instanceof Error ? error.message : '未知错误')\n );\n }\n }\n\n /**\n * 从数据库删除文件元数据 (通过持久化仓储)\n */\n private async deleteFileMetadata(fileId: string): Promise<void> {\n if (!this.config.persistence?.enabled || !this.config.persistence.repository) {\n return;\n }\n\n try {\n await this.config.persistence.repository.delete(fileId);\n logger.info('🗑️ [UniversalFileService] 文件元数据删除成功:', fileId);\n } catch (error) {\n console.error('❌ [UniversalFileService] 删除文件元数据失败:', error);\n throw new FileUploadError(\n '删除文件元数据失败: ' + (error instanceof Error ? error.message : '未知错误')\n );\n }\n }\n\n /**\n * 更新访问统计\n */\n private async updateAccessStats(fileId: string): Promise<void> {\n // 访问统计更新由数据库仓储实现决定\n // 这里只记录日志\n logger.info('📊 [UniversalFileService] 需要更新访问统计:', fileId);\n }\n\n /**\n * 检查文件访问权限\n */\n private async checkFileAccess(metadata: FileMetadata, userId?: string): Promise<void> {\n // 如果文件是公开的,允许访问\n if (metadata.permission === 'public') {\n return;\n }\n\n // 如果是私有文件,检查用户权限\n if (metadata.permission === 'private' && metadata.uploaderId !== userId) {\n throw new FileUploadError('无权限访问此文件');\n }\n\n // 如果是认证用户可访问,检查是否提供了 userId\n if (metadata.permission === 'authenticated' && !userId) {\n throw new FileUploadError('需要登录才能访问此文件');\n }\n }\n\n /**\n * 检查文件删除权限\n */\n private async checkFileDeleteAccess(metadata: FileMetadata, userId?: string): Promise<void> {\n // 只有上传者可以删除文件\n if (metadata.uploaderId !== userId) {\n throw new FileUploadError('无权限删除此文件');\n }\n }\n\n /**\n * 检查服务是否完全可用(包括存储提供者)\n */\n isFullyInitialized(): boolean {\n // 检查是否有可用的存储提供者\n const hasStorageProvider = Array.from(this.storageProviders.values()).some(provider =>\n provider.type === 'aliyun-oss' || provider.type === 'local'\n );\n\n return hasStorageProvider;\n }\n\n /**\n * 等待服务完全初始化(带超时)\n */\n async waitForInitialization(timeoutMs: number = 30000): Promise<void> {\n const startTime = Date.now();\n\n while (!this.isFullyInitialized()) {\n if (Date.now() - startTime > timeoutMs) {\n throw new Error('服务初始化超时 (' + (timeoutMs) + 'ms)');\n }\n\n // 等待100ms后重试\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n\n logger.info('✅ [UniversalFileService] 服务完全初始化就绪');\n }\n}\n"]}
|
package/dist/chunk-ACLOJXXE.js
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkZ6ZWNWWR_js = require('./chunk-Z6ZWNWWR.js');
|
|
4
|
-
|
|
5
|
-
// src/logger/types.ts
|
|
6
|
-
exports.LogLevel = void 0;
|
|
7
|
-
var init_types = chunkZ6ZWNWWR_js.__esm({
|
|
8
|
-
"src/logger/types.ts"() {
|
|
9
|
-
exports.LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
10
|
-
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
|
|
11
|
-
LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
|
|
12
|
-
LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
|
|
13
|
-
LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
|
|
14
|
-
LogLevel2[LogLevel2["NONE"] = 4] = "NONE";
|
|
15
|
-
return LogLevel2;
|
|
16
|
-
})(exports.LogLevel || {});
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// src/logger/console-adapter.ts
|
|
21
|
-
exports.ConsoleLoggerAdapter = void 0;
|
|
22
|
-
var init_console_adapter = chunkZ6ZWNWWR_js.__esm({
|
|
23
|
-
"src/logger/console-adapter.ts"() {
|
|
24
|
-
exports.ConsoleLoggerAdapter = class {
|
|
25
|
-
constructor() {
|
|
26
|
-
this.colors = {
|
|
27
|
-
DEBUG: "\x1B[36m",
|
|
28
|
-
// Cyan
|
|
29
|
-
INFO: "\x1B[32m",
|
|
30
|
-
// Green
|
|
31
|
-
WARN: "\x1B[33m",
|
|
32
|
-
// Yellow
|
|
33
|
-
ERROR: "\x1B[31m",
|
|
34
|
-
// Red
|
|
35
|
-
RESET: "\x1B[0m"
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
log(entry) {
|
|
39
|
-
const { level, message, timestamp, data, context, error } = entry;
|
|
40
|
-
let logMessage = "";
|
|
41
|
-
if (timestamp) {
|
|
42
|
-
logMessage += "[" + this.formatTimestamp(timestamp) + "] ";
|
|
43
|
-
}
|
|
44
|
-
const levelName = this.getLevelName(level);
|
|
45
|
-
logMessage += levelName + ": ";
|
|
46
|
-
if (context) {
|
|
47
|
-
logMessage += "[" + context + "] ";
|
|
48
|
-
}
|
|
49
|
-
logMessage += message;
|
|
50
|
-
switch (level) {
|
|
51
|
-
case 0:
|
|
52
|
-
console.debug(this.colorize(logMessage, "DEBUG"), data || "");
|
|
53
|
-
break;
|
|
54
|
-
case 1:
|
|
55
|
-
console.info(this.colorize(logMessage, "INFO"), data || "");
|
|
56
|
-
break;
|
|
57
|
-
case 2:
|
|
58
|
-
console.warn(this.colorize(logMessage, "WARN"), data || "");
|
|
59
|
-
break;
|
|
60
|
-
case 3:
|
|
61
|
-
console.error(this.colorize(logMessage, "ERROR"), data || "");
|
|
62
|
-
if (error) {
|
|
63
|
-
console.error(error);
|
|
64
|
-
}
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
formatTimestamp(date) {
|
|
69
|
-
return date.toISOString();
|
|
70
|
-
}
|
|
71
|
-
getLevelName(level) {
|
|
72
|
-
const names = ["DEBUG", "INFO", "WARN", "ERROR", "NONE"];
|
|
73
|
-
return names[level] || "UNKNOWN";
|
|
74
|
-
}
|
|
75
|
-
colorize(message, level) {
|
|
76
|
-
if (typeof process !== "undefined" && process.stdout?.isTTY) {
|
|
77
|
-
return this.colors[level] + message + this.colors.RESET;
|
|
78
|
-
}
|
|
79
|
-
return message;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// src/logger/Logger.ts
|
|
86
|
-
function createLogger(context, config) {
|
|
87
|
-
return new exports.Logger(config, context);
|
|
88
|
-
}
|
|
89
|
-
exports.Logger = void 0; exports.logger = void 0;
|
|
90
|
-
var init_Logger = chunkZ6ZWNWWR_js.__esm({
|
|
91
|
-
"src/logger/Logger.ts"() {
|
|
92
|
-
init_console_adapter();
|
|
93
|
-
exports.Logger = class _Logger {
|
|
94
|
-
constructor(config, context) {
|
|
95
|
-
const isProduction = typeof process !== "undefined" ? process.env.NODE_ENV === "production" : false;
|
|
96
|
-
this.config = {
|
|
97
|
-
minLevel: config?.minLevel ?? (isProduction ? 1 : 0),
|
|
98
|
-
// INFO in prod, DEBUG in dev
|
|
99
|
-
enableTimestamp: config?.enableTimestamp ?? true,
|
|
100
|
-
enableContext: config?.enableContext ?? true,
|
|
101
|
-
environment: config?.environment ?? (isProduction ? "production" : "development"),
|
|
102
|
-
adapter: config?.adapter ?? new exports.ConsoleLoggerAdapter()
|
|
103
|
-
};
|
|
104
|
-
this.adapter = this.config.adapter;
|
|
105
|
-
this.context = context;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* 创建带上下文的子 Logger
|
|
109
|
-
*/
|
|
110
|
-
createChild(context) {
|
|
111
|
-
return new _Logger(this.config, context);
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* 调试日志
|
|
115
|
-
*/
|
|
116
|
-
debug(message, data) {
|
|
117
|
-
this.log(0, message, data);
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* 信息日志
|
|
121
|
-
*/
|
|
122
|
-
info(message, data) {
|
|
123
|
-
this.log(1, message, data);
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* 警告日志
|
|
127
|
-
*/
|
|
128
|
-
warn(message, data) {
|
|
129
|
-
this.log(2, message, data);
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* 错误日志
|
|
133
|
-
*/
|
|
134
|
-
error(message, error) {
|
|
135
|
-
this.log(
|
|
136
|
-
3,
|
|
137
|
-
// LogLevel.ERROR
|
|
138
|
-
message,
|
|
139
|
-
error instanceof Error ? void 0 : error,
|
|
140
|
-
error instanceof Error ? error : void 0
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* 核心日志方法
|
|
145
|
-
*/
|
|
146
|
-
log(level, message, data, error) {
|
|
147
|
-
if (level < this.config.minLevel) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
|
|
151
|
-
const loggerDebug = localStorage.getItem("logger-debug");
|
|
152
|
-
if (loggerDebug === "false" && level < 3) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
const entry = {
|
|
157
|
-
level,
|
|
158
|
-
message,
|
|
159
|
-
timestamp: this.config.enableTimestamp ? /* @__PURE__ */ new Date() : void 0,
|
|
160
|
-
data,
|
|
161
|
-
context: this.config.enableContext ? this.context : void 0,
|
|
162
|
-
error
|
|
163
|
-
};
|
|
164
|
-
this.adapter.log(entry);
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* 设置日志级别
|
|
168
|
-
*/
|
|
169
|
-
setLevel(level) {
|
|
170
|
-
this.config.minLevel = level;
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* 获取当前日志级别
|
|
174
|
-
*/
|
|
175
|
-
getLevel() {
|
|
176
|
-
return this.config.minLevel;
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
exports.logger = new exports.Logger();
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
// src/logger/index.ts
|
|
184
|
-
var init_logger = chunkZ6ZWNWWR_js.__esm({
|
|
185
|
-
"src/logger/index.ts"() {
|
|
186
|
-
init_types();
|
|
187
|
-
init_Logger();
|
|
188
|
-
init_console_adapter();
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
exports.createLogger = createLogger;
|
|
193
|
-
exports.init_logger = init_logger;
|
|
194
|
-
//# sourceMappingURL=chunk-ACLOJXXE.js.map
|
|
195
|
-
//# sourceMappingURL=chunk-ACLOJXXE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logger/types.ts","../src/logger/console-adapter.ts","../src/logger/Logger.ts","../src/logger/index.ts"],"names":["LogLevel","__esm","ConsoleLoggerAdapter","Logger","logger"],"mappings":"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","file":"chunk-ACLOJXXE.js","sourcesContent":["/**\n * 日志级别\n */\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n NONE = 4, // 禁用所有日志\n}\n\n/**\n * 日志条目\n */\nexport interface LogEntry {\n level: LogLevel;\n message: string;\n timestamp: Date;\n data?: any;\n context?: string;\n error?: Error;\n}\n\n/**\n * 日志适配器接口\n * 不同平台实现不同的日志输出方式\n */\nexport interface LoggerAdapter {\n /**\n * 输出日志\n */\n log(entry: LogEntry): void;\n\n /**\n * 批量输出日志(可选)\n */\n logBatch?(entries: LogEntry[]): void;\n}\n\n/**\n * 日志配置\n */\nexport interface LoggerConfig {\n /**\n * 最小日志级别\n * 只有大于等于此级别的日志才会输出\n */\n minLevel: LogLevel;\n\n /**\n * 是否启用时间戳\n */\n enableTimestamp?: boolean;\n\n /**\n * 是否启用上下文(模块名)\n */\n enableContext?: boolean;\n\n /**\n * 环境(development/production)\n */\n environment?: 'development' | 'production';\n\n /**\n * 自定义适配器\n */\n adapter?: LoggerAdapter;\n}\n\n","import type { LoggerAdapter, LogEntry, LogLevel } from './types';\n\n/**\n * 控制台日志适配器\n * 使用 console.info/warn/error 输出日志\n */\nexport class ConsoleLoggerAdapter implements LoggerAdapter {\n private readonly colors = {\n DEBUG: '\\x1b[36m', // Cyan\n INFO: '\\x1b[32m', // Green\n WARN: '\\x1b[33m', // Yellow\n ERROR: '\\x1b[31m', // Red\n RESET: '\\x1b[0m',\n };\n\n log(entry: LogEntry): void {\n const { level, message, timestamp, data, context, error } = entry;\n\n // 构建日志消息\n let logMessage = '';\n\n // 添加时间戳\n if (timestamp) {\n logMessage += '[' + (this.formatTimestamp(timestamp)) + '] ';\n }\n\n // 添加日志级别\n const levelName = this.getLevelName(level);\n logMessage += (levelName) + ': ';\n\n // 添加上下文\n if (context) {\n logMessage += '[' + (context) + '] ';\n }\n\n // 添加消息\n logMessage += message;\n\n // 根据日志级别选择输出方式\n switch (level) {\n case 0: // DEBUG\n console.debug(this.colorize(logMessage, 'DEBUG'), data || '');\n break;\n case 1: // INFO\n console.info(this.colorize(logMessage, 'INFO'), data || '');\n break;\n case 2: // WARN\n console.warn(this.colorize(logMessage, 'WARN'), data || '');\n break;\n case 3: // ERROR\n console.error(this.colorize(logMessage, 'ERROR'), data || '');\n if (error) {\n console.error(error);\n }\n break;\n }\n }\n\n private formatTimestamp(date: Date): string {\n return date.toISOString();\n }\n\n private getLevelName(level: LogLevel): string {\n const names = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'];\n return names[level] || 'UNKNOWN';\n }\n\n private colorize(message: string, level: keyof typeof this.colors): string {\n // 只在支持颜色的环境中使用颜色\n if (typeof process !== 'undefined' && process.stdout?.isTTY) {\n return (this.colors[level]) + (message) + (this.colors.RESET);\n }\n return message;\n }\n}\n\n","import type { LogLevel, LogEntry, LoggerConfig, LoggerAdapter } from './types';\nimport { ConsoleLoggerAdapter } from './console-adapter';\n\n/**\n * 统一日志管理类\n */\nexport class Logger {\n private config: Required<LoggerConfig>;\n private adapter: LoggerAdapter;\n private context?: string;\n\n constructor(config?: Partial<LoggerConfig>, context?: string) {\n const isProduction =\n typeof process !== 'undefined' ? process.env.NODE_ENV === 'production' : false;\n\n this.config = {\n minLevel: config?.minLevel ?? (isProduction ? 1 : 0), // INFO in prod, DEBUG in dev\n enableTimestamp: config?.enableTimestamp ?? true,\n enableContext: config?.enableContext ?? true,\n environment: config?.environment ?? (isProduction ? 'production' : 'development'),\n adapter: config?.adapter ?? new ConsoleLoggerAdapter(),\n };\n this.adapter = this.config.adapter;\n this.context = context;\n }\n\n /**\n * 创建带上下文的子 Logger\n */\n createChild(context: string): Logger {\n return new Logger(this.config, context);\n }\n\n /**\n * 调试日志\n */\n debug(message: string, data?: any): void {\n this.log(0, message, data); // LogLevel.DEBUG\n }\n\n /**\n * 信息日志\n */\n info(message: string, data?: any): void {\n this.log(1, message, data); // LogLevel.INFO\n }\n\n /**\n * 警告日志\n */\n warn(message: string, data?: any): void {\n this.log(2, message, data); // LogLevel.WARN\n }\n\n /**\n * 错误日志\n */\n error(message: string, error?: Error | any): void {\n this.log(\n 3, // LogLevel.ERROR\n message,\n error instanceof Error ? undefined : error,\n error instanceof Error ? error : undefined\n );\n }\n\n /**\n * 核心日志方法\n */\n private log(level: LogLevel, message: string, data?: any, error?: Error): void {\n // 检查日志级别\n if (level < this.config.minLevel) {\n return;\n }\n\n // 检查动态调试配置(仅在浏览器环境)\n if (typeof window !== 'undefined' && typeof localStorage !== 'undefined') {\n const loggerDebug = localStorage.getItem('logger-debug');\n // 如果明确设置为 false,则不输出(但 Error 级别始终输出)\n if (loggerDebug === 'false' && level < 3) {\n // level < ERROR\n return;\n }\n }\n\n const entry: LogEntry = {\n level,\n message,\n timestamp: this.config.enableTimestamp ? new Date() : (undefined as any),\n data,\n context: this.config.enableContext ? this.context : undefined,\n error,\n };\n\n this.adapter.log(entry);\n }\n\n /**\n * 设置日志级别\n */\n setLevel(level: LogLevel): void {\n this.config.minLevel = level;\n }\n\n /**\n * 获取当前日志级别\n */\n getLevel(): LogLevel {\n return this.config.minLevel;\n }\n}\n\n/**\n * 默认全局 Logger 实例\n */\nexport const logger = new Logger();\n\n/**\n * 创建带上下文的 Logger\n */\nexport function createLogger(context: string, config?: Partial<LoggerConfig>): Logger {\n return new Logger(config, context);\n}\n\n","export * from './types';\nexport * from './Logger';\nexport * from './console-adapter';\n\n"]}
|
package/dist/chunk-AEXPAH7Z.mjs
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { __esm } from './chunk-WMJKH4XE.mjs';
|
|
2
|
-
|
|
3
|
-
// src/universalFile/server/types.ts
|
|
4
|
-
var FileServiceError, StorageProviderError, CDNProviderError;
|
|
5
|
-
var init_types = __esm({
|
|
6
|
-
"src/universalFile/server/types.ts"() {
|
|
7
|
-
FileServiceError = class extends Error {
|
|
8
|
-
constructor(message, code, details) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.code = code;
|
|
11
|
-
this.details = details;
|
|
12
|
-
this.name = "FileServiceError";
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
StorageProviderError = class extends FileServiceError {
|
|
16
|
-
constructor(message, details) {
|
|
17
|
-
super(message, "STORAGE_PROVIDER_ERROR", details);
|
|
18
|
-
this.name = "StorageProviderError";
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
CDNProviderError = class extends FileServiceError {
|
|
22
|
-
constructor(message, details) {
|
|
23
|
-
super(message, "CDN_PROVIDER_ERROR", details);
|
|
24
|
-
this.name = "CDNProviderError";
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
export { CDNProviderError, StorageProviderError, init_types };
|
|
31
|
-
//# sourceMappingURL=chunk-AEXPAH7Z.mjs.map
|
|
32
|
-
//# sourceMappingURL=chunk-AEXPAH7Z.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/universalFile/server/types.ts"],"names":[],"mappings":";;;AAAA,IA8ca,kBA4BA,oBAAA,CAAA,CAQA;AAlfb,IAAA,UAAA,GAAA,KAAA,CAAA;AAAA,EAAA,mCAAA,GAAA;AA8cO,IAAM,gBAAA,GAAN,cAA+B,KAAA,CAAM;AAAA,MAC1C,WAAA,CACE,OAAA,EACgB,IAAA,EACA,OAAA,EAChB;AACA,QAAA,KAAA,CAAM,OAAO,CAAA;AAHG,QAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,QAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGhB,QAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,MACd;AAAA,KACF;AAmBO,IAAM,oBAAA,GAAN,cAAmC,gBAAA,CAAiB;AAAA,MACzD,WAAA,CAAY,SAAiB,OAAA,EAA+B;AAC1D,QAAA,KAAA,CAAM,OAAA,EAAS,0BAA0B,OAAO,CAAA;AAChD,QAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AAAA,MACd;AAAA,KACF;AAGO,IAAM,gBAAA,GAAN,cAA+B,gBAAA,CAAiB;AAAA,MACrD,WAAA,CAAY,SAAiB,OAAA,EAA+B;AAC1D,QAAA,KAAA,CAAM,OAAA,EAAS,sBAAsB,OAAO,CAAA;AAC5C,QAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,MACd;AAAA,KACF;AAAA,EAAA;AAAA,CAAA","file":"chunk-AEXPAH7Z.mjs","sourcesContent":["/**\n * UniversalFile Server 端类型定义\n */\n\nimport type {\n StorageType as _StorageType,\n CDNType as _CDNType,\n ProcessorType as _ProcessorType,\n FileMetadata,\n UploadStatus,\n AccessPermission,\n UploadFileInfo as _UploadFileInfo,\n ProcessingOptions as _ProcessingOptions,\n} from '../types';\n\n// Re-export client types for server use\nexport type StorageType = _StorageType;\nexport type CDNType = _CDNType;\nexport type ProcessorType = _ProcessorType;\nexport type UploadFileInfo = _UploadFileInfo;\nexport type ProcessingOptions = _ProcessingOptions;\n\n// ============= Provider 接口 =============\n\n/** 存储提供者接口 */\nexport interface IStorageProvider {\n /** 提供者类型 */\n readonly type: StorageType;\n\n /** 初始化 */\n initialize(config: StorageConfig): Promise<void>;\n\n /** 上传文件 */\n upload(fileInfo: UploadFileInfo, path: string): Promise<StorageResult>;\n\n /** 下载文件 */\n download(path: string): Promise<Buffer>;\n\n /** 删除文件 */\n delete(path: string): Promise<StorageResult>;\n\n /** 获取文件信息 */\n getFileInfo(path: string): Promise<StorageResult>;\n\n /** 生成访问URL */\n getAccessUrl(path: string, expiresIn?: number): Promise<string>;\n\n /** 生成预签名上传URL */\n getUploadUrl(path: string, expiresIn?: number): Promise<string>;\n\n /** 检查文件是否存在 */\n exists(path: string): Promise<boolean>;\n\n /** 列出文件 */\n list(prefix: string, maxKeys?: number): Promise<string[]>;\n}\n\n/** CDN 提供者接口 */\nexport interface ICDNProvider {\n /** 提供者类型 */\n readonly type: CDNType;\n\n /** 初始化 */\n initialize(config: CDNConfig): Promise<void>;\n\n /** 生成CDN URL */\n generateUrl(originalUrl: string): Promise<string>;\n\n /** 刷新缓存 */\n refreshCache(urls: string[]): Promise<CDNResult>;\n\n /** 预热缓存 */\n preheatCache(urls: string[]): Promise<CDNResult>;\n\n /** 获取访问统计 */\n getAccessStats(startTime: Date, endTime: Date): Promise<CDNResult>;\n}\n\n/** 文件处理器接口 */\nexport interface IFileProcessor {\n /** 处理器类型 */\n readonly type: ProcessorType;\n\n /** 初始化 */\n initialize(): Promise<void>;\n\n /** 处理文件 */\n process(\n inputPath: string,\n outputPath: string,\n options: ProcessingOptions\n ): Promise<ProcessingResult>;\n\n /** 检查文件是否支持处理 */\n supports(mimeType: string): boolean;\n\n /** 获取文件信息 */\n getFileInfo(filePath: string): Promise<Record<string, any>>;\n}\n\n// ============= 配置接口 =============\n\n/** 存储配置基础接口 */\nexport interface StorageConfig {\n /** 存储类型 */\n type: StorageType;\n /** 是否启用 */\n enabled: boolean;\n}\n\n/** 本地存储配置 */\nexport interface LocalStorageConfig extends StorageConfig {\n type: 'local';\n /** 存储根目录 */\n rootPath: string;\n /** 基础URL */\n baseUrl: string;\n}\n\n/** 阿里云 OSS 配置 */\nexport interface AliyunOSSConfig extends StorageConfig {\n type: 'aliyun-oss';\n /** 地域 */\n region: string;\n /** 存储桶名称 */\n bucket: string;\n /** 访问密钥ID */\n accessKeyId: string;\n /** 访问密钥密码 */\n accessKeySecret: string;\n /** 自定义域名 */\n customDomain?: string;\n /** 是否使用HTTPS */\n secure?: boolean;\n /** 是否使用内网访问 */\n internal?: boolean;\n}\n\n/** CDN配置基础接口 */\nexport interface CDNConfig {\n /** CDN类型 */\n type: CDNType;\n /** 是否启用 */\n enabled: boolean;\n}\n\n/** 阿里云 CDN 配置 */\nexport interface AliyunCDNConfig extends CDNConfig {\n type: 'aliyun-cdn';\n /** CDN域名 */\n domain: string;\n /** 访问密钥ID */\n accessKeyId: string;\n /** 访问密钥密码 */\n accessKeySecret: string;\n /** 地域 */\n region?: string;\n}\n\n/** 缓存配置 */\nexport interface CacheConfig {\n /** 是否启用缓存 */\n enabled: boolean;\n /** 最大缓存大小 */\n maxSize?: number;\n /** 缓存 TTL(秒) */\n ttl?: number;\n /** 是否使用 Redis */\n useRedis?: boolean;\n /** Redis 配置 */\n redisConfig?: {\n host: string;\n port: number;\n password?: string;\n db?: number;\n };\n}\n\n/** 文件服务配置 */\n/** 缓存配置扩展 */\nexport interface CacheConfig {\n /** 是否启用缓存 */\n enabled: boolean;\n /** 元数据缓存TTL(秒) */\n metadataTTL?: number;\n /** URL缓存TTL(秒) */\n urlTTL?: number;\n /** 最大缓存条目数 */\n maxSize?: number;\n}\n\nexport interface UniversalFileServiceConfig {\n /** 存储配置 */\n storage: StorageConfig;\n /** CDN 配置(可选) */\n cdn?: CDNConfig;\n /** 缓存配置(可选) */\n cache?: CacheConfig;\n /** 数据库持久化配置(可选) */\n persistence?: FileServicePersistenceConfig;\n /** 启用的处理器 */\n processors?: ProcessorType[];\n /** 数据库连接(可选) @deprecated 使用 persistence.repository 代替 */\n db?: any;\n /** 最大文件大小(字节) */\n maxFileSize?: number;\n /** 允许的文件类型 */\n allowedMimeTypes?: string[];\n /** 是否启用监控 */\n enableMonitoring?: boolean;\n\n // 运行时字段(由服务类内部管理)\n /** 存储提供者映射(内部使用) */\n storageProviders?: Map<StorageType, IStorageProvider>;\n /** 默认存储类型 */\n defaultStorage?: StorageType;\n /** 默认CDN类型 */\n defaultCDN?: CDNType;\n}\n\n// ============= 结果类型 =============\n\n/** 存储结果 */\n/** 存储操作结果 */\nexport interface StorageResult {\n /** 是否成功 */\n success: boolean;\n /** 存储路径 */\n path?: string;\n /** 访问URL */\n url?: string;\n /** 文件大小 */\n size?: number;\n /** 错误信息 */\n error?: string;\n /** 额外数据 */\n data?: Record<string, any>;\n}\n\n/** 存储元数据 */\nexport interface StorageMetadata {\n /** 文件大小 */\n size: number;\n /** MIME 类型 */\n mimeType: string;\n /** 最后修改时间 */\n lastModified: Date;\n /** 自定义元数据 */\n metadata?: Record<string, any>;\n}\n\n/** CDN 结果 */\n/** CDN操作结果 */\nexport interface CDNResult {\n /** 是否成功 */\n success: boolean;\n /** CDN URL */\n url?: string;\n /** 错误信息 */\n error?: string;\n /** 额外数据 */\n data?: Record<string, any>;\n}\n\n/** CDN 统计信息 */\nexport interface CDNStats {\n /** 带宽(字节/秒) */\n bandwidth: number;\n /** 请求数 */\n requests: number;\n /** 流量(字节) */\n traffic: number;\n /** 统计时间范围 */\n timeRange: {\n start: Date;\n end: Date;\n };\n}\n\n/** 处理结果 */\nexport interface ProcessingResult {\n /** 是否成功 */\n success: boolean;\n /** 处理后的文件路径 */\n processedPath?: string;\n /** 处理后的文件大小 */\n processedSize?: number;\n /** 缩略图路径 */\n thumbnailPath?: string;\n /** 错误信息 */\n error?: string;\n /** 处理耗时(毫秒) */\n processingTime?: number;\n /** 额外数据 */\n data?: Record<string, any>;\n}\n\n/** 处理器信息 */\nexport interface ProcessorInfo {\n /** 处理器名称 */\n name: string;\n /** 处理器版本 */\n version: string;\n /** 支持的格式 */\n supportedFormats: string[];\n /** 支持的操作 */\n supportedOperations: string[];\n}\n\n// ============= 数据库相关类型 =============\n\n/** 文件数据库记录 */\nexport interface FileRecord extends FileMetadata {\n /** 创建时间 */\n createdAt: Date | string;\n /** 更新时间 */\n updatedAt: Date | string;\n}\n\n/** 文件查询选项 */\nexport interface FileQueryOptions {\n /** 模块 ID */\n moduleId?: string;\n /** 业务 ID */\n businessId?: string;\n /** 上传者 ID */\n uploaderId?: string;\n /** 文件类型 */\n mimeType?: string;\n /** 访问权限 */\n permission?: AccessPermission;\n /** 状态 */\n status?: UploadStatus;\n /** 分页 */\n page?: number;\n pageSize?: number;\n /** 排序 */\n orderBy?: string;\n orderDirection?: 'asc' | 'desc';\n}\n\n/** 分页结果 */\nexport interface PaginatedResult<T> {\n /** 数据列表 */\n items: T[];\n /** 总数 */\n total: number;\n /** 当前页 */\n page: number;\n /** 每页大小 */\n pageSize: number;\n /** 总页数 */\n totalPages: number;\n}\n\n// ============= 事件类型 =============\n\n/** 文件事件类型 */\nexport type FileEventType =\n | 'upload:start'\n | 'upload:progress'\n | 'upload:complete'\n | 'upload:error'\n | 'download:start'\n | 'download:complete'\n | 'download:error'\n | 'delete:complete'\n | 'delete:error'\n | 'process:start'\n | 'process:complete'\n | 'process:error';\n\n/** 文件事件 */\nexport interface FileEvent {\n /** 事件类型 */\n type: FileEventType;\n /** 文件 ID */\n fileId: string;\n /** 事件数据 */\n data?: any;\n /** 时间戳 */\n timestamp: Date;\n}\n\n/** 事件监听器 */\nexport type FileEventListener = (event: FileEvent) => void | Promise<void>;\n\n// ============= 数据库持久化接口 =============\n\n/**\n * 文件元数据数据库持久化接口\n *\n * 实现此接口以提供自定义的数据库持久化支持\n *\n * @example\n * ```typescript\n * // Drizzle ORM 实现\n * class DrizzleFileRepository implements IFileMetadataRepository {\n * async save(metadata: FileMetadata): Promise<void> {\n * await db.insert(fileMetadata).values(metadata);\n * }\n * // ... 其他方法\n * }\n * ```\n */\nexport interface IFileMetadataRepository {\n /**\n * 保存文件元数据到数据库\n */\n save(metadata: FileMetadata): Promise<void>;\n\n /**\n * 从数据库获取文件元数据\n */\n get(fileId: string): Promise<FileMetadata | null>;\n\n /**\n * 查询文件列表\n */\n query(options: FileQueryOptions): Promise<PaginatedResult<FileMetadata>>;\n\n /**\n * 从数据库删除文件元数据\n */\n delete(fileId: string): Promise<void>;\n\n /**\n * 批量删除文件元数据\n */\n batchDelete(fileIds: string[]): Promise<void>;\n}\n\n/**\n * 数据库持久化配置\n */\nexport interface FileServicePersistenceConfig {\n /**\n * 是否启用持久化\n */\n enabled: boolean;\n\n /**\n * 持久化仓储实现\n */\n repository: IFileMetadataRepository;\n\n /**\n * 是否自动持久化(默认 true)\n * 如果为 true,文件上传完成后自动保存到数据库\n */\n autoPersist?: boolean;\n\n /**\n * 是否优先使用缓存(默认 false)\n * 如果为 true,查询时优先从缓存获取\n */\n cacheFirst?: boolean;\n}\n\n// ============= 异常类型定义 =============\n\n/** 文件服务异常基类 */\nexport class FileServiceError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly details?: Record<string, any>\n ) {\n super(message);\n this.name = 'FileServiceError';\n }\n}\n\n/** 文件上传异常 */\nexport class FileUploadError extends FileServiceError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'FILE_UPLOAD_ERROR', details);\n this.name = 'FileUploadError';\n }\n}\n\n/** 文件处理异常 */\nexport class FileProcessingError extends FileServiceError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'FILE_PROCESSING_ERROR', details);\n this.name = 'FileProcessingError';\n }\n}\n\n/** 存储提供者异常 */\nexport class StorageProviderError extends FileServiceError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'STORAGE_PROVIDER_ERROR', details);\n this.name = 'StorageProviderError';\n }\n}\n\n/** CDN提供者异常 */\nexport class CDNProviderError extends FileServiceError {\n constructor(message: string, details?: Record<string, any>) {\n super(message, 'CDN_PROVIDER_ERROR', details);\n this.name = 'CDNProviderError';\n }\n}\n"]}
|