/** * Clone gallery_prod → gallery_dev (PostgreSQL TEMPLATE). * Requires superuser or CREATEDB on the Postgres host. */ const path = require('path'); const { execFileSync } = require('child_process'); const pg = require('pg'); const { DEV_DB_NAME, PROD_DB_NAME, loadProdPgConfig, rootDir, } = require('./db-env'); const { Client } = pg; function quoteIdent(ident) { return `"${ident.replace(/"/g, '""')}"`; } async function main() { const prodConfig = loadProdPgConfig(); const { host, port, user, password } = prodConfig; const admin = new Client({ host, port, user, password, database: 'postgres' }); await admin.connect(); console.log(`Terminating connections to "${DEV_DB_NAME}"...`); await admin.query( `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`, [DEV_DB_NAME], ); const exists = await admin.query( 'SELECT 1 FROM pg_database WHERE datname = $1', [DEV_DB_NAME], ); if (exists.rowCount > 0) { console.log(`Dropping "${DEV_DB_NAME}"...`); await admin.query(`DROP DATABASE ${quoteIdent(DEV_DB_NAME)}`); } console.log(`Terminating connections to "${PROD_DB_NAME}"...`); await admin.query( `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`, [PROD_DB_NAME], ); console.log(`Cloning "${PROD_DB_NAME}" → "${DEV_DB_NAME}" (TEMPLATE)...`); await admin.query( `CREATE DATABASE ${quoteIdent(DEV_DB_NAME)} WITH TEMPLATE ${quoteIdent(PROD_DB_NAME)} OWNER ${quoteIdent(user)}`, ); await admin.end(); const verify = new Client({ host, port, user, password, database: DEV_DB_NAME }); await verify.connect(); const tables = await verify.query( `SELECT count(*)::int AS n FROM information_schema.tables WHERE table_schema = 'public' AND table_type = 'BASE TABLE'`, ); const paintings = await verify.query('SELECT count(*)::int AS n FROM paintings'); await verify.end(); console.log(`Done. "${DEV_DB_NAME}" is a copy of "${PROD_DB_NAME}" (${tables.rows[0].n} tables, ${paintings.rows[0].n} paintings).`); console.log('Syncing image files from production...'); execFileSync('powershell', ['-NoProfile', '-File', path.join(rootDir, 'infra', 'scripts', 'sync-images-from-prod.ps1'), '-SkipConfirm'], { cwd: rootDir, stdio: 'inherit', }); } main().catch((error) => { console.error(error); process.exit(1); });