Handle unloaded site workspace in CMS

This commit is contained in:
DCCONSTRUCTIONS
2026-07-06 11:55:08 +03:00
parent 33ab11ab08
commit dc49acaa43
5 changed files with 214 additions and 22 deletions
+55 -1
View File
@@ -1,5 +1,5 @@
import { createServer } from "node:http";
import { createReadStream } from "node:fs";
import { createReadStream, statSync } from "node:fs";
import { copyFile, cp, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
import { extname, join, normalize, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";
@@ -117,6 +117,15 @@ const REFERENCE_TEXT_EXTENSIONS = new Set([
".xml",
]);
const REQUIRED_SITE_FILES = [
{ key: "page", label: "content/pages/home.json", path: pagePath },
{ key: "knowledge", label: "content/knowledge.json", path: knowledgePath },
{ key: "blockTemplates", label: "content/block-templates/home.json", path: blockTemplatesPath },
{ key: "renderHome", label: "tools/render-home.mjs", path: join(repoRoot, "tools", "render-home.mjs") },
{ key: "renderKnowledge", label: "tools/render-knowledge.mjs", path: join(repoRoot, "tools", "render-knowledge.mjs") },
{ key: "homeShell", label: "templates/pages/home/shell.html", path: join(repoRoot, "templates", "pages", "home", "shell.html") },
];
const MIME = {
".html": "text/html; charset=utf-8",
".css": "text/css; charset=utf-8",
@@ -206,6 +215,42 @@ function trailingSlashUrl(value) {
return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
}
function fileReady(filePath) {
try {
return statSync(filePath).isFile();
} catch {
return false;
}
}
function currentSiteStatus() {
const files = REQUIRED_SITE_FILES.map((item) => ({
key: item.key,
label: item.label,
exists: fileReady(item.path),
}));
const missingFiles = files.filter((item) => !item.exists).map((item) => item.label);
return {
ready: missingFiles.length === 0,
root: repoRoot,
requiredFiles: files,
missingFiles,
};
}
function ensureSiteReady(res) {
const site = currentSiteStatus();
if (site.ready) return true;
sendJson(res, 409, {
ok: false,
code: "SITE_NOT_READY",
error: "Сайт не загружен в локальный workspace CMS.",
site,
});
return false;
}
const authConfig = {
enabled: boolEnv(process.env.CMS_AUTH_ENABLED, false),
baseUrl: String(process.env.CMS_BASE_URL || "").trim(),
@@ -773,6 +818,7 @@ function publicProjectConfig() {
configPath: projectConfigPath,
siteRootChangesRequireRestart: true,
},
site: currentSiteStatus(),
};
}
@@ -2165,16 +2211,19 @@ const server = createServer(async (req, res) => {
}
if (req.method === "GET" && url.pathname === "/api/page/home") {
if (!ensureSiteReady(res)) return;
send(res, 200, await readFile(pagePath, "utf8"), "application/json; charset=utf-8");
return;
}
if (req.method === "GET" && url.pathname === "/api/knowledge") {
if (!ensureSiteReady(res)) return;
send(res, 200, await readFile(knowledgePath, "utf8"), "application/json; charset=utf-8");
return;
}
if (req.method === "GET" && url.pathname === "/api/landing-targets") {
if (!ensureSiteReady(res)) return;
const page = JSON.parse(await readFile(pagePath, "utf8"));
validateLandingTargets(page);
sendJson(res, 200, { ok: true, targets: landingTargetsForPage(page) });
@@ -2182,6 +2231,7 @@ const server = createServer(async (req, res) => {
}
if (req.method === "GET" && url.pathname === "/api/block-templates/home") {
if (!ensureSiteReady(res)) return;
send(res, 200, await readFile(blockTemplatesPath, "utf8"), "application/json; charset=utf-8");
return;
}
@@ -2207,6 +2257,7 @@ const server = createServer(async (req, res) => {
}
if (req.method === "PUT" && url.pathname === "/api/page/home") {
if (!ensureSiteReady(res)) return;
const body = await readBody(req);
const parsed = JSON.parse(body);
validateLandingTargets(parsed);
@@ -2216,6 +2267,7 @@ const server = createServer(async (req, res) => {
}
if (req.method === "PUT" && url.pathname === "/api/knowledge") {
if (!ensureSiteReady(res)) return;
const body = await readBody(req);
const parsed = JSON.parse(body);
await writeFile(knowledgePath, `${JSON.stringify(parsed, null, 2)}\n`);
@@ -2224,12 +2276,14 @@ const server = createServer(async (req, res) => {
}
if (req.method === "POST" && url.pathname === "/api/render/home") {
if (!ensureSiteReady(res)) return;
const result = await runNodeScript("render-home.mjs");
sendJson(res, 200, { ok: true, ...result });
return;
}
if (req.method === "POST" && url.pathname === "/api/render/knowledge") {
if (!ensureSiteReady(res)) return;
const result = await runNodeScript("render-knowledge.mjs");
sendJson(res, 200, { ok: true, ...result });
return;