← back to Interiordesignershowroom
scripts/fix-dangling-scenes.js
71 lines
#!/usr/bin/env node
// Fix dangling scene_image references — sets scene_image=NULL for rows where
// the file no longer exists on disk. Safe: the server already gracefully falls
// back to product thumbs when scene_image is NULL.
// Run locally: node ids-fix-dangling-scenes.js [--apply]
// Run on prod: SSH to Kamatera, copy this file, run with --apply
const { Pool } = require('pg');
const fs = require('fs');
const path = require('path');
const APPLY = process.argv.includes('--apply');
const PUBLIC_DIR = path.join(__dirname, '..', 'public'); // on prod: /root/Projects/interiordesignershowroom/public
const pool = new Pool({
connectionString: process.env.DATABASE_URL || 'postgresql://localhost:5432/idshowroom',
});
async function main() {
const client = await pool.connect();
try {
const { rows } = await client.query(
`SELECT id, slug, scene_image FROM rooms WHERE scene_image IS NOT NULL ORDER BY id`
);
console.log(`Found ${rows.length} rooms with scene_image set.`);
const dangling = [];
for (const row of rows) {
const imgPath = path.join(PUBLIC_DIR, row.scene_image);
if (!fs.existsSync(imgPath)) {
dangling.push(row);
console.log(`MISSING: /room/${row.slug} → ${row.scene_image}`);
} else {
console.log(`OK: /room/${row.slug} → ${row.scene_image}`);
}
}
console.log(`\nTotal dangling: ${dangling.length}/${rows.length}`);
if (dangling.length === 0) {
console.log('Nothing to fix — all scene_image files exist.');
return;
}
if (!APPLY) {
console.log('\nDRY RUN — pass --apply to NULL out dangling references.');
console.log('Nulling these would let the server fall back to product thumbs (graceful-degrade).');
return;
}
await client.query('BEGIN');
const ids = dangling.map(r => r.id);
const { rowCount } = await client.query(
`UPDATE rooms SET scene_image = NULL WHERE id = ANY($1::int[])`,
[ids]
);
await client.query('COMMIT');
console.log(`\nApplied: NULLed scene_image on ${rowCount} rows.`);
console.log('These rooms now show product thumbs as their hero (graceful-degrade is live).');
} catch (e) {
await client.query('ROLLBACK').catch(() => {});
console.error('Error:', e.message);
process.exit(1);
} finally {
client.release();
await pool.end();
}
}
main();