import { logger } from '../../debugConfig'; const apiBase = (import.meta.env.VITE_API_BASE as string) || ''; export interface BootstrapProfile { id: string; email: string; display_name: string; user_type: string; school_id: string | null; } export interface BootstrapMembership { institute_id: string; role: string; status: string; is_active: boolean; institute: { id: string; name: string; urn: string | null; }; } export interface BootstrapActiveInstitute { id: string | null; source: string; membership_role: string | null; } export interface BootstrapPermissions { platform_admin: boolean; platform_super_admin: boolean; can_create_school: boolean; can_manage_school: boolean; can_manage_calendar: boolean; can_manage_timetable: boolean; can_invite_staff: boolean; can_manage_classes: boolean; can_view_student_data: boolean; can_use_canvas: boolean; } export interface BootstrapOnboarding { next_step: string; required: string[]; optional: string[]; message: string; } export interface BootstrapCalendarStatus { available: boolean; academic_year_count: number; term_count: number; current_academic_year_id: string | null; needs_setup: boolean; } export interface BootstrapTimetableStatus { available: boolean; teacher_timetable_id: string | null; slot_count: number; needs_setup: boolean; } export interface BootstrapGraphStatus { available: boolean; user_db: string | null; institute_db: string | null; projection_state: string; needs_rebuild: boolean; last_checked_at: string | null; error_code: string | null; } export interface BootstrapResponse { profile: BootstrapProfile; memberships: BootstrapMembership[]; active_institute: BootstrapActiveInstitute; permissions: BootstrapPermissions; school_status: string; onboarding: BootstrapOnboarding; calendar_status: BootstrapCalendarStatus; timetable_status: BootstrapTimetableStatus; graph_status: BootstrapGraphStatus; } let cachedBootstrap: BootstrapResponse | null = null; let cacheTimestamp = 0; const CACHE_TTL_MS = 60_000; // 60 second cache export async function fetchBootstrapData(accessToken: string): Promise { if (!accessToken) return null; // Return cached data if fresh if (cachedBootstrap && Date.now() - cacheTimestamp < CACHE_TTL_MS) { return cachedBootstrap; } try { const res = await fetch(`${apiBase}/me/bootstrap`, { headers: { Authorization: `Bearer ${accessToken}` }, }); if (!res.ok) { logger.warn('bootstrap-service', `Bootstrap fetch failed: ${res.status}`); return cachedBootstrap; // Return stale cache on error } const data: BootstrapResponse = await res.json(); cachedBootstrap = data; cacheTimestamp = Date.now(); return data; } catch (err) { logger.error('bootstrap-service', 'Bootstrap fetch error', { err }); return cachedBootstrap; // Return stale cache on error } } export function invalidateBootstrapCache(): void { cachedBootstrap = null; cacheTimestamp = 0; }