Handle unloaded site workspace in CMS
This commit is contained in:
+55
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user