feat: add workspace service and route for directory management

This commit is contained in:
plenarius
2026-04-20 18:26:51 -04:00
parent 421d591c1e
commit ee7a0783ea
3 changed files with 99 additions and 0 deletions
+3
View File
@@ -4,6 +4,7 @@ import { createServer } from "http";
import path from "path"; import path from "path";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
import { initWebSocket, getClientCount } from "./services/ws.service.js"; import { initWebSocket, getClientCount } from "./services/ws.service.js";
import workspaceRouter from "./routes/workspace.js";
const __dirname = path.dirname(fileURLToPath(import.meta.url)); const __dirname = path.dirname(fileURLToPath(import.meta.url));
const app = express(); const app = express();
@@ -22,6 +23,8 @@ app.get("/api/health", (_req, res) => {
}); });
}); });
app.use("/api/workspace", workspaceRouter);
const frontendDist = path.resolve(__dirname, "../../frontend/dist"); const frontendDist = path.resolve(__dirname, "../../frontend/dist");
app.use(express.static(frontendDist)); app.use(express.static(frontendDist));
app.get("*path", (_req, res) => { app.get("*path", (_req, res) => {
+29
View File
@@ -0,0 +1,29 @@
import { Router } from "express";
import {
ensureWorkspaceStructure,
readConfig,
writeConfig,
getWorkspacePath,
} from "../services/workspace.service.js";
const router = Router();
router.get("/config", async (_req, res) => {
const config = await readConfig();
const sanitized = { ...config, githubPat: config.githubPat ? "***" : undefined };
res.json(sanitized);
});
router.put("/config", async (req, res) => {
const current = await readConfig();
const updated = { ...current, ...req.body };
await writeConfig(updated);
res.json({ ok: true });
});
router.post("/init", async (_req, res) => {
await ensureWorkspaceStructure();
res.json({ ok: true, path: getWorkspacePath() });
});
export default router;
@@ -0,0 +1,67 @@
import fs from "fs/promises";
import path from "path";
const WORKSPACE_PATH = process.env.WORKSPACE_PATH || "/workspace";
interface ForgeConfig {
githubPat?: string;
workspacePath: string;
nwnHomePath: string;
setupComplete: boolean;
editorState?: {
openTabs: string[];
activeTab?: string;
cursorPositions: Record<string, { line: number; column: number }>;
};
}
const REQUIRED_DIRS = [
"repos",
"server/modules",
"server/hak",
"server/tlk",
"server/servervault",
"server/database",
"server/development",
"server/override",
"server/portraits",
"logs",
"config",
];
export async function ensureWorkspaceStructure(): Promise<void> {
for (const dir of REQUIRED_DIRS) {
await fs.mkdir(path.join(WORKSPACE_PATH, dir), { recursive: true });
}
}
export async function readConfig(): Promise<ForgeConfig> {
const configPath = path.join(WORKSPACE_PATH, "config", "forge.json");
try {
const raw = await fs.readFile(configPath, "utf-8");
return JSON.parse(raw);
} catch {
return {
workspacePath: WORKSPACE_PATH,
nwnHomePath: process.env.NWN_HOME_PATH || "",
setupComplete: false,
};
}
}
export async function writeConfig(config: ForgeConfig): Promise<void> {
const configPath = path.join(WORKSPACE_PATH, "config", "forge.json");
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
}
export function getWorkspacePath(): string {
return WORKSPACE_PATH;
}
export function getServerPath(...segments: string[]): string {
return path.join(WORKSPACE_PATH, "server", ...segments);
}
export function getRepoPath(repo: string, ...segments: string[]): string {
return path.join(WORKSPACE_PATH, "repos", repo, ...segments);
}