import { existsSync, readFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; function resolveWorkspaceRoot() { const currentDir = dirname(fileURLToPath(import.meta.url)); return resolve(currentDir, "../../../"); } export function resolveWorkspaceEnvPaths(options: { workspaceRoot?: string; nodeEnv?: string | undefined } = {}) { const workspaceRoot = options.workspaceRoot ?? resolveWorkspaceRoot(); const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV; const candidates = [".env"]; if (nodeEnv) { candidates.push(`.env.${nodeEnv}`); } candidates.push(".env.local"); if (nodeEnv) { candidates.push(`.env.${nodeEnv}.local`); } return [...new Set(candidates.map((candidate) => resolve(workspaceRoot, candidate)))]; } export function loadWorkspaceEnv(options: { workspaceRoot?: string; nodeEnv?: string | undefined } = {}) { const envPaths = resolveWorkspaceEnvPaths(options); const originalKeys = new Set(Object.keys(process.env)); const loadedPaths: string[] = []; for (const envPath of envPaths) { if (!existsSync(envPath)) { continue; } const contents = readFileSync(envPath, "utf8"); for (const rawLine of contents.split(/\r?\n/u)) { const line = rawLine.trim(); if (!line || line.startsWith("#")) { continue; } const separatorIndex = line.indexOf("="); if (separatorIndex <= 0) { continue; } const key = line.slice(0, separatorIndex).trim(); const rawValue = line.slice(separatorIndex + 1).trim(); const quoted = (rawValue.startsWith("\"") && rawValue.endsWith("\"")) || (rawValue.startsWith("'") && rawValue.endsWith("'")); const value = quoted ? rawValue.slice(1, -1) : rawValue; if (!originalKeys.has(key)) { process.env[key] = value; } } loadedPaths.push(envPath); } return loadedPaths; } export function resolveWorkspacePath(...segments: string[]) { return resolve(resolveWorkspaceRoot(), ...segments); }