Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970import { isDid } from "@atcute/lexicons/syntax";import { error } from "@sveltejs/kit";import { serviceUrlFor, tryHostForKnot } from "#lib/api/_request.ts";import { createBobbinClient } from "#lib/api/client.ts";import { httpStatusFor, toHttpError } from "#lib/api/load.ts";import { getRepoByRepoDid, type RepoView } from "#lib/api/records.ts";import { didFromUri } from "#lib/api/uri.ts";import { getConfig } from "#lib/server/config.ts";import { capture } from "#lib/server/posthog.ts";import { resolveRepoViewFromParams } from "#lib/server/repo.ts";interface GitEvent<Params> { params: Params; url: URL; fetch: typeof fetch; platform?: App.Platform;}
// git follows this once on info/refs and sends the rest of the clone or push// straight to the knotconst knotRedirect = (view: RepoView, repoDid: string, service: string, url: URL) => { const host = tryHostForKnot(view.knot); if (!host) error(404, "This repository doesn't have a knot yet"); return new Response(null, { status: 307, headers: { location: `${serviceUrlFor(host)}/${repoDid}/${service}${url.search}` } });};
// the knot serves the clone itself, so its ref advertisement here is the one place// we see it. fetches and pulls ask for the same thing, as they did on the appviewconst trackClone = (event: GitEvent<unknown>, view: RepoView, repoDid: string, service: string) => { if (service !== "info/refs" || event.url.searchParams.get("service") !== "git-upload-pack") return; const declaration = view.value.declaration; const sent = capture(getConfig(event.platform), "clone", declaration?.owner ?? repoDid, { repo: declaration?.name, repo_at: view.uri }); // on workers the event has to outlive the redirect it rides on event.platform?.ctx?.waitUntil(sent);};
export const redirectToKnot = (service: string) => async (event: GitEvent<{ handle: string; repo: string }>): Promise<Response> => { const { view } = await resolveRepoViewFromParams({ params: { handle: event.params.handle, repo: event.params.repo.replace(/\.git$/, "") }, fetch: event.fetch }); const repoDid = didFromUri(view.uri); const response = knotRedirect(view, repoDid, service, event.url); trackClone(event, view, repoDid, service); return response; };
export const redirectRepoDidToKnot = (service: string) => async (event: GitEvent<{ handle: string }>): Promise<Response> => { const repoDid = event.params.handle; if (!isDid(repoDid)) error(404, "Not found"); const ctx = createBobbinClient({ serviceUrl: getConfig().bobbinUrl, fetch: event.fetch }); const view = await getRepoByRepoDid(ctx, repoDid).catch((cause) => httpStatusFor(cause) === 404 ? null : toHttpError(cause, "Could not load repository") ); if (!view) error(404, `${repoDid} does not exist`); const response = knotRedirect(view, repoDid, service, event.url); trackClone(event, view, repoDid, service); return response; };