@flusys/nestjs-storage 0.1.0-alpha.1

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 (77) hide show
  1. package/cjs/config-index.js +1 -0
  2. package/cjs/controllers-index.js +31 -0
  3. package/cjs/docs-index.js +257 -0
  4. package/cjs/dtos-index.js +1 -0
  5. package/cjs/entities-index.js +1 -0
  6. package/cjs/enums-index.js +1 -0
  7. package/cjs/index.js +287 -0
  8. package/cjs/interfaces-index.js +1 -0
  9. package/cjs/modules-index.js +31 -0
  10. package/cjs/providers-index.js +1 -0
  11. package/cjs/services-index.js +1 -0
  12. package/cjs/utils-index.js +1 -0
  13. package/config/index.d.ts +2 -0
  14. package/config/storage-config.service.d.ts +20 -0
  15. package/config/storage.constants.d.ts +11 -0
  16. package/controllers/file-manager.controller.d.ts +21 -0
  17. package/controllers/folder.controller.d.ts +17 -0
  18. package/controllers/index.d.ts +4 -0
  19. package/controllers/storage-config.controller.d.ts +17 -0
  20. package/controllers/upload.controller.d.ts +15 -0
  21. package/docs/index.d.ts +1 -0
  22. package/docs/storage-swagger.config.d.ts +3 -0
  23. package/dtos/file-manager.dto.d.ts +29 -0
  24. package/dtos/folder.dto.d.ts +13 -0
  25. package/dtos/index.d.ts +4 -0
  26. package/dtos/storage-config.dto.d.ts +21 -0
  27. package/dtos/upload.dto.d.ts +29 -0
  28. package/entities/file-manager-base.entity.d.ts +13 -0
  29. package/entities/file-manager-with-company.entity.d.ts +6 -0
  30. package/entities/file-manager.entity.d.ts +5 -0
  31. package/entities/folder-base.entity.d.ts +5 -0
  32. package/entities/folder-with-company.entity.d.ts +5 -0
  33. package/entities/folder.entity.d.ts +4 -0
  34. package/entities/index.d.ts +19 -0
  35. package/entities/storage-config-base.entity.d.ts +7 -0
  36. package/entities/storage-config-with-company.entity.d.ts +4 -0
  37. package/entities/storage-config.entity.d.ts +3 -0
  38. package/enums/file-location.enum.d.ts +6 -0
  39. package/enums/index.d.ts +1 -0
  40. package/fesm/config-index.js +1 -0
  41. package/fesm/controllers-index.js +31 -0
  42. package/fesm/docs-index.js +257 -0
  43. package/fesm/dtos-index.js +1 -0
  44. package/fesm/entities-index.js +1 -0
  45. package/fesm/enums-index.js +1 -0
  46. package/fesm/index.js +287 -0
  47. package/fesm/interfaces-index.js +0 -0
  48. package/fesm/modules-index.js +31 -0
  49. package/fesm/providers-index.js +1 -0
  50. package/fesm/services-index.js +1 -0
  51. package/fesm/utils-index.js +1 -0
  52. package/index.d.ts +11 -0
  53. package/interfaces/file-manager.interface.d.ts +13 -0
  54. package/interfaces/file-upload-response.interface.d.ts +6 -0
  55. package/interfaces/folder.interface.d.ts +6 -0
  56. package/interfaces/index.d.ts +6 -0
  57. package/interfaces/storage-config.interface.d.ts +28 -0
  58. package/interfaces/storage-module-options.interface.d.ts +26 -0
  59. package/interfaces/storage-provider.interface.d.ts +20 -0
  60. package/modules/index.d.ts +1 -0
  61. package/modules/storage.module.d.ts +9 -0
  62. package/package.json +109 -0
  63. package/providers/azure-provider.optional.d.ts +21 -0
  64. package/providers/index.d.ts +3 -0
  65. package/providers/local-provider.d.ts +24 -0
  66. package/providers/s3-provider.optional.d.ts +21 -0
  67. package/providers/sftp-provider.optional.d.ts +25 -0
  68. package/providers/storage-factory.service.d.ts +13 -0
  69. package/providers/storage-provider.registry.d.ts +10 -0
  70. package/services/file-manager.service.d.ts +39 -0
  71. package/services/folder.service.d.ts +28 -0
  72. package/services/index.d.ts +5 -0
  73. package/services/storage-datasource.provider.d.ts +25 -0
  74. package/services/storage-provider-config.service.d.ts +31 -0
  75. package/services/upload.service.d.ts +23 -0
  76. package/utils/image-compressor.util.d.ts +14 -0
  77. package/utils/index.d.ts +1 -0
@@ -0,0 +1 @@
1
+ "use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf;var __hasOwnProp=Object.prototype.hasOwnProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:true});var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:true}):target,mod));var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var __decorateClass=(decorators,target,key,kind)=>{var result=kind>1?void 0:kind?__getOwnPropDesc(target,key):target;for(var i=decorators.length-1,decorator;i>=0;i--)if(decorator=decorators[i])result=(kind?decorator(target,key,result):decorator(result))||result;if(kind&&result)__defProp(target,key,result);return result};var index_exports={};__export(index_exports,{LocalProvider:()=>LocalProvider,StorageFactoryService:()=>StorageFactoryService,StorageProviderRegistry:()=>StorageProviderRegistry});module.exports=__toCommonJS(index_exports);var StorageProviderRegistry=class{static{__name(this,"StorageProviderRegistry")}static providers=new Map;static register(providerName,providerClass){this.providers.set(providerName.toLowerCase(),providerClass)}static get(providerName){return this.providers.get(providerName.toLowerCase())}static has(providerName){return this.providers.has(providerName.toLowerCase())}static getAll(){return Array.from(this.providers.keys())}static clear(){this.providers.clear()}};var import_common=require("@nestjs/common");var crypto=__toESM(require("crypto"));var StorageFactoryService=class{logger=new import_common.Logger(StorageFactoryService.name);providerCache=new Map;generateCacheKey(config){const configString=JSON.stringify(config.config,Object.keys(config.config||{}).sort());const configHash=crypto.createHash("sha256").update(configString).digest("hex").substring(0,16);return`${config.provider}-${configHash}`}async createProvider(config){const providerKey=this.generateCacheKey(config);if(this.providerCache.has(providerKey)){return this.providerCache.get(providerKey)}const ProviderClass=StorageProviderRegistry.get(config.provider);if(!ProviderClass){throw new import_common.NotFoundException(`Storage provider '${config.provider}' is not registered. Available providers: ${StorageProviderRegistry.getAll().join(", ")}`)}try{const instance=new ProviderClass;if("initialize"in instance&&typeof instance.initialize==="function"){await instance.initialize(config.config)}this.providerCache.set(providerKey,instance);this.logger.log(`Created storage provider: ${config.provider} (key: ${providerKey})`);return instance}catch(error){this.logger.error(`Failed to create provider ${config.provider}:`,error);const originalMessage=error?.message||"Unknown error";throw new Error(`Failed to initialize storage provider '${config.provider}': ${originalMessage}`)}}async getProvider(providerName){const cachedKey=Array.from(this.providerCache.keys()).find(key=>key.startsWith(providerName));if(cachedKey){return this.providerCache.get(cachedKey)}return this.createProvider({provider:providerName,config:{}})}clearCache(){this.providerCache.clear()}isProviderAvailable(providerName){return StorageProviderRegistry.has(providerName)}getAvailableProviders(){return StorageProviderRegistry.getAll()}async onModuleDestroy(){this.logger.log("Cleaning up storage provider connections...");const closePromises=[];for(const[key,provider]of this.providerCache.entries()){if("close"in provider&&typeof provider.close==="function"){closePromises.push(provider.close().then(()=>this.logger.debug(`Closed provider: ${key}`)).catch(err=>this.logger.warn(`Failed to close provider ${key}: ${err.message}`)))}}await Promise.allSettled(closePromises);this.providerCache.clear();this.logger.log("Storage provider cleanup complete")}};__name(StorageFactoryService,"StorageFactoryService");StorageFactoryService=__decorateClass([(0,import_common.Injectable)()],StorageFactoryService);var sharp=__toESM(require("sharp"));var ImageCompressor=class{static{__name(this,"ImageCompressor")}static async compress(buffer,mimetype,options={}){const{maxWidth=1280,maxHeight=1280,quality=85,format="original"}=options;if(mimetype==="image/svg+xml"){return{buffer,format:mimetype}}const image=sharp(buffer,{failOnError:false,density:300});image.resize({width:maxWidth,height:maxHeight,fit:"inside",withoutEnlargement:true});let targetFormat=format!=="original"?format:mimetype.split("/")[1];switch(targetFormat.toLowerCase()){case"jpeg":case"jpg":image.jpeg({quality,mozjpeg:true,chromaSubsampling:"4:4:4"});break;case"png":image.png({compressionLevel:9,adaptiveFiltering:true,palette:true,quality,colors:256,dither:1});break;case"webp":image.webp({quality,smartSubsample:true,effort:6,lossless:quality===100});break;case"avif":image.avif({quality,effort:6,chromaSubsampling:"4:4:4"});break;case"tiff":image.tiff({quality,compression:"lzw",predictor:"horizontal",pyramid:true});break;case"gif":image.gif({colours:256,effort:10,dither:1});break;case"jp2":image.jp2({quality,lossless:quality===100});break;default:targetFormat="webp";image.webp({quality,smartSubsample:true,effort:6});break}try{const{data,info}=await image.toBuffer({resolveWithObject:true});return{buffer:data,format:`image/${targetFormat}`}}catch(error){console.warn(`Image processing failed: ${error instanceof Error?error.message:String(error)}`);return{buffer,format:mimetype}}}};var import_common2=require("@nestjs/common");var fs=__toESM(require("fs/promises"));var path=__toESM(require("path"));var import_uuid=require("uuid");var LocalProvider=class _LocalProvider{static{__name(this,"LocalProvider")}logger=new import_common2.Logger(_LocalProvider.name);basePath="";baseUrl="";async initialize(config){this.basePath=path.resolve(config.basePath);this.baseUrl=config.baseUrl||"";await fs.mkdir(this.basePath,{recursive:true});this.logger.log(`Local Provider initialized: ${this.basePath}`)}async uploadFile(file,options){let processedBuffer=file.buffer;let contentType=file.mimetype;const fileName=`${(0,import_uuid.v4)()}-${file.originalname}`;if(options.compress&&file.mimetype.startsWith("image/")){const result=await ImageCompressor.compress(file.buffer,file.mimetype,{maxWidth:options.maxWidth,maxHeight:options.maxHeight,quality:options.quality,format:options.format});processedBuffer=result.buffer;contentType=result.format}const folderPath=options.folderPath?path.join(this.basePath,options.folderPath):this.basePath;const filePath=path.join(folderPath,fileName);await fs.mkdir(folderPath,{recursive:true});await fs.writeFile(filePath,processedBuffer);const relativeKey=path.relative(this.basePath,filePath);this.logger.log(`Uploaded file to local storage: ${relativeKey}`);return{name:fileName,key:relativeKey,size:processedBuffer.length,contentType}}async uploadMultipleFiles(files,options){return Promise.all(files.map(file=>this.uploadFile(file,options)))}async deleteFile(key){try{const filePath=path.join(this.basePath,key);await fs.unlink(filePath);this.logger.log(`Deleted file from local storage: ${key}`)}catch(_error){this.logger.warn(`Failed to delete file from local storage: ${key}`)}}async deleteMultipleFiles(keys){await Promise.all(keys.map(key=>this.deleteFile(key)));this.logger.log(`Deleted ${keys.length} files from local storage`)}async generatePresignedUrl(key,_expiresInSeconds){return this.baseUrl?`${this.baseUrl}/${key}`:`/${key}`}async healthCheck(){try{await fs.access(this.basePath);return true}catch{return false}}getAbsolutePath(key){return path.join(this.basePath,key)}async fileExists(key){try{const filePath=path.join(this.basePath,key);await fs.access(filePath);return true}catch{return false}}async getFileStats(key){const filePath=path.join(this.basePath,key);const stats=await fs.stat(filePath);return{size:stats.size,createdAt:stats.birthtime,modifiedAt:stats.mtime}}};0&&(module.exports={LocalProvider,StorageFactoryService,StorageProviderRegistry});
@@ -0,0 +1 @@
1
+ "use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf;var __hasOwnProp=Object.prototype.hasOwnProperty;var __defNormalProp=(obj,key,value)=>key in obj?__defProp(obj,key,{enumerable:true,configurable:true,writable:true,value}):obj[key]=value;var __name=(target,value)=>__defProp(target,"name",{value,configurable:true});var __esm=(fn,res)=>function __init(){return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:true}):target,mod));var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var __decorateClass=(decorators,target,key,kind)=>{var result=kind>1?void 0:kind?__getOwnPropDesc(target,key):target;for(var i=decorators.length-1,decorator;i>=0;i--)if(decorator=decorators[i])result=(kind?decorator(target,key,result):decorator(result))||result;if(kind&&result)__defProp(target,key,result);return result};var __decorateParam=(index,decorator)=>(target,key)=>decorator(target,key,index);var __publicField=(obj,key,value)=>__defNormalProp(obj,typeof key!=="symbol"?key+"":key,value);var sharp,ImageCompressor;var init_image_compressor_util=__esm({"projects/nestjs-storage/src/utils/image-compressor.util.ts"(){"use strict";sharp=__toESM(require("sharp"));ImageCompressor=class{static{__name(this,"ImageCompressor")}static async compress(buffer,mimetype,options={}){const{maxWidth=1280,maxHeight=1280,quality=85,format="original"}=options;if(mimetype==="image/svg+xml"){return{buffer,format:mimetype}}const image=sharp(buffer,{failOnError:false,density:300});image.resize({width:maxWidth,height:maxHeight,fit:"inside",withoutEnlargement:true});let targetFormat=format!=="original"?format:mimetype.split("/")[1];switch(targetFormat.toLowerCase()){case"jpeg":case"jpg":image.jpeg({quality,mozjpeg:true,chromaSubsampling:"4:4:4"});break;case"png":image.png({compressionLevel:9,adaptiveFiltering:true,palette:true,quality,colors:256,dither:1});break;case"webp":image.webp({quality,smartSubsample:true,effort:6,lossless:quality===100});break;case"avif":image.avif({quality,effort:6,chromaSubsampling:"4:4:4"});break;case"tiff":image.tiff({quality,compression:"lzw",predictor:"horizontal",pyramid:true});break;case"gif":image.gif({colours:256,effort:10,dither:1});break;case"jp2":image.jp2({quality,lossless:quality===100});break;default:targetFormat="webp";image.webp({quality,smartSubsample:true,effort:6});break}try{const{data,info}=await image.toBuffer({resolveWithObject:true});return{buffer:data,format:`image/${targetFormat}`}}catch(error){console.warn(`Image processing failed: ${error instanceof Error?error.message:String(error)}`);return{buffer,format:mimetype}}}}}});var local_provider_exports={};__export(local_provider_exports,{LocalProvider:()=>LocalProvider});var import_common,fs,path,import_uuid,LocalProvider;var init_local_provider=__esm({"projects/nestjs-storage/src/providers/local-provider.ts"(){"use strict";init_image_compressor_util();import_common=require("@nestjs/common");fs=__toESM(require("fs/promises"));path=__toESM(require("path"));import_uuid=require("uuid");LocalProvider=class _LocalProvider{static{__name(this,"LocalProvider")}logger=new import_common.Logger(_LocalProvider.name);basePath="";baseUrl="";async initialize(config){this.basePath=path.resolve(config.basePath);this.baseUrl=config.baseUrl||"";await fs.mkdir(this.basePath,{recursive:true});this.logger.log(`Local Provider initialized: ${this.basePath}`)}async uploadFile(file,options){let processedBuffer=file.buffer;let contentType=file.mimetype;const fileName=`${(0,import_uuid.v4)()}-${file.originalname}`;if(options.compress&&file.mimetype.startsWith("image/")){const result=await ImageCompressor.compress(file.buffer,file.mimetype,{maxWidth:options.maxWidth,maxHeight:options.maxHeight,quality:options.quality,format:options.format});processedBuffer=result.buffer;contentType=result.format}const folderPath=options.folderPath?path.join(this.basePath,options.folderPath):this.basePath;const filePath=path.join(folderPath,fileName);await fs.mkdir(folderPath,{recursive:true});await fs.writeFile(filePath,processedBuffer);const relativeKey=path.relative(this.basePath,filePath);this.logger.log(`Uploaded file to local storage: ${relativeKey}`);return{name:fileName,key:relativeKey,size:processedBuffer.length,contentType}}async uploadMultipleFiles(files,options){return Promise.all(files.map(file=>this.uploadFile(file,options)))}async deleteFile(key){try{const filePath=path.join(this.basePath,key);await fs.unlink(filePath);this.logger.log(`Deleted file from local storage: ${key}`)}catch(_error){this.logger.warn(`Failed to delete file from local storage: ${key}`)}}async deleteMultipleFiles(keys){await Promise.all(keys.map(key=>this.deleteFile(key)));this.logger.log(`Deleted ${keys.length} files from local storage`)}async generatePresignedUrl(key,_expiresInSeconds){return this.baseUrl?`${this.baseUrl}/${key}`:`/${key}`}async healthCheck(){try{await fs.access(this.basePath);return true}catch{return false}}getAbsolutePath(key){return path.join(this.basePath,key)}async fileExists(key){try{const filePath=path.join(this.basePath,key);await fs.access(filePath);return true}catch{return false}}async getFileStats(key){const filePath=path.join(this.basePath,key);const stats=await fs.stat(filePath);return{size:stats.size,createdAt:stats.birthtime,modifiedAt:stats.mtime}}}}});var s3_provider_optional_exports={};__export(s3_provider_optional_exports,{S3Provider:()=>S3Provider});var import_common2,import_uuid2,S3Provider;var init_s3_provider_optional=__esm({"projects/nestjs-storage/src/providers/s3-provider.optional.ts"(){"use strict";init_image_compressor_util();import_common2=require("@nestjs/common");import_uuid2=require("uuid");S3Provider=class _S3Provider{static{__name(this,"S3Provider")}logger=new import_common2.Logger(_S3Provider.name);s3;bucketName="";region="";async initialize(config){try{const{S3Client}=await import("@aws-sdk/client-s3");this.region=config.region;this.bucketName=config.bucket;this.s3=new S3Client({region:config.region,credentials:config.accessKeyId&&config.secretAccessKey?{accessKeyId:config.accessKeyId,secretAccessKey:config.secretAccessKey}:void 0,endpoint:config.endpoint});this.logger.log(`S3 Provider initialized: region=${config.region}, bucket=${config.bucket}`)}catch(_error){this.logger.error("Failed to initialize S3Provider. Make sure @aws-sdk packages are installed.");throw new Error("AWS SDK not found. Install it with: npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner")}}async uploadFile(file,options){const{Upload}=await import("@aws-sdk/lib-storage");let processedBuffer=file.buffer;let contentType=file.mimetype;const fileName=`${(0,import_uuid2.v4)()}-${file.originalname}`;if(options.compress&&file.mimetype.startsWith("image/")){const result=await ImageCompressor.compress(file.buffer,file.mimetype,{maxWidth:options.maxWidth,maxHeight:options.maxHeight,quality:options.quality,format:options.format});processedBuffer=result.buffer;contentType=result.format}const key=options.folderPath?`${options.folderPath}/${fileName}`:fileName;const upload=new Upload({client:this.s3,params:{Bucket:this.bucketName,Key:key,Body:processedBuffer,ContentType:contentType}});await upload.done();return{name:fileName,key,size:processedBuffer.length,contentType}}async uploadMultipleFiles(files,options){return Promise.all(files.map(file=>this.uploadFile(file,options)))}async deleteFile(key){const{DeleteObjectCommand}=await import("@aws-sdk/client-s3");const command=new DeleteObjectCommand({Bucket:this.bucketName,Key:key});await this.s3.send(command);this.logger.log(`Deleted file from S3: ${key}`)}async deleteMultipleFiles(keys){const{DeleteObjectsCommand}=await import("@aws-sdk/client-s3");const command=new DeleteObjectsCommand({Bucket:this.bucketName,Delete:{Objects:keys.map(key=>({Key:key}))}});await this.s3.send(command);this.logger.log(`Deleted ${keys.length} files from S3`)}async generatePresignedUrl(key,expiresInSeconds=3600){const{GetObjectCommand}=await import("@aws-sdk/client-s3");const{getSignedUrl}=await import("@aws-sdk/s3-request-presigner");const command=new GetObjectCommand({Bucket:this.bucketName,Key:key});return getSignedUrl(this.s3,command,{expiresIn:expiresInSeconds})}async healthCheck(){try{const{HeadBucketCommand}=await import("@aws-sdk/client-s3");const command=new HeadBucketCommand({Bucket:this.bucketName});await this.s3.send(command);return true}catch{return false}}}}});var azure_provider_optional_exports={};__export(azure_provider_optional_exports,{AzureProvider:()=>AzureProvider});var import_common3,import_uuid3,AzureProvider;var init_azure_provider_optional=__esm({"projects/nestjs-storage/src/providers/azure-provider.optional.ts"(){"use strict";init_image_compressor_util();import_common3=require("@nestjs/common");import_uuid3=require("uuid");AzureProvider=class _AzureProvider{static{__name(this,"AzureProvider")}logger=new import_common3.Logger(_AzureProvider.name);blobServiceClient;containerClient;containerName="";accountName="";async initialize(config){try{const{BlobServiceClient}=await import("@azure/storage-blob");this.accountName=config.accountName;this.containerName=config.containerName;if(config.connectionString){this.blobServiceClient=BlobServiceClient.fromConnectionString(config.connectionString)}else{const{StorageSharedKeyCredential}=await import("@azure/storage-blob");const sharedKeyCredential=new StorageSharedKeyCredential(config.accountName,config.accountKey);this.blobServiceClient=new BlobServiceClient(`https://${config.accountName}.blob.core.windows.net`,sharedKeyCredential)}this.containerClient=this.blobServiceClient.getContainerClient(config.containerName);await this.containerClient.createIfNotExists();this.logger.log(`Azure Provider initialized: account=${config.accountName}, container=${config.containerName}`)}catch(error){this.logger.error("Failed to initialize AzureProvider. Make sure @azure/storage-blob is installed.");throw new Error("Azure Storage SDK not found. Install it with: npm install @azure/storage-blob")}}async uploadFile(file,options){let processedBuffer=file.buffer;let contentType=file.mimetype;const fileName=`${(0,import_uuid3.v4)()}-${file.originalname}`;if(options.compress&&file.mimetype.startsWith("image/")){const result=await ImageCompressor.compress(file.buffer,file.mimetype,{maxWidth:options.maxWidth,maxHeight:options.maxHeight,quality:options.quality,format:options.format});processedBuffer=result.buffer;contentType=result.format}const blobName=options.folderPath?`${options.folderPath}/${fileName}`:fileName;const blockBlobClient=this.containerClient.getBlockBlobClient(blobName);await blockBlobClient.upload(processedBuffer,processedBuffer.length,{blobHTTPHeaders:{blobContentType:contentType}});const url=blockBlobClient.url;return{name:fileName,key:blobName,size:processedBuffer.length,contentType}}async uploadMultipleFiles(files,options){return Promise.all(files.map(file=>this.uploadFile(file,options)))}async deleteFile(key){const blockBlobClient=this.containerClient.getBlockBlobClient(key);await blockBlobClient.deleteIfExists();this.logger.log(`Deleted file from Azure: ${key}`)}async deleteMultipleFiles(keys){await Promise.all(keys.map(key=>this.deleteFile(key)));this.logger.log(`Deleted ${keys.length} files from Azure`)}async generatePresignedUrl(key,expiresInSeconds=3600){const{BlobSASPermissions,generateBlobSASQueryParameters}=await import("@azure/storage-blob");const blockBlobClient=this.containerClient.getBlockBlobClient(key);const startsOn=new Date;const expiresOn=new Date(startsOn.getTime()+expiresInSeconds*1e3);const sasToken=generateBlobSASQueryParameters({containerName:this.containerName,blobName:key,permissions:BlobSASPermissions.parse("r"),startsOn,expiresOn},blockBlobClient.credential).toString();return`${blockBlobClient.url}?${sasToken}`}async healthCheck(){try{await this.containerClient.exists();return true}catch{return false}}}}});var sftp_provider_optional_exports={};__export(sftp_provider_optional_exports,{SftpProvider:()=>SftpProvider});var import_common4,path2,import_uuid4,SftpProvider;var init_sftp_provider_optional=__esm({"projects/nestjs-storage/src/providers/sftp-provider.optional.ts"(){"use strict";init_image_compressor_util();import_common4=require("@nestjs/common");path2=__toESM(require("path"));import_uuid4=require("uuid");SftpProvider=class _SftpProvider{static{__name(this,"SftpProvider")}logger=new import_common4.Logger(_SftpProvider.name);sftp;config;connected=false;async initialize(config){try{const sftp=await import("ssh2-sftp-client");const SftpClient=sftp.default||sftp;this.sftp=new SftpClient;this.config={host:config.host,port:config.port||22,username:config.username,password:config.password,privateKey:config.privateKey,basePath:config.basePath||"/uploads"};await this.connect();await this.ensureDirectory(this.config.basePath);this.logger.log(`SFTP Provider initialized: ${config.username}@${config.host}:${config.port||22}`)}catch(_error){this.logger.error("Failed to initialize SftpProvider. Make sure ssh2-sftp-client is installed.");throw new Error("SFTP client not found. Install it with: npm install ssh2-sftp-client")}}async connect(){if(!this.connected){await this.sftp.connect({host:this.config.host,port:this.config.port,username:this.config.username,password:this.config.password,privateKey:this.config.privateKey});this.connected=true}}async ensureDirectory(dirPath){try{await this.sftp.mkdir(dirPath,true)}catch(_error){}}async uploadFile(file,options){await this.connect();let processedBuffer=file.buffer;let contentType=file.mimetype;const fileName=`${(0,import_uuid4.v4)()}-${file.originalname}`;if(options.compress&&file.mimetype.startsWith("image/")){const result=await ImageCompressor.compress(file.buffer,file.mimetype,{maxWidth:options.maxWidth,maxHeight:options.maxHeight,quality:options.quality,format:options.format});processedBuffer=result.buffer;contentType=result.format}const remotePath=options.folderPath?path2.join(this.config.basePath,options.folderPath,fileName):path2.join(this.config.basePath,fileName);const remoteDir=path2.dirname(remotePath);await this.ensureDirectory(remoteDir);await this.sftp.put(processedBuffer,remotePath);return{name:fileName,key:remotePath,size:processedBuffer.length,contentType}}async uploadMultipleFiles(files,options){return Promise.all(files.map(file=>this.uploadFile(file,options)))}async deleteFile(key){await this.connect();try{await this.sftp.delete(key);this.logger.log(`Deleted file from SFTP: ${key}`)}catch(_error){this.logger.warn(`Failed to delete file from SFTP: ${key}`)}}async deleteMultipleFiles(keys){await Promise.all(keys.map(key=>this.deleteFile(key)));this.logger.log(`Deleted ${keys.length} files from SFTP`)}async generatePresignedUrl(key,_expiresInSeconds){return key}async healthCheck(){try{await this.connect();return this.connected}catch{return false}}async close(){if(this.connected){await this.sftp.end();this.connected=false}}}}});var import_entities,import_typeorm,FileManagerBase;var init_file_manager_base_entity=__esm({"projects/nestjs-storage/src/entities/file-manager-base.entity.ts"(){"use strict";import_entities=require("@flusys/nestjs-shared/entities");import_typeorm=require("typeorm");FileManagerBase=class extends import_entities.Identity{static{__name(this,"FileManagerBase")}name;contentType;size;key;url;location;storageConfigId;expiresAt=null;isPrivate};__decorateClass([(0,import_typeorm.Column)({type:"varchar",length:255,nullable:false})],FileManagerBase.prototype,"name",2);__decorateClass([(0,import_typeorm.Column)({type:"varchar",length:255,nullable:false})],FileManagerBase.prototype,"contentType",2);__decorateClass([(0,import_typeorm.Column)({type:"varchar",length:255,nullable:false})],FileManagerBase.prototype,"size",2);__decorateClass([(0,import_typeorm.Column)({type:"text",nullable:false})],FileManagerBase.prototype,"key",2);__decorateClass([(0,import_typeorm.Column)({type:"text",nullable:true})],FileManagerBase.prototype,"url",2);__decorateClass([(0,import_typeorm.Column)({type:"text",nullable:false})],FileManagerBase.prototype,"location",2);__decorateClass([(0,import_typeorm.Column)({type:"uuid",nullable:true})],FileManagerBase.prototype,"storageConfigId",2);__decorateClass([(0,import_typeorm.Column)({type:"bigint",nullable:true})],FileManagerBase.prototype,"expiresAt",2);__decorateClass([(0,import_typeorm.Column)({type:"boolean",nullable:false,default:false})],FileManagerBase.prototype,"isPrivate",2)}});var import_entities2,import_typeorm2,FolderBase;var init_folder_base_entity=__esm({"projects/nestjs-storage/src/entities/folder-base.entity.ts"(){"use strict";import_entities2=require("@flusys/nestjs-shared/entities");import_typeorm2=require("typeorm");FolderBase=class extends import_entities2.Identity{static{__name(this,"FolderBase")}name;slug};__decorateClass([(0,import_typeorm2.Column)({type:"varchar",length:255,nullable:false})],FolderBase.prototype,"name",2);__decorateClass([(0,import_typeorm2.Column)({type:"varchar",length:255,nullable:false})],FolderBase.prototype,"slug",2)}});var import_entities3,import_enums,import_typeorm3,StorageConfigBase;var init_storage_config_base_entity=__esm({"projects/nestjs-storage/src/entities/storage-config-base.entity.ts"(){"use strict";import_entities3=require("@flusys/nestjs-shared/entities");import_enums=require("@flusys/nestjs-storage/enums");import_typeorm3=require("typeorm");StorageConfigBase=class extends import_entities3.Identity{static{__name(this,"StorageConfigBase")}name;storage;config};__decorateClass([(0,import_typeorm3.Column)({type:"varchar",length:255,nullable:false})],StorageConfigBase.prototype,"name",2);__decorateClass([(0,import_typeorm3.Column)({type:"enum",enum:import_enums.FileLocationEnum,nullable:false})],StorageConfigBase.prototype,"storage",2);__decorateClass([(0,import_typeorm3.Column)({type:"json",nullable:false})],StorageConfigBase.prototype,"config",2)}});var import_typeorm4,FileManager;var init_file_manager_entity=__esm({"projects/nestjs-storage/src/entities/file-manager.entity.ts"(){"use strict";import_typeorm4=require("typeorm");init_file_manager_base_entity();FileManager=class extends FileManagerBase{folder};__name(FileManager,"FileManager");__decorateClass([(0,import_typeorm4.ManyToOne)("Folder",folder=>folder.fileManager,{nullable:true,onDelete:"SET NULL"}),(0,import_typeorm4.JoinColumn)({name:"folder_id"})],FileManager.prototype,"folder",2);FileManager=__decorateClass([(0,import_typeorm4.Entity)({name:"file_manager"})],FileManager)}});var import_typeorm5,Folder;var init_folder_entity=__esm({"projects/nestjs-storage/src/entities/folder.entity.ts"(){"use strict";import_typeorm5=require("typeorm");init_folder_base_entity();Folder=class extends FolderBase{fileManager};__name(Folder,"Folder");__decorateClass([(0,import_typeorm5.OneToMany)("FileManager",fileManager=>fileManager.folder)],Folder.prototype,"fileManager",2);Folder=__decorateClass([(0,import_typeorm5.Entity)({name:"folder"})],Folder)}});var import_typeorm6,StorageConfig;var init_storage_config_entity=__esm({"projects/nestjs-storage/src/entities/storage-config.entity.ts"(){"use strict";import_typeorm6=require("typeorm");init_storage_config_base_entity();StorageConfig=class extends StorageConfigBase{};__name(StorageConfig,"StorageConfig");StorageConfig=__decorateClass([(0,import_typeorm6.Entity)({name:"storage_config"})],StorageConfig)}});var import_typeorm7,FileManagerWithCompany;var init_file_manager_with_company_entity=__esm({"projects/nestjs-storage/src/entities/file-manager-with-company.entity.ts"(){"use strict";import_typeorm7=require("typeorm");init_file_manager_base_entity();FileManagerWithCompany=class extends FileManagerBase{companyId;folder};__name(FileManagerWithCompany,"FileManagerWithCompany");__decorateClass([(0,import_typeorm7.Column)({type:"uuid",nullable:true})],FileManagerWithCompany.prototype,"companyId",2);__decorateClass([(0,import_typeorm7.ManyToOne)("FolderWithCompany",folder=>folder.fileManager,{nullable:true,onDelete:"SET NULL"}),(0,import_typeorm7.JoinColumn)({name:"folder_id"})],FileManagerWithCompany.prototype,"folder",2);FileManagerWithCompany=__decorateClass([(0,import_typeorm7.Entity)({name:"file_manager"})],FileManagerWithCompany)}});var import_typeorm8,FolderWithCompany;var init_folder_with_company_entity=__esm({"projects/nestjs-storage/src/entities/folder-with-company.entity.ts"(){"use strict";import_typeorm8=require("typeorm");init_folder_base_entity();FolderWithCompany=class extends FolderBase{companyId;fileManager};__name(FolderWithCompany,"FolderWithCompany");__decorateClass([(0,import_typeorm8.Column)({type:"uuid",nullable:true})],FolderWithCompany.prototype,"companyId",2);__decorateClass([(0,import_typeorm8.OneToMany)("FileManagerWithCompany",fileManager=>fileManager.folder)],FolderWithCompany.prototype,"fileManager",2);FolderWithCompany=__decorateClass([(0,import_typeorm8.Entity)({name:"folder"})],FolderWithCompany)}});var import_typeorm9,StorageConfigWithCompany;var init_storage_config_with_company_entity=__esm({"projects/nestjs-storage/src/entities/storage-config-with-company.entity.ts"(){"use strict";import_typeorm9=require("typeorm");init_storage_config_base_entity();StorageConfigWithCompany=class extends StorageConfigBase{companyId};__name(StorageConfigWithCompany,"StorageConfigWithCompany");__decorateClass([(0,import_typeorm9.Column)({type:"uuid",nullable:true})],StorageConfigWithCompany.prototype,"companyId",2);StorageConfigWithCompany=__decorateClass([(0,import_typeorm9.Entity)({name:"storage_config"})],StorageConfigWithCompany)}});var entities_exports={};__export(entities_exports,{FileManager:()=>FileManager,FileManagerBase:()=>FileManagerBase,FileManagerWithCompany:()=>FileManagerWithCompany,Folder:()=>Folder,FolderBase:()=>FolderBase,FolderWithCompany:()=>FolderWithCompany,StorageAllEntities:()=>StorageAllEntities,StorageCompanyEntities:()=>StorageCompanyEntities,StorageConfig:()=>StorageConfig,StorageConfigBase:()=>StorageConfigBase,StorageConfigWithCompany:()=>StorageConfigWithCompany,StorageCoreEntities:()=>StorageCoreEntities,getStorageEntitiesByConfig:()=>getStorageEntitiesByConfig});function getStorageEntitiesByConfig(enableCompanyFeature){return enableCompanyFeature?StorageCompanyEntities:StorageCoreEntities}var StorageCoreEntities,StorageCompanyEntities,StorageAllEntities;var init_entities=__esm({"projects/nestjs-storage/src/entities/index.ts"(){"use strict";init_file_manager_base_entity();init_folder_base_entity();init_storage_config_base_entity();init_file_manager_entity();init_folder_entity();init_storage_config_entity();init_file_manager_with_company_entity();init_folder_with_company_entity();init_storage_config_with_company_entity();init_file_manager_entity();init_folder_entity();init_storage_config_entity();init_file_manager_with_company_entity();init_folder_with_company_entity();init_storage_config_with_company_entity();StorageCoreEntities=[FileManager,Folder,StorageConfig];StorageCompanyEntities=[FileManagerWithCompany,FolderWithCompany,StorageConfigWithCompany];StorageAllEntities=[...StorageCoreEntities,...StorageCompanyEntities];__name(getStorageEntitiesByConfig,"getStorageEntitiesByConfig")}});var index_exports={};__export(index_exports,{FileManagerService:()=>FileManagerService,FolderService:()=>FolderService,StorageDataSourceProvider:()=>StorageDataSourceProvider,StorageProviderConfigService:()=>StorageProviderConfigService,UploadService:()=>UploadService});module.exports=__toCommonJS(index_exports);var import_classes=require("@flusys/nestjs-shared/classes");var import_dtos=require("@flusys/nestjs-storage/dtos");var import_file_location2=require("@flusys/nestjs-storage/enums/file-location.enum");var import_entities4=require("@flusys/nestjs-storage/entities");var import_common7=require("@nestjs/common");var import_typeorm10=require("typeorm");var import_common5=require("@nestjs/common");var StorageProviderRegistry=class{static{__name(this,"StorageProviderRegistry")}static providers=new Map;static register(providerName,providerClass){this.providers.set(providerName.toLowerCase(),providerClass)}static get(providerName){return this.providers.get(providerName.toLowerCase())}static has(providerName){return this.providers.has(providerName.toLowerCase())}static getAll(){return Array.from(this.providers.keys())}static clear(){this.providers.clear()}};var UploadService=class{constructor(storageFactory,storageConfigService,storageProviderConfigService){this.storageFactory=storageFactory;this.storageConfigService=storageConfigService;this.storageProviderConfigService=storageProviderConfigService}logger=new import_common5.Logger(UploadService.name);async onModuleInit(){try{const{LocalProvider:LocalProvider2}=await Promise.resolve().then(()=>(init_local_provider(),local_provider_exports));StorageProviderRegistry.register("local",LocalProvider2);this.logger.log("\u2705 Local Storage Provider registered")}catch(error){this.logger.error("\u274C Failed to register Local Storage Provider",error)}try{const{S3Provider:S3Provider2}=await Promise.resolve().then(()=>(init_s3_provider_optional(),s3_provider_optional_exports));StorageProviderRegistry.register("aws",S3Provider2);this.logger.log("\u2705 AWS S3 Provider registered")}catch{this.logger.warn("\u26A0\uFE0F AWS S3 Provider not available")}try{const{AzureProvider:AzureProvider2}=await Promise.resolve().then(()=>(init_azure_provider_optional(),azure_provider_optional_exports));StorageProviderRegistry.register("azure",AzureProvider2);this.logger.log("\u2705 Azure Blob Provider registered")}catch{this.logger.warn("\u26A0\uFE0F Azure Blob Provider not available")}try{const{SftpProvider:SftpProvider2}=await Promise.resolve().then(()=>(init_sftp_provider_optional(),sftp_provider_optional_exports));StorageProviderRegistry.register("sftp",SftpProvider2);this.logger.log("\u2705 SFTP Provider registered")}catch{this.logger.warn("\u26A0\uFE0F SFTP Provider not available")}this.logger.log(`Available providers: ${this.storageFactory.getAvailableProviders().join(", ")}`)}validateFile(file){const sizeValidation=this.storageConfigService.validateFileSize(file.size);if(!sizeValidation.valid){throw new import_common5.BadRequestException(sizeValidation.message)}const typeValidation=this.storageConfigService.validateFileType(file.mimetype);if(!typeValidation.valid){throw new import_common5.BadRequestException(typeValidation.message)}}async getStorageProvider(storageConfigId,user){let storageConfig;if(storageConfigId){const config=await this.storageProviderConfigService.findById(storageConfigId,user??null,["name","storage","config","companyId"]);if(!config){throw new import_common5.NotFoundException("Storage configuration not found")}if(this.storageConfigService.isCompanyFeatureEnabled()&&user?.companyId){const configWithCompany=config;if(configWithCompany.companyId&&configWithCompany.companyId!==user.companyId){throw new import_common5.BadRequestException("Storage configuration belongs to another company")}}storageConfig=config}else{const defaultConfig=await this.storageProviderConfigService.getDefaultConfig(user);if(!defaultConfig){throw new import_common5.NotFoundException("No default storage configuration found for your company/branch. Please create one.")}storageConfig=defaultConfig}const providerConfig={provider:storageConfig.storage,config:storageConfig.config};return await this.storageFactory.createProvider(providerConfig)}async uploadSingleFile(file,options,user){try{this.validateFile(file);const provider=await this.getStorageProvider(options.storageConfigId,user);return await provider.uploadFile(file,options)}catch(err){this.logger.error("Single file upload failed",err);throw new import_common5.InternalServerErrorException(err.message)}}async uploadMultipleFiles(files,options,user){try{for(const file of files){this.validateFile(file)}const provider=await this.getStorageProvider(options.storageConfigId,user);return await provider.uploadMultipleFiles(files,options)}catch(err){this.logger.error("Multiple files upload failed",err);throw new import_common5.InternalServerErrorException(err.message)}}async deleteSingleFile(key,storageConfigId,user){try{if(!key)throw new Error("No file path provided");const provider=await this.getStorageProvider(storageConfigId,user);await provider.deleteFile(key);return true}catch(err){this.logger.error("Delete single file failed",err);throw new import_common5.InternalServerErrorException(err.message)}}async deleteMultipleFile(keys,storageConfigId,user){try{if(!keys||!keys.length)throw new Error("No file paths provided");const provider=await this.getStorageProvider(storageConfigId,user);await provider.deleteMultipleFiles(keys);return true}catch(err){this.logger.error("Delete multiple files failed",err);throw new import_common5.InternalServerErrorException(err.message)}}bytesToKb(bytes){return Number((bytes*.001).toFixed(2))}async makeFileUrl(key,storageConfigId,expiresIn=3600,user){try{const provider=await this.getStorageProvider(storageConfigId,user);if(provider.generatePresignedUrl){return await provider.generatePresignedUrl(key,expiresIn)}return key}catch(err){this.logger.error("Generate file URL failed",err);throw new import_common5.InternalServerErrorException(err.message)}}};__name(UploadService,"UploadService");UploadService=__decorateClass([(0,import_common5.Injectable)()],UploadService);var STORAGE_MODULE_OPTIONS="STORAGE_MODULE_OPTIONS";var DEFAULT_MAX_FILE_SIZE=100*1024*1024;var DEFAULT_ALLOWED_FILE_TYPES=["*/*"];var import_common6=require("@nestjs/common");var StorageConfigService=class{constructor(options){this.options=options}isCompanyFeatureEnabled(){return this.options.bootstrapAppConfig?.enableCompanyFeature??false}getDatabaseMode(){return this.options.bootstrapAppConfig?.databaseMode??"single"}getMaxFileSize(){return this.options.config?.maxFileSize??DEFAULT_MAX_FILE_SIZE}getAllowedFileTypes(){return this.options.config?.allowedFileTypes??DEFAULT_ALLOWED_FILE_TYPES}isFileTypeAllowed(mimeType){const allowedTypes=this.getAllowedFileTypes();if(allowedTypes.includes("*/*")){return true}return allowedTypes.some(allowedType=>{if(allowedType.endsWith("/*")){const prefix=allowedType.slice(0,-2);return mimeType.startsWith(prefix)}return allowedType===mimeType})}validateFileSize(fileSize){const maxSize=this.getMaxFileSize();if(fileSize>maxSize){const maxSizeMB=(maxSize/(1024*1024)).toFixed(2);const fileSizeMB=(fileSize/(1024*1024)).toFixed(2);return{valid:false,message:`File size (${fileSizeMB}MB) exceeds the maximum allowed size of ${maxSizeMB}MB`}}return{valid:true}}validateFileType(mimeType){if(!this.isFileTypeAllowed(mimeType)){const allowedTypes=this.getAllowedFileTypes();return{valid:false,message:`File type "${mimeType}" is not allowed. Allowed types: ${allowedTypes.join(", ")}`}}return{valid:true}}getDefaultDatabaseConfig(){return this.options.config?.defaultDatabaseConfig}getOptions(){return this.options}};__name(StorageConfigService,"StorageConfigService");StorageConfigService=__decorateClass([(0,import_common6.Injectable)(),__decorateParam(0,(0,import_common6.Inject)(STORAGE_MODULE_OPTIONS))],StorageConfigService);var USER_ACTION_PERMISSION_CACHE_KEY="user_action_permission";var SHOW_PRIVATE_FILE_ACTION="storage.file.viewPrivate";var FileManagerService=class extends import_classes.RequestScopedApiService{constructor(cacheManager,utilsService,uploadService,storageConfig,dataSourceProvider){super("file_manager",null,cacheManager,utilsService,FileManagerService.name,true);this.cacheManager=cacheManager;this.utilsService=utilsService;this.uploadService=uploadService;this.storageConfig=storageConfig;this.dataSourceProvider=dataSourceProvider}FILE_URL_EXPIRY_SECONDS=3600;resolveEntity(){const enableCompanyFeature=this.storageConfig.isCompanyFeatureEnabled();return enableCompanyFeature?import_entities4.FileManagerWithCompany:import_entities4.FileManager}getDataSourceProvider(){return this.dataSourceProvider}async convertSingleDtoToEntity(dto,user){let fileManager={};if(dto instanceof import_dtos.UpdateFileManagerDto&&dto.id){const dbData=await this.repository.findOne({where:{id:dto.id}});if(!dbData){throw new import_common7.NotFoundException("No such entity data found for update! Please, Try Again.")}fileManager=dbData}let validatedFolder=null;if(dto.folderId){const enableCompanyFeature=this.storageConfig.isCompanyFeatureEnabled();const folderEntity=enableCompanyFeature?import_entities4.FolderWithCompany:import_entities4.Folder;const folderRepository=await this.dataSourceProvider.getRepository(folderEntity);const whereCondition={id:dto.folderId};if(enableCompanyFeature&&user?.companyId){whereCondition.companyId=user.companyId}const folder=await folderRepository.findOne({where:whereCondition});if(!folder){throw new import_common7.BadRequestException(`Folder with ID ${dto.folderId} does not exist or you don't have access to it.`)}validatedFolder={id:dto.folderId}}let storageLocation=dto.location||import_file_location2.FileLocationEnum.LOCAL;if(dto.storageConfigId){try{const enableCompanyFeature=this.storageConfig.isCompanyFeatureEnabled();const storageConfigEntity=enableCompanyFeature?(await Promise.resolve().then(()=>(init_entities(),entities_exports))).StorageConfigWithCompany:(await Promise.resolve().then(()=>(init_entities(),entities_exports))).StorageConfig;const storageConfigRepository=await this.dataSourceProvider.getRepository(storageConfigEntity);const whereCondition={id:dto.storageConfigId};if(enableCompanyFeature&&user?.companyId){whereCondition.companyId=user.companyId}const storageConfig=await storageConfigRepository.findOne({where:whereCondition});if(storageConfig){storageLocation=storageConfig.storage}}catch(error){this.logger.warn(`Failed to get storage location from config: ${error}`)}}fileManager={...fileManager,...dto,location:storageLocation,folder:validatedFolder};if("companyId"in fileManager){fileManager.companyId=user?.companyId??null}return fileManager}async getSelectQuery(query,_user,select){if(!select||!select.length){select=["id","name","contentType","size","key","url","location","isPrivate","createdAt","deletedAt"]}const selectFields=select.map(field=>`${this.entityName}.${field}`);if(this.storageConfig.isCompanyFeatureEnabled()){selectFields.push("file_manager.companyId")}selectFields.push("folder.id");selectFields.push("folder.name");query.leftJoinAndSelect("file_manager.folder","folder");query.select(selectFields);return{query,isRaw:false}}async getFilterQuery(query,filter,_user){Object.entries(filter).forEach(([key,value])=>{if(key==="contentType"){const types=value.split(",").map(t=>t.trim());const patterns=types.map(t=>t.replace("*","%"));query.where(new import_typeorm10.Brackets(qb1=>{patterns.forEach((p,i)=>{const param=`p${i}`;if(i===0)qb1.where(`${this.entityName}.contentType LIKE :${param}`,{[param]:p});else qb1.orWhere(`${this.entityName}.contentType LIKE :${param}`,{[param]:p})})}));return}query.andWhere(`${this.entityName}.${key} = :value`,{value})});return{query,isRaw:false}}async getExtraManipulateQuery(query,filterDto,user){const result=await super.getExtraManipulateQuery(query,filterDto,user);const enableCompanyFeature=this.storageConfig.isCompanyFeatureEnabled();if(enableCompanyFeature&&user?.companyId){query.andWhere("file_manager.companyId = :companyId",{companyId:user.companyId})}if(user){const cacheKey=enableCompanyFeature?`${USER_ACTION_PERMISSION_CACHE_KEY}_${user.id}_${user.companyId}`:`${USER_ACTION_PERMISSION_CACHE_KEY}_${user.id}`;const userActions=await this.cacheManager.get(cacheKey);if(userActions){const userActionUrls=userActions.map(item=>item.url);if(!userActionUrls.includes(SHOW_PRIVATE_FILE_ACTION)){query.andWhere("file_manager.isPrivate = :isPrivate",{isPrivate:false})}}else{query.andWhere("file_manager.isPrivate = :isPrivate",{isPrivate:false})}}else{query.andWhere("file_manager.isPrivate = :isPrivate",{isPrivate:false})}return result}async beforeDeleteOperation(dto,_user,_queryRunner){if(dto.type==="permanent"){const ids=Array.isArray(dto.id)?dto.id:[dto.id];const fileManager=await this.repository.findBy({id:(0,import_typeorm10.In)(ids)});const filesByConfig=new Map;fileManager.forEach(file=>{const configId=file.storageConfigId||"default";if(!filesByConfig.has(configId)){filesByConfig.set(configId,[])}filesByConfig.get(configId).push(file.key)});for(const[configId,keys]of filesByConfig){await this.uploadService.deleteMultipleFile(keys,configId==="default"?void 0:configId)}}}async getFiles(dtos,protocol,host,user){await this.ensureRepositoryInitialized();const ids=dtos.map(d=>d.id).filter(Boolean);if(!ids.length)throw new import_common7.BadRequestException("No valid file IDs provided");const files=await this.repository.findBy({id:(0,import_typeorm10.In)(ids)});const now=Date.now();const expiresIn=this.FILE_URL_EXPIRY_SECONDS;const updatedFiles=[];const responses=await Promise.all(files.map(async file=>{let shouldUpdate=false;if(!file.storageConfigId){this.logger.warn(`File ${file.id} has no storageConfigId. Please update this file with a valid storage config.`)}const needsNewUrl=!file.url||file.location===import_file_location2.FileLocationEnum.AWS&&(typeof file.expiresAt!=="number"||now>=file.expiresAt)||file.location===import_file_location2.FileLocationEnum.AZURE&&(typeof file.expiresAt!=="number"||now>=file.expiresAt);if(needsNewUrl&&file.storageConfigId){try{file.url=await this.uploadService.makeFileUrl(file.key,file.storageConfigId,expiresIn,user);file.expiresAt=now+expiresIn*1e3;shouldUpdate=true}catch(error){this.logger.error(`Failed to generate URL for file ${file.id}: ${error?.message||"Unknown error"}`);file.url=`${protocol}://${host}/storage/upload/file/${file.key}`}}if(file.location===import_file_location2.FileLocationEnum.SFTP||file.location===import_file_location2.FileLocationEnum.LOCAL){const expectedUrl=`${protocol}://${host}/storage/upload/file/${file.key}`;if(file.url!==expectedUrl){file.url=expectedUrl;shouldUpdate=true}}if(shouldUpdate)updatedFiles.push(file);return{id:file.id,name:file.name,contentType:file.contentType,url:file.url||""}}));if(updatedFiles.length>0){try{await this.repository.save(updatedFiles)}catch(error){this.logger.error(`Failed to save updated file URLs: ${error?.message||"Unknown error"}`)}}return responses}};__name(FileManagerService,"FileManagerService");FileManagerService=__decorateClass([(0,import_common7.Injectable)(),__decorateParam(0,(0,import_common7.Inject)("CACHE_INSTANCE")),__decorateParam(2,(0,import_common7.Inject)(UploadService)),__decorateParam(3,(0,import_common7.Inject)(StorageConfigService))],FileManagerService);var import_classes2=require("@flusys/nestjs-shared/classes");var import_dtos2=require("@flusys/nestjs-storage/dtos");var import_entities5=require("@flusys/nestjs-storage/entities");var import_common8=require("@nestjs/common");var FolderService=class extends import_classes2.RequestScopedApiService{constructor(cacheManager,utilsService,storageConfig,dataSourceProvider){super("folder",null,cacheManager,utilsService,FolderService.name,true);this.cacheManager=cacheManager;this.utilsService=utilsService;this.storageConfig=storageConfig;this.dataSourceProvider=dataSourceProvider}resolveEntity(){const enableCompanyFeature=this.storageConfig.isCompanyFeatureEnabled();return enableCompanyFeature?import_entities5.FolderWithCompany:import_entities5.Folder}getDataSourceProvider(){return this.dataSourceProvider}async convertSingleDtoToEntity(dto,user){let folder={};if(dto instanceof import_dtos2.UpdateFolderDto&&dto.id){const dbData=await this.repository.findOne({where:{id:dto.id}});if(!dbData){throw new import_common8.NotFoundException("No such entity data found for update! Please, Try Again.")}folder=dbData}folder={...folder,...dto};if("companyId"in folder){folder.companyId=user?.companyId??null}return folder}async getSelectQuery(query,_user,select){if(!select||!select.length){select=["id","name","slug","createdAt","deletedAt"]}const selectFields=select.map(field=>`${this.entityName}.${field}`);if(this.storageConfig.isCompanyFeatureEnabled()){selectFields.push("folder.companyId")}query.select(selectFields);return{query,isRaw:false}}async getExtraManipulateQuery(query,filterDto,user){const result=await super.getExtraManipulateQuery(query,filterDto,user);const enableCompanyFeature=this.storageConfig.isCompanyFeatureEnabled();if(enableCompanyFeature&&user?.companyId){query.andWhere("folder.companyId = :companyId",{companyId:user.companyId})}return result}};__name(FolderService,"FolderService");FolderService=__decorateClass([(0,import_common8.Injectable)(),__decorateParam(0,(0,import_common8.Inject)("CACHE_INSTANCE")),__decorateParam(2,(0,import_common8.Inject)(StorageConfigService))],FolderService);var import_classes3=require("@flusys/nestjs-shared/classes");var import_entities6=require("@flusys/nestjs-storage/entities");var import_common9=require("@nestjs/common");var StorageProviderConfigService=class extends import_classes3.RequestScopedApiService{constructor(cacheManager,utilsService,storageConfig,dataSourceProvider){super("storageConfig",null,cacheManager,utilsService,StorageProviderConfigService.name,true);this.cacheManager=cacheManager;this.utilsService=utilsService;this.storageConfig=storageConfig;this.dataSourceProvider=dataSourceProvider}resolveEntity(){const enableCompanyFeature=this.storageConfig.isCompanyFeatureEnabled();return enableCompanyFeature?import_entities6.StorageConfigWithCompany:import_entities6.StorageConfig}getDataSourceProvider(){return this.dataSourceProvider}async convertSingleDtoToEntity(dto,user){let storageConfig={};storageConfig={...storageConfig,...dto};if("companyId"in storageConfig){storageConfig.companyId=user?.companyId??null}return storageConfig}async getSelectQuery(query,_user,select){if(!select||!select.length){select=["id","name","storage","config","createdAt","updatedAt"];if(this.storageConfig.isCompanyFeatureEnabled()){select.push("companyId")}}const selectFields=select.map(field=>`${this.entityName}.${field}`);query.select(selectFields);return{query,isRaw:false}}async getExtraManipulateQuery(query,filterDto,user){const result=await super.getExtraManipulateQuery(query,filterDto,user);const enableCompanyFeature=this.storageConfig.isCompanyFeatureEnabled();if(enableCompanyFeature&&user?.companyId){query.andWhere("storageConfig.companyId = :companyId",{companyId:user.companyId})}query.orderBy(`${this.entityName}.createdAt`,"DESC");return result}async getDefaultConfig(user){await this.ensureRepositoryInitialized();const baseWhere={};if(this.storageConfig.isCompanyFeatureEnabled()&&user?.companyId){baseWhere.companyId=user.companyId}const defaultConfig=await this.repository.findOne({where:{...baseWhere,name:"default"},order:{createdAt:"ASC"}});if(defaultConfig){return defaultConfig}return await this.repository.findOne({where:baseWhere,order:{createdAt:"ASC"}})}async getConfigByType(storage,user){await this.ensureRepositoryInitialized();const where={storage};if(this.storageConfig.isCompanyFeatureEnabled()&&user?.companyId){where.companyId=user.companyId}return await this.repository.find({where})}};__name(StorageProviderConfigService,"StorageProviderConfigService");StorageProviderConfigService=__decorateClass([(0,import_common9.Injectable)(),__decorateParam(0,(0,import_common9.Inject)("CACHE_INSTANCE")),__decorateParam(2,(0,import_common9.Inject)(StorageConfigService))],StorageProviderConfigService);var import_modules=require("@flusys/nestjs-shared/modules");var import_common10=require("@nestjs/common");var import_core=require("@nestjs/core");var StorageDataSourceProvider=class extends import_modules.MultiTenantDataSourceService{constructor(storageOptions,request){super(StorageDataSourceProvider.buildParentOptions(storageOptions),request);this.storageOptions=storageOptions}logger=new import_common10.Logger(StorageDataSourceProvider.name);static buildParentOptions(options){return{bootstrapAppConfig:options.bootstrapAppConfig,defaultDatabaseConfig:options.config?.defaultDatabaseConfig,tenantDefaultDatabaseConfig:options.config?.tenantDefaultDatabaseConfig,tenants:options.config?.tenants}}getEnableCompanyFeature(){return this.storageOptions.bootstrapAppConfig?.enableCompanyFeature??false}getEnableCompanyFeatureForTenant(tenant){return tenant?.enableCompanyFeature??this.getEnableCompanyFeature()}getEnableCompanyFeatureForCurrentTenant(){return this.getEnableCompanyFeatureForTenant(this.getCurrentTenant()??void 0)}async getStorageEntities(enableCompanyFeature){const enable=enableCompanyFeature??this.getEnableCompanyFeature();const{FileManager:FileManager3,Folder:Folder4,StorageConfig:StorageConfig3}=await Promise.resolve().then(()=>(init_entities(),entities_exports));if(enable){const{FileManagerWithCompany:FileManagerWithCompany3,FolderWithCompany:FolderWithCompany4,StorageConfigWithCompany:StorageConfigWithCompany3}=await Promise.resolve().then(()=>(init_entities(),entities_exports));return[FileManagerWithCompany3,FolderWithCompany4,StorageConfigWithCompany3]}return[FileManager3,Folder4,StorageConfig3]}async createDataSourceFromConfig(config){const currentTenant=this.getCurrentTenant();const enableCompanyFeature=this.getEnableCompanyFeatureForTenant(currentTenant??void 0);const entities=await this.getStorageEntities(enableCompanyFeature);return super.createDataSourceFromConfig(config,entities)}async getSingleDataSource(){if(StorageDataSourceProvider.singleDataSource?.isInitialized){return StorageDataSourceProvider.singleDataSource}if(StorageDataSourceProvider.singleConnectionLock){return StorageDataSourceProvider.singleConnectionLock}const config=this.getDefaultDatabaseConfig();if(!config){throw new Error("No database config available. Provide defaultDatabaseConfig or tenantDefaultDatabaseConfig.")}const connectionPromise=this.createDataSourceFromConfig(config);StorageDataSourceProvider.singleConnectionLock=connectionPromise;try{const dataSource=await connectionPromise;StorageDataSourceProvider.singleDataSource=dataSource;return dataSource}finally{StorageDataSourceProvider.singleConnectionLock=null}}async getOrCreateTenantConnection(tenant){const existing=StorageDataSourceProvider.tenantConnections.get(tenant.id);if(existing?.isInitialized){return existing}const pendingConnection=StorageDataSourceProvider.connectionLocks.get(tenant.id);if(pendingConnection){return pendingConnection}const config=this.buildTenantDatabaseConfig(tenant);const connectionPromise=this.createDataSourceFromConfig(config);StorageDataSourceProvider.connectionLocks.set(tenant.id,connectionPromise);try{const dataSource=await connectionPromise;StorageDataSourceProvider.tenantConnections.set(tenant.id,dataSource);return dataSource}finally{StorageDataSourceProvider.connectionLocks.delete(tenant.id)}}};__name(StorageDataSourceProvider,"StorageDataSourceProvider");__publicField(StorageDataSourceProvider,"tenantConnections",new Map);__publicField(StorageDataSourceProvider,"singleDataSource",null);__publicField(StorageDataSourceProvider,"tenantsRegistry",new Map);__publicField(StorageDataSourceProvider,"initialized",false);__publicField(StorageDataSourceProvider,"connectionLocks",new Map);__publicField(StorageDataSourceProvider,"singleConnectionLock",null);StorageDataSourceProvider=__decorateClass([(0,import_common10.Injectable)({scope:import_common10.Scope.REQUEST}),__decorateParam(0,(0,import_common10.Inject)(STORAGE_MODULE_OPTIONS)),__decorateParam(1,(0,import_common10.Optional)()),__decorateParam(1,(0,import_common10.Inject)(import_core.REQUEST))],StorageDataSourceProvider);0&&(module.exports={FileManagerService,FolderService,StorageDataSourceProvider,StorageProviderConfigService,UploadService});
@@ -0,0 +1 @@
1
+ "use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf;var __hasOwnProp=Object.prototype.hasOwnProperty;var __name=(target,value)=>__defProp(target,"name",{value,configurable:true});var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:true}):target,mod));var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var index_exports={};__export(index_exports,{ImageCompressor:()=>ImageCompressor});module.exports=__toCommonJS(index_exports);var sharp=__toESM(require("sharp"));var ImageCompressor=class{static{__name(this,"ImageCompressor")}static async compress(buffer,mimetype,options={}){const{maxWidth=1280,maxHeight=1280,quality=85,format="original"}=options;if(mimetype==="image/svg+xml"){return{buffer,format:mimetype}}const image=sharp(buffer,{failOnError:false,density:300});image.resize({width:maxWidth,height:maxHeight,fit:"inside",withoutEnlargement:true});let targetFormat=format!=="original"?format:mimetype.split("/")[1];switch(targetFormat.toLowerCase()){case"jpeg":case"jpg":image.jpeg({quality,mozjpeg:true,chromaSubsampling:"4:4:4"});break;case"png":image.png({compressionLevel:9,adaptiveFiltering:true,palette:true,quality,colors:256,dither:1});break;case"webp":image.webp({quality,smartSubsample:true,effort:6,lossless:quality===100});break;case"avif":image.avif({quality,effort:6,chromaSubsampling:"4:4:4"});break;case"tiff":image.tiff({quality,compression:"lzw",predictor:"horizontal",pyramid:true});break;case"gif":image.gif({colours:256,effort:10,dither:1});break;case"jp2":image.jp2({quality,lossless:quality===100});break;default:targetFormat="webp";image.webp({quality,smartSubsample:true,effort:6});break}try{const{data,info}=await image.toBuffer({resolveWithObject:true});return{buffer:data,format:`image/${targetFormat}`}}catch(error){console.warn(`Image processing failed: ${error instanceof Error?error.message:String(error)}`);return{buffer,format:mimetype}}}};0&&(module.exports={ImageCompressor});
@@ -0,0 +1,2 @@
1
+ export * from './storage.constants';
2
+ export * from './storage-config.service';
@@ -0,0 +1,20 @@
1
+ import { StorageModuleOptions } from '../interfaces';
2
+ export declare class StorageConfigService {
3
+ private readonly options;
4
+ constructor(options: StorageModuleOptions);
5
+ isCompanyFeatureEnabled(): boolean;
6
+ getDatabaseMode(): 'single' | 'multi-tenant';
7
+ getMaxFileSize(): number;
8
+ getAllowedFileTypes(): string[];
9
+ isFileTypeAllowed(mimeType: string): boolean;
10
+ validateFileSize(fileSize: number): {
11
+ valid: boolean;
12
+ message?: string;
13
+ };
14
+ validateFileType(mimeType: string): {
15
+ valid: boolean;
16
+ message?: string;
17
+ };
18
+ getDefaultDatabaseConfig(): import("@flusys/nestjs-core").IDatabaseConfig;
19
+ getOptions(): StorageModuleOptions;
20
+ }
@@ -0,0 +1,11 @@
1
+ export declare const STORAGE_MODULE_OPTIONS = "STORAGE_MODULE_OPTIONS";
2
+ export declare const STORAGE_CONFIG_SERVICE = "STORAGE_CONFIG_SERVICE";
3
+ export declare const STORAGE_DATA_SOURCE_PROVIDER = "STORAGE_DATA_SOURCE_PROVIDER";
4
+ export declare const DEFAULT_MAX_FILE_SIZE: number;
5
+ export declare const DEFAULT_ALLOWED_FILE_TYPES: string[];
6
+ export declare const FILE_VALIDATION_MESSAGES: {
7
+ readonly FILE_TOO_LARGE: "File size exceeds the maximum allowed size";
8
+ readonly INVALID_FILE_TYPE: "File type is not allowed";
9
+ readonly NO_FILE_PROVIDED: "No file was provided";
10
+ readonly UPLOAD_FAILED: "File upload failed";
11
+ };
@@ -0,0 +1,21 @@
1
+ import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
2
+ import { SingleResponseDto } from '@flusys/nestjs-shared/dtos';
3
+ import { CreateFileManagerDto, FileManagerResponseDto, FilesResponseDto, GetFilesRequestDto, UpdateFileManagerDto } from '@flusys/nestjs-storage/dtos';
4
+ import { Request } from 'express';
5
+ import { FileManagerService } from '../services/file-manager.service';
6
+ declare const FileManagerController_base: abstract new (service: FileManagerService) => {
7
+ service: FileManagerService;
8
+ insert(addDto: CreateFileManagerDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<FileManagerResponseDto>>;
9
+ insertMany(addDto: CreateFileManagerDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FileManagerResponseDto>>;
10
+ getById(id: string, body: import("@flusys/nestjs-shared/dtos").GetByIdBodyDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<FileManagerResponseDto>>;
11
+ update(updateDto: UpdateFileManagerDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<FileManagerResponseDto>>;
12
+ updateMany(updateDtos: UpdateFileManagerDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FileManagerResponseDto>>;
13
+ getAll(filterAndPaginationDto: import("@flusys/nestjs-shared/dtos").FilterAndPaginationDto, user: ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared/dtos").ListResponseDto<FileManagerResponseDto>>;
14
+ delete(deleteDto: import("@flusys/nestjs-shared/dtos").DeleteDto, user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").MessageResponseDto>;
15
+ };
16
+ export declare class FileManagerController extends FileManagerController_base {
17
+ protected fileService: FileManagerService;
18
+ constructor(fileService: FileManagerService);
19
+ getFiles(dto: Array<GetFilesRequestDto>, req: Request, user: ILoggedUserInfo): Promise<SingleResponseDto<FilesResponseDto[]>>;
20
+ }
21
+ export {};
@@ -0,0 +1,17 @@
1
+ import { CreateFolderDto, FolderResponseDto, UpdateFolderDto } from '@flusys/nestjs-storage/dtos';
2
+ import { FolderService } from '../services/folder.service';
3
+ declare const FolderController_base: abstract new (service: FolderService) => {
4
+ service: FolderService;
5
+ insert(addDto: CreateFolderDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<FolderResponseDto>>;
6
+ insertMany(addDto: CreateFolderDto[], user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FolderResponseDto>>;
7
+ getById(id: string, body: import("@flusys/nestjs-shared/dtos").GetByIdBodyDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<FolderResponseDto>>;
8
+ update(updateDto: UpdateFolderDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<FolderResponseDto>>;
9
+ updateMany(updateDtos: UpdateFolderDto[], user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FolderResponseDto>>;
10
+ getAll(filterAndPaginationDto: import("@flusys/nestjs-shared/dtos").FilterAndPaginationDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared/dtos").ListResponseDto<FolderResponseDto>>;
11
+ delete(deleteDto: import("@flusys/nestjs-shared/dtos").DeleteDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").MessageResponseDto>;
12
+ };
13
+ export declare class FolderController extends FolderController_base {
14
+ folderService: FolderService;
15
+ constructor(folderService: FolderService);
16
+ }
17
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from './file-manager.controller';
2
+ export * from './folder.controller';
3
+ export * from './storage-config.controller';
4
+ export * from './upload.controller';
@@ -0,0 +1,17 @@
1
+ import { CreateStorageConfigDto, StorageConfigResponseDto, UpdateStorageConfigDto } from '@flusys/nestjs-storage/dtos';
2
+ import { StorageProviderConfigService } from '../services/storage-provider-config.service';
3
+ declare const StorageConfigController_base: abstract new (service: StorageProviderConfigService) => {
4
+ service: StorageProviderConfigService;
5
+ insert(addDto: CreateStorageConfigDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<StorageConfigResponseDto>>;
6
+ insertMany(addDto: CreateStorageConfigDto[], user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<StorageConfigResponseDto>>;
7
+ getById(id: string, body: import("@flusys/nestjs-shared/dtos").GetByIdBodyDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<StorageConfigResponseDto>>;
8
+ update(updateDto: UpdateStorageConfigDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<StorageConfigResponseDto>>;
9
+ updateMany(updateDtos: UpdateStorageConfigDto[], user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<StorageConfigResponseDto>>;
10
+ getAll(filterAndPaginationDto: import("@flusys/nestjs-shared/dtos").FilterAndPaginationDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared/dtos").ListResponseDto<StorageConfigResponseDto>>;
11
+ delete(deleteDto: import("@flusys/nestjs-shared/dtos").DeleteDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").MessageResponseDto>;
12
+ };
13
+ export declare class StorageConfigController extends StorageConfigController_base {
14
+ storageConfigService: StorageProviderConfigService;
15
+ constructor(storageConfigService: StorageProviderConfigService);
16
+ }
17
+ export {};
@@ -0,0 +1,15 @@
1
+ import { SingleResponseDto } from '@flusys/nestjs-shared/dtos';
2
+ import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
+ import { DeleteMultipleFileDto, DeleteSingleFileDto, FileUploadResponsePayloadDto, UploadOptionsDto } from '@flusys/nestjs-storage/dtos';
4
+ import { Response } from 'express';
5
+ import { UploadService } from '../services/upload.service';
6
+ export declare class UploadController {
7
+ private uploadService;
8
+ private logger;
9
+ constructor(uploadService: UploadService);
10
+ uploadSingleFile(file: Express.Multer.File, options: UploadOptionsDto, user: ILoggedUserInfo): Promise<SingleResponseDto<FileUploadResponsePayloadDto>>;
11
+ uploadMultipleFiles(files: Express.Multer.File[], options: UploadOptionsDto, user: ILoggedUserInfo): Promise<SingleResponseDto<FileUploadResponsePayloadDto[]>>;
12
+ deleteSingleFile(dto: DeleteSingleFileDto, user: ILoggedUserInfo): Promise<SingleResponseDto<boolean>>;
13
+ deleteMultipleFile(dto: DeleteMultipleFileDto, user: ILoggedUserInfo): Promise<SingleResponseDto<boolean>>;
14
+ seeUploadedFile(filePath: string | string[], res: Response): Promise<void>;
15
+ }
@@ -0,0 +1 @@
1
+ export { storageSwaggerConfig } from './storage-swagger.config';
@@ -0,0 +1,3 @@
1
+ import { IBootstrapAppConfig } from '@flusys/nestjs-core';
2
+ import { IModuleSwaggerOptions } from '@flusys/nestjs-core/docs';
3
+ export declare function storageSwaggerConfig(bootstrapConfig?: IBootstrapAppConfig): IModuleSwaggerOptions;
@@ -0,0 +1,29 @@
1
+ import { FileLocationEnum } from '@flusys/nestjs-storage/enums';
2
+ export declare class CreateFileManagerDto implements Record<string, unknown> {
3
+ [key: string]: unknown;
4
+ name: string;
5
+ key: string;
6
+ size: string;
7
+ contentType: string;
8
+ isPrivate: boolean;
9
+ folderId?: string;
10
+ storageConfigId?: string;
11
+ location?: FileLocationEnum;
12
+ }
13
+ declare const UpdateFileManagerDto_base: import("@nestjs/common").Type<Partial<CreateFileManagerDto>>;
14
+ export declare class UpdateFileManagerDto extends UpdateFileManagerDto_base implements Record<string, unknown> {
15
+ [key: string]: unknown;
16
+ id: string;
17
+ }
18
+ export declare class FileManagerResponseDto extends UpdateFileManagerDto {
19
+ }
20
+ export declare class GetFilesRequestDto {
21
+ id: string;
22
+ }
23
+ export declare class FilesResponseDto {
24
+ id: string;
25
+ name: string;
26
+ contentType: string;
27
+ url: string;
28
+ }
29
+ export {};
@@ -0,0 +1,13 @@
1
+ export declare class CreateFolderDto implements Record<string, unknown> {
2
+ [key: string]: unknown;
3
+ name: string;
4
+ }
5
+ declare const UpdateFolderDto_base: import("@nestjs/common").Type<Partial<CreateFolderDto>>;
6
+ export declare class UpdateFolderDto extends UpdateFolderDto_base implements Record<string, unknown> {
7
+ [key: string]: unknown;
8
+ id: string;
9
+ }
10
+ export declare class FolderResponseDto extends UpdateFolderDto {
11
+ slug: string;
12
+ }
13
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from './folder.dto';
2
+ export * from './file-manager.dto';
3
+ export * from './upload.dto';
4
+ export * from './storage-config.dto';
@@ -0,0 +1,21 @@
1
+ import { IdentityResponseDto } from '@flusys/nestjs-shared/dtos';
2
+ import { FileLocationEnum } from '@flusys/nestjs-storage/enums';
3
+ export declare class CreateStorageConfigDto implements Record<string, unknown> {
4
+ [key: string]: unknown;
5
+ name: string;
6
+ storage: FileLocationEnum;
7
+ config: Record<string, any>;
8
+ }
9
+ export declare class UpdateStorageConfigDto implements Record<string, unknown> {
10
+ [key: string]: unknown;
11
+ id: string;
12
+ name?: string;
13
+ storage?: FileLocationEnum;
14
+ config?: Record<string, any>;
15
+ }
16
+ export declare class StorageConfigResponseDto extends IdentityResponseDto implements Record<string, unknown> {
17
+ [key: string]: unknown;
18
+ name: string;
19
+ storage: FileLocationEnum;
20
+ config: Record<string, any>;
21
+ }
@@ -0,0 +1,29 @@
1
+ export declare enum ImageFormat {
2
+ ORIGINAL = "original",
3
+ JPEG = "jpeg",
4
+ PNG = "png",
5
+ WEBP = "webp"
6
+ }
7
+ export declare class DeleteSingleFileDto {
8
+ key: string;
9
+ storageConfigId?: string;
10
+ }
11
+ export declare class DeleteMultipleFileDto {
12
+ keys: string[];
13
+ storageConfigId?: string;
14
+ }
15
+ export declare class UploadOptionsDto {
16
+ storageConfigId?: string;
17
+ folderPath?: string;
18
+ maxWidth?: number;
19
+ maxHeight?: number;
20
+ quality?: number;
21
+ format?: ImageFormat;
22
+ compress?: boolean;
23
+ }
24
+ export declare class FileUploadResponsePayloadDto {
25
+ name: string;
26
+ contentType: string;
27
+ size: number;
28
+ key: string;
29
+ }
@@ -0,0 +1,13 @@
1
+ import { Identity } from '@flusys/nestjs-shared/entities';
2
+ import { FileLocationEnum } from '@flusys/nestjs-storage/enums';
3
+ export declare abstract class FileManagerBase extends Identity {
4
+ name: string;
5
+ contentType: string;
6
+ size: string;
7
+ key: string;
8
+ url: string | null;
9
+ location: FileLocationEnum;
10
+ storageConfigId: string | null;
11
+ expiresAt: number | null;
12
+ isPrivate: boolean;
13
+ }
@@ -0,0 +1,6 @@
1
+ import { FileManagerBase } from './file-manager-base.entity';
2
+ import { FolderWithCompany } from './folder-with-company.entity';
3
+ export declare class FileManagerWithCompany extends FileManagerBase {
4
+ companyId: string | null;
5
+ folder: FolderWithCompany | null;
6
+ }
@@ -0,0 +1,5 @@
1
+ import { FileManagerBase } from './file-manager-base.entity';
2
+ import { Folder } from './folder.entity';
3
+ export declare class FileManager extends FileManagerBase {
4
+ folder: Folder | null;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { Identity } from '@flusys/nestjs-shared/entities';
2
+ export declare abstract class FolderBase extends Identity {
3
+ name: string;
4
+ slug: string;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { FolderBase } from './folder-base.entity';
2
+ export declare class FolderWithCompany extends FolderBase {
3
+ companyId: string | null;
4
+ fileManager: any[];
5
+ }
@@ -0,0 +1,4 @@
1
+ import { FolderBase } from './folder-base.entity';
2
+ export declare class Folder extends FolderBase {
3
+ fileManager: any[];
4
+ }
@@ -0,0 +1,19 @@
1
+ export * from './file-manager-base.entity';
2
+ export * from './folder-base.entity';
3
+ export * from './storage-config-base.entity';
4
+ export * from './file-manager.entity';
5
+ export * from './folder.entity';
6
+ export * from './storage-config.entity';
7
+ export * from './file-manager-with-company.entity';
8
+ export * from './folder-with-company.entity';
9
+ export * from './storage-config-with-company.entity';
10
+ import { FileManager } from './file-manager.entity';
11
+ import { Folder } from './folder.entity';
12
+ import { StorageConfig } from './storage-config.entity';
13
+ import { FileManagerWithCompany } from './file-manager-with-company.entity';
14
+ import { FolderWithCompany } from './folder-with-company.entity';
15
+ import { StorageConfigWithCompany } from './storage-config-with-company.entity';
16
+ export declare const StorageCoreEntities: (typeof Folder | typeof FileManager | typeof StorageConfig)[];
17
+ export declare const StorageCompanyEntities: (typeof FolderWithCompany | typeof FileManagerWithCompany | typeof StorageConfigWithCompany)[];
18
+ export declare const StorageAllEntities: (typeof Folder | typeof FileManager | typeof StorageConfig)[];
19
+ export declare function getStorageEntitiesByConfig(enableCompanyFeature: boolean): any[];
@@ -0,0 +1,7 @@
1
+ import { Identity } from '@flusys/nestjs-shared/entities';
2
+ import { FileLocationEnum } from '@flusys/nestjs-storage/enums';
3
+ export declare abstract class StorageConfigBase extends Identity {
4
+ name: string;
5
+ storage: FileLocationEnum;
6
+ config: Record<string, any>;
7
+ }
@@ -0,0 +1,4 @@
1
+ import { StorageConfigBase } from './storage-config-base.entity';
2
+ export declare class StorageConfigWithCompany extends StorageConfigBase {
3
+ companyId: string | null;
4
+ }
@@ -0,0 +1,3 @@
1
+ import { StorageConfigBase } from './storage-config-base.entity';
2
+ export declare class StorageConfig extends StorageConfigBase {
3
+ }
@@ -0,0 +1,6 @@
1
+ export declare enum FileLocationEnum {
2
+ AWS = "aws",
3
+ AZURE = "azure",
4
+ SFTP = "sftp",
5
+ LOCAL = "local"
6
+ }
@@ -0,0 +1 @@
1
+ export * from './file-location.enum';
@@ -0,0 +1 @@
1
+ var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __name=(target,value)=>__defProp(target,"name",{value,configurable:true});var __decorateClass=(decorators,target,key,kind)=>{var result=kind>1?void 0:kind?__getOwnPropDesc(target,key):target;for(var i=decorators.length-1,decorator;i>=0;i--)if(decorator=decorators[i])result=(kind?decorator(target,key,result):decorator(result))||result;if(kind&&result)__defProp(target,key,result);return result};var __decorateParam=(index,decorator)=>(target,key)=>decorator(target,key,index);var STORAGE_MODULE_OPTIONS="STORAGE_MODULE_OPTIONS";var STORAGE_CONFIG_SERVICE="STORAGE_CONFIG_SERVICE";var STORAGE_DATA_SOURCE_PROVIDER="STORAGE_DATA_SOURCE_PROVIDER";var DEFAULT_MAX_FILE_SIZE=100*1024*1024;var DEFAULT_ALLOWED_FILE_TYPES=["*/*"];var FILE_VALIDATION_MESSAGES={FILE_TOO_LARGE:"File size exceeds the maximum allowed size",INVALID_FILE_TYPE:"File type is not allowed",NO_FILE_PROVIDED:"No file was provided",UPLOAD_FAILED:"File upload failed"};import{Inject,Injectable}from"@nestjs/common";var StorageConfigService=class{constructor(options){this.options=options}isCompanyFeatureEnabled(){return this.options.bootstrapAppConfig?.enableCompanyFeature??false}getDatabaseMode(){return this.options.bootstrapAppConfig?.databaseMode??"single"}getMaxFileSize(){return this.options.config?.maxFileSize??DEFAULT_MAX_FILE_SIZE}getAllowedFileTypes(){return this.options.config?.allowedFileTypes??DEFAULT_ALLOWED_FILE_TYPES}isFileTypeAllowed(mimeType){const allowedTypes=this.getAllowedFileTypes();if(allowedTypes.includes("*/*")){return true}return allowedTypes.some(allowedType=>{if(allowedType.endsWith("/*")){const prefix=allowedType.slice(0,-2);return mimeType.startsWith(prefix)}return allowedType===mimeType})}validateFileSize(fileSize){const maxSize=this.getMaxFileSize();if(fileSize>maxSize){const maxSizeMB=(maxSize/(1024*1024)).toFixed(2);const fileSizeMB=(fileSize/(1024*1024)).toFixed(2);return{valid:false,message:`File size (${fileSizeMB}MB) exceeds the maximum allowed size of ${maxSizeMB}MB`}}return{valid:true}}validateFileType(mimeType){if(!this.isFileTypeAllowed(mimeType)){const allowedTypes=this.getAllowedFileTypes();return{valid:false,message:`File type "${mimeType}" is not allowed. Allowed types: ${allowedTypes.join(", ")}`}}return{valid:true}}getDefaultDatabaseConfig(){return this.options.config?.defaultDatabaseConfig}getOptions(){return this.options}};__name(StorageConfigService,"StorageConfigService");StorageConfigService=__decorateClass([Injectable(),__decorateParam(0,Inject(STORAGE_MODULE_OPTIONS))],StorageConfigService);export{DEFAULT_ALLOWED_FILE_TYPES,DEFAULT_MAX_FILE_SIZE,FILE_VALIDATION_MESSAGES,STORAGE_CONFIG_SERVICE,STORAGE_DATA_SOURCE_PROVIDER,STORAGE_MODULE_OPTIONS,StorageConfigService};