// services/storageService.js const multer = require('multer'); const multerS3 = require('multer-s3'); const { S3Client } = require('@aws-sdk/client-s3'); const path = require('path'); const fs = require('fs'); const config = require('../config'); class StorageService { constructor() { this.mode = config.site.deployment; this.s3Client = null; if (this.mode === 'cloud' && config.site.awsS3Bucket) { this.s3Client = new S3Client({ region: config.site.awsRegion }); } } getUploadMiddleware() { if (this.mode === 'cloud' && config.site.awsS3Bucket) { // Cloud mode: Use S3 return multer({ storage: multerS3({ s3: this.s3Client, bucket: config.site.awsS3Bucket, acl: 'public-read', key: (req, file, cb) => { const folder = req.path.includes('/product') ? 'products' : 'blog'; cb(null, `${folder}/${Date.now()}-${file.originalname}`); } }), fileFilter: this._fileFilter, limits: { fileSize: 10 * 1024 * 1024 } }); } else { // Self-hosted mode: Use local storage return multer({ storage: multer.diskStorage({ destination: (req, file, cb) => { const uploadDir = path.join(__dirname, '../../public/uploads'); const folder = req.path.includes('/product') ? 'products' : 'blog'; const finalPath = path.join(uploadDir, folder); // Ensure directory exists if (!fs.existsSync(finalPath)) { fs.mkdirSync(finalPath, { recursive: true }); } cb(null, finalPath); }, filename: (req, file, cb) => { cb(null, `${Date.now()}-${file.originalname}`); } }), fileFilter: this._fileFilter, limits: { fileSize: 10 * 1024 * 1024 } }); } } _fileFilter(req, file, cb) { if (file.mimetype.startsWith('image/')) { cb(null, true); } else { cb(new Error('Only image files are allowed!'), false); } } getImageUrl(path) { if (!path) return null; if (this.mode === 'cloud' && config.site.cdnDomain) { // Use CloudFront CDN in cloud mode return `https://${config.site.cdnDomain}${path}`; } else { // Use direct path in self-hosted mode return path; } } } const storageService = new StorageService(); module.exports = storageService;