/** * Blog API functions */ import { apiRequest } from '../utils/api'; import type { UploadPresignedURLResponse, DownloadPresignedURLResponse, CreatePostResponse, } from './types'; const API_BASE = '/api/blog'; /** * Get presigned URL for file upload */ export async function getUploadPresignedURL(fileName: string): Promise { const response = await apiRequest(`${API_BASE}/file/upload`, { method: 'POST', body: JSON.stringify({ fileName }), }); if (!response.ok) { throw new Error(`Failed to get upload URL: ${response.statusText}`); } return response.json(); } /** * Get presigned URL for file download */ export async function getDownloadPresignedURL(fileKey: string): Promise { const response = await apiRequest(`${API_BASE}/file/download`, { method: 'POST', body: JSON.stringify({ fileKey }), }); if (!response.ok) { throw new Error(`Failed to get download URL: ${response.statusText}`); } return response.json(); } /** * Upload file to S3 using presigned URL */ export async function uploadFileToS3( url: string, file: File, onProgress?: (progress: number) => void ): Promise { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); // Track upload progress xhr.upload.addEventListener('progress', (event) => { if (event.lengthComputable && onProgress) { const progress = (event.loaded / event.total) * 100; onProgress(progress); } }); xhr.addEventListener('load', () => { if (xhr.status >= 200 && xhr.status < 300) { resolve(); } else { reject(new Error(`Upload failed with status ${xhr.status}`)); } }); xhr.addEventListener('error', () => { reject(new Error('Upload failed')); }); xhr.addEventListener('abort', () => { reject(new Error('Upload aborted')); }); xhr.open('PUT', url); xhr.setRequestHeader('Content-Type', file.type); xhr.send(file); }); } /** * Complete image upload workflow */ export async function uploadImage( file: File, onProgress?: (progress: number) => void ): Promise<{ fileKey: string; url: string }> { // Step 1: Get presigned URL const { url: uploadUrl, fileKey } = await getUploadPresignedURL(file.name); // Step 2: Upload file to S3 await uploadFileToS3(uploadUrl, file, onProgress); // Step 3: Get download URL const { url: downloadUrl } = await getDownloadPresignedURL(fileKey); return { fileKey, url: downloadUrl }; } /** * Create a new blog post */ export async function createBlogPost( title: string, content: string, coverImageKey: string ): Promise { const response = await apiRequest(`${API_BASE}/post/create`, { method: 'POST', body: JSON.stringify({ title, content, coverImageKey, }), }); if (!response.ok) { throw new Error(`Failed to create post: ${response.statusText}`); } return response.json(); }