Files
2026-08-14 17:04:04 +01:00

99 lines
3.5 KiB
TypeScript

"use client";
import { useCallback, useEffect } from "react";
import { fetchGitHubStatus } from "@/lib/api/domains/github-api";
import { useAppStore } from "@/components/state-provider";
import type { GitHubStatus, GitHubStatusResponse } from "@/lib/types/github";
import { subscribeIntegrationAvailability } from "@/lib/integrations/integration-availability-events";
const requestVersions = new Map<string, number>();
function nextRequestVersion(workspaceId: string) {
const version = (requestVersions.get(workspaceId) ?? 0) + 1;
requestVersions.set(workspaceId, version);
return version;
}
function isCurrentRequest(workspaceId: string, version: number) {
return requestVersions.get(workspaceId) === version;
}
export function normalizeGitHubStatus(response: GitHubStatusResponse): GitHubStatus {
const automation = response.automation ?? null;
const personal = response.personal ?? null;
const active = response.authenticated;
const username = response.authenticated ? (response.effective_personal_actor?.login ?? "") : "";
return {
...response,
automation,
personal,
app_available: response.app_available ?? response.github_app_available,
authenticated: active,
username,
auth_method: active ? response.auth_method : "none",
token_configured: response.token_configured,
required_scopes: response.required_scopes,
};
}
export function useGitHubStatus(requestedWorkspaceId?: string | null) {
const activeWorkspaceId = useAppStore((state) => state.workspaces.activeId);
const workspaceId = requestedWorkspaceId ?? activeWorkspaceId;
const statusState = useAppStore((state) =>
workspaceId ? state.githubStatus.byWorkspaceId[workspaceId] : undefined,
);
const setGitHubStatus = useAppStore((state) => state.setGitHubStatus);
const setGitHubStatusLoading = useAppStore((state) => state.setGitHubStatusLoading);
const resetGitHubStatus = useAppStore((state) => state.resetGitHubStatus);
const invalidateSystemHealth = useAppStore((state) => state.invalidateSystemHealth);
const doFetch = useCallback(
(refreshRateLimit = false) => {
if (!workspaceId) return;
const version = nextRequestVersion(workspaceId);
setGitHubStatusLoading(workspaceId, true);
fetchGitHubStatus(workspaceId, { cache: "no-store" }, refreshRateLimit)
.then((response) => {
if (isCurrentRequest(workspaceId, version)) {
setGitHubStatus(workspaceId, normalizeGitHubStatus(response));
}
})
.catch(() => {
if (isCurrentRequest(workspaceId, version)) setGitHubStatus(workspaceId, null);
})
.finally(() => {
if (isCurrentRequest(workspaceId, version)) {
setGitHubStatusLoading(workspaceId, false);
}
});
},
[setGitHubStatus, setGitHubStatusLoading, workspaceId],
);
useEffect(() => {
if (!workspaceId) return;
if (!statusState) {
resetGitHubStatus(workspaceId);
doFetch();
return;
}
if (!statusState.loaded && !statusState.loading) doFetch();
}, [doFetch, resetGitHubStatus, statusState?.loaded, statusState?.loading, workspaceId]);
useEffect(() => subscribeIntegrationAvailability(doFetch), [doFetch]);
const refresh = useCallback(() => {
invalidateSystemHealth();
if (!workspaceId) return;
doFetch(true);
}, [doFetch, invalidateSystemHealth, workspaceId]);
return {
workspaceId,
status: statusState?.status ?? null,
loaded: statusState?.loaded ?? false,
loading: statusState?.loading ?? false,
refresh,
};
}