racecraft/src/api/client.ts
Jan-Peter v. Hunnius cf9af73281 feat: initial Racecraft web client v0.1.0
Vue 3 + TypeScript + Vite web client for rusty-telemetry.

- Dashboard with system status, live feeds, quick actions
- Live telemetry view with real-time gauges (speed/RPM/gear)
- Session management (create, run, complete, analyze)
- Shift point analysis with Chart.js visualizations
- Track map with Canvas 2D boundary rendering
- Typed API client for all 19 REST endpoints
- Dark theme, network-accessible via Vite 0.0.0.0 bind
2026-06-05 16:12:33 +02:00

118 lines
3.3 KiB
TypeScript

import axios from 'axios'
import type {
LiveTelemetryResponse,
RecordingManifest,
StartRecordingRequest,
UseCaseSession,
CreateSessionRequest,
StartRunRequest,
SessionRun,
UseCase,
Game,
} from '@/types'
const api = axios.create({
baseURL: '/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
})
// ── Live Telemetry ──
export async function getLiveTelemetry(): Promise<LiveTelemetryResponse> {
const res = await api.get<LiveTelemetryResponse>('/live')
return res.data
}
// ── Recordings ──
export async function listRecordings(): Promise<RecordingManifest[]> {
const res = await api.get<RecordingManifest[]>('/recordings')
return res.data
}
export async function getRecording(id: string): Promise<RecordingManifest> {
const res = await api.get<RecordingManifest>(`/recordings/${id}`)
return res.data
}
export async function startRecording(req?: StartRecordingRequest): Promise<RecordingManifest> {
const res = await api.post<RecordingManifest>('/recordings', req ?? {})
return res.data
}
export async function stopActiveRecording(): Promise<RecordingManifest> {
const res = await api.post<RecordingManifest>('/recordings/stop')
return res.data
}
export async function stopRecording(id: string): Promise<RecordingManifest> {
const res = await api.post<RecordingManifest>(`/recordings/${id}/stop`)
return res.data
}
export async function deleteRecording(id: string): Promise<void> {
await api.delete(`/recordings/${id}`)
}
// ── Sessions ──
export async function listSessions(): Promise<UseCaseSession[]> {
const res = await api.get<UseCaseSession[]>('/sessions')
return res.data
}
export async function getSession(id: string): Promise<UseCaseSession> {
const res = await api.get<UseCaseSession>(`/sessions/${id}`)
return res.data
}
export async function createSession(req: CreateSessionRequest): Promise<UseCaseSession> {
const res = await api.post<UseCaseSession>('/sessions', req)
return res.data
}
export async function deleteSession(id: string): Promise<void> {
await api.delete(`/sessions/${id}`)
}
export async function startRun(sessionId: string, req: StartRunRequest): Promise<SessionRun> {
const res = await api.post<SessionRun>(`/sessions/${sessionId}/runs`, req)
return res.data
}
export async function stopRun(sessionId: string, runId: string): Promise<SessionRun> {
const res = await api.post<SessionRun>(`/sessions/${sessionId}/runs/${runId}/stop`)
return res.data
}
export async function completeSession(id: string): Promise<UseCaseSession> {
const res = await api.post<UseCaseSession>(`/sessions/${id}/complete`)
return res.data
}
export async function getAnalysis(id: string): Promise<Record<string, unknown>> {
const res = await api.get<Record<string, unknown>>(`/sessions/${id}/analysis`)
return res.data
}
export async function reAnalyze(id: string): Promise<Record<string, unknown>> {
const res = await api.post<Record<string, unknown>>(`/sessions/${id}/analyze`)
return res.data
}
// ── Metadata ──
export async function getUseCases(): Promise<UseCase[]> {
const res = await api.get<UseCase[]>('/use-cases')
return res.data
}
export async function getGames(): Promise<Game[]> {
const res = await api.get<Game[]>('/games')
return res.data
}
export default api