feat: add environment variable interpolation for API keys

- Add interpolateEnvVars function to support $VAR_NAME and ${VAR_NAME} syntax
- Apply interpolation to config after JSON5 parsing in readConfigFile()
- Enables secure API key management without hardcoding in config.json
- Supports nested objects and arrays for comprehensive interpolation
- Maintains backward compatibility with existing configurations

Example usage in config.json:
{
  "OPENAI_API_KEY": "$OPENAI_API_KEY",
  "Providers": [
    {
      "name": "openai",
      "api_key": "$OPENAI_API_KEY"
    }
  ]
}
This commit is contained in:
Fredrik Bränström
2025-08-11 21:43:32 +02:00
parent 075ec76ec1
commit 3ad140d2f5

View File

@@ -11,6 +11,26 @@ import {
import { getSystemUUID, generateTempAPIKey, getTempAPIKey } from "./systemUUID";
import { cleanupLogFiles } from "./logCleanup";
// Function to interpolate environment variables in config values
const interpolateEnvVars = (obj: any): any => {
if (typeof obj === "string") {
// Replace $VAR_NAME or ${VAR_NAME} with environment variable values
return obj.replace(/\$\{([^}]+)\}|\$([A-Z_][A-Z0-9_]*)/g, (match, braced, unbraced) => {
const varName = braced || unbraced;
return process.env[varName] || match; // Keep original if env var doesn't exist
});
} else if (Array.isArray(obj)) {
return obj.map(interpolateEnvVars);
} else if (obj !== null && typeof obj === "object") {
const result: any = {};
for (const [key, value] of Object.entries(obj)) {
result[key] = interpolateEnvVars(value);
}
return result;
}
return obj;
};
const ensureDir = async (dir_path: string) => {
try {
await fs.access(dir_path);
@@ -52,7 +72,9 @@ export const readConfigFile = async () => {
const config = await fs.readFile(CONFIG_FILE, "utf-8");
try {
// Try to parse with JSON5 first (which also supports standard JSON)
return JSON5.parse(config);
const parsedConfig = JSON5.parse(config);
// Interpolate environment variables in the parsed config
return interpolateEnvVars(parsedConfig);
} catch (parseError) {
console.error(`Failed to parse config file at ${CONFIG_FILE}`);
console.error("Error details:", (parseError as Error).message);