26 lines
907 B
TypeScript
26 lines
907 B
TypeScript
import { z } from "zod";
|
|||
|
|
|
||
|
|
// ACCESS_PASSWORD gates the login form; AUTH_SECRET signs the session JWT.
|
||
|
|
// These are deliberately separate - reusing the login password as the
|
||
|
|
// signing key would let a JWT-signing weakness leak the login secret itself.
|
||
|
|
const envSchema = z.object({
|
||
|
|
ACCESS_PASSWORD: z.string().min(1, "ACCESS_PASSWORD must be set"),
|
||
|
|
AUTH_SECRET: z.string().min(16, "AUTH_SECRET must be at least 16 characters"),
|
||
|
|
DATABASE_PATH: z.string().min(1).default("./data/app.db"),
|
||
|
|
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).optional(),
|
||
|
|
});
|
||
|
|
|
||
|
|
export type Env = z.infer<typeof envSchema>;
|
||
|
|
|
||
|
|
let cached: Env | undefined;
|
||
|
|
|
||
|
|
export function getEnv(): Env {
|
||
|
|
if (cached) return cached;
|
||
|
|
const parsed = envSchema.safeParse(process.env);
|
||
|
|
if (!parsed.success) {
|
||
|
|
throw new Error(`Invalid environment configuration: ${parsed.error.message}`);
|
||
|
|
}
|
||
|
|
cached = parsed.data;
|
||
|
|
return cached;
|
||
|
|
}
|