import { useState, useCallback } from 'react'; import axios from 'axios'; import type { FileMetadata, FileServiceConfig, UploadResponse } from '../types'; const DEFAULT_API_URL = 'http://localhost:3002/api/file-service'; export function useFileService(config?: FileServiceConfig) { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const apiUrl = config?.apiUrl || DEFAULT_API_URL; const uploadFile = useCallback( async (file: File): Promise => { setLoading(true); setError(null); try { if (config?.maxFileSize && file.size > config.maxFileSize) { throw new Error(`File size exceeds maximum of ${config.maxFileSize} bytes`); } if (config?.acceptedFileTypes && !config.acceptedFileTypes.includes(file.type)) { throw new Error(`File type ${file.type} is not accepted`); } const formData = new FormData(); formData.append('file', file); const response = await axios.post<{ id: string }>( `${apiUrl}/files/upload`, formData, { headers: { 'Content-Type': 'multipart/form-data', }, } ); setLoading(false); return { success: true, file: { id: response.data.id } as FileMetadata, }; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Upload failed'; setError(errorMessage); setLoading(false); return { success: false, error: errorMessage, }; } }, [apiUrl, config] ); const getFile = useCallback( async (fileId: string): Promise => { setLoading(true); setError(null); try { // First get metadata to get presigned URL const metadata = await axios.get(`${apiUrl}/files/${fileId}`); // If storagePath is a presigned URL, use it to download the file if (metadata.data.storagePath && metadata.data.storagePath.startsWith('http')) { const blobResponse = await axios.get(metadata.data.storagePath, { responseType: 'blob', }); setLoading(false); return blobResponse.data; } // Fallback: try direct download (may not work if endpoint returns JSON) const response = await axios.get(`${apiUrl}/files/${fileId}/download`, { responseType: 'blob', }).catch(() => { // If download endpoint doesn't exist, return null return null; }); setLoading(false); return response ? response.data : null; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'File download failed'; setError(errorMessage); setLoading(false); return null; } }, [apiUrl] ); const getFileMetadata = useCallback( async (fileId: string): Promise => { setLoading(true); setError(null); try { const response = await axios.get( `${apiUrl}/files/${fileId}` ); setLoading(false); return response.data; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to get file metadata'; setError(errorMessage); setLoading(false); return null; } }, [apiUrl] ); const deleteFile = useCallback( async (fileId: string): Promise => { setLoading(true); setError(null); try { await axios.delete(`${apiUrl}/files/${fileId}`); setLoading(false); return true; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'File deletion failed'; setError(errorMessage); setLoading(false); return false; } }, [apiUrl] ); const listFiles = useCallback(async (): Promise => { setLoading(true); setError(null); try { const response = await axios.get(`${apiUrl}/files`); setLoading(false); return response.data; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to list files'; setError(errorMessage); setLoading(false); return []; } }, [apiUrl]); return { uploadFile, getFile, getFileMetadata, deleteFile, listFiles, loading, error, }; }