feat: add script hot-reload and compile-on-save
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import { buildModule } from "../services/build.service.js";
|
import {
|
||||||
|
buildModule,
|
||||||
|
hotReloadScripts,
|
||||||
|
compileSingle,
|
||||||
|
} from "../services/build.service.js";
|
||||||
|
|
||||||
const router = Router();
|
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;
|
export default router;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import fs from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
import { runEphemeralContainer } from "./docker.service.js";
|
import { runEphemeralContainer } from "./docker.service.js";
|
||||||
import {
|
import {
|
||||||
getWorkspacePath,
|
getWorkspacePath,
|
||||||
@@ -41,3 +43,53 @@ export async function buildModule(
|
|||||||
|
|
||||||
return { success, output: result.output };
|
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 };
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user