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 (
{describeReason(devServer)} {changedAt ? ` ยท updated ${changedAt}` : ""}
pnpm dev:once after the active work is safe to interrupt