import { all, first, MAX_IN_LIST, placeholders, run } from "../db";
import { encryptRepoSecret } from "../secrets";
import { assertBelowCap, CAPS } from "../limits";
import { canAdministerAccount } from "../repos";
import { notFoundError, forbidden } from "../errors";
import type { OwnerVisibility } from "./config-values";
import type { Viewer } from "~/lib/types";
export type ConfigScope =
| { kind: "repo"; id: string }
| { kind: "environment"; id: string }
| { kind: "owner"; id: string; visibility: OwnerVisibility; selectedRepos: string[] };
const TABLES = {
variable: {
repo: ["repo_variables", "repo_id"],
environment: ["environment_variables", "environment_id"],
owner: ["owner_variables", "owner_id"],
},
secret: {
repo: ["secrets", "repo_id"],
environment: ["environment_secrets", "environment_id"],
owner: ["owner_secrets", "owner_id"],
},
} as const;
type Kind = keyof typeof TABLES;
function table(kind: Kind, scope: ConfigScope): readonly [string, string] {
return TABLES[kind][scope.kind];
}
async function assertRoom(kind: Kind, scope: ConfigScope, name: string): Promise<void> {
const [target, column] = table(kind, scope);
if (await first(`SELECT 1 AS ok FROM ${target} WHERE ${column} = ? AND name = ?`, scope.id, name)) return;
const count = await first<{ count: number }>(`SELECT COUNT(*) AS count FROM ${target} WHERE ${column} = ?`, scope.id);
assertBelowCap(count?.count ?? 0, kind === "secret" ? CAPS.secretsPerRepo : CAPS.variablesPerScope, `${kind}s`);
}
function ownerColumns(scope: ConfigScope): { names: string; values: string; params: string[] } {