124 lines
3.1 KiB
JavaScript
124 lines
3.1 KiB
JavaScript
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,
|
|
}
|