import { env } from "cloudflare:workers";
import { viewerFromRequest } from "../auth";
import { randomToken, sha256Hex } from "../crypto";
import { HttpError } from "../errors";
import { callerKey, enforceRateLimit, limitWrite } from "../limits";
import { hasPermission, loadRepo, repoPermission } from "../repos";
import { clampLimit, createLock, deleteLock, listLocks, lockJson } from "./locks";
import { findObject, findObjects, openObject, storeObject } from "./objects";
import { isValidOid } from "./pointer";
import { assertStorageAvailable, chargeBandwidth, maxObjectBytes } from "./quota";
import type { Permission, RepoRow, Viewer } from "~/lib/types";
const LFS_PATH = /^\/([^/]+)\/([^/]+?)(?:\.git)?\/info\/lfs\/(.+)$/;
const OBJECT_PATH = /^objects\/([0-9a-f]{64})(\/verify)?$/;
const UNLOCK_PATH = /^locks\/([a-z0-9]+)\/unlock$/;
const LFS_JSON = "application/vnd.git-lfs+json";
const MAX_JSON_BYTES = 1024 * 1024;
const MAX_BATCH_OBJECTS = 100;
const TRANSFER_TTL_SECONDS = 3600;
const TRANSFER_HEADER = "x-stig-lfs-transfer";
const HTTP_UNAUTHORIZED = 401;
const BASIC_CHALLENGE = 'Basic realm="stig"';
type LfsRoute = { owner: string; repo: string; rest: string };
type Operation = "upload" | "download";
type TransferGrant = { repoId: string; op: Operation; objects: Record<string, number> };
type Caller = { viewer: Viewer | null; permission: Permission; repo: RepoRow };
type BatchObject = { oid: string; size: number };
export function matchLfsRoute(url: URL): LfsRoute | null {
const match = LFS_PATH.exec(url.pathname);
return match ? { owner: match[1], repo: match[2], rest: match[3] } : null;
}
function lfsJson(body: unknown, status = 200): Response {
return new Response(JSON.stringify(body), { status, headers: { "content-type": LFS_JSON } });
}
function lfsError(status: number, message: string): Response {
const headers = new Headers({ "content-type": LFS_JSON });