2026-04-24 16:52:40 -05:00
|
|
|
import { httpFetch } from "@/lib/http";
|
2026-04-24 21:30:48 -05:00
|
|
|
import { z } from "zod";
|
|
|
|
|
|
2026-04-24 16:52:40 -05:00
|
|
|
const CONFIG_KEY = "openconcho:config";
|
2026-04-24 21:30:48 -05:00
|
|
|
|
|
|
|
|
export const configSchema = z.object({
|
|
|
|
|
baseUrl: z.string().url("Must be a valid URL"),
|
|
|
|
|
token: z.string().optional().default(""),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export type Config = z.infer<typeof configSchema>;
|
|
|
|
|
|
|
|
|
|
export function loadConfig(): Config | null {
|
|
|
|
|
try {
|
|
|
|
|
const raw = localStorage.getItem(CONFIG_KEY);
|
|
|
|
|
if (!raw) return null;
|
|
|
|
|
const parsed = JSON.parse(raw);
|
|
|
|
|
return configSchema.parse(parsed);
|
|
|
|
|
} catch {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function saveConfig(config: Config): void {
|
|
|
|
|
localStorage.setItem(CONFIG_KEY, JSON.stringify(config));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function clearConfig(): void {
|
|
|
|
|
localStorage.removeItem(CONFIG_KEY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type HealthStatus = "ok" | "auth-required" | "unreachable" | "checking";
|
|
|
|
|
|
2026-04-24 16:52:40 -05:00
|
|
|
export async function checkConnection(
|
|
|
|
|
baseUrl: string,
|
|
|
|
|
token?: string,
|
|
|
|
|
): Promise<{
|
2026-04-24 21:30:48 -05:00
|
|
|
status: HealthStatus;
|
|
|
|
|
message: string;
|
|
|
|
|
}> {
|
|
|
|
|
try {
|
|
|
|
|
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
2026-04-24 16:52:40 -05:00
|
|
|
if (token) headers.Authorization = `Bearer ${token}`;
|
2026-04-24 21:30:48 -05:00
|
|
|
|
2026-04-24 16:52:40 -05:00
|
|
|
const res = await httpFetch(`${baseUrl}/v3/workspaces/list`, {
|
2026-04-24 21:30:48 -05:00
|
|
|
method: "POST",
|
|
|
|
|
headers,
|
|
|
|
|
body: JSON.stringify({}),
|
|
|
|
|
signal: AbortSignal.timeout(5000),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res.ok) return { status: "ok", message: "Connected successfully" };
|
|
|
|
|
if (res.status === 401 || res.status === 403) {
|
|
|
|
|
return { status: "auth-required", message: "Authentication required — provide an API token" };
|
|
|
|
|
}
|
|
|
|
|
return { status: "unreachable", message: `Server returned ${res.status}` };
|
|
|
|
|
} catch (err) {
|
|
|
|
|
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
|
|
|
if (msg.includes("AbortError") || msg.includes("timeout")) {
|
|
|
|
|
return { status: "unreachable", message: "Connection timed out" };
|
|
|
|
|
}
|
|
|
|
|
return { status: "unreachable", message: `Cannot reach server: ${msg}` };
|
|
|
|
|
}
|
|
|
|
|
}
|