import { first } from "../db";
import { forbidden, notFoundError } from "../errors";
import { canAdministerAccount, requireRepoAccess } from "../repos";
import type { Viewer } from "~/lib/types";
import { containerLimits, containersEnabled, containerStub } from "./container-config";
import {
closeOrphanSession,
containersAllowedFor,
containerUsage,
listContainerSessions,
loadContainerSession,
} from "./container-meter";
import type { ContainerSessionRow, ContainerUsage } from "./container-meter";
export type ContainerOverview = {
enabled: boolean;
/** Whether the scope's plan (the account's, or the viewer's for a repo) includes containers. */
allowed: boolean;
idleMinutes: number;
capHours: number;
sessions: ContainerSessionRow[];
/** Present for an account scope; a repo spans many billed accounts. */
usage: ContainerUsage | null;
};
async function accountByName(name: string): Promise<{ id: string; name: string }> {
const account = await first<{ id: string; name: string }>(
"SELECT id, name FROM accounts WHERE name = ? COLLATE NOCASE",
name,
);
if (!account) throw notFoundError("Account not found");
return account;
}
/** The viewer themselves, or an org they own (site admins may see any account). */
export async function requireContainerAccount(
viewer: Viewer,
org: string | null,
): Promise<{ id: string; name: string }> {
if (!org) return { id: viewer.id, name: viewer.name };