import { originRequest } from './request.ts' import { type OriginRepoSummary } from './types.ts' /** * List Origin repositories for an owner the app installation can see. * * @param params.ownerSlug - Origin owner slug (for example `kentcdodds`). * @param params.pageSize - Optional page size. * @param params.pageToken - Optional pagination token from a previous call. * @param params.filter - Optional Origin list filter string. * @param params.installationId - Optional installation id override. * @returns `{ items, nextPageToken }` of slim repo summaries. * @example * import listOriginRepos from 'kody:@kentcdodds/origin/repos' * const { items } = await listOriginRepos({ ownerSlug: 'kentcdodds', pageSize: 5 }) * // => { items: [{ id: '...', name: 'kody', fullName: 'kentcdodds/kody', ... }], nextPageToken: null } */ export async function listOriginRepos(params: { ownerSlug: string pageSize?: number pageToken?: string filter?: string installationId?: string }): Promise<{ items: Array; nextPageToken: string | null }> { const ownerSlug = params.ownerSlug.trim() if (!ownerSlug) { throw new Error('ownerSlug is required.') } const result = await originRequest({ path: `/repos/${encodeURIComponent(ownerSlug)}`, auth: 'installation', installationId: params.installationId, query: { pageSize: params.pageSize, pageToken: params.pageToken, filter: params.filter, }, }) 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 repos: ${message}`) } const payload = isRecord(result.body) ? result.body : {} const raw = Array.isArray(payload.repositories) ? payload.repositories : [] return { items: raw.map((item) => slimRepo(asRecord(item))), nextPageToken: typeof payload.nextPageToken === 'string' && payload.nextPageToken ? payload.nextPageToken : null, } } export async function getOriginRepo(params: { ownerSlug: string repoName: string installationId?: string }): Promise { 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)}`, 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 repo: ${message}`) } return slimRepo(asRecord(result.body)) } export default listOriginRepos function slimRepo(item: Record): OriginRepoSummary { const owner = isRecord(item.owner) ? item.owner : null const mirror = isRecord(item.mirror) ? item.mirror : null return { id: stringField(item.id) ?? '', name: stringField(item.name) ?? '', fullName: stringField(item.fullName), owner: owner ? { slug: stringField(owner.slug) ?? '', id: stringField(owner.id) ?? '', } : null, defaultBranch: stringField(item.defaultBranch), cloneUrl: stringField(item.cloneUrl), mirror: mirror ? { source: stringField(mirror.source), status: stringField(mirror.status), } : null, } } 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 }