UNPKG

npm-storage-package

Version:

Universal cloud storage package for AWS S3, Google Cloud Storage, and Azure Blob Storage with Express.js integration

188 lines 9.16 kB
import { storageAction } from "./storageAction.js"; import fs from "fs"; // Create storage upload middleware function export function createStorageUploadMiddleware(options) { return async (req, res, next) => { try { // Initialize uploadedFiles if not present if (!req.uploadedFiles) { req.uploadedFiles = {}; } // Handle multiple fields if provided if (options.fields && options.fields.length > 0) { const files = req.files; for (const fieldConfig of options.fields) { const fieldFiles = files?.[fieldConfig.fieldName]; if (!fieldFiles) continue; const filesToProcess = Array.isArray(fieldFiles) ? fieldFiles : [fieldFiles]; const uploadedUrls = []; for (const file of filesToProcess) { // Apply field-specific filter if (fieldConfig.fileFilter && !fieldConfig.fileFilter(req, file)) { // Clean up the temp file if (file.path && fs.existsSync(file.path)) { fs.unlinkSync(file.path); } continue; } // Generate filename using field-specific function or folder let fileName; if (fieldConfig.generateFileName) { fileName = fieldConfig.generateFileName(req, file); } else if (fieldConfig.folder) { fileName = `${fieldConfig.folder}/${Date.now()}-${file.originalname}`; } else { fileName = file.filename || file.originalname; } // Upload the file const uploadedUrl = await storageAction(options.provider, "upload", options.config, { fileName, filePath: file.path, mimeType: file.mimetype, }); uploadedUrls.push(uploadedUrl); // Clean up temp file if (file.path && fs.existsSync(file.path)) { fs.unlinkSync(file.path); } } // Store the URL(s) based on maxCount if (fieldConfig.maxCount === 1 || uploadedUrls.length === 1) { req.uploadedFiles[fieldConfig.fieldName] = uploadedUrls[0] || ""; } else { req.uploadedFiles[fieldConfig.fieldName] = uploadedUrls; } } } else { // Original single field logic const { fieldName = "file", multiple = false, fileFilter, limits, generateFileName, } = options; if (multiple) { const files = Array.isArray(req.files) ? req.files : req.files ? [req.files] : []; if (files.length > 0) { // Apply file filter if provided const filteredFiles = fileFilter ? files.filter((file) => fileFilter(req, file)) : files; // Check limits if (limits?.files && filteredFiles.length > limits.files) { return next(new Error(`Too many files. Maximum ${limits.files} allowed.`)); } const uploadPromises = filteredFiles.map(async (file) => { // Check file size limit if (limits?.fileSize && file.size > limits.fileSize) { throw new Error(`File ${file.originalname} exceeds size limit of ${limits.fileSize} bytes`); } // Generate filename if custom generator provided const fileName = generateFileName ? generateFileName(req, file) : file.filename || file.originalname; const uploadedUrl = await storageAction(options.provider, "upload", options.config, { fileName, filePath: file.path, mimeType: file.mimetype, }); // Clean up temp file if it exists if (file.path && fs.existsSync(file.path)) { fs.unlinkSync(file.path); } return uploadedUrl; }); req.uploadedFiles[fieldName] = await Promise.all(uploadPromises); } } else { const file = req.file; if (file) { // Apply file filter if provided if (fileFilter && !fileFilter(req, file)) { return next(new Error("File type not allowed")); } // Check file size limit if (limits?.fileSize && file.size > limits.fileSize) { return next(new Error(`File exceeds size limit of ${limits.fileSize} bytes`)); } // Generate filename if custom generator provided const fileName = generateFileName ? generateFileName(req, file) : file.filename || file.originalname; const uploadedUrl = await storageAction(options.provider, "upload", options.config, { fileName, filePath: file.path, mimeType: file.mimetype, }); // Clean up temp file if it exists if (file.path && fs.existsSync(file.path)) { fs.unlinkSync(file.path); } req.uploadedFiles[fieldName] = uploadedUrl; } } } next(); } catch (error) { // Clean up temp files in case of error try { if (options.fields) { // Clean up multiple field files const files = req.files; options.fields.forEach((fieldConfig) => { const fieldFiles = files?.[fieldConfig.fieldName]; const filesToClean = Array.isArray(fieldFiles) ? fieldFiles : fieldFiles ? [fieldFiles] : []; filesToClean.forEach((file) => { if (file.path && fs.existsSync(file.path)) { fs.unlinkSync(file.path); } }); }); } else if (options.multiple) { const files = Array.isArray(req.files) ? req.files : req.files ? [req.files] : []; files.forEach((file) => { if (file.path && fs.existsSync(file.path)) { fs.unlinkSync(file.path); } }); } else { const file = req.file; if (file && file.path && fs.existsSync(file.path)) { fs.unlinkSync(file.path); } } } catch (cleanupError) { console.error("Error cleaning up temp files:", cleanupError); } next(error); } }; } // Specific middleware creators for each provider export function s3UploadMiddleware(options) { return createStorageUploadMiddleware({ ...options, provider: "s3" }); } export function gcsUploadMiddleware(options) { return createStorageUploadMiddleware({ ...options, provider: "gcs" }); } export function azureUploadMiddleware(options) { return createStorageUploadMiddleware({ ...options, provider: "azure" }); } // Utility function to delete files export async function deleteStorageFile(provider, config, key) { return (await storageAction(provider, "delete", config, { key })); } // Utility function to get file URL export async function getStorageFileUrl(provider, config, key) { return (await storageAction(provider, "getUrl", config, { key })); } //# sourceMappingURL=middleware.js.map