import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { get_env } from './env.js'; function must_get(key) { const v = get_env(key); if (v === undefined || v === null || v === '') { throw new Error(`缺少配置 ${key}`); } return v; } function get_bool(key, default_value) { const v = get_env(key); if (v === undefined || v === null || v === '') { return default_value; } return String(v).toLowerCase() === 'true'; } function get_int(key, default_value) { const v = get_env(key); if (v === undefined || v === null || v === '') { return default_value; } const n = Number(v); if (Number.isNaN(n)) { throw new Error(`配置 ${key} 必须是数字`); } return n; } let cached = null; export function get_app_config() { if (cached) { return cached; } const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); cached = { mysql: { host: must_get('MYSQL_HOST'), port: get_int('MYSQL_PORT', 3306), user: must_get('MYSQL_USER'), password: must_get('MYSQL_PASSWORD'), database: must_get('MYSQL_DATABASE') }, server: { port: get_int('SERVER_PORT', 38080) }, crawler: { crx_src_path: must_get('CRX_SRC_PATH'), action_timeout_ms: get_int('ACTION_TIMEOUT_MS', 300000), puppeteer_headless: get_bool('PUPPETEER_HEADLESS', false), chrome_executable_path: (get_env('CHROME_EXECUTABLE_PATH') || '').trim() || path.resolve(__dirname, '../../chrome-win/chrome.exe'), log_invoke_action: get_bool('LOG_INVOKE_ACTION', true) } }; return cached; }