| 1 | /** How big an artifact is, as people read sizes. */ |
| 2 | export function formatBytes(bytes: number): string { |
| 3 | if (bytes < 1024 * 1024) return `${Math.max(1, Math.round(bytes / 1024))} KB`; |
| 4 | if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; |
| 5 | return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`; |
| 6 | } |
| 7 | |
| 8 | /** When an artifact goes, from now: "expires today", "expires in 13 days". */ |
| 9 | export function expiresIn(at: string | null, now: number = Date.now()): string { |
| 10 | if (!at) return ""; |
| 11 | const ms = Date.parse(at) - now; |
| 12 | if (Number.isNaN(ms)) return ""; |
| 13 | if (ms <= 0) return "expired"; |
| 14 | const days = Math.floor(ms / 86_400_000); |
| 15 | if (days === 0) return "expires today"; |
| 16 | if (days === 1) return "expires tomorrow"; |
| 17 | return `expires in ${days} days`; |
| 18 | } |