import { error } from "@sveltejs/kit";
import { createBobbinClient, type BobbinContext } from "#lib/api/client.ts";
import {
branches as knotMirrorBranches,
blob as knotMirrorBlob,
blobRawUrl as knotMirrorBlobRawUrl,
languages as knotMirrorLanguages,
getRef as knotMirrorGetRef,
tags as knotMirrorTags,
tree as knotMirrorTree,
listCommitsByRef
} from "#lib/api/knotmirror.ts";
import type { Did } from "@atcute/lexicons";
import type { GitInfo } from "#lib/api/records.ts";
import type { Fetch } from "#lib/fetch.ts";
export interface GitServiceConfig {
bobbinUrl: string;
}
export interface GitTarget {
ctx: BobbinContext;
repo: Did;
}
export const knotMirrorTarget = (
config: GitServiceConfig,
repo: { repoDid: string },
fetch: Fetch
): GitTarget => ({
// git json (diffs, trees) carries no handles and can run to megabytes, so the ssr
// diff cap has to see it stream
ctx: createBobbinClient({ serviceUrl: config.bobbinUrl, fetch, normalizeHandles: false }),
repo: repo.repoDid as Did
});
export const hasGit = <R extends { git?: GitInfo }>(repo: R): repo is R & { git: GitInfo } =>
repo.git !== undefined;
export const requireGit = <R extends { git?: GitInfo }>(repo: R): R & { git: GitInfo } => {
if (!hasGit(repo)) error(404, "This repository doesn't support git");
return repo;
};
export const gitTarget = (
config: GitServiceConfig,
repo: { uri: string; repoDid?: string },
fetch: Fetch
): GitTarget => {
if (!repo.repoDid) error(404, "This repository has not been indexed yet");
return knotMirrorTarget(config, { repoDid: repo.repoDid }, fetch);
};
export const tree = (target: GitTarget, params: { ref: string; path?: string }) =>
knotMirrorTree(target.ctx, { repo: target.repo, ...params });
export const log = (target: GitTarget, params: { ref: string; limit: number; skip?: number }) =>
listCommitsByRef(target.ctx, {
repo: target.repo,
ranges: [params.ref],
limit: params.limit,
skip: params.skip
});
export const branch = (target: GitTarget, name: string) =>
knotMirrorGetRef(target.ctx, { repo: target.repo, ref: name });
export const branches = (target: GitTarget, limit: number, cursor?: string) =>
knotMirrorBranches(target.ctx, { repo: target.repo, limit, cursor });
export const tags = (target: GitTarget, limit: number, cursor?: string) =>
knotMirrorTags(target.ctx, { repo: target.repo, limit, cursor });
export const tag = (target: GitTarget, name: string) =>
knotMirrorGetRef(target.ctx, { repo: target.repo, ref: `refs/tags/${name}` });
export const languages = (target: GitTarget, ref: string) =>
knotMirrorLanguages(target.ctx, { repo: target.repo, ref });
export const blob = (target: GitTarget, params: { ref: string; path: string }, maxBytes: number) =>
knotMirrorBlob(target.ctx, { repo: target.repo, ...params }, maxBytes);
export const blobRawUrl = (
target: GitTarget,
params: { ref: string; path: string; download?: boolean }
): string => knotMirrorBlobRawUrl(target.ctx.serviceUrl, { repo: target.repo, ...params });