codex-proxy / shared /hooks /use-proxies.ts
icebear0828
feat: proxy pool add form with separate protocol/host/port/auth fields
af3e19d
raw
history blame
5.43 kB
import { useState, useEffect, useCallback } from "preact/hooks";
import type { ProxyEntry, ProxyAssignment } from "../types";
export interface AddProxyFields {
name: string;
protocol: string;
host: string;
port: string;
username: string;
password: string;
}
export interface ProxiesState {
proxies: ProxyEntry[];
assignments: ProxyAssignment[];
healthCheckIntervalMinutes: number;
loading: boolean;
refresh: () => Promise<void>;
addProxy: (fields: AddProxyFields) => Promise<string | null>;
removeProxy: (id: string) => Promise<string | null>;
checkProxy: (id: string) => Promise<void>;
checkAll: () => Promise<void>;
enableProxy: (id: string) => Promise<void>;
disableProxy: (id: string) => Promise<void>;
assignProxy: (accountId: string, proxyId: string) => Promise<void>;
unassignProxy: (accountId: string) => Promise<void>;
setInterval: (minutes: number) => Promise<void>;
}
export function useProxies(): ProxiesState {
const [proxies, setProxies] = useState<ProxyEntry[]>([]);
const [assignments, setAssignments] = useState<ProxyAssignment[]>([]);
const [healthCheckIntervalMinutes, setHealthInterval] = useState(5);
const [loading, setLoading] = useState(true);
const refresh = useCallback(async () => {
try {
const resp = await fetch("/api/proxies");
const data = await resp.json();
setProxies(data.proxies || []);
setAssignments(data.assignments || []);
setHealthInterval(data.healthCheckIntervalMinutes || 5);
} catch {
// ignore
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
refresh();
}, [refresh]);
const addProxy = useCallback(
async (fields: AddProxyFields): Promise<string | null> => {
try {
const resp = await fetch("/api/proxies", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: fields.name,
protocol: fields.protocol,
host: fields.host,
port: fields.port,
username: fields.username,
password: fields.password,
}),
});
const data = await resp.json();
if (!resp.ok) return data.error || "Failed to add proxy";
await refresh();
return null;
} catch (err) {
return err instanceof Error ? err.message : "Network error";
}
},
[refresh],
);
const removeProxy = useCallback(
async (id: string): Promise<string | null> => {
try {
const resp = await fetch(`/api/proxies/${encodeURIComponent(id)}`, {
method: "DELETE",
});
if (!resp.ok) {
const data = await resp.json();
return data.error || "Failed to remove proxy";
}
await refresh();
return null;
} catch (err) {
return err instanceof Error ? err.message : "Network error";
}
},
[refresh],
);
const checkProxy = useCallback(
async (id: string) => {
try {
await fetch(`/api/proxies/${encodeURIComponent(id)}/check`, {
method: "POST",
});
} catch {
// network error — refresh will show stale state
}
await refresh();
},
[refresh],
);
const checkAll = useCallback(async () => {
try {
await fetch("/api/proxies/check-all", { method: "POST" });
} catch {
// network error
}
await refresh();
}, [refresh]);
const enableProxy = useCallback(
async (id: string) => {
try {
await fetch(`/api/proxies/${encodeURIComponent(id)}/enable`, {
method: "POST",
});
} catch {
// network error
}
await refresh();
},
[refresh],
);
const disableProxy = useCallback(
async (id: string) => {
try {
await fetch(`/api/proxies/${encodeURIComponent(id)}/disable`, {
method: "POST",
});
} catch {
// network error
}
await refresh();
},
[refresh],
);
const assignProxy = useCallback(
async (accountId: string, proxyId: string) => {
try {
await fetch("/api/proxies/assign", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ accountId, proxyId }),
});
} catch {
// network error
}
await refresh();
},
[refresh],
);
const unassignProxy = useCallback(
async (accountId: string) => {
try {
await fetch(`/api/proxies/assign/${encodeURIComponent(accountId)}`, {
method: "DELETE",
});
} catch {
// network error
}
await refresh();
},
[refresh],
);
const setIntervalMinutes = useCallback(
async (minutes: number) => {
try {
await fetch("/api/proxies/settings", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ healthCheckIntervalMinutes: minutes }),
});
} catch {
// network error
}
await refresh();
},
[refresh],
);
return {
proxies,
assignments,
healthCheckIntervalMinutes,
loading,
refresh,
addProxy,
removeProxy,
checkProxy,
checkAll,
enableProxy,
disableProxy,
assignProxy,
unassignProxy,
setInterval: setIntervalMinutes,
};
}