import { Injectable, signal } from '@angular/core'; export interface BootstrapPayload { initialized: boolean; pageTitle: string; logo: string; welcomeMarkdown: string; theme: any; defaultChallengeIp: string; registrationsEnabled: boolean; } @Injectable({ providedIn: 'root' }) export class BootstrapService { readonly payload = signal(null); readonly initialized = signal(false); async load(): Promise { try { const res = await fetch('/api/v1/bootstrap', { credentials: 'include' }); const data = (await res.json()) as BootstrapPayload; this.payload.set(data); this.initialized.set(data.initialized); this.applyTheme(data.theme); return data; } catch (e) { console.error('Bootstrap load failed', e); return null; } } private applyTheme(theme: any): void { if (!theme?.tokens) return; const root = document.documentElement.style; const t = theme.tokens; root.setProperty('--color-primary', t.primary); root.setProperty('--color-secondary', t.secondary); root.setProperty('--color-accent', t.accent); root.setProperty('--color-surface', t.surface); root.setProperty('--color-text', t.text); root.setProperty('--color-success', t.success); root.setProperty('--color-warning', t.warning); root.setProperty('--color-danger', t.danger); root.setProperty('--font-family', t.fontFamily); root.setProperty('--radius-sm', t.radii.sm); root.setProperty('--radius-md', t.radii.md); root.setProperty('--radius-lg', t.radii.lg); } }