feat(foundry): productionize Cesium Map Page and platform runtime
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { cp, mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
|
||||
import { dirname, join, relative, resolve } from "node:path";
|
||||
|
||||
const root = resolve(new URL("..", import.meta.url).pathname);
|
||||
const runtimeDir = process.env.FOUNDRY_RUNTIME_DIR ? resolve(root, process.env.FOUNDRY_RUNTIME_DIR) : join(root, "runtime-data");
|
||||
const seedDir = resolve(process.env.FOUNDRY_RUNTIME_SEED_DIR || join(root, "runtime-seed"));
|
||||
const manifestPath = join(seedDir, "seed-manifest.json");
|
||||
|
||||
function isInside(parent, target) {
|
||||
const path = relative(parent, target);
|
||||
return path && !path.startsWith("..") && !path.includes("../");
|
||||
}
|
||||
|
||||
async function exists(path) {
|
||||
try { await stat(path); return true; } catch (error) { if (error?.code === "ENOENT") return false; throw error; }
|
||||
}
|
||||
|
||||
async function copySeedFile(file) {
|
||||
const source = resolve(seedDir, file);
|
||||
const target = resolve(runtimeDir, file);
|
||||
if (!isInside(seedDir, source) || !isInside(runtimeDir, target)) throw new Error("runtime_seed_path_invalid");
|
||||
if (!await exists(source)) throw new Error(`runtime_seed_file_missing:${file}`);
|
||||
await mkdir(dirname(target), { recursive: true });
|
||||
await cp(source, target, { force: true, preserveTimestamps: true });
|
||||
}
|
||||
|
||||
async function isGeneratedFallback() {
|
||||
const profilePath = join(runtimeDir, "design-profiles", "default.json");
|
||||
if (!await exists(profilePath)) return true;
|
||||
try {
|
||||
const profile = JSON.parse(await readFile(profilePath, "utf8"));
|
||||
// The server fallback has the same default media paths as the canonical
|
||||
// profile, but it has never been persisted as a real Design Profile
|
||||
// layout. `savedAt` is written by the baseline/profile save path. A
|
||||
// subsequently edited user profile must never be replaced implicitly.
|
||||
return profile?.id === "default"
|
||||
&& profile?.name === "NODE.DC Default"
|
||||
&& profile?.status === "draft"
|
||||
&& !String(profile?.layout?.savedAt || "").trim()
|
||||
&& String(profile?.timestamps?.createdAt || "") === String(profile?.timestamps?.updatedAt || "");
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
||||
if (!/^\d+\.\d+\.\d+$/.test(String(manifest.version || ""))) throw new Error("runtime_seed_version_invalid");
|
||||
if (!Array.isArray(manifest.files) || !manifest.files.every((file) => typeof file === "string" && file.length > 0)) {
|
||||
throw new Error("runtime_seed_manifest_invalid");
|
||||
}
|
||||
|
||||
const marker = join(runtimeDir, "runtime-seed", `${manifest.version}.json`);
|
||||
if (!await exists(marker)) {
|
||||
const shouldApply = await isGeneratedFallback();
|
||||
if (shouldApply) for (const file of manifest.files) await copySeedFile(file);
|
||||
await mkdir(dirname(marker), { recursive: true });
|
||||
const temporaryMarker = `${marker}.tmp`;
|
||||
await writeFile(temporaryMarker, `${JSON.stringify({ version: manifest.version, appliedAt: new Date().toISOString(), applied: shouldApply }, null, 2)}\n`, "utf8");
|
||||
await rename(temporaryMarker, marker);
|
||||
console.log(`Foundry runtime seed ${manifest.version}: ${shouldApply ? "applied" : "preserved existing runtime"}`);
|
||||
}
|
||||
Reference in New Issue
Block a user