const fs = require('fs'); const path = require('path'); const readline = require('readline'); const rootDir = path.resolve(__dirname, '..'); const PROD_DB_SUFFIX = '_prod'; const DEV_DB_NAME = 'gallery_dev'; const PROD_DB_NAME = 'gallery_prod'; const LEGACY_DB_NAMES = ['Gallery', 'gallery']; function loadEnvFile(filePath) { if (!fs.existsSync(filePath)) return; const content = fs.readFileSync(filePath, 'utf8'); for (const line of content.split(/\r?\n/)) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith('#')) continue; const eq = trimmed.indexOf('='); if (eq === -1) continue; const key = trimmed.slice(0, eq).trim(); let value = trimmed.slice(eq + 1).trim(); if ( (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")) ) { value = value.slice(1, -1); } if (process.env[key] === undefined) process.env[key] = value; } } function pgConfigFromEnv() { const host = process.env.DB_HOST || '192.168.10.122'; const port = Number(process.env.DB_PORT || 5432); const user = process.env.DB_USER; const password = process.env.DB_PASSWORD; const database = process.env.DB_NAME; if (!user || !password || !database) { throw new Error('DB_USER, DB_PASSWORD, and DB_NAME are required'); } return { host, port, user, password, database }; } function assertProdDatabase(dbName) { if (!dbName.endsWith(PROD_DB_SUFFIX) && dbName !== PROD_DB_NAME) { throw new Error( `Refusing prod operation on database "${dbName}". ` + `Target must be "${PROD_DB_NAME}" or end with "${PROD_DB_SUFFIX}".`, ); } return dbName; } function assertDevDatabase(dbName) { if (dbName === PROD_DB_NAME || dbName.endsWith(PROD_DB_SUFFIX)) { throw new Error( `Refusing dev operation on production database "${dbName}". ` + `Use "${DEV_DB_NAME}" for development.`, ); } return dbName; } function loadDevPgConfig() { loadEnvFile(path.join(rootDir, '.env')); const config = pgConfigFromEnv(); assertDevDatabase(config.database); return config; } function loadProdPgConfig() { loadEnvFile(path.join(rootDir, 'infra', 'docker', '.env.prod')); const config = pgConfigFromEnv(); assertProdDatabase(config.database); return config; } async function confirmProdAction(message) { if (process.env.CONFIRM_PROD === '1') return; const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const answer = await new Promise((resolve) => { rl.question(`${message}\nType "yes" to continue: `, resolve); }); rl.close(); if (answer.trim().toLowerCase() !== 'yes') { throw new Error('Aborted.'); } } module.exports = { PROD_DB_SUFFIX, DEV_DB_NAME, PROD_DB_NAME, LEGACY_DB_NAMES, rootDir, loadEnvFile, pgConfigFromEnv, assertProdDatabase, assertDevDatabase, loadDevPgConfig, loadProdPgConfig, confirmProdAction, };