149 lines
5.8 KiB
JavaScript

// --- 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<object>} - 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<object>} - 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<object>} - 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<object>} - 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<object>} - 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<object>} - 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<object>} - 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<object>} - 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 };