Files
Minikura/apps/web/hooks/use-k8s-resources.ts
T

155 lines
4.5 KiB
TypeScript
Raw Normal View History

2026-02-13 15:52:13 +07:00
"use client";
import type {
CustomResourceSummary,
DeploymentInfo,
K8sConfigMapSummary,
K8sServiceSummary,
K8sStatus,
2026-08-13 01:58:19 +07:00
PodInfo,
2026-02-13 15:52:13 +07:00
StatefulSetInfo,
} from "@minikura/api";
2026-08-13 01:58:19 +07:00
import { useCallback, useEffect, useRef, useState } from "react";
2026-02-17 18:12:02 +07:00
import { api } from "@/lib/api-client";
2026-02-13 15:52:13 +07:00
2026-08-13 01:58:19 +07:00
function getErrorMessage(error: unknown) {
if (error instanceof Error) {
return error.message;
}
if (typeof error === "object" && error) {
const value = "value" in error ? error.value : error;
if (typeof value === "object" && value && "message" in value) {
return String(value.message);
}
}
return "Failed to fetch Kubernetes resources";
}
2026-02-13 15:52:13 +07:00
export function useK8sResources() {
2026-08-13 01:58:19 +07:00
const [status, setStatus] = useState<K8sStatus | null>(null);
const [pods, setPods] = useState<PodInfo[]>([]);
2026-02-13 15:52:13 +07:00
const [statefulSets, setStatefulSets] = useState<StatefulSetInfo[]>([]);
const [deployments, setDeployments] = useState<DeploymentInfo[]>([]);
const [services, setServices] = useState<K8sServiceSummary[]>([]);
const [configMaps, setConfigMaps] = useState<K8sConfigMapSummary[]>([]);
const [minecraftServers, setMinecraftServers] = useState<CustomResourceSummary[]>([]);
const [reverseProxyServers, setReverseProxyServers] = useState<CustomResourceSummary[]>([]);
2026-08-13 01:58:19 +07:00
const [initialLoading, setInitialLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
2026-02-13 15:52:13 +07:00
const [error, setError] = useState<string | null>(null);
2026-08-13 01:58:19 +07:00
const hasLoaded = useRef(false);
2026-02-13 15:52:13 +07:00
const fetchData = useCallback(async () => {
2026-08-13 01:58:19 +07:00
const isInitialLoad = !hasLoaded.current;
if (!isInitialLoad) {
setRefreshing(true);
}
setError(null);
2026-02-13 15:52:13 +07:00
try {
const [
2026-08-13 01:58:19 +07:00
statusRes,
podsRes,
2026-02-13 15:52:13 +07:00
deploymentsRes,
statefulSetsRes,
servicesRes,
configMapsRes,
minecraftServersRes,
reverseProxyServersRes,
] = await Promise.allSettled([
api.api.k8s.status.get(),
api.api.k8s.pods.get(),
api.api.k8s.deployments.get(),
api.api.k8s.statefulsets.get(),
api.api.k8s.services.get(),
api.api.k8s.configmaps.get(),
api.api.k8s["minecraft-servers"].get(),
api.api.k8s["reverse-proxy-servers"].get(),
]);
2026-08-13 01:58:19 +07:00
if (statusRes.status === "fulfilled" && statusRes.value.data) {
setStatus(statusRes.value.data as K8sStatus);
}
if (podsRes.status === "fulfilled" && podsRes.value.data) {
setPods(podsRes.value.data as PodInfo[]);
}
2026-02-13 15:52:13 +07:00
if (statefulSetsRes.status === "fulfilled" && statefulSetsRes.value.data) {
setStatefulSets(statefulSetsRes.value.data as StatefulSetInfo[]);
}
if (deploymentsRes.status === "fulfilled" && deploymentsRes.value.data) {
setDeployments(deploymentsRes.value.data as DeploymentInfo[]);
}
if (servicesRes.status === "fulfilled" && servicesRes.value.data) {
setServices(servicesRes.value.data as K8sServiceSummary[]);
}
if (configMapsRes.status === "fulfilled" && configMapsRes.value.data) {
setConfigMaps(configMapsRes.value.data as K8sConfigMapSummary[]);
}
if (minecraftServersRes.status === "fulfilled" && minecraftServersRes.value.data) {
setMinecraftServers(minecraftServersRes.value.data as CustomResourceSummary[]);
}
if (reverseProxyServersRes.status === "fulfilled" && reverseProxyServersRes.value.data) {
setReverseProxyServers(reverseProxyServersRes.value.data as CustomResourceSummary[]);
}
2026-08-13 01:58:19 +07:00
const failedRequest = [
statusRes,
podsRes,
deploymentsRes,
statefulSetsRes,
servicesRes,
configMapsRes,
minecraftServersRes,
reverseProxyServersRes,
].find((result) => result.status === "rejected" || Boolean(result.value.error));
if (failedRequest) {
setError(
getErrorMessage(
failedRequest.status === "rejected" ? failedRequest.reason : failedRequest.value.error
)
);
}
2026-02-13 15:52:13 +07:00
} catch (err: unknown) {
2026-08-13 01:58:19 +07:00
setError(getErrorMessage(err));
2026-02-13 15:52:13 +07:00
} finally {
2026-08-13 01:58:19 +07:00
hasLoaded.current = true;
setInitialLoading(false);
setRefreshing(false);
2026-02-13 15:52:13 +07:00
}
}, []);
useEffect(() => {
2026-08-13 01:58:19 +07:00
void fetchData();
const interval = setInterval(() => {
void fetchData();
}, 30000);
2026-02-13 15:52:13 +07:00
return () => clearInterval(interval);
2026-08-13 01:58:19 +07:00
}, [fetchData]);
2026-02-13 15:52:13 +07:00
return {
2026-08-13 01:58:19 +07:00
status,
pods,
2026-02-13 15:52:13 +07:00
statefulSets,
deployments,
services,
configMaps,
minecraftServers,
reverseProxyServers,
2026-08-13 01:58:19 +07:00
initialLoading,
refreshing,
2026-02-13 15:52:13 +07:00
error,
refresh: fetchData,
};
}