import fs from "fs/promises"; import path from "path"; import { runEphemeralContainer } from "./docker.service.js"; import { getWorkspacePath, getServerPath, } from "./workspace.service.js"; import { broadcast } from "./ws.service.js"; export async function buildModule( target: string = "bare", mode: "compile" | "pack" = "compile", ): Promise<{ success: boolean; output: string }> { const workspacePath = getWorkspacePath(); const cmd = mode === "compile" ? ["nasher", "compile", target, "--yes"] : ["nasher", "pack", target, "--yes"]; broadcast("build", "start", { type: "module", target, mode }); const result = await runEphemeralContainer({ image: "layonara-builder", cmd, binds: [ `${workspacePath}/repos/nwn-module:/build/nwn-module`, `${workspacePath}/server/modules:/output/modules`, ], workingDir: "/build/nwn-module", }); const success = result.statusCode === 0; broadcast("build", success ? "complete" : "failed", { type: "module", target, mode, exitCode: result.statusCode, }); if (success && mode === "pack") { broadcast("build", "info", { message: "Module packed successfully" }); } 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 }; }