import db from "./db.js"; function toIso(value) { return value ? new Date(value).toISOString() : null; } function serializeRepo(row) { if (!row) return null; return { id: row.id, provider: row.provider, ownerRepo: row.owner_repo, baseUrl: row.base_url, label: row.label, createdAt: toIso(row.created_at), updatedAt: toIso(row.updated_at) }; } export async function countRepos() { const [[{ count }]] = await db.query(`SELECT COUNT(*) AS count FROM repos`); return Number(count) || 0; } export async function listRepos() { const [rows] = await db.query(`SELECT * FROM repos ORDER BY created_at ASC, id ASC`); return rows.map(serializeRepo); } export async function getRepoById(id) { if (!id) return null; const [rows] = await db.query(`SELECT * FROM repos WHERE id = ? LIMIT 1`, [id]); return serializeRepo(rows[0]); } export async function findRepoByOwnerRepo(ownerRepo, provider = null) { if (!ownerRepo) return null; if (provider) { const [rows] = await db.query( `SELECT * FROM repos WHERE owner_repo = ? AND provider = ? LIMIT 1`, [ownerRepo, provider.toLowerCase()] ); return serializeRepo(rows[0]); } const [rows] = await db.query(`SELECT * FROM repos WHERE owner_repo = ? LIMIT 1`, [ownerRepo]); return serializeRepo(rows[0]); } export async function createRepo({ provider = "github", ownerRepo, baseUrl = null, label = null }) { if (!ownerRepo) { const error = new Error("Repo ontbreekt."); error.meta = "INVALID_REPO"; throw error; } const normalizedProvider = String(provider || "github").toLowerCase(); const trimmedOwnerRepo = ownerRepo.trim(); const sanitizedBaseUrl = baseUrl ? baseUrl.trim() : null; const safeLabel = label ? label.trim() : null; try { const [result] = await db.query( `INSERT INTO repos (provider, owner_repo, base_url, label) VALUES (?, ?, ?, ?)`, [normalizedProvider, trimmedOwnerRepo, sanitizedBaseUrl, safeLabel] ); return await getRepoById(result.insertId); } catch (error) { if (error?.code === "ER_DUP_ENTRY") { const dup = new Error("Deze repository bestaat al."); dup.meta = "DUPLICATE"; throw dup; } throw error; } } export async function updateRepo(id, { provider, ownerRepo, baseUrl, label }) { const repo = await getRepoById(id); if (!repo) { const error = new Error("Repo niet gevonden."); error.meta = "NOT_FOUND"; throw error; } const fields = []; const values = []; if (provider) { fields.push("provider = ?"); values.push(String(provider).toLowerCase()); } if (ownerRepo) { fields.push("owner_repo = ?"); values.push(ownerRepo.trim()); } if (typeof baseUrl !== "undefined") { fields.push("base_url = ?"); values.push(baseUrl ? baseUrl.trim() : null); } if (typeof label !== "undefined") { fields.push("label = ?"); values.push(label ? label.trim() : null); } if (fields.length === 0) { return repo; } try { await db.query(`UPDATE repos SET ${fields.join(", ")}, updated_at = NOW() WHERE id = ?`, [...values, id]); } catch (error) { if (error?.code === "ER_DUP_ENTRY") { const dup = new Error("Deze repository bestaat al."); dup.meta = "DUPLICATE"; throw dup; } throw error; } return await getRepoById(id); } export async function deleteRepo(id) { const repo = await getRepoById(id); if (!repo) { const error = new Error("Repo niet gevonden."); error.meta = "NOT_FOUND"; throw error; } const [[{ count }]] = await db.query(`SELECT COUNT(*) AS count FROM licenses WHERE repo_id = ?`, [id]); if (Number(count) > 0) { const error = new Error("Repo is gekoppeld aan bestaande licenties."); error.meta = "IN_USE"; throw error; } await db.query(`DELETE FROM repos WHERE id = ? LIMIT 1`, [id]); return repo; }