import { error } from "@sveltejs/kit";
import { isDid, isHandle } from "@atcute/lexicons/syntax";
import { createBobbinClient, type BobbinContext } from "#lib/api/client.ts";
import { gitTarget, requireGit, type GitTarget } from "#lib/api/gitclient.ts";
import { resolveMiniDoc, type MiniDoc } from "#lib/api/identity.ts";
import { toHttpError } from "#lib/api/load.ts";
import type { RepoView } from "#lib/api/records.ts";
import { resolveRepoByName } from "#lib/api/repo.ts";
import { didFromUri } from "#lib/api/uri.ts";
import { getConfig } from "#lib/server/config.ts";
import type { Fetch } from "#lib/fetch.ts";
export interface ResolvedRepo {
ctx: BobbinContext;
git: GitTarget;
doc: MiniDoc;
view: RepoView;
}
type RepoParamsEvent = {
params: { handle?: string; repo?: string };
fetch: Fetch;
};
// the handle/repo preamble shared by the server routes, params arrive already
// decoded
export const resolveRepoViewFromParams = async (event: RepoParamsEvent) => {
const identifier = event.params.handle ?? "";
const name = event.params.repo ?? "";
// rejects bare words, unrelated paths must 404 instead of resolving as actors
if (!isDid(identifier) && !isHandle(identifier)) {
error(404, "Not found");
}
const config = getConfig();
const ctx = createBobbinClient({ serviceUrl: config.bobbinUrl, fetch: event.fetch });
const doc = await resolveMiniDoc(ctx, identifier).catch((cause) =>
toHttpError(cause, "Could not resolve user")
);
const view = await resolveRepoByName(ctx, doc.did, name).catch((cause) =>
toHttpError(cause, "Could not load repository")
);
if (!view) error(404, `${doc.handle}/${name} does not exist`);
return { ctx, doc, view, config };
};
export const resolveRepoFromParams = async (event: RepoParamsEvent): Promise<ResolvedRepo> => {
const { ctx, doc, view, config } = await resolveRepoViewFromParams(event);
requireGit(view);
const git = gitTarget(config, { uri: view.uri, repoDid: didFromUri(view.uri) }, event.fetch);
return { ctx, git, doc, view };
};