import fs from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; import express from "express"; import { identify } from "./auth.ts"; import { config } from "./config.ts"; import { publishSnapshot } from "./git.ts"; import { listRepos } from "./repos.ts"; import { adminRouter } from "./routes/admin.ts"; import { gitHttpHandler } from "./routes/smart-http.ts"; import { repoBrowser, repoIndex, sendError } from "./routes/web.ts"; const here = path.dirname(fileURLToPath(import.meta.url)); const publicDir = path.resolve(here, "..", "public"); const app = express(); app.disable("x-powered-by"); if (config.trustProxy) app.set("trust proxy", true); app.use((_req, res, next) => { res.setHeader( "Content-Security-Policy", "default-src 'self'; script-src 'none'; style-src 'self'; img-src 'self' data: https:; frame-ancestors 'none'; base-uri 'none'; form-action 'self'", ); res.setHeader("X-Content-Type-Options", "nosniff"); res.setHeader("Referrer-Policy", "same-origin"); next(); }); app.use(identify); // Het git-transport moet de ruwe request-body kunnen streamen, dus dit staat // bewust vóór express.urlencoded — die zou de stream anders al opgeslurpt hebben. app.use(config.gitPrefix, gitHttpHandler(false)); app.use(config.gitFullPrefix, gitHttpHandler(true)); app.use("/assets", express.static(publicDir, { maxAge: "1h", index: false })); app.use(express.urlencoded({ extended: false, limit: "64kb" })); app.use(adminRouter); app.get("/", repoIndex); app.use("/r", repoBrowser); app.use((req, res) => { sendError(req, res, 404, "Deze pagina bestaat niet."); }); app.use( ( error: Error, req: express.Request, res: express.Response, _next: express.NextFunction, ): void => { console.error(error); if (res.headersSent) { res.end(); return; } sendError(req, res, 500, "Er ging iets mis op de server."); }, ); await fs.mkdir(config.repoRoot, { recursive: true }); // Zorgt dat elke repository een publieke momentopname heeft, ook eentje die er al // stond voordat dit bestond. Ongewijzigde inhoud levert geen nieuwe commit op. for (const repo of await listRepos()) { try { await publishSnapshot(repo.dir, repo.publishedDir); } catch (error) { console.error(`[publish] ${repo.name}: momentopname bijwerken mislukt`, error); } } app.listen(config.port, config.host, () => { console.log(`pub-repo luistert op http://${config.host}:${config.port}`); console.log(`repositories in ${config.repoRoot}`); console.log(`clone-URL's: ${config.publicUrl}${config.gitPrefix}/.git`); });