UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

95 lines (94 loc) 3.46 kB
import { o as resolveRequiredHomeDir } from "./home-dir-BjcCg_IW.js"; import { a as normalizeEnvVarKey } from "./host-env-security-RnaFYKhk.js"; import { d as resolveConfigDir } from "./utils-CCC-BEJH.js"; import { t as createSubsystemLogger } from "./subsystem-BzXSmsuh.js"; import fs from "node:fs"; import path from "node:path"; import os from "node:os"; import dotenv from "dotenv"; //#region src/infra/dotenv-global.ts const logger = createSubsystemLogger("infra:dotenv"); function readGlobalRuntimeDotEnvFile(params) { let content; try { content = fs.readFileSync(params.filePath, "utf8"); } catch (error) { if (!params.quiet) { if ((error && typeof error === "object" && "code" in error ? String(error.code) : void 0) !== "ENOENT") logger.warn(`Failed to read ${params.filePath}: ${String(error)}`, { error }); } return null; } let parsed; try { parsed = dotenv.parse(content); } catch (error) { if (!params.quiet) logger.warn(`Failed to parse ${params.filePath}: ${String(error)}`, { error }); return null; } const entries = []; for (const [rawKey, value] of Object.entries(parsed)) { const key = normalizeEnvVarKey(rawKey, { portable: true }); if (key) entries.push({ key, value }); } return { filePath: params.filePath, entries }; } function loadParsedDotEnvFiles(files) { const preExistingKeys = new Set(Object.keys(process.env)); const conflicts = /* @__PURE__ */ new Map(); const firstSeen = /* @__PURE__ */ new Map(); for (const file of files) for (const { key, value } of file.entries) { if (preExistingKeys.has(key)) continue; const previous = firstSeen.get(key); if (previous) { if (previous.value !== value) { const conflictKey = `${previous.filePath}\u0000${file.filePath}`; const existing = conflicts.get(conflictKey); if (existing) existing.keys.add(key); else conflicts.set(conflictKey, { keptPath: previous.filePath, ignoredPath: file.filePath, keys: new Set([key]) }); } continue; } firstSeen.set(key, { value, filePath: file.filePath }); if (process.env[key] === void 0) process.env[key] = value; } for (const conflict of conflicts.values()) { const keys = [...conflict.keys].toSorted(); if (keys.length === 0) continue; logger.warn(`Conflicting values in ${conflict.keptPath} and ${conflict.ignoredPath} for ${keys.join(", ")}; keeping ${conflict.keptPath}.`, { keptPath: conflict.keptPath, ignoredPath: conflict.ignoredPath, keys }); } } /** Load global runtime dotenv files into `process.env` with first-wins precedence. */ function loadGlobalRuntimeDotEnvFiles(opts) { const quiet = opts?.quiet ?? true; const stateEnvPath = opts?.stateEnvPath ?? path.join(resolveConfigDir(process.env), ".env"); const defaultStateEnvPath = path.join(resolveRequiredHomeDir(process.env, os.homedir), ".openclaw", ".env"); const hasExplicitNonDefaultStateDir = process.env.OPENCLAW_STATE_DIR?.trim() !== void 0 && path.resolve(stateEnvPath) !== path.resolve(defaultStateEnvPath); const parsedFiles = [readGlobalRuntimeDotEnvFile({ filePath: stateEnvPath, quiet })]; if (!hasExplicitNonDefaultStateDir) parsedFiles.push(readGlobalRuntimeDotEnvFile({ filePath: path.join(resolveRequiredHomeDir(process.env, os.homedir), ".config", "openclaw", "gateway.env"), quiet })); loadParsedDotEnvFiles(parsedFiles.filter((file) => file !== null)); } //#endregion export { loadGlobalRuntimeDotEnvFiles as t };