/** * Versionsstempel der Web-Oberflaeche (quick-260914-ku1). * * Quelle fuer das Abzeichen unten in der Seitenleiste (`AppVersionBadge`) * UND fuer den kommenden Fehler-melden-Knopf: beide brauchen die Fassung, * die der Anwender gerade benutzt. * * Wichtig: Next.js ersetzt `process.env.NEXT_PUBLIC_*` nur dann zur Bauzeit * im Browser-Bundle, wenn der Ausdruck woertlich mit vollem Namen im Code * steht — kein Destructuring, kein `process.env[name]`. Sonst ist der Wert * im Browser leer. Die Werte setzt `apps/web/Dockerfile` (builder-Stufe) * aus den Build-Args des CI-Skripts `.gitea/scripts/publish-images.sh`; * lokal greifen die Vorgaben `dev`. */ export type AppChannel = 'beta' | 'live' | 'dev'; export interface AppVersionInfo { version: string; channel: AppChannel; commit: string; } /** * Spiegel von `VersionResponse` aus `packages/shared`: `apps/web` haengt * nicht von `@tessera/shared` ab, und ein neuer Import wuerde Lockfile und * die deps-Stufe des Dockerfiles aendern. Die API-Wahrheit bleibt dort. */ export interface ApiVersionInfo { name: string; version: string; channel: string; commit: string; buildTime: string; } const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001'; function normalizeChannel(raw: string | undefined): AppChannel { if (raw === 'beta' || raw === 'live') return raw; return 'dev'; } export const appVersion: AppVersionInfo = { version: process.env.NEXT_PUBLIC_APP_VERSION || 'dev', channel: normalizeChannel(process.env.NEXT_PUBLIC_APP_CHANNEL), commit: process.env.NEXT_PUBLIC_APP_COMMIT || '', }; let apiVersionPromise: Promise | null = null; /** * Laedt `GET /health/version` genau einmal je Seitenladung (memoisiert); * jeder Fehler (Netz, Nicht-2xx) ist still und liefert `null`. */ export function loadApiVersion(): Promise { if (!apiVersionPromise) { apiVersionPromise = fetch(`${API_URL}/health/version`, { credentials: 'include' }) .then((res) => (res.ok ? (res.json() as Promise) : null)) .catch(() => null); } return apiVersionPromise; }