/ opencodehub / community / src / lib / instance-client.ts
swadhinbiswas feat: optimize Docker CI/CD builds, refine site-wide UI aesthetic, and remediate secrets · 8/19/2026
c3e5c18
45 lines · 2.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
export interface InstanceInfo {
  product: string; name: string; siteUrl: string; version: string; capabilities: string[];
}
export interface RemoteRepo {
  id: string; name: string; fullName: string; description: string | null;
  visibility: string; defaultBranch: string; starCount: number; forkCount: number; watchCount: number;
  language: string | null; topics: string[]; httpCloneUrl: string; updatedAt: string; createdAt: string;
  owner: { id: string; username: string; displayName: string | null; avatarUrl: string | null; };
}

export async function probeInstance(baseUrl: string): Promise<{ ok: true; info: InstanceInfo } | { ok: false; error: string }> {
  try {
    const origin = new URL(baseUrl).origin;
    const ctrl = new AbortController(); const t = setTimeout(()=>ctrl.abort(), 8000);
    const res = await fetch(`${origin}/api/instance`, { signal: ctrl.signal, headers: { Accept: "application/json" } });
    clearTimeout(t);
    if (!res.ok) return { ok: false, error: `Instance probe failed: ${res.status}` };
    const json = await res.json();
    if (json?.data?.product !== "opencodehub") return { ok: false, error: "Not an OpenCodeHub instance" };
    return { ok: true, info: json.data as InstanceInfo };
  } catch (e: any) {
    return { ok: false, error: e?.message || "Network error" };
  }
}

export async function fetchPublicRepos(origin: string, page = 1, perPage = 50): Promise<{ repos: RemoteRepo[]; total: number; totalPages: number }> {
  const url = `${new URL(origin).origin}/api/repos?visibility=public&sort=updated&page=${page}&per_page=${perPage}`;
  const res = await fetch(url, { headers: { Accept: "application/json", "User-Agent": "CommunityHub/1.0" } });
  if (!res.ok) throw new Error(`Failed to fetch repos: ${res.status}`);
  const json = await res.json();
  if (!json.success) throw new Error(json.error?.message || "Failed");
  return { repos: json.data as RemoteRepo[], total: json.meta?.total || json.data.length, totalPages: json.meta?.totalPages || 1 };
}

export async function fetchAllPublicRepos(origin: string): Promise<RemoteRepo[]> {
  let page = 1; const all: RemoteRepo[] = [];
  while (true) {
    const { repos, totalPages } = await fetchPublicRepos(origin, page, 100);
    all.push(...repos);
    if (page >= totalPages || repos.length === 0) break;
    page++; await new Promise(r=>setTimeout(r,150));
  }
  return all;
}