1// REST API client for git repository browsing.
2// Endpoints are served by the Go backend at /api/git/*.
3
4export interface GitRef {
5 name: string // full ref: "refs/heads/main"
6 shortName: string // "main"
7 type: 'branch' | 'tag'
8 hash: string
9 isDefault: boolean
10}
11
12export interface GitTreeEntry {
13 name: string
14 type: 'tree' | 'blob'
15 hash: string
16 mode: string
17 // Last commit touching this entry (may be absent if expensive to compute)
18 lastCommit?: {
19 hash: string
20 shortHash: string
21 message: string
22 authorName: string
23 date: string
24 }
25}
26
27export interface GitBlob {
28 path: string
29 content: string // UTF-8 text; empty string when isBinary is true
30 size: number
31 isBinary: boolean
32}
33
34export interface GitCommit {
35 hash: string
36 shortHash: string
37 message: string
38 authorName: string
39 authorEmail: string
40 date: string
41 parents: string[]
42}
43
44export interface GitCommitDetail extends GitCommit {
45 fullMessage: string
46 files: Array<{
47 path: string
48 oldPath?: string
49 status: 'added' | 'modified' | 'deleted' | 'renamed'
50 }>
51}
52
53// ── Fetch helpers ─────────────────────────────────────────────────────────────
54
55async function get<T>(path: string, params: Record<string, string> = {}): Promise<T> {
56 const search = new URLSearchParams(params).toString()
57 const url = `/api/git${path}${search ? `?${search}` : ''}`
58 const res = await fetch(url)
59 if (!res.ok) {
60 const text = await res.text().catch(() => res.statusText)
61 throw new Error(text || res.statusText)
62 }
63 return res.json()
64}
65
66// ── API calls ─────────────────────────────────────────────────────────────────
67
68export function getRefs(): Promise<GitRef[]> {
69 return get('/refs')
70}
71
72export function getTree(ref: string, path: string): Promise<GitTreeEntry[]> {
73 return get('/tree', { ref, path })
74}
75
76export function getBlob(ref: string, path: string): Promise<GitBlob> {
77 return get('/blob', { ref, path })
78}
79
80export function getCommits(
81 ref: string,
82 opts: { path?: string; limit?: number; after?: string } = {},
83): Promise<GitCommit[]> {
84 const params: Record<string, string> = { ref, limit: String(opts.limit ?? 20) }
85 if (opts.path) params.path = opts.path
86 if (opts.after) params.after = opts.after
87 return get('/commits', params)
88}
89
90export function getCommit(hash: string): Promise<GitCommitDetail> {
91 return get('/commit', { hash })
92}