import { Router, type Request } from "express"; import sandbox from "../lib/sandbox"; import db from "~/server/db"; import { and, eq, isNull } from "drizzle-orm"; import { project } from "~/server/db/schema/project"; import { unpackProject } from "../lib/unpack-project"; import { APIError } from "~/lib/api"; const router = Router(); router.post("/:slug/start", async (req, res) => { const { slug } = req.params as any; const data = await getProjectBySlug(slug); if (!data) { return res.status(404).send("Project not found!"); } try { const path = await unpackProject(data); const result = await sandbox.start(data.slug, path + "/api"); if (!result.ok) { const body = await result.text(); throw new APIError(body, result.status); } res.json({ success: true }); } catch (err) { const error = err as any; res .status(typeof error?.code === "number" ? error.code : 500) .send(error?.message || "An error occured!"); } }); router.post("/:slug/stop", async (req, res) => { const { slug } = req.params as any; const data = await getProjectBySlug(slug); if (!data) { return res.status(404).send("Project not found!"); } try { await sandbox.stop(data.slug); res.json({ success: true }); } catch (err) { res.status(500).send("An error occured!"); } }); router.post("/:slug/restart", async (req, res) => { const { slug } = req.params as any; const data = await getProjectBySlug(slug); if (!data) { return res.status(404).send("Project not found!"); } try { await unpackProject(data); const result = await sandbox.restart(data.slug); if (!result.ok) { const body = await result.text(); throw new APIError(body, result.status); } res.json({ success: true }); } catch (err) { const error = err as any; res .status(typeof error?.code === "number" ? error.code : 500) .send(error?.message || "An error occured!"); } }); router.get("/:slug/stats", async (req, res) => { const { slug } = req.params as any; const data = await getProjectBySlug(slug); if (!data) { return res.status(404).send("Project not found!"); } try { const result = await sandbox.getStats(data.slug); res.json({ success: true, result }); } catch (err) { const error = err as any; res .status(typeof error.code === "number" ? error.code : 500) .send(error.message || "An error occured!"); } }); router.get("/:slug/logs", async (req, res) => { const { slug } = req.params as any; const data = await getProjectBySlug(slug); if (!data) { return res.status(404).send("Project not found!"); } try { const { body, headers } = await sandbox.getLogs(data.slug); if (!body) { throw new Error("No body response."); } headers.forEach((value, key) => res.setHeader(key, value)); body.pipe(res); } catch (err) { res.status(500).send("An error occured!"); } }); router.get("/:slug/proxy*", async (req, res) => { const params = req.params as any; const { slug } = params; const pathname = params?.[0]; const searchParams = new URLSearchParams(); Object.entries(req.query || {}).forEach(([key, value]) => { searchParams.set(key, value as string); }); const data = await getProjectBySlug(slug); if (!data) { return res.status(404).send("Project not found!"); } try { const { body, headers, status } = await sandbox.proxy(data.slug, { pathname: pathname + "?" + searchParams.toString(), headers: getHeadersFromReq(req), }); if (!body) { throw new Error("No body response."); } headers.forEach((value, key) => res.setHeader(key, value)); res.status(status); body.pipe(res); } catch (err) { const error = err as any; res .status(typeof error?.code === "number" ? error.code : 500) .send(error?.message || "An error occured!"); } }); function getHeadersFromReq(req: Request) { const headers = new Headers(); for (const [key, value] of Object.entries(req.headers)) { if (typeof value === "string") { headers.set(key, value); } else if (Array.isArray(value)) { value.forEach((val) => headers.append(key, val)); } } return headers; } async function getProjectBySlug(slug: string) { return db.query.project.findFirst({ where: and(eq(project.slug, slug), isNull(project.deletedAt)), }); } export default router;