diff --git a/packages/backend/src/routes/build.ts b/packages/backend/src/routes/build.ts index 7d26b28..ca2bf40 100644 --- a/packages/backend/src/routes/build.ts +++ b/packages/backend/src/routes/build.ts @@ -1,5 +1,9 @@ import { Router } from "express"; -import { buildModule } from "../services/build.service.js"; +import { + buildModule, + hotReloadScripts, + compileSingle, +} from "../services/build.service.js"; const router = Router(); @@ -23,4 +27,24 @@ router.post("/module/pack", async (req, res) => { } }); +router.post("/deploy", async (_req, res) => { + try { + const result = await hotReloadScripts(); + res.json(result); + } catch (err: any) { + res.status(500).json({ error: err.message }); + } +}); + +router.post("/compile-single", async (req, res) => { + const { filePath } = req.body; + if (!filePath) return res.status(400).json({ error: "filePath required" }); + try { + const result = await compileSingle(filePath); + res.json(result); + } catch (err: any) { + res.status(500).json({ error: err.message }); + } +}); + export default router; diff --git a/packages/backend/src/services/build.service.ts b/packages/backend/src/services/build.service.ts index 27e442c..03777bb 100644 --- a/packages/backend/src/services/build.service.ts +++ b/packages/backend/src/services/build.service.ts @@ -1,3 +1,5 @@ +import fs from "fs/promises"; +import path from "path"; import { runEphemeralContainer } from "./docker.service.js"; import { getWorkspacePath, @@ -41,3 +43,53 @@ export async function buildModule( return { success, output: result.output }; } + +export async function hotReloadScripts(): Promise<{ + success: boolean; + output: string; + scripts: string[]; +}> { + const workspacePath = getWorkspacePath(); + + broadcast("build", "start", { type: "hot-reload" }); + + const result = await buildModule("bare", "compile"); + if (!result.success) { + return { success: false, output: result.output, scripts: [] }; + } + + const cacheDir = path.join( + workspacePath, + "repos/nwn-module/.nasher/cache/bare", + ); + const devDir = getServerPath("development"); + + let scripts: string[] = []; + try { + const files = await fs.readdir(cacheDir); + const ncsFiles = files.filter((f) => f.endsWith(".ncs")); + + await fs.mkdir(devDir, { recursive: true }); + for (const ncs of ncsFiles) { + await fs.copyFile(path.join(cacheDir, ncs), path.join(devDir, ncs)); + scripts.push(ncs); + } + } catch { + // cache dir may not exist yet + } + + broadcast("build", "complete", { type: "hot-reload", scripts }); + return { success: true, output: result.output, scripts }; +} + +export async function compileSingle( + filePath: string, +): Promise<{ success: boolean; errors: string[] }> { + const result = await buildModule("bare", "compile"); + const errors = result.output + .split("\n") + .filter((line) => line.toLowerCase().includes("error")) + .map((line) => line.trim()); + + return { success: result.success, errors }; +}