import { AlertTriangle, RotateCcw, TimerReset } from "lucide-react"; import type { DevServerHealthStatus } from "../api/health"; function formatRelativeTimestamp(value: string | null): string | null { if (!value) return null; const timestamp = new Date(value).getTime(); if (Number.isNaN(timestamp)) return null; const deltaMs = Date.now() - timestamp; if (deltaMs < 60_000) return "just now"; const deltaMinutes = Math.round(deltaMs / 60_000); if (deltaMinutes < 60) return `${deltaMinutes}m ago`; const deltaHours = Math.round(deltaMinutes / 60); if (deltaHours < 24) return `${deltaHours}h ago`; const deltaDays = Math.round(deltaHours / 24); return `${deltaDays}d ago`; } function describeReason(devServer: DevServerHealthStatus): string { if (devServer.reason === "backend_changes_and_pending_migrations") { return "backend files changed and migrations are pending"; } if (devServer.reason === "pending_migrations") { return "pending migrations need a fresh boot"; } return "backend files changed since this server booted"; } export function DevRestartBanner({ devServer }: { devServer?: DevServerHealthStatus }) { if (!devServer?.enabled || !devServer.restartRequired) return null; const changedAt = formatRelativeTimestamp(devServer.lastChangedAt); const sample = devServer.changedPathsSample.slice(0, 3); return (
Restart Required {devServer.autoRestartEnabled ? ( Auto-Restart On ) : null}

{describeReason(devServer)} {changedAt ? ` ยท updated ${changedAt}` : ""}

{sample.length > 0 ? ( Changed: {sample.join(", ")} {devServer.changedPathCount > sample.length ? ` +${devServer.changedPathCount - sample.length} more` : ""} ) : null} {devServer.pendingMigrations.length > 0 ? ( Pending migrations: {devServer.pendingMigrations.slice(0, 2).join(", ")} {devServer.pendingMigrations.length > 2 ? ` +${devServer.pendingMigrations.length - 2} more` : ""} ) : null}
{devServer.waitingForIdle ? (
Waiting for {devServer.activeRunCount} live run{devServer.activeRunCount === 1 ? "" : "s"} to finish
) : devServer.autoRestartEnabled ? (
Auto-restart will trigger when the instance is idle
) : (
Restart pnpm dev:once after the active work is safe to interrupt
)}
); }