const RAW_API_BASE = String(import.meta.env.VITE_API_BASE || 'http://localhost:8000') .trim() .replace(/\/$/, ''); export const RESOURCE_BASE = RAW_API_BASE.replace(/\/api\/?$/i, '').replace(/\/$/, ''); export const isAbsoluteLikeUrl = (url: string): boolean => ( /^(https?:)?\/\//i.test(url) || /^(blob|data):/i.test(url) ); export const isBlobUrl = (url?: string | null): boolean => !!url && /^blob:/i.test(url.trim()); export const apiUrl = (url?: string | null): string => { if (!url) return ''; const value = String(url).trim(); if (!value) return ''; if (isAbsoluteLikeUrl(value)) return value; if (!RESOURCE_BASE) { return value.startsWith('/') ? value : `/${value}`; } return `${RESOURCE_BASE}${value.startsWith('/') ? value : `/${value}`}`; }; export const isUrlExpired = (url?: string | null): boolean => { if (!url || isBlobUrl(url)) return false; try { const parsed = new URL(apiUrl(url), window.location.origin); const expireValue = parsed.searchParams.get('exp') || parsed.searchParams.get('expires') || parsed.searchParams.get('expire') || parsed.searchParams.get('expires_at') || parsed.searchParams.get('x-expires'); if (!expireValue) return false; const expireNumber = Number(expireValue); if (!Number.isFinite(expireNumber)) return false; const expireMs = expireNumber > 10_000_000_000 ? expireNumber : expireNumber * 1000; return Date.now() >= expireMs; } catch { return false; } };