// --- API Interaction Functions --- /** * Makes a fetch request and handles common scenarios like JSON parsing and HTTP errors. * @param {string} url - The URL to fetch. * @param {object} options - Fetch options (method, headers, body, etc.). * @returns {Promise} - A promise that resolves with the parsed JSON data. * @throws {Error} - Throws an error if the fetch fails or the response is not ok. */ async function fetchApi(url, options = {}) { try { const response = await fetch(url, options); // Try to parse JSON regardless of status code for potential error details let data = {}; try { // Handle potential non-JSON responses (e.g., empty body on 204) const text = await response.text(); if (text) { data = JSON.parse(text); } else { data = { success: response.ok, message: response.statusText }; // Basic success/failure if body empty } } catch (e) { console.warn(`Could not parse JSON response from ${url}. Status: ${response.status}`); // If JSON parsing fails, still check the HTTP status if (!response.ok) { throw new Error(options.errorMessage || `Request failed with status ${response.status}. No details available.`); } // If response was OK but JSON failed, might be acceptable depending on endpoint // Or return a default success object if appropriate data = { success: true, message: "Operation successful, but response was not valid JSON." }; } if (!response.ok) { // Use the message from parsed JSON if available, otherwise default error throw new Error(data.message || options.errorMessage || `Request failed with status ${response.status}`); } // Ensure the returned data always has a `success` property if not present if (typeof data.success === 'undefined') { data.success = true; // Assume success if HTTP status was OK and no success flag found } return data; } catch (error) { console.error(`API Error (${options.method || 'GET'} ${url}):`, error); // Re-throw the error so the calling function can handle it (e.g., display to user) throw error; // Keep original error type/message if possible } } // --- Specific API Call Functions --- /** * Fetches the list of PDF files for a given project. * @param {string} projectName - The name of the project. * @returns {Promise} - The API response (e.g., { success: true, files: [...] }). */ async function apiListPdfs(projectName) { return fetchApi(`/list_pdfs/${encodeURIComponent(projectName)}`, { errorMessage: 'Failed to list PDF files' }); } /** * Deletes a specific PDF file from a project. * @param {string} projectName - The name of the project. * @param {string} filename - The name of the PDF file to delete. * @returns {Promise} - The API response (e.g., { success: true, message: "..." }). */ async function apiDeletePdf(projectName, filename) { return fetchApi(`/delete_pdf/${encodeURIComponent(projectName)}`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ filename: filename }), errorMessage: 'Failed to delete PDF file' }); } /** * Uploads one or more PDF files to a project. * @param {string} projectName - The name of the project. * @param {FormData} formData - The FormData object containing the files. * @returns {Promise} - The API response (e.g., { success: true, message: "..." }). */ async function apiUploadPdfs(projectName, formData) { return fetchApi(`/upload_pdfs/${encodeURIComponent(projectName)}`, { method: 'POST', body: formData, // FormData sets Content-Type automatically errorMessage: 'File upload failed' }); } /** * Triggers a background analysis for a specific project. * @param {string} projectName - The name of the project. * @returns {Promise} - The API response (e.g., { success: true, message: "..." }). */ async function apiTriggerAnalysis(projectName) { return fetchApi(`/trigger_analysis/${encodeURIComponent(projectName)}`, { method: 'POST', errorMessage: 'Failed to trigger analysis' }); } /** * Adds a new project. * @param {FormData} formData - The FormData object containing project details and files. * @returns {Promise} - The API response (e.g., { success: true, message: "..." }). */ async function apiAddProject(formData) { return fetchApi('/add_project', { method: 'POST', body: formData, errorMessage: 'Failed to add project' }); } /** * Deletes an entire project. * @param {string} projectName - The name of the project to delete. * @returns {Promise} - The API response (e.g., { success: true, message: "..." }). */ async function apiDeleteProject(projectName) { return fetchApi(`/delete_project/${encodeURIComponent(projectName)}`, { method: 'POST', // Backend expects POST errorMessage: 'Failed to delete project' }); } /** * Uploads and overwrites the manifest file for a project. * @param {string} projectName - The name of the project. * @param {FormData} formData - The FormData object containing the manifest file. * @returns {Promise} - The API response (e.g., { success: true, message: "..." }). */ async function apiUploadManifest(projectName, formData) { return fetchApi(`/upload_manifest/${encodeURIComponent(projectName)}`, { method: 'POST', body: formData, errorMessage: 'Failed to upload manifest' }); } // --- Export (if using modules in the future) --- // export { apiListPdfs, apiDeletePdf, apiUploadPdfs, apiTriggerAnalysis, apiAddProject, apiDeleteProject, apiUploadManifest };