import { env } from "cloudflare:workers";
import { all } from "../db";
import { repoDb } from "../scoped-db";
import { ownerSiteScopes } from "./store";
import { sitesDomain } from "./config";
const API = "https://api.cloudflare.com/client/v4";
const HOSTS_PER_CALL = 30;
const SITE_LABELS_MAX = 500;
/** The account's Sites: labels (production, previews, PR aliases) under `SITES_DOMAIN`, and their custom domains. */
export async function accountSitesHosts(accountId: string): Promise<{ labels: string[]; custom: string[] }> {
// A site counts when the account owns it or its repository; repository scopes are already the account's.
const repos = new Set(
(await all<{ id: string }>("SELECT id FROM repos WHERE owner_id = ?", accountId)).map((repo) => repo.id),
);
const rows: Array<{ host: string; custom: number }> = [];
for (const scope of await ownerSiteScopes(accountId)) {
if (rows.length >= SITE_LABELS_MAX) break;
const owned = repos.has(scope) ? "SELECT id FROM sites" : "SELECT id FROM sites WHERE owner_id = ?1";
rows.push(
...(await repoDb(scope).all<{ host: string; custom: number }>(
`SELECT label AS host, 0 AS custom FROM sites WHERE id IN (${owned})
UNION SELECT label, 0 FROM site_deployments WHERE site_id IN (${owned})
UNION SELECT label, 0 FROM site_pr_aliases WHERE site_id IN (${owned})
UNION SELECT custom_domain, 1 FROM sites WHERE id IN (${owned}) AND custom_domain IS NOT NULL
LIMIT ${SITE_LABELS_MAX}`,
accountId,
)),
);
}
const domain = sitesDomain();
const labels = domain
? rows.filter((row) => row.custom === 0).map((row) => `${row.host.toLowerCase()}.${domain}`)
: [];
const custom = rows.filter((row) => row.custom === 1).map((row) => row.host.toLowerCase());
return { labels: [...new Set(labels)], custom: [...new Set(custom)] };
}
async function purgeHosts(zoneId: string, hosts: string[], accountId: string): Promise<number> {