// Domain-Trennung craftvia.de ↔ app.craftvia.de (src/lib/marketing/hosts.ts) // // Lauf: npx tsx scripts/test-host-routing.ts import { hostSplit, routeByHost, type HostDecision } from "../src/lib/marketing/hosts"; let failures = 0; const ok = (cond: boolean, msg: string) => { console.log(`${cond ? "✓" : "✗ FEHLER"} ${msg}`); if (!cond) failures++; }; const env = { MARKETING_HOST: "craftvia.de", AUTH_URL: "https://app.craftvia.de" }; const split = hostSplit(env)!; const route = (host: string, path: string, hasSession = false): HostDecision => { const [pathname, query] = path.split("?"); return routeByHost({ host, pathname, search: query ? `?${query}` : "", hasSession }, split); }; const to = (d: HostDecision) => (d.kind === "redirect" ? `${d.status} ${d.location}` : "next"); console.log("\n— Konfiguration —"); ok(hostSplit({ AUTH_URL: "https://app.craftvia.de" }) === null, "ohne MARKETING_HOST keine Trennung (lokal)"); ok(hostSplit({ MARKETING_HOST: "craftvia.de" }) === null, "ohne AUTH_URL keine Trennung"); ok(hostSplit({ MARKETING_HOST: "app.craftvia.de", AUTH_URL: "https://app.craftvia.de" }) === null, "gleiche Domain → keine Trennung"); ok(hostSplit({ MARKETING_HOST: "https://Craftvia.de/", AUTH_URL: "https://app.craftvia.de" })?.marketingHost === "craftvia.de", "MARKETING_HOST mit Schema/Slash/Großschreibung wird normalisiert"); console.log("\n— Website-Domain —"); ok(to(route("craftvia.de", "/")) === "next", "/ zeigt die Startseite"); ok(to(route("craftvia.de", "/funktionen/planung")) === "next", "Funktionsseiten bleiben auf der Website"); ok(to(route("craftvia.de", "/impressum")) === "next", "Impressum bleibt auf der Website"); ok(to(route("craftvia.de", "/login")) === "308 https://app.craftvia.de/login", "/login → App-Domain"); ok(to(route("craftvia.de", "/testen?ref=preise")) === "308 https://app.craftvia.de/testen?ref=preise", "/testen → App-Domain, Query bleibt erhalten"); ok(to(route("craftvia.de", "/dashboard")) === "308 https://app.craftvia.de/dashboard", "App-Seiten → App-Domain"); ok(to(route("craftvia.de", "/api/v1/sync")) === "308 https://app.craftvia.de/api/v1/sync", "API → App-Domain (308 behält die Methode)"); ok(to(route("craftvia.de:443", "/preise")) === "next", "Port im Host wird ignoriert"); ok(to(route("www.craftvia.de", "/preise")) === "308 https://craftvia.de/preise", "www → Hauptdomain"); console.log("\n— App-Domain —"); ok(to(route("app.craftvia.de", "/")) === "307 https://app.craftvia.de/login", "/ ohne Sitzung → Login"); ok(to(route("app.craftvia.de", "/", true)) === "next", "/ mit Sitzung → weiter (Seite leitet auf Dashboard bzw. /m)"); ok(to(route("app.craftvia.de", "/funktionen")) === "308 https://craftvia.de/funktionen", "Produktseiten → Website"); ok(to(route("app.craftvia.de", "/impressum")) === "308 https://craftvia.de/impressum", "Impressum → Website"); ok(to(route("app.craftvia.de", "/testen")) === "next", "Testphase bleibt in der App"); ok(to(route("app.craftvia.de", "/planning", true)) === "next", "App-Seiten bleiben in der App"); console.log("\n— Interne Aufrufe —"); ok(to(route("127.0.0.1:3000", "/")) === "next", "Healthcheck über 127.0.0.1 unverändert"); ok(to(route("craftvia-app:3000", "/login")) === "next", "Container-interne Aufrufe unverändert"); console.log(failures ? `\n✗ ${failures} Fehler` : "\n✓ alle Prüfungen grün"); process.exit(failures ? 1 : 0);