Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135import { parseCanonicalResourceUri } from "@atcute/lexicons/syntax";import type { OAuthUserAgent } from "@atcute/oauth-browser-client";import { mintServiceAuth, serviceDidForHost } from "#lib/auth/agent.ts";import { attested, knotProcedure, type CobRef, type KnotWrite } from "#lib/api/cob.ts";import { createTicket, eraseTicket, type TicketProse } from "#lib/api/ticket.ts";import { didOf, nsidOf, type AtUri, type Did, type GitOid, type KnotOrigin, type Nsid} from "#lib/api/syntax.ts";import { buildUrl, toResponseError } from "#lib/api/_request.ts";
export interface PatchRange { base: GitOid; head: GitOid;}
export interface PatchSource { repo: Did; branch: string;}
const SUBMIT_PATCH_NSID = nsidOf("org.tangled.review.submitPatch");
export const createPatch = async ( agent: OAuthUserAgent, knot: KnotOrigin, ticket: AtUri, { base, head }: PatchRange, source: PatchSource): Promise<CobRef> => { const { repo, rkey } = parseCanonicalResourceUri(ticket); const patch = { ticket: rkey, base: { oid: base }, head: { oid: head }, sourceRepo: source.repo, sourceBranch: source.branch }; return attested( agent, knot, await knotProcedure<KnotWrite>(agent, knot, didOf(repo), SUBMIT_PATCH_NSID, { patch }) );};
// if the knot refuses the patch, erase the ticket again so there's no pull without a diffexport const openPull = async ( agent: OAuthUserAgent, knot: KnotOrigin, repo: Did, prose: TicketProse, targetBranch: string, range: PatchRange, source: PatchSource): Promise<CobRef> => { const ticket = await createTicket(agent, knot, repo, { ...prose, targetBranch }); try { await createPatch(agent, knot, ticket.uri, range, source); } catch (cause) { await eraseTicket(agent, knot, ticket).catch(() => {}); throw cause; } return ticket;};
const MERGE_COMMIT_NSID = nsidOf("sh.tangled.git.mergeCommit");const DELETE_BRANCH_NSID = nsidOf("org.tangled.temp.git.deleteBranch");const PUSH_NSID = nsidOf("org.tangled.git.receivePack");
export interface MergeCommitInput { /** the repo and branch being merged into */ target: { repo: string; branch: string; commit: string }; /** the repo the head commit lives in, and the commit itself */ source: { repo: string; commit: string }; style: "rebase";}
const mirrorPush = async ( agent: OAuthUserAgent, bobbin: string, knot: string, nsid: Nsid, body: unknown, fetch: typeof globalThis.fetch): Promise<void> => { const token = await mintServiceAuth(agent, { aud: serviceDidForHost(knot), // knotmirror forwards this token to the knot's receive-pack lxm: PUSH_NSID }); const response = await fetch(buildUrl(bobbin, nsid), { method: "POST", headers: { "content-type": "application/json", accept: "application/json", authorization: `Bearer ${token}` }, body: JSON.stringify(body) }); if (!response.ok) throw await toResponseError(response);};
export const mergeCommit = ( agent: OAuthUserAgent, bobbin: string, knot: string, input: MergeCommitInput, fetch: typeof globalThis.fetch = globalThis.fetch): Promise<void> => mirrorPush( agent, bobbin, knot, MERGE_COMMIT_NSID, { target: { $type: `${MERGE_COMMIT_NSID}#target`, ...input.target }, source: { $type: `${MERGE_COMMIT_NSID}#source`, ...input.source }, style: input.style }, fetch );
export const deleteBranch = ( agent: OAuthUserAgent, bobbin: string, knot: string, input: { repo: string; branch: string }, fetch: typeof globalThis.fetch = globalThis.fetch): Promise<void> => mirrorPush(agent, bobbin, knot, DELETE_BRANCH_NSID, input, fetch);