import { all, chunks, first, placeholders } from "./db";
import { forbidden, notFoundError } from "./errors";
import type { Permission, RepoRow, RepoSummary, Viewer } from "~/lib/types";
const PERMISSION_RANK: Record<Permission, number> = { none: 0, read: 1, write: 2, admin: 3 };
export const REPO_SELECT = `SELECT r.*, a.name AS owner_name FROM repos r JOIN accounts a ON a.id = r.owner_id`;
/** Follows rename and transfer redirects so old URLs (web, raw and git) keep working. */
export async function loadRepo(owner: string, name: string): Promise<RepoRow | null> {
return (
(await first<RepoRow>(`${REPO_SELECT} WHERE a.name = ? AND r.name = ?`, owner, name)) ??
(await first<RepoRow>(
`${REPO_SELECT} WHERE r.id = COALESCE(
(SELECT repo_id FROM repo_redirects WHERE owner_name = ?1 AND repo_name = ?2),
(SELECT r2.id FROM account_redirects ar JOIN repos r2 ON r2.owner_id = ar.account_id
WHERE ar.old_name = ?1 AND r2.name = ?2 COLLATE NOCASE))`,
owner,
name,
))
);
}
export async function loadRepoById(id: string): Promise<RepoRow | null> {
return first<RepoRow>(`${REPO_SELECT} WHERE r.id = ?`, id);
}
export async function loadRepoByArtifactsName(artifactsName: string): Promise<RepoRow | null> {
return first<RepoRow>(`${REPO_SELECT} WHERE r.artifacts_name = ?`, artifactsName);
}
export function hasPermission(actual: Permission, needed: Permission): boolean {
return PERMISSION_RANK[actual] >= PERMISSION_RANK[needed];
}
export async function repoPermission(repo: RepoRow, viewer: Viewer | null): Promise<Permission> {
const base: Permission = repo.visibility === "public" ? "read" : "none";
if (!viewer) return base;
if (viewer.isAdmin || repo.owner_id === viewer.id) return "admin";