Files
planer/src/server/umgebung.ts
T
Florian WildeandClaude Opus 5 e2b00f4a57 feat(instanz): Instanzsteuerung mit serverseitigem Riegel
INSTANZ entscheidet, welche Kalenderanbieter, Postfächer und
Integrationen es gibt. Was eine Instanz nicht darf, liefert dort 404
statt eines Hinweises. Ein falsch geschriebener Wert bricht ab, statt
still auf einen Standard zu fallen.

Die Konfiguration wird mit zod geprüft; Fehlermeldungen nennen den
Variablennamen, nie den Wert.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 12:41:29 +02:00

72 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'server-only'
import { z } from 'zod'
import { INSTANZEN, type Instanz } from '@/lib/instanz'
/**
* Jede Einstellung von aussen wird geprueft, bevor sie benutzt wird. Fehlt
* etwas Pflichtiges, faellt das beim ersten Zugriff auf – mit einer Meldung,
* die den Variablennamen nennt, nie deren Wert.
*/
const jaNein = z
.enum(['true', 'false', '1', '0', 'ja', 'nein'])
.transform((w) => w === 'true' || w === '1' || w === 'ja')
const schema = z.object({
INSTANZ: z.enum(INSTANZEN),
APP_URL: z.url().transform((u) => u.replace(/\/+$/, '')),
DATABASE_URL: z.string().min(1),
AUTH_SECRET: z.string().min(16, 'AUTH_SECRET ist zu kurz, mindestens 16 Zeichen.'),
AUTH_TRUST_HOST: jaNein.default(false),
ANMELDUNG_PASSWORT: jaNein.default(false),
OIDC_NAME: z.string().trim().default(''),
OIDC_ISSUER: z.string().trim().default(''),
OIDC_CLIENT_ID: z.string().trim().default(''),
OIDC_CLIENT_SECRET: z.string().trim().default(''),
WEBAUTHN_RP_ID: z.string().min(1),
WEBAUTHN_RP_NAME: z.string().min(1).default('Planer'),
WEBAUTHN_ORIGIN: z.url(),
DEMO_MODUS: jaNein.default(false),
})
export type Umgebung = z.infer<typeof schema> & {
instanz: Instanz
/** OIDC ist nur eingerichtet, wenn alle vier Werte gesetzt sind. */
oidcAktiv: boolean
}
let zwischengespeichert: Umgebung | null = null
function lesen(): Umgebung {
const ergebnis = schema.safeParse(process.env)
if (!ergebnis.success) {
const felder = ergebnis.error.issues
.map((f) => `${f.path.join('.')}: ${f.message}`)
.join('\n ')
throw new Error(`Die Konfiguration ist unvollstaendig:\n ${felder}`)
}
const werte = ergebnis.data
return {
...werte,
instanz: werte.INSTANZ,
oidcAktiv: Boolean(
werte.OIDC_ISSUER && werte.OIDC_CLIENT_ID && werte.OIDC_CLIENT_SECRET,
),
}
}
/** Die geprueften Einstellungen. Erst beim ersten Aufruf ausgewertet. */
export function umgebung(): Umgebung {
zwischengespeichert ??= lesen()
return zwischengespeichert
}
/** Nur fuer Tests: erzwingt beim naechsten Aufruf ein erneutes Einlesen. */
export function umgebungVergessen(): void {
zwischengespeichert = null
}