|
1 | 1 | import type { CLI } from '@stacksjs/clapp' |
2 | | -import { exec, formatBytes, formatPercent, getSystemInfo } from '@system-cleaner/core' |
| 2 | +import { exec, formatBytes, formatPercent, getSystemInfo, checkSoftwareUpdates } from '@system-cleaner/core' |
3 | 3 | import { getMemoryMetrics } from '@system-cleaner/monitor' |
4 | 4 |
|
5 | 5 | interface CheckResult { |
@@ -31,15 +31,20 @@ export function registerCheckCommand(app: CLI): void { |
31 | 31 | checkMemory(), |
32 | 32 | checkSwap(), |
33 | 33 | checkHomebrewUpdates(), |
34 | | - checkMacosUpdates(), |
| 34 | + checkSystemUpdates(), |
35 | 35 | checkTouchIdSudo(), |
36 | 36 | checkRosetta(), |
37 | 37 | checkGitConfig(), |
38 | 38 | ]) |
39 | 39 |
|
40 | 40 | for (const result of results) { |
41 | | - if (result.status === 'fulfilled') |
42 | | - checks.push(result.value) |
| 41 | + if (result.status === 'fulfilled') { |
| 42 | + const value = result.value |
| 43 | + if (Array.isArray(value)) |
| 44 | + checks.push(...value) |
| 45 | + else |
| 46 | + checks.push(value) |
| 47 | + } |
43 | 48 | } |
44 | 49 |
|
45 | 50 | s.stop(`Completed ${checks.length} checks`) |
@@ -82,7 +87,7 @@ export function registerCheckCommand(app: CLI): void { |
82 | 87 | // Updates |
83 | 88 | log.info('') |
84 | 89 | log.info('──── Updates ─────────────────────────') |
85 | | - for (const c of checks.filter(c => ['Homebrew Updates', 'macOS Updates'].includes(c.name))) { |
| 90 | + for (const c of checks.filter(c => ['Homebrew Updates', 'macOS Updates', 'Xcode CLT'].includes(c.name))) { |
86 | 91 | // eslint-disable-next-line no-console |
87 | 92 | console.log(` ${colors[c.status]}${icons[c.status]}${reset} ${c.name}: ${c.message}`) |
88 | 93 | } |
@@ -178,15 +183,42 @@ async function checkHomebrewUpdates(): Promise<CheckResult> { |
178 | 183 | return { name: 'Homebrew Updates', status: 'pass', message: 'All packages up to date' } |
179 | 184 | } |
180 | 185 |
|
181 | | -async function checkMacosUpdates(): Promise<CheckResult> { |
182 | | - // --no-scan uses cached results (fast but may be stale) |
183 | | - const r = await exec('softwareupdate -l --no-scan 2>&1', { timeout: 15_000 }) |
184 | | - if (!r.ok || r.stdout.includes('No new software available')) |
185 | | - return { name: 'macOS Updates', status: 'pass', message: 'System up to date (cached check)' } |
186 | | - const count = (r.stdout.match(/\*/g) || []).length |
187 | | - if (count > 0) |
188 | | - return { name: 'macOS Updates', status: 'warn', message: `${count} update(s) available` } |
189 | | - return { name: 'macOS Updates', status: 'pass', message: 'System up to date' } |
| 186 | +async function checkSystemUpdates(): Promise<CheckResult[]> { |
| 187 | + const result = await checkSoftwareUpdates({ fullScan: false }) |
| 188 | + const macosUpdates = result.updates.filter(u => u.kind === 'macos') |
| 189 | + const cltUpdates = result.updates.filter(u => u.kind === 'cltools') |
| 190 | + const otherSystem = result.updates.filter(u => u.kind !== 'macos' && u.kind !== 'cltools') |
| 191 | + const installed = result.clToolsInfo.version |
| 192 | + |
| 193 | + const macosCheck: CheckResult = result.updates.length === 0 |
| 194 | + ? { name: 'macOS Updates', status: 'pass', message: 'System up to date (cached check)' } |
| 195 | + : { |
| 196 | + name: 'macOS Updates', |
| 197 | + status: 'warn', |
| 198 | + message: (() => { |
| 199 | + const parts: string[] = [] |
| 200 | + if (macosUpdates.length > 0) parts.push(`${macosUpdates.length} macOS`) |
| 201 | + if (cltUpdates.length > 0) parts.push(`${cltUpdates.length} CLT`) |
| 202 | + if (otherSystem.length > 0) parts.push(`${otherSystem.length} other`) |
| 203 | + return `${result.updates.length} update(s) available (${parts.join(', ')})` |
| 204 | + })(), |
| 205 | + } |
| 206 | + |
| 207 | + const cltCheck: CheckResult = cltUpdates.length === 0 |
| 208 | + ? { |
| 209 | + name: 'Xcode CLT', |
| 210 | + status: 'pass', |
| 211 | + message: installed ? `Command Line Tools ${installed} up to date` : 'No CLT updates pending', |
| 212 | + } |
| 213 | + : { |
| 214 | + name: 'Xcode CLT', |
| 215 | + status: 'warn', |
| 216 | + message: installed |
| 217 | + ? `Update available: ${installed} → ${cltUpdates[0]?.version || '?'}` |
| 218 | + : `${cltUpdates.length} Command Line Tools update(s) available (${cltUpdates[0]?.version || '?'})`, |
| 219 | + } |
| 220 | + |
| 221 | + return [macosCheck, cltCheck] |
190 | 222 | } |
191 | 223 |
|
192 | 224 | async function checkTouchIdSudo(): Promise<CheckResult> { |
|
0 commit comments