#!/usr/bin/env node /** * Befüllt .cache/cms mit allen relevanten API-Responses. * CMS muss erreichbar sein (PUBLIC_CMS_URL, Standard: http://localhost:3000). * Nutzung: yarn cache:warm oder node scripts/warm-cache.mjs */ import { createHash } from "node:crypto"; import { writeFile, mkdir } from "node:fs/promises"; import { existsSync } from "node:fs"; import { join, dirname } from "node:path"; import { fileURLToPath } from "node:url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const root = join(__dirname, ".."); const CACHE_DIR = join(root, ".cache", "cms"); const BASE = process.env.PUBLIC_CMS_URL?.trim() || "http://localhost:3000"; function cacheKey(url) { return createHash("sha256").update(url).digest("hex"); } async function fetchAndCache(url) { const key = cacheKey(url); try { const res = await fetch(url); const body = await res.text(); if (!existsSync(CACHE_DIR)) { await mkdir(CACHE_DIR, { recursive: true }); } const path = join(CACHE_DIR, `${key}.json`); await writeFile( path, JSON.stringify({ status: res.status, body }), "utf-8" ); return { url, ok: res.ok, status: res.status }; } catch (err) { return { url, ok: false, error: err.message }; } } /** Basis-URLs, die beim Build/Dev immer angefragt werden. */ const BASE_URLS = [ `${BASE}/api-docs/openapi.json`, `${BASE}/api/content/page`, `${BASE}/api/content/page_config?_per_page=50&_locale=de`, `${BASE}/api/content/translation_bundle/app?_resolve=all&_locale=de`, `${BASE}/api/content/navigation?_locale=de&_resolve=links&_page=1&_per_page=50`, `${BASE}/api/content/navigation?_locale=de&_resolve=all&_page=1&_per_page=50`, `${BASE}/api/content/post?_per_page=100`, `${BASE}/api/content/tag`, `${BASE}/api/content/footer/footer-main?_locale=de&_resolve=row1Content,row2Content,row3Content`, `${BASE}/api/content/page_config/page-config-default?_locale=de&_resolve=logo`, `${BASE}/api/content/page_config/default?_locale=de&_resolve=logo`, ]; async function main() { console.log("Cache befüllen: .cache/cms"); console.log("CMS-Basis:", BASE); const results = []; for (const url of BASE_URLS) { const r = await fetchAndCache(url); results.push(r); const status = r.ok ? r.status : r.error || r.status; console.log(r.ok ? " ✓" : " ✗", url.replace(BASE, ""), status); } // Page-Slugs und einzelne Pages try { const pageRes = await fetch(`${BASE}/api/content/page?_per_page=200`); const pageData = await pageRes.json(); const items = pageData?.items ?? []; for (const p of items.slice(0, 50)) { const slug = p._slug ?? p.slug ?? ""; if (!slug) continue; const url = `${BASE}/api/content/page/${encodeURIComponent(slug)}?_locale=de&_resolve=all`; const r = await fetchAndCache(url); results.push(r); if (!r.ok) console.log(" ✗", slug, r.error || r.status); } if (items.length > 0) { console.log(" ✓", items.length, "Pages (erste 50 gecacht)"); } } catch (e) { console.log(" ✗ Pages-Liste", e.message); } // Post-Slugs und einzelne Posts try { const postRes = await fetch( `${BASE}/api/content/post?_per_page=200&_resolve=postImage,postTag,row1Content,row2Content,row3Content` ); const postData = await postRes.json(); const items = postData?.items ?? []; for (const p of items.slice(0, 50)) { const slug = p._slug ?? p.slug ?? ""; if (!slug) continue; const url = `${BASE}/api/content/post/${encodeURIComponent(slug)}?_locale=de&_resolve=postImage,postTag,row1Content,row2Content,row3Content`; const r = await fetchAndCache(url); results.push(r); if (!r.ok) console.log(" ✗", slug, r.error || r.status); } if (items.length > 0) { console.log(" ✓", items.length, "Posts (erste 50 gecacht)"); } } catch (e) { console.log(" ✗ Posts-Liste", e.message); } const failed = results.filter((r) => !r.ok); if (failed.length > 0) { console.log("\nFehlgeschlagen:", failed.length); process.exitCode = 1; } else { console.log("\nCache befüllt."); } } main().catch((e) => { console.error(e); process.exit(1); });