Files
insta-recipe/src/routes/share/components/LlmHealthIndicator.svelte
Giancarmine Salucci 8545744bb1 fix(ssr): resolve EventSource SSR violations and implement best practices
- Fix EventSource is not defined error in queue dashboard
- Add browser guards for all EventSource usage
- Replace static constants (EventSource.OPEN/CLOSED) with numeric values
- Fix setInterval SSR violation in LLM health indicator
- Replace $effect anti-pattern with onMount in share page
- Add comprehensive SvelteKit SSR best practices documentation
- Add SSR audit and testing verification

All changes follow SvelteKit best practices and are verified against
official documentation. Production build succeeds with no SSR errors.

Closes: FixEventSourceSSR
See: docs/outcomes/FixEventSourceSSR.md
2025-12-22 03:00:29 +01:00

63 lines
1.6 KiB
Svelte

<script lang="ts">
import { onMount } from 'svelte';
interface HealthState {
status: 'checking' | 'healthy' | 'unhealthy' | 'error';
message: string;
lastChecked: Date | null;
}
let { pollInterval = 30000 } = $props<{
pollInterval?: number;
}>();
let health = $state<HealthState>({
status: 'checking',
message: '',
lastChecked: null
});
async function checkHealth() {
try {
const res = await fetch('/api/llm-health');
const data = await res.json();
health = {
status: data.status === 'healthy' ? 'healthy' : 'unhealthy',
message: data.message,
lastChecked: new Date()
};
} catch (e) {
health = {
status: 'error',
message: e instanceof Error ? e.message : 'Network error',
lastChecked: new Date()
};
}
}
// Use onMount instead of $effect for timer-based side effects
// onMount only runs in browser, no SSR guard needed
onMount(() => {
checkHealth(); // Initial check
const interval = setInterval(checkHealth, pollInterval);
return () => clearInterval(interval);
});
</script>
<div class="flex items-center gap-2 text-sm">
<div class="flex items-center gap-1">
{#if health.status === 'checking'}
🟡 <span>Checking LLM...</span>
{:else if health.status === 'healthy'}
🟢 <span class="text-green-600">LLM Ready</span>
{:else if health.status === 'unhealthy'}
🔴 <span class="text-red-600">LLM Unavailable</span>
{:else}
🔴 <span class="text-red-600">LLM Error</span>
{/if}
</div>
<div class="text-xs text-gray-500" title={health.message}>
{health.lastChecked ? `Last: ${health.lastChecked.toLocaleTimeString()}` : ''}
</div>
</div>