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:
@@ -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.`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user