Skip to content
Clone
main
70 lines 2.9 KB
/**
* 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<EnvelopeCommitsPage['data']>
export type CommitRow = NonNullable<CommitsPage['items']>[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<CommitsPage>(
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<CommitRow | null> {
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<NumstatRow[]> {
const data = await unwrapApi<unknown>(
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<DiffStyle> {
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<string>(Apis.diffs.diff_raw({ pathParams: { space_name: space, repo_name: repo }, params: { base, head } }))