import { env } from "cloudflare:workers";
import { all, first, run } from "../db";
import { hmacSha256Hex, randomId, randomToken, sha256Hex } from "../crypto";
import { HttpError, badRequest } from "../errors";
import { enforceRateLimit, numberVar, requestIp } from "../limits";
import { DeployError, extractArtifact } from "../pages/collect";
import { cookieSecret, labelUrl, manifestKey, metaKey, publishMeta, SCRATCH_LIMITS, slotKey } from "./config";
import {
activateSiteDeployment,
assertLabelFree,
failSiteDeployment,
insertDeployment,
loadSiteById,
unpublishSite,
} from "./deploy";
import { claimedLabel, scratchLabel } from "./naming";
import { plain } from "./static";
import type { SiteMeta, SiteRow } from "./config";
import type { Viewer } from "~/lib/types";
const DAY = 24 * 60 * 60 * 1000;
const HTTP_TOO_MANY = 429;
const HTTP_TOO_LARGE = 413;
const SWEEP_BATCH = 50;
const CLAIM_PREFIX = "gitfor_claim";
/** Keyed so stored hashes can't be reversed by enumerating the IPv4 space. */
function ipHash(request: Request): Promise<string> {
return hmacSha256Hex(cookieSecret(), `site-ip:${requestIp(request)}`);
}
async function readCapped(request: Request): Promise<Uint8Array<ArrayBuffer>> {
const declared = Number(request.headers.get("content-length") ?? "0");
if (declared > SCRATCH_LIMITS.maxUploadBytes) throw new HttpError(HTTP_TOO_LARGE, "Upload exceeds 10 MiB");
if (!request.body) throw badRequest("Send a .tar.gz archive as the request body");
const reader = request.body.getReader();
const chunks: Uint8Array[] = [];
let size = 0;
for (;;) {
const next = await reader.read();