const fs = require('node:fs') const path = require('node:path') const ENABLED_VALUES = new Set(['1', 'true', 'yes']) function parseEnvFile(content) { const env = {} for (const rawLine of content.split(/\r?\n/)) { const line = rawLine.trim() if (!line || line.startsWith('#')) continue const normalized = line.startsWith('export ') ? line.slice(7).trim() : line const separatorIndex = normalized.indexOf('=') if (separatorIndex === -1) continue const key = normalized.slice(0, separatorIndex).trim() if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue let value = normalized.slice(separatorIndex + 1) if ( (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")) ) { const quote = value[0] value = value.slice(1, -1) if (quote === '"') { value = value .replace(/\\n/g, '\n') .replace(/\\r/g, '\r') .replace(/\\t/g, '\t') .replace(/\\"/g, '"') .replace(/\\\\/g, '\\') } } env[key] = value } return env } function loadEnvFile(filePath, env = process.env, { override = false } = {}) { if (!fs.existsSync(filePath)) return false const parsed = parseEnvFile(fs.readFileSync(filePath, 'utf8')) for (const [key, value] of Object.entries(parsed)) { if (override || env[key] === undefined) { env[key] = value } } return true } function isRunningInContainer() { return fs.existsSync('/.dockerenv') } function normalizeDatabaseUrlForExecution(env = process.env) { if (!env.DATABASE_URL) return env.DATABASE_URL let parsed try { parsed = new URL(env.DATABASE_URL) } catch { return env.DATABASE_URL } if (parsed.hostname !== 'postgres' || isRunningInContainer()) { return env.DATABASE_URL } const fallbackHost = env.POSTGRES_HOST_LOCAL ?? 'localhost' parsed.hostname = fallbackHost env.DATABASE_URL = parsed.toString() return env.DATABASE_URL } function loadDefaultEnvFiles(baseDir, env = process.env) { const candidates = [ path.join(baseDir, '.env'), path.join(baseDir, '.env.local'), path.join(baseDir, '.env.docker.dev'), ] for (const candidate of candidates) { loadEnvFile(candidate, env) } } function ensureDatabaseUrl(env = process.env) { const shouldBuildFromPostgres = ENABLED_VALUES.has( env.DATABASE_URL_FROM_POSTGRES?.trim().toLowerCase() ?? '', ) if (!shouldBuildFromPostgres) { return env.DATABASE_URL } if (!env.POSTGRES_PASSWORD) { throw new Error('DATABASE_URL_FROM_POSTGRES is enabled but POSTGRES_PASSWORD is not set') } const user = env.POSTGRES_USER ?? 'postgres' const password = env.POSTGRES_PASSWORD const host = env.POSTGRES_HOST ?? 'postgres' const port = env.POSTGRES_PORT ?? '5432' const database = env.POSTGRES_DB ?? 'rentaldrivego' env.DATABASE_URL = `postgresql://${encodeURIComponent(user)}:${encodeURIComponent(password)}@${host}:${port}/${encodeURIComponent(database)}` return env.DATABASE_URL } module.exports = { ensureDatabaseUrl, loadDefaultEnvFiles, loadEnvFile, normalizeDatabaseUrlForExecution, }