Add WiFi config and system info endpoints

This commit is contained in:
Chris Wanstrath 2026-03-04 11:39:37 -08:00
parent 8f74f9daa0
commit f8c5890e07
3 changed files with 20 additions and 93 deletions

View File

@ -4,15 +4,8 @@ export const getLogDates = (name: string): Promise<string[]> =>
export const getLogsForDate = (name: string, date: string): Promise<string[]> =>
fetch(`/api/apps/${name}/logs?date=${date}`).then(r => r.json())
export const getWifiConfig = (): Promise<{ network: string, password: string }> =>
fetch('/api/system/wifi').then(r => r.json())
export const saveWifiConfig = (config: { network: string, password: string }) =>
fetch('/api/system/wifi', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config),
}).then(r => r.json())
export const getSystemInfo = (): Promise<{ version: string, sha: string }> =>
fetch('/api/system/info').then(r => r.json())
export const shareApp = (name: string) =>
fetch(`/api/apps/${name}/tunnel`, { method: 'POST' })

View File

@ -1,13 +1,9 @@
import { useEffect, useState } from 'hono/jsx'
import { getWifiConfig, saveWifiConfig } from '../api'
import { getSystemInfo } from '../api'
import { navigate } from '../router'
import {
Button,
DashboardInstallCmd,
FormActions,
FormField,
FormInput,
FormLabel,
HeaderActions,
Main,
MainContent,
@ -18,15 +14,13 @@ import {
} from '../styles'
export function SettingsPage({ render }: { render: () => void }) {
const [network, setNetwork] = useState('')
const [password, setPassword] = useState('')
const [saving, setSaving] = useState(false)
const [saved, setSaved] = useState(false)
const [version, setVersion] = useState('')
const [sha, setSha] = useState('')
useEffect(() => {
getWifiConfig().then(config => {
setNetwork(config.network)
setPassword(config.password)
getSystemInfo().then(info => {
setVersion(info.version)
setSha(info.sha)
})
}, [])
@ -34,15 +28,6 @@ export function SettingsPage({ render }: { render: () => void }) {
navigate('/')
}
const handleSave = async (e: Event) => {
e.preventDefault()
setSaving(true)
setSaved(false)
await saveWifiConfig({ network, password })
setSaving(false)
setSaved(true)
}
return (
<Main>
<MainHeader centered>
@ -53,33 +38,11 @@ export function SettingsPage({ render }: { render: () => void }) {
</MainHeader>
<MainContent centered>
<Section>
<SectionTitle>WiFi</SectionTitle>
<form onSubmit={handleSave} style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 400 }}>
<FormField>
<FormLabel>Network</FormLabel>
<FormInput
type="text"
value={network}
onInput={(e: Event) => setNetwork((e.target as HTMLInputElement).value)}
placeholder="SSID"
/>
</FormField>
<FormField>
<FormLabel>Password</FormLabel>
<FormInput
type="password"
value={password}
onInput={(e: Event) => setPassword((e.target as HTMLInputElement).value)}
placeholder="Password"
/>
</FormField>
<FormActions>
{saved && <span style={{ fontSize: 13, color: '#888', alignSelf: 'center' }}>Saved</span>}
<Button variant="primary" type="submit" disabled={saving}>
{saving ? 'Saving...' : 'Save'}
</Button>
</FormActions>
</form>
<SectionTitle>About</SectionTitle>
<div style={{ display: 'flex', flexDirection: 'column', gap: 8, fontSize: 14 }}>
<span>Version: {version}</span>
<span>SHA: {sha}</span>
</div>
</Section>
<Section>
<SectionTitle>Install CLI</SectionTitle>

View File

@ -1,9 +1,9 @@
import { allApps, APPS_DIR, onChange, TOES_DIR } from '$apps'
import { allApps, APPS_DIR, onChange } from '$apps'
import { onHostLog } from '../tui'
import { Hype } from '@because/hype'
import { cpus, freemem, platform, totalmem } from 'os'
import { join } from 'path'
import { existsSync, mkdirSync, readFileSync, statfsSync, writeFileSync } from 'fs'
import { readFileSync, statfsSync } from 'fs'
export interface AppMetrics {
cpu: number
@ -18,11 +18,6 @@ export interface SystemMetrics {
apps: Record<string, AppMetrics>
}
export interface WifiConfig {
network: string
password: string
}
export interface UnifiedLogLine {
time: number
app: string
@ -190,36 +185,12 @@ router.sse('/metrics/stream', (send) => {
return () => clearInterval(interval)
})
// WiFi config
const CONFIG_DIR = join(TOES_DIR, 'config')
const WIFI_PATH = join(CONFIG_DIR, 'wifi.json')
// System info
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '../../../package.json'), 'utf-8'))
const sha = Bun.spawnSync(['git', 'rev-parse', '--short', 'HEAD'], { cwd: join(import.meta.dir, '../../..') }).stdout.toString().trim() || 'unknown'
function readWifiConfig(): WifiConfig {
try {
if (existsSync(WIFI_PATH)) {
return JSON.parse(readFileSync(WIFI_PATH, 'utf-8'))
}
} catch {}
return { network: '', password: '' }
}
function writeWifiConfig(config: WifiConfig) {
if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true })
writeFileSync(WIFI_PATH, JSON.stringify(config, null, 2))
}
router.get('/wifi', c => {
return c.json(readWifiConfig())
})
router.put('/wifi', async c => {
const body = await c.req.json<WifiConfig>()
const config: WifiConfig = {
network: String(body.network ?? ''),
password: String(body.password ?? ''),
}
writeWifiConfig(config)
return c.json(config)
router.get('/info', c => {
return c.json({ version: pkg.version, sha })
})
// Get recent unified logs