import type { BobbinContext, XrpcRequestInit } from "#lib/api/client.ts";
import { jsonGet } from "#lib/api/_request.ts";
import type * as OrgTangledActorGetProfileActivity from "#lib/api/lexicons/types/org/tangled/actor/getProfileActivity.ts";
import type * as OrgTangledActorProfile from "#lib/api/lexicons/types/org/tangled/actor/profile.ts";
import type * as OrgTangledFeedStar from "#lib/api/lexicons/types/org/tangled/feed/star.ts";
import type * as OrgTangledGraphVouch from "#lib/api/lexicons/types/org/tangled/graph/vouch.ts";
import type * as OrgTangledRepoDefs from "#lib/api/lexicons/types/org/tangled/repo/defs.ts";
import type * as OrgTangledRepoManifest from "#lib/api/lexicons/types/org/tangled/repo/manifest.ts";
import type * as OrgTangledReviewPatch from "#lib/api/lexicons/types/org/tangled/review/patch.ts";
import type * as OrgTangledSnippetString from "#lib/api/lexicons/types/org/tangled/snippet/string.ts";
import type * as OrgTangledTrackGetTicketView from "#lib/api/lexicons/types/org/tangled/track/getTicketView.ts";
import type * as OrgTangledTrackTicket from "#lib/api/lexicons/types/org/tangled/track/ticket.ts";
export interface RecordView<V> {
uri: string;
cid?: string;
value: V;
}
export interface RecordList<V> {
items: RecordView<V>[];
}
export type RepoRecord = OrgTangledRepoManifest.Main;
export type ProfileRecord = OrgTangledActorProfile.Main;
export type TicketRecord = OrgTangledTrackTicket.Main;
export type TicketState = OrgTangledTrackTicket.Main["state"];
export type StringRecord = OrgTangledSnippetString.Main;
export type StarRecord = OrgTangledFeedStar.Main;
export type VouchRecord = OrgTangledGraphVouch.Main;
export type ProfileActivityOutput = OrgTangledActorGetProfileActivity.$output;
export type ProfileActivityRepoRef = OrgTangledActorGetProfileActivity.RepoRef;
export const BULK_LIMIT = 50;
// absent when the repo doesn't support git at all
export interface GitInfo {
defaultBranch: string;
isEmpty: boolean;
languages?: OrgTangledRepoDefs.Language[];
}
export type RepoView = RecordView<RepoRecord> & { knot?: string; git?: GitInfo };
export const getRepo = (ctx: BobbinContext, repo: string, init?: XrpcRequestInit) =>
jsonGet<RepoView>(ctx, "org.tangled.repo.getRepo", { repo }, init);
export const getRepoByRepoDid = (ctx: BobbinContext, repoDid: string, init?: XrpcRequestInit) =>
jsonGet<RepoView>(ctx, "org.tangled.repo.getRepoByRepoDid", { repoDid }, init);
export const getRepoByName = (
ctx: BobbinContext,
owner: string,
name: string,
init?: XrpcRequestInit
) => jsonGet<RepoView>(ctx, "org.tangled.temp.repo.getRepoByName", { owner, name }, init);
export interface RepoListPage {
cursor?: string | null;
items: RecordView<RepoRecord>[];
}
export const listRepos = (
ctx: BobbinContext,
subject: string,
filter: { limit?: number; cursor?: string; order?: "asc" | "desc" } = {},
init?: XrpcRequestInit
) => jsonGet<RepoListPage>(ctx, "org.tangled.repo.listRepos", { subject, ...filter }, init);
export const getProfile = (ctx: BobbinContext, did: string, init?: XrpcRequestInit) =>
jsonGet<RecordView<ProfileRecord>>(
ctx,
"org.tangled.actor.getProfile",
{ actor: `at://${did}/org.tangled.actor.profile/self` },
init
);
export type TicketViewDetailed = OrgTangledTrackGetTicketView.$output;
export type PatchRecord = OrgTangledReviewPatch.Main;
export const listPatches = (ctx: BobbinContext, ticket: string, init?: XrpcRequestInit) =>
jsonGet<RecordList<PatchRecord>>(
ctx,
"org.tangled.temp.review.listPatches",
{ ticket, order: "asc", limit: 500 },
init
);
export interface PullListItem {
cid?: string;
commentCount: number;
state: TicketState;
stateUpdatedAt?: string;
uri: string;
value: TicketRecord;
}
export interface PullListPage {
cursor?: string | null;
total?: number;
items: PullListItem[];
}
export interface ListPullsFilter {
status?: TicketState;
author?: string;
limit?: number;
cursor?: string;
order?: "asc" | "desc";
}
export const listPulls = (
ctx: BobbinContext,
subject: string,
filter: ListPullsFilter = {},
init?: XrpcRequestInit
) => jsonGet<PullListPage>(ctx, "org.tangled.repo.listPulls", { subject, ...filter }, init);
export const getRepos = (ctx: BobbinContext, repos: readonly string[], init?: XrpcRequestInit) =>
jsonGet<RecordList<RepoRecord>>(ctx, "org.tangled.repo.getRepos", { repos }, init);
export const getReposByRepoDids = (
ctx: BobbinContext,
dids: readonly string[],
init?: XrpcRequestInit
) => jsonGet<RecordList<RepoRecord>>(ctx, "org.tangled.repo.getReposByRepoDids", { dids }, init);
export const getProfileActivity = (
ctx: BobbinContext,
actor: string,
months = 7,
init?: XrpcRequestInit
) =>
jsonGet<ProfileActivityOutput>(
ctx,
"org.tangled.actor.getProfileActivity",
{ actor, months },
init
);
export const getProfiles = (
ctx: BobbinContext,
actors: readonly string[],
init?: XrpcRequestInit
) => jsonGet<RecordList<ProfileRecord>>(ctx, "org.tangled.actor.getProfiles", { actors }, init);
// one uri outside org.tangled.track.ticket fails the whole batch with a 400
export const getTickets = async (
ctx: BobbinContext,
uris: readonly string[],
init?: XrpcRequestInit
): Promise<RecordList<TicketRecord>> => {
const pages = await Promise.all(
Array.from({ length: Math.ceil(uris.length / BULK_LIMIT) }, (_, index) =>
jsonGet<RecordList<TicketRecord>>(
ctx,
"org.tangled.track.getTickets",
{ uris: uris.slice(index * BULK_LIMIT, (index + 1) * BULK_LIMIT) },
init
)
)
);
return { items: pages.flatMap((page) => page.items) };
};
export interface StarListPage {
cursor?: string | null;
total?: number;
items: RecordView<StarRecord>[];
}
export const listStars = (
ctx: BobbinContext,
subject: string,
filter: { limit?: number; cursor?: string; offset?: number; order?: "asc" | "desc" } = {},
init?: XrpcRequestInit
) => jsonGet<StarListPage>(ctx, "org.tangled.feed.listStars", { subject, ...filter }, init);
export const getString = (ctx: BobbinContext, uri: string, init?: XrpcRequestInit) =>
jsonGet<RecordView<StringRecord>>(ctx, "org.tangled.string.getString", { uri }, init);