import { originRequest } from './request.ts' import { type OriginPullSummary } from './types.ts' /** * List pull requests for an Origin repo the app installation can see. * * @param params.ownerSlug - Origin owner slug (for example `kentcdodds`). * @param params.repoName - Repository name. * @param params.installationId - Optional installation id override. * @returns `{ items }` of slim pull summaries (number, title, state, head, base, url). * @example * import listOriginPulls from 'kody:@kentcdodds/origin/pulls' * const { items } = await listOriginPulls({ ownerSlug: 'kentcdodds', repoName: 'kody' }) * // => { items: [{ number: 12, title: '...', state: 'open', head: 'feat', base: 'main', url: '...' }] } */ export async function listOriginPulls(params: { ownerSlug: string repoName: string installationId?: string }): Promise<{ items: Array }> { const ownerSlug = params.ownerSlug.trim() const repoName = params.repoName.trim() if (!ownerSlug || !repoName) { throw new Error('ownerSlug and repoName are required.') } const result = await originRequest({ path: `/repos/${encodeURIComponent(ownerSlug)}/${encodeURIComponent(repoName)}/pulls`, auth: 'installation', installationId: params.installationId, }) if (!result.ok) { const message = isRecord(result.body) && typeof result.body.message === 'string' ? result.body.message : `HTTP ${String(result.status)}` throw new Error(`Failed to list Origin pull requests: ${message}`) } const payload = isRecord(result.body) ? result.body : {} const raw = Array.isArray(payload.pulls) ? payload.pulls : Array.isArray(payload.items) ? payload.items : Array.isArray(result.body) ? result.body : [] return { items: raw.map((item) => slimPull(asRecord(item))), } } export async function getOriginPull(params: { ownerSlug: string repoName: string pullNumber: string | number installationId?: string }): Promise { const ownerSlug = params.ownerSlug.trim() const repoName = params.repoName.trim() const pullNumber = String(params.pullNumber).trim() if (!ownerSlug || !repoName || !pullNumber) { throw new Error('ownerSlug, repoName, and pullNumber are required.') } const result = await originRequest({ path: `/repos/${encodeURIComponent(ownerSlug)}/${encodeURIComponent(repoName)}/pulls/${encodeURIComponent(pullNumber)}`, auth: 'installation', installationId: params.installationId, }) if (!result.ok) { const message = isRecord(result.body) && typeof result.body.message === 'string' ? result.body.message : `HTTP ${String(result.status)}` throw new Error(`Failed to get Origin pull request: ${message}`) } return slimPull(asRecord(result.body)) } export default listOriginPulls function slimPull(item: Record): OriginPullSummary { const head = isRecord(item.head) ? item.head : null const base = isRecord(item.base) ? item.base : null return { number: typeof item.number === 'string' || typeof item.number === 'number' ? item.number : null, title: stringField(item.title), state: stringField(item.state), head: stringField(head?.ref) ?? stringField(item.head), base: stringField(base?.ref) ?? stringField(item.base), url: stringField(item.url) ?? stringField(item.htmlUrl), } } function asRecord(value: unknown): Record { return isRecord(value) ? value : {} } function isRecord(value: unknown): value is Record { return value !== null && typeof value === 'object' && !Array.isArray(value) } function stringField(value: unknown): string | null { return typeof value === 'string' && value.length > 0 ? value : null }