import type { DnsReport, Category, Summary } from '~/types/dns' interface StreamEvent { domain: string category: Category done?: boolean } export function useDnsCheck() { const config = useRuntimeConfig() const report = ref(null) const loading = ref(false) const error = ref(null) const progress = ref(0) const totalCategories = 8 async function checkDomain(domain: string) { loading.value = true error.value = null report.value = null progress.value = 0 // Initialize empty report const startTime = Date.now() const partialReport: DnsReport = { domain, timestamp: new Date().toISOString(), duration_ms: 0, summary: { pass: 0, warn: 0, fail: 0, info: 0 }, categories: [], } try { const url = `${config.public.apiBase}/check/stream?domain=${encodeURIComponent(domain)}` const eventSource = new EventSource(url) await new Promise((resolve, reject) => { const timeout = setTimeout(() => { eventSource.close() reject(new Error('Request timed out after 30 seconds')) }, 30000) eventSource.onmessage = (event) => { try { const data = JSON.parse(event.data) as StreamEvent & { done?: boolean } if (data.done) { clearTimeout(timeout) eventSource.close() partialReport.duration_ms = Date.now() - startTime resolve() return } if (data.category) { partialReport.categories.push(data.category) progress.value = partialReport.categories.length // Recalculate summary const summary: Summary = { pass: 0, warn: 0, fail: 0, info: 0 } for (const cat of partialReport.categories) { for (const check of cat.checks) { summary[check.status]++ } } partialReport.summary = summary partialReport.duration_ms = Date.now() - startTime // Update reactively report.value = { ...partialReport, categories: [...partialReport.categories] } } } catch { // ignore parse errors } } eventSource.onerror = () => { clearTimeout(timeout) eventSource.close() if (partialReport.categories.length > 0) { // Got some results, show them partialReport.duration_ms = Date.now() - startTime report.value = { ...partialReport } resolve() } else { reject(new Error('Connection to DNS check server failed')) } } }) } catch (e: any) { // Fallback to non-streaming API try { const data = await $fetch(`${config.public.apiBase}/check?domain=${encodeURIComponent(domain)}`) report.value = data progress.value = totalCategories } catch (e2: any) { error.value = e2.data?.error || e2.message || e.message || 'Failed to check domain' } } finally { loading.value = false progress.value = totalCategories } } return { report, loading, error, progress, totalCategories, checkDomain } }