import fs from "node:fs"; interface EnvEntry { key: string; value: string; } function parseEnvLines(content: string): EnvEntry[] { const entries: EnvEntry[] = []; for (const line of content.split("\n")) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith("#")) continue; const eq = trimmed.indexOf("="); if (eq === -1) continue; entries.push({ key: trimmed.slice(0, eq), value: trimmed.slice(eq + 1) }); } return entries; } /** Loads a `.env` file into `process.env`, without overriding vars already set. */ export function loadDotenv(envPath: string): void { if (!fs.existsSync(envPath)) return; for (const { key, value } of parseEnvLines(fs.readFileSync(envPath, "utf-8"))) { if (process.env[key] === undefined) process.env[key] = value; } } /** Sets `key=value` in a `.env` file, replacing an existing line for that key rather than duplicating it. */ export function upsertEnvVar(envPath: string, key: string, value: string): void { const lines = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8").split("\n") : []; const prefix = `${key}=`; const index = lines.findIndex((line) => line.startsWith(prefix)); const newLine = `${key}=${value}`; if (index >= 0) { lines[index] = newLine; } else { if (lines.length > 0 && lines[lines.length - 1] === "") lines.pop(); lines.push(newLine); } fs.writeFileSync(envPath, lines.join("\n") + "\n"); }