export async function apiRequest(path, token, options = {}) { const response = await fetch(path, { ...options, headers: { ...(options.body instanceof FormData ? {} : { 'Content-Type': 'application/json' }), ...(token ? { Authorization: `Bearer ${token}` } : {}), ...(options.headers || {}) } }); if (!response.ok) { const body = await response.json().catch(() => ({})); // An invalid/expired token (401) means the session is no longer valid — signal the // app to drop back to the login screen. (403 is a role/permission denial, not a session issue.) if (response.status === 401) { window.dispatchEvent(new CustomEvent('mixedassets:unauthorized')); } throw new Error(body.error || `Request failed: ${response.status}`); } return response; } export async function loginRequest(credentials) { const response = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials) }); const data = await response.json(); if (!response.ok) throw new Error(data.error || 'Unable to sign in'); return data; } export function saveBlob(blob, filename) { const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; link.click(); URL.revokeObjectURL(url); }