feat: add ComponentGrid and ComponentTable components for displaying components in grid and table formats
feat: implement HealthBadge and RoleBadge components for displaying health status and roles feat: create LogViewer component for streaming logs of services feat: develop SecretsEditor for managing secrets with CRUD operations feat: introduce ToolCard component for displaying tool information style: add global CSS variables and styles for consistent theming feat: set up API client for handling requests to the backend feat: implement hooks for fetching components, statuses, and tools feat: create routes for dashboard, component details, and tools feat: add service management endpoints for starting, stopping, and restarting services feat: implement event bus for handling real-time updates via SSE feat: create health check and logs endpoints for monitoring services feat: add tests for health and tools endpoints to ensure functionality chore: update project configuration files and dependencies for better development experience
This commit is contained in:
64
app/src/services/api/client.ts
Normal file
64
app/src/services/api/client.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
const BASE_URL = import.meta.env.VITE_API_BASE_URL ?? "/api"
|
||||
|
||||
class ApiError extends Error {
|
||||
status: number
|
||||
constructor(status: number, message: string) {
|
||||
super(message)
|
||||
this.status = status
|
||||
}
|
||||
}
|
||||
|
||||
class ApiClient {
|
||||
private baseUrl: string
|
||||
|
||||
constructor(baseUrl = BASE_URL) {
|
||||
this.baseUrl = baseUrl
|
||||
}
|
||||
|
||||
async get<T>(path: string): Promise<T> {
|
||||
const resp = await fetch(`${this.baseUrl}${path}`)
|
||||
if (!resp.ok) {
|
||||
throw new ApiError(resp.status, await resp.text())
|
||||
}
|
||||
return resp.json()
|
||||
}
|
||||
|
||||
async post<T>(path: string, body?: unknown): Promise<T> {
|
||||
const resp = await fetch(`${this.baseUrl}${path}`, {
|
||||
method: "POST",
|
||||
headers: body ? { "Content-Type": "application/json" } : {},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
if (!resp.ok) {
|
||||
throw new ApiError(resp.status, await resp.text())
|
||||
}
|
||||
return resp.json()
|
||||
}
|
||||
|
||||
async put<T>(path: string, body?: unknown): Promise<T> {
|
||||
const resp = await fetch(`${this.baseUrl}${path}`, {
|
||||
method: "PUT",
|
||||
headers: body ? { "Content-Type": "application/json" } : {},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
if (!resp.ok) {
|
||||
throw new ApiError(resp.status, await resp.text())
|
||||
}
|
||||
return resp.json()
|
||||
}
|
||||
|
||||
async delete<T>(path: string): Promise<T> {
|
||||
const resp = await fetch(`${this.baseUrl}${path}`, { method: "DELETE" })
|
||||
if (!resp.ok) {
|
||||
throw new ApiError(resp.status, await resp.text())
|
||||
}
|
||||
return resp.json()
|
||||
}
|
||||
|
||||
streamUrl(path: string): string {
|
||||
return `${this.baseUrl}${path}`
|
||||
}
|
||||
}
|
||||
|
||||
export const apiClient = new ApiClient()
|
||||
export { ApiError }
|
||||
Reference in New Issue
Block a user