This repository has no description
1import { createBobbinClient, type BobbinContext } from "./client";
2import {
3 branches as knotMirrorBranches,
4 blob as knotMirrorBlob,
5 blobRawUrl as knotMirrorBlobRawUrl,
6 createKnotMirrorClient,
7 languages as knotMirrorLanguages,
8 log as knotMirrorLog,
9 getTag as knotMirrorGetTag,
10 tags as knotMirrorTags,
11 tree as knotMirrorTree
12} from "./knotmirror";
13import {
14 blob as knotBlob,
15 blobRawUrl as knotBlobRawUrl,
16 getDefaultBranch,
17 languages as knotLanguages,
18 tree as knotTree
19} from "./knot";
20import { branchesFor, logFor, tagFor, tagsFor } from "./repo";
21import type { Did, ResourceUri } from "@atcute/lexicons";
22
23export interface GitServiceConfig {
24 bobbinUrl: string;
25 knotMirrorUrl: string;
26}
27
28export interface GitTarget {
29 ctx: BobbinContext;
30 repo: Did | ResourceUri;
31 via: "mirror" | "bobbin";
32}
33
34export const gitTarget = (
35 config: GitServiceConfig,
36 repo: { uri: string; repoDid?: string },
37 fetch: typeof globalThis.fetch
38): GitTarget =>
39 config.knotMirrorUrl && repo.repoDid
40 ? {
41 ctx: createKnotMirrorClient(config.knotMirrorUrl, fetch),
42 repo: repo.repoDid as Did,
43 via: "mirror"
44 }
45 : {
46 ctx: createBobbinClient({ serviceUrl: config.bobbinUrl, fetch }),
47 repo: repo.uri as ResourceUri,
48 via: "bobbin"
49 };
50
51// the mirror has no getDefaultBranch, the default falls out of the branch
52// list's is_default flag instead
53export const resolveDefaultBranch = (
54 target: GitTarget,
55 init?: { signal?: AbortSignal }
56): Promise<string | null> =>
57 target.via === "mirror"
58 ? (async () => {
59 for (let offset = 0; ; offset += 100) {
60 const response = await knotMirrorBranches(
61 target.ctx,
62 { repo: target.repo, limit: 100, cursor: offset ? `${offset}` : undefined },
63 init
64 );
65 const list = response.branches ?? [];
66 const found = list.find((branch) => branch.is_default)?.reference.name;
67 if (found) return found;
68 if (list.length < 100) return null;
69 }
70 })().catch(() => null)
71 : getDefaultBranch(target.ctx, { repo: target.repo })
72 .then((branch) => branch.name)
73 .catch(() => null);
74
75export const tree = (target: GitTarget, params: { ref: string; path?: string }) =>
76 target.via === "mirror"
77 ? knotMirrorTree(target.ctx, { repo: target.repo, ...params })
78 : knotTree(target.ctx, { repo: target.repo, ...params });
79
80export const log = (target: GitTarget, params: { ref: string; limit: number; cursor?: string }) =>
81 target.via === "mirror"
82 ? knotMirrorLog(target.ctx, { repo: target.repo, ...params })
83 : logFor(target.ctx, target.repo, params.ref, params.limit, params.cursor);
84
85export const branches = (target: GitTarget, limit: number, cursor?: string) =>
86 target.via === "mirror"
87 ? knotMirrorBranches(target.ctx, { repo: target.repo, limit, cursor })
88 : branchesFor(target.ctx, target.repo, limit, cursor);
89
90export const tags = (target: GitTarget, limit: number, cursor?: string) =>
91 target.via === "mirror"
92 ? knotMirrorTags(target.ctx, { repo: target.repo, limit, cursor })
93 : tagsFor(target.ctx, target.repo, limit, cursor);
94
95export const tag = (target: GitTarget, name: string) =>
96 target.via === "mirror"
97 ? knotMirrorGetTag(target.ctx, { repo: target.repo, tag: name })
98 : tagFor(target.ctx, target.repo, name);
99
100export const languages = (
101 target: GitTarget,
102 ref: string
103): Promise<{ languages?: { name: string; size: number }[] }> =>
104 target.via === "mirror"
105 ? knotMirrorLanguages(target.ctx, { repo: target.repo, ref })
106 : knotLanguages(target.ctx, { repo: target.repo, ref });
107
108// only the mirror needs the inline cap, the knot enforces its own and 413s
109// past it
110export const blob = (target: GitTarget, params: { ref: string; path: string }, maxBytes: number) =>
111 target.via === "mirror"
112 ? knotMirrorBlob(target.ctx, { repo: target.repo, ...params }, maxBytes)
113 : knotBlob(target.ctx, { repo: target.repo as ResourceUri, ...params });
114
115export const blobRawUrl = (target: GitTarget, params: { ref: string; path: string }): string =>
116 target.via === "mirror"
117 ? knotMirrorBlobRawUrl(target.ctx.serviceUrl, { repo: target.repo, ...params })
118 : knotBlobRawUrl(target.ctx.serviceUrl, { repo: target.repo, ...params });