import { api } from './api.js';
const LS_KEY = 'trusty-analyzer.selectedIndex';
const LS_THEME_KEY = 'trusty-analyzer.theme';
const _initialTheme =
(typeof localStorage !== 'undefined' && localStorage.getItem(LS_THEME_KEY)) ||
'system';
let _theme = $state(_initialTheme);
export const getTheme = () => _theme;
export function applyTheme(t) {
if (typeof document === 'undefined') return;
const resolved =
t === 'system'
? window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
: t;
document.documentElement.setAttribute('data-theme', resolved);
}
export function setTheme(t) {
_theme = t;
if (typeof localStorage !== 'undefined') {
localStorage.setItem(LS_THEME_KEY, t);
}
applyTheme(t);
}
if (typeof document !== 'undefined') {
applyTheme(_initialTheme);
if (typeof window !== 'undefined' && window.matchMedia) {
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', () => {
if (getTheme() === 'system') applyTheme('system');
});
}
}
let _health = $state(null);
let _indexes = $state([]);
let _selectedIndex = $state(
typeof localStorage !== 'undefined' ? localStorage.getItem(LS_KEY) || '' : ''
);
let _quality = $state(null);
let _hotspots = $state([]);
let _smells = $state([]);
let _refactors = $state([]);
let _clusters = $state([]);
let _facts = $state([]);
let _sseConnected = $state(false);
export const getHealth = () => _health;
export const getIndexes = () => _indexes;
export const getSelectedIndex = () => _selectedIndex;
export const getQuality = () => _quality;
export const getHotspots = () => _hotspots;
export const getSmells = () => _smells;
export const getRefactors = () => _refactors;
export const getClusters = () => _clusters;
export const getFacts = () => _facts;
export const getSseConnected = () => _sseConnected;
export function setSelectedIndex(id) {
_selectedIndex = id || '';
if (typeof localStorage !== 'undefined') {
if (id) localStorage.setItem(LS_KEY, id);
else localStorage.removeItem(LS_KEY);
}
}
export async function refreshHealth() {
_health = await api.health();
return _health;
}
export async function refreshIndexes() {
_indexes = await api.indexes();
const ids = _indexes.map((idx) => (typeof idx === 'string' ? idx : idx.id));
if (_selectedIndex && !ids.includes(_selectedIndex)) {
setSelectedIndex('');
}
if (!_selectedIndex && ids.length > 0) {
setSelectedIndex(ids[0]);
}
return _indexes;
}
export async function refreshQuality(id) {
if (!id) return null;
_quality = await api.quality(id);
return _quality;
}
export async function refreshHotspots(id, topK = 20) {
if (!id) return [];
_hotspots = await api.complexityHotspots(id, topK);
return _hotspots;
}
export async function refreshSmells(id, category) {
if (!id) return [];
_smells = await api.smells(id, category);
return _smells;
}
export async function refreshRefactors(id, opts) {
if (!id) return [];
_refactors = await api.refactorSuggestions(id, opts);
return _refactors;
}
export async function refreshClusters(id, opts) {
if (!id) return [];
_clusters = await api.clusters(id, opts);
return _clusters;
}
export async function refreshFacts(subject, predicate) {
_facts = await api.listFacts(subject, predicate);
return _facts;
}
export function initEventStream() {
const es = new EventSource('/sse');
es.onopen = () => {
_sseConnected = true;
};
es.onmessage = (e) => {
let event;
try {
event = JSON.parse(e.data);
} catch {
return;
}
const id = _selectedIndex;
switch (event.type) {
case 'connected':
_sseConnected = true;
break;
case 'analysis_started':
break;
case 'analysis_completed':
refreshIndexes().catch(() => {});
if (id) {
refreshQuality(id).catch(() => {});
refreshHotspots(id).catch(() => {});
refreshSmells(id).catch(() => {});
refreshRefactors(id).catch(() => {});
}
break;
case 'fact_upserted':
case 'fact_deleted':
refreshFacts().catch(() => {});
break;
case 'scip_ingested':
if (id) refreshClusters(id).catch(() => {});
break;
default:
break;
}
};
es.onerror = () => {
_sseConnected = false;
console.warn('SSE connection lost, will reconnect...');
};
return es;
}