import { CONFIG } from './config.js'; export class ApiError extends Error { constructor(message, status = null) { super(message); this.name = 'ApiError'; this.status = status; } } async function request(path) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), CONFIG.requestTimeoutMs); try { const res = await fetch(`${CONFIG.apiBaseUrl}${path}`, { headers: { Accept: 'application/json' }, credentials: 'same-origin', // ready for cookie/session auth behind nginx signal: controller.signal, }); // 401 means the nginx/SSO session lapsed; a reload sends the user back through sign-in if (res.status === 401) throw new ApiError('Your session has expired. Reload the page to sign in again', 401); if (!res.ok) throw new ApiError(`Server returned HTTP ${res.status}`, res.status); return await res.json(); } catch (err) { if (err.name === 'AbortError') throw new ApiError('Request timed out'); if (err instanceof ApiError) throw err; throw new ApiError(`Network error: ${err.message}`); } finally { clearTimeout(timer); } } const httpApi = { /** GET /jobs → { generated_at, jobs: Job[] } */ async listJobs() { const data = await request('/jobs'); if (!Array.isArray(data?.jobs)) throw new ApiError('Unexpected response shape from /jobs'); return data; }, /** GET /jobs/:id → JobDetail */ getJob(id) { return request(`/jobs/${encodeURIComponent(id)}`); }, /** GET /jobs/:id/runs?days=N → { job_id, since, runs: RunSummary[] } (newest first, no messages) */ listRuns(id, days) { return request(`/jobs/${encodeURIComponent(id)}/runs?days=${encodeURIComponent(days)}`); }, /** GET /runs/:id → Run (with message and details) */ getRun(id) { return request(`/runs/${encodeURIComponent(id)}`); }, /** GET /me → { email, name } of the Microsoft 365 user, both null without sign-in */ getMe() { return request('/me'); }, }; // Mock is loaded lazily so it never ships in the production request path. export async function getApi() { if (CONFIG.useMock) { const { mockApi } = await import('./mock.js'); return mockApi; } return httpApi; }