feat: add workspace-aware extension dashboard
Build / build (push) Successful in 12s

This commit is contained in:
2026-07-17 15:02:08 -05:00
parent 8351fc65f5
commit 85379f42f3
14 changed files with 1369 additions and 94 deletions
+118 -4
View File
@@ -12,6 +12,46 @@ export interface GiteaUser {
email?: string;
}
interface GiteaRepoOwner {
login: string;
}
interface GiteaRepoResponse {
name: string;
full_name?: string;
description?: string;
html_url?: string;
clone_url?: string;
ssh_url?: string;
updated_at?: string;
default_branch?: string;
private?: boolean;
owner?: GiteaRepoOwner;
}
interface GiteaBranchResponse {
name: string;
commit?: {
id?: string;
message?: string;
timestamp?: string;
url?: string;
};
}
export interface GiteaRepoSummary {
name: string;
fullName: string;
description: string;
webUrl: string;
cloneUrl: string;
defaultBranch: string;
isPrivate: boolean;
lastCommitAt: string;
lastCommitSha: string;
lastCommitMessage: string;
}
export const giteaConfig = {
baseUrl: rawGiteaBaseUrl,
hasToken: giteaToken.length > 0,
@@ -24,16 +64,34 @@ export const giteaConfig = {
isConfigured: rawGiteaBaseUrl.length > 0 && giteaToken.length > 0
};
function getApiBaseUrl(baseUrl: string): string {
export function getApiBaseUrl(baseUrl: string): string {
const normalized = baseUrl.replace(/\/+$/, "");
return normalized.endsWith("/api/v1") ? normalized : `${normalized}/api/v1`;
}
export async function getCurrentGiteaUser(): Promise<GiteaUser> {
function assertGiteaConfigured(): void {
if (!giteaConfig.isConfigured) {
throw new Error("Set VITE_GITEA_BASE_URL and VITE_GITEA_TOKEN before testing the connection.");
}
}
function createGiteaClient() {
assertGiteaConfigured();
return axios.create({
baseURL: getApiBaseUrl(giteaConfig.baseUrl),
headers: {
Authorization: `token ${giteaToken}`
}
});
}
export async function getCurrentGiteaUser(): Promise<GiteaUser> {
const client = createGiteaClient();
const response = await client.get<GiteaUser>("/user");
return response.data;
}
export async function getReposOrderedByLastCommit(): Promise<GiteaRepoSummary[]> {
const client = axios.create({
baseURL: getApiBaseUrl(giteaConfig.baseUrl),
headers: {
@@ -41,6 +99,62 @@ export async function getCurrentGiteaUser(): Promise<GiteaUser> {
}
});
const response = await client.get<GiteaUser>("/user");
return response.data;
assertGiteaConfigured();
const repos: GiteaRepoResponse[] = [];
let page = 1;
while (page <= 10) {
const response = await client.get<GiteaRepoResponse[]>("/user/repos", {
params: {
limit: 50,
page
}
});
repos.push(...response.data);
if (response.data.length < 50) {
break;
}
page += 1;
}
const repoDetails = await Promise.all(
repos.map(async (repo): Promise<GiteaRepoSummary> => {
const owner = repo.owner?.login || giteaConfig.repoOwner;
const defaultBranch = repo.default_branch || "main";
const fullName = repo.full_name || `${owner}/${repo.name}`;
let branch: GiteaBranchResponse | null = null;
try {
const branchResponse = await client.get<GiteaBranchResponse>(
`/repos/${owner}/${repo.name}/branches/${defaultBranch}`
);
branch = branchResponse.data;
} catch {
branch = null;
}
return {
name: repo.name,
fullName,
description: repo.description || "",
webUrl: repo.html_url || `${giteaConfig.baseUrl.replace(/\/+$/, "")}/${fullName}`,
cloneUrl: repo.clone_url || "",
defaultBranch,
isPrivate: Boolean(repo.private),
lastCommitAt: branch?.commit?.timestamp || repo.updated_at || "",
lastCommitSha: branch?.commit?.id || "",
lastCommitMessage: branch?.commit?.message?.split("\n")[0] || "No commit message available"
};
})
);
return repoDetails.sort((a, b) => {
const aTime = a.lastCommitAt ? Date.parse(a.lastCommitAt) : 0;
const bTime = b.lastCommitAt ? Date.parse(b.lastCommitAt) : 0;
return bTime - aTime || a.fullName.localeCompare(b.fullName);
});
}