mirror of
				https://github.com/khairul169/code-share.git
				synced 2025-10-31 11:49:35 +07:00 
			
		
		
		
	
		
			
				
	
	
		
			171 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 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;
 |