import { isHostedAuthMode } from "@/lib/auth-mode"; let workersEnvPromise: Promise | null> | null = null; export async function getOptionalEnvValue( name: string, ): Promise { return getEnvValueSync((await getWorkersEnv()) ?? {}, name); } /** * Sync variant for callers that already hold an env record (e.g. a Durable * Object's `this.env`, needed because Think's `getModel()` hook is sync). * Same policy as the async form: process.env first (where local `.env.local` * secrets land in dev), skipping empty strings, then the given env. */ export function getEnvValueSync( // `object` so interface-typed envs (e.g. Cloudflare.Env) are accepted // without a cast. env: object, name: string, ): string | undefined { const processValue = typeof process !== "undefined" ? process.env?.[name] : undefined; if (processValue) { return processValue; } const value: unknown = Reflect.get(env, name); return typeof value === "string" && value !== "" ? value : undefined; } export async function getRequiredEnvValue(name: string): Promise { const value = await getOptionalEnvValue(name); if (!value) { throw new Error(`Missing required environment variable: ${name}`); } return value; } export async function isHostedServerAuthMode(): Promise { return isHostedAuthMode(await getOptionalEnvValue("AUTH_MODE")); } async function getWorkersEnv(): Promise | null> { if (!workersEnvPromise) { workersEnvPromise = loadWorkersEnv(); } return workersEnvPromise; } async function loadWorkersEnv(): Promise | null> { try { const workersModule = await import("cloudflare:workers"); return isRecord(workersModule.env) ? workersModule.env : null; } catch { return null; } } function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null; }