Update project configuration and enhance translation support. Added caching mechanism for CMS responses with a new script, updated .gitignore to include cache files, and introduced translation handling in various components. Enhanced package.json with new scripts for cache warming and deployment. Added new translation-related components and improved existing ones for better localization support.

This commit is contained in:
Peter Meier
2026-03-17 22:32:31 +01:00
parent 1f5454d04e
commit daa4ea17b1
46 changed files with 5207 additions and 781 deletions
+77
View File
@@ -0,0 +1,77 @@
/**
* Cache für CMS-API-Responses (nur serverseitig, Node fs/crypto).
* Wird ausschließlich per dynamic import aus cms.ts geladen nie von Layout/Middleware,
* damit es nicht ins Client-Bundle gelangt. Flag/State: cms-cache-state.ts.
*/
import { createHash } from "node:crypto";
import { readFile, writeFile, mkdir } from "node:fs/promises";
import { existsSync } from "node:fs";
import { setCmsFromCacheUsed } from "./cms-cache-state";
const CACHE_DIR = `${process.cwd()}/.cache/cms`;
function cacheKeyFromUrl(url: string): string {
return createHash("sha256").update(url).digest("hex");
}
async function ensureCacheDir(): Promise<void> {
if (!existsSync(CACHE_DIR)) {
await mkdir(CACHE_DIR, { recursive: true });
}
}
interface CachedResponse {
status: number;
body: string;
}
async function getCached(key: string): Promise<CachedResponse | null> {
try {
const path = `${CACHE_DIR}/${key}.json`;
if (!existsSync(path)) return null;
const raw = await readFile(path, "utf-8");
const data = JSON.parse(raw) as CachedResponse;
return data?.body != null ? data : null;
} catch {
return null;
}
}
async function setCached(key: string, data: CachedResponse): Promise<void> {
try {
await ensureCacheDir();
const path = `${CACHE_DIR}/${key}.json`;
await writeFile(path, JSON.stringify(data), "utf-8");
} catch {
// Cache schreiben optional
}
}
/**
* Fetch mit Cache: bei Erfolg wird die Response in .cache/cms gespeichert (überschreibt vorhanden).
* Bei Fehler wird versucht, aus dem Cache zu lesen; wenn gefunden, wird usedCacheThisRequest gesetzt.
*/
export async function cachedFetch(url: string): Promise<Response> {
const key = cacheKeyFromUrl(url);
try {
const res = await fetch(url);
const body = await res.text();
await setCached(key, { status: res.status, body });
return new Response(body, {
status: res.status,
headers: res.headers,
});
} catch {
const cached = await getCached(key);
if (cached) {
setCmsFromCacheUsed();
return new Response(cached.body, {
status: cached.status,
headers: { "Content-Type": "application/json" },
});
}
throw new Error(`CMS nicht erreichbar (${url}) und kein Cache für diese Anfrage.`);
}
}