/** * Presigned URL API Endpoint * Agent 3: File Upload & Storage System * * POST /api/upload/presigned - Get a presigned URL for direct upload */ import type { NextApiRequest, NextApiResponse } from 'next'; import { getUploadService } from '../../../lib/storage'; import type { FileCategory, PresignedUrlResponse } from '../../../lib/storage/types'; interface RequestBody { filename: string; contentType: string; category: FileCategory; expiresIn?: number; } interface PresignedResponse { success: boolean; data?: PresignedUrlResponse; error?: string; } export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method !== 'POST') { return res.status(405).json({ success: false, error: 'Method not allowed' }); } try { const { filename, contentType, category, expiresIn } = req.body as RequestBody; // Validate required fields if (!filename || !contentType || !category) { return res.status(400).json({ success: false, error: 'Missing required fields: filename, contentType, category', }); } // Validate category const validCategories: FileCategory[] = ['plant-photo', 'certificate', 'document', 'report', 'avatar']; if (!validCategories.includes(category)) { return res.status(400).json({ success: false, error: `Invalid category. Must be one of: ${validCategories.join(', ')}`, }); } // Validate content type const allowedContentTypes = [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/heic', 'image/heif', 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', ]; if (!allowedContentTypes.includes(contentType)) { return res.status(400).json({ success: false, error: `Invalid content type. Must be one of: ${allowedContentTypes.join(', ')}`, }); } const uploadService = getUploadService(); const presignedUrl = await uploadService.getPresignedUploadUrl({ filename, contentType, category, expiresIn: expiresIn || 3600, // Default 1 hour }); return res.status(200).json({ success: true, data: presignedUrl, }); } catch (error) { console.error('Presigned URL error:', error); return res.status(500).json({ success: false, error: error instanceof Error ? error.message : 'Internal server error', }); } }