/** * Commit-history domain: the commit list endpoints (including raw patch text * and numstat) that feed the history tab and the commit view. */ import { unwrapApi } from '@app/lib' import type { EnvelopeCommitsPage } from '@app/services/api' import Apis from '@app/services/api' import { type DiffStyle, type NumstatRow, normalizeDiffStyle } from './diff' export type CommitsPage = NonNullable export type CommitRow = NonNullable[number] /** One page of commit history for `revision` (optionally filtered to a path). */ export async function listCommitsPage( space: string, repo: string, opts: { revision: string; skip: number; limit: number; path?: string; firstParent?: boolean }, ): Promise<{ commits: CommitRow[]; total: number; hasMore: boolean }> { const page = await unwrapApi( Apis.commits.list_commits({ pathParams: { space_name: space, repo_name: repo }, params: { revision: opts.revision, offset: opts.skip, limit: opts.limit, first_parent: opts.firstParent ?? false, ...(opts.path ? { path: opts.path } : {}), }, }), ) return { commits: page.items ?? [], total: page.total ?? 0, hasMore: Boolean(page.has_more), } } /** Single commit by sha — reuse the list endpoint so the payload shape (hex * ids, unix times) matches everything else on the page. */ export async function fetchCommit(space: string, repo: string, sha: string): Promise { const page = await listCommitsPage(space, repo, { revision: sha, skip: 0, limit: 1 }) return page.commits[0] ?? null } /** Per-file +/- counts for `base..head` (`view=numstat`; `shortstat` 500s on * the server today, so totals are summed client-side). */ export async function fetchNumstat(space: string, repo: string, base: string, head: string): Promise { const data = await unwrapApi( Apis.diffs.get_diff({ pathParams: { space_name: space, repo_name: repo }, params: { base, head, view: 'numstat' }, }), ) return Array.isArray(data) ? (data as NumstatRow[]) : [] } // TODO: crosses the repo/account boundary — inject the viewer's saved style // from the caller (or a preferences slice) instead of reaching into // Apis.account here. Kept as-is during the structural split. /** The viewer's saved diff layout. Read here rather than imported from * another slice — features own their API surface. */ export async function fetchDiffStyle(): Promise { const prefs = await unwrapApi<{ diff_view_style?: string | null }>(Apis.account.get_preferences()) return normalizeDiffStyle(prefs?.diff_view_style) } /** Raw unified patch text for `base..head`. */ export const fetchRawDiff = (space: string, repo: string, base: string, head: string) => unwrapApi(Apis.diffs.diff_raw({ pathParams: { space_name: space, repo_name: repo }, params: { base, head } }))