/** * One-shot bulk action: drop the seed demo KCN rows and publish every * OSM-imported KCN to the public catalog. * * Usage: * NODE_OPTIONS="-r dotenv/config" DOTENV_CONFIG_PATH=.env \ * pnpm tsx scripts/promote-all-osm.ts [--dry-run] [--keep-manual] * * Flags: * --dry-run Show what would change, don't write. * --keep-manual Skip the seed-row deletion step (only promote OSM). * * What it does: * 1. Optionally `DELETE FROM IndustrialPark WHERE dataSource = 'MANUAL'` * (cascade drops any IndustrialListing rows pointing at them via FK). * 2. `UPDATE IndustrialPark SET dataSource = 'OSM_PROMOTED', isPublic = true * WHERE dataSource = 'OSM'` — every row goes public in one shot. * * Safe to re-run: idempotent on the OSM side (already-promoted rows are * skipped by the WHERE clause). Manual deletion is also safe — once they're * gone, subsequent runs find nothing to delete. */ import 'dotenv/config'; import { PrismaPg } from '@prisma/adapter-pg'; import { PrismaClient } from '@prisma/client'; import pg from 'pg'; const pool = new pg.Pool({ connectionString: process.env['DATABASE_URL'] }); const adapter = new PrismaPg(pool); const prisma = new PrismaClient({ adapter }); const dryRun = process.argv.includes('--dry-run'); const keepManual = process.argv.includes('--keep-manual'); async function main(): Promise { // ── Pre-flight counts ───────────────────────────────────────────── const [{ count: manualCount }] = await prisma.$queryRawUnsafe< [{ count: bigint }] >(`SELECT COUNT(*)::bigint AS count FROM "IndustrialPark" WHERE "dataSource" = 'MANUAL'`); const [{ count: osmCount }] = await prisma.$queryRawUnsafe<[{ count: bigint }]>( `SELECT COUNT(*)::bigint AS count FROM "IndustrialPark" WHERE "dataSource" = 'OSM'`, ); const [{ count: promotedCount }] = await prisma.$queryRawUnsafe< [{ count: bigint }] >( `SELECT COUNT(*)::bigint AS count FROM "IndustrialPark" WHERE "dataSource" = 'OSM_PROMOTED'`, ); console.log('📊 Current catalog:'); console.log(` MANUAL ${manualCount}`); console.log(` OSM ${osmCount}`); console.log(` OSM_PROMOTED ${promotedCount}`); console.log(''); // ── Listings on MANUAL rows that will be cascaded out ───────────── if (!keepManual && manualCount > 0n) { const [{ count: listingCount }] = await prisma.$queryRawUnsafe< [{ count: bigint }] >( `SELECT COUNT(*)::bigint AS count FROM "IndustrialListing" l JOIN "IndustrialPark" p ON p.id = l."parkId" WHERE p."dataSource" = 'MANUAL'`, ); if (listingCount > 0n) { console.log( `⚠ Will cascade-delete ${listingCount} listings attached to MANUAL parks.`, ); } } if (dryRun) { console.log('💡 --dry-run: no writes performed.'); return; } // ── 1. Drop demo seed rows (cascade FK = listings removed too) ─── if (!keepManual && manualCount > 0n) { console.log('🗑 Deleting MANUAL (demo seed) rows…'); const result = await prisma.$executeRawUnsafe( `DELETE FROM "IndustrialPark" WHERE "dataSource" = 'MANUAL'`, ); console.log(` → ${result} rows removed.`); } // ── 2. Promote every OSM row in one shot ───────────────────────── if (osmCount > 0n) { console.log('🚀 Promoting all OSM rows → OSM_PROMOTED + isPublic=true…'); const result = await prisma.$executeRawUnsafe( `UPDATE "IndustrialPark" SET "dataSource" = 'OSM_PROMOTED', "isPublic" = true, "updatedAt" = NOW() WHERE "dataSource" = 'OSM'`, ); console.log(` → ${result} rows promoted.`); } else { console.log('✓ No OSM raw rows to promote.'); } // ── Final counts ───────────────────────────────────────────────── const [{ count: finalManual }] = await prisma.$queryRawUnsafe< [{ count: bigint }] >(`SELECT COUNT(*)::bigint AS count FROM "IndustrialPark" WHERE "dataSource" = 'MANUAL'`); const [{ count: finalOsm }] = await prisma.$queryRawUnsafe<[{ count: bigint }]>( `SELECT COUNT(*)::bigint AS count FROM "IndustrialPark" WHERE "dataSource" = 'OSM'`, ); const [{ count: finalPromoted }] = await prisma.$queryRawUnsafe< [{ count: bigint }] >( `SELECT COUNT(*)::bigint AS count FROM "IndustrialPark" WHERE "dataSource" = 'OSM_PROMOTED'`, ); console.log(''); console.log('📊 Final catalog:'); console.log(` MANUAL ${finalManual}`); console.log(` OSM ${finalOsm}`); console.log(` OSM_PROMOTED ${finalPromoted}`); } main() .catch((err) => { console.error(err); process.exitCode = 1; }) .finally(async () => { await prisma.$disconnect(); await pool.end(); });