import { aiApiClient } from "../api/client"; // Optional token getter - will be set by the app let authTokenGetter: (() => Promise) | null = null; // Simple cache to prevent repeated requests const blobUrlCache = new Map(); const pendingRequests = new Map>(); export const setMediaAuthTokenGetter = (getter: (() => Promise) | null) => { authTokenGetter = getter; }; // Clear cache for specific URL or all URLs export const clearMediaCache = (url?: string) => { if (url) { blobUrlCache.delete(url); pendingRequests.delete(url); } else { blobUrlCache.clear(); pendingRequests.clear(); } }; export async function fetchMediaBlobUrl(pathOrUrl: string): Promise { try { // Check cache first if (blobUrlCache.has(pathOrUrl)) { return blobUrlCache.get(pathOrUrl) || null; } // Check if there's already a pending request for this URL if (pendingRequests.has(pathOrUrl)) { return pendingRequests.get(pathOrUrl) || null; } // Create new request const requestPromise = (async () => { // If full URL (http/https), use as-is; otherwise ensure leading slash const isAbsolute = /^https?:\/\//i.test(pathOrUrl); const rel = isAbsolute ? pathOrUrl : pathOrUrl.startsWith("/") ? pathOrUrl : `/${pathOrUrl}`; // Try to get token and add as query parameter as fallback for endpoints that support it // This helps with endpoints that use get_current_user_with_query_token let url = rel; if (authTokenGetter) { try { const token = await authTokenGetter(); if (token) { // Add token as query parameter for endpoints that support it const separator = url.includes('?') ? '&' : '?'; url = `${url}${separator}token=${encodeURIComponent(token)}`; } } catch (tokenError) { console.warn(`[fetchMediaBlobUrl] Failed to get token for query param:`, tokenError); } } const res = await aiApiClient.get(url, { responseType: "blob" }); const blobUrl = URL.createObjectURL(res.data); // Cache the result blobUrlCache.set(pathOrUrl, blobUrl); pendingRequests.delete(pathOrUrl); return blobUrl; })(); // Store pending request pendingRequests.set(pathOrUrl, requestPromise); return await requestPromise; } catch (err: any) { // Cache the failure to prevent repeated requests blobUrlCache.set(pathOrUrl, null); pendingRequests.delete(pathOrUrl); // Gracefully handle 404s and other errors - file might not exist or was regenerated if (err?.response?.status === 404) { console.warn(`Media file not found (404): ${pathOrUrl}`); return null; } // Re-throw other errors throw err; } }