/** * One-shot: load the 117-berth NocoDB snapshot into the port-nimara * port, skipping any moorings that already exist. * * The original seed only seeded 12 hand-rolled berths into port-nimara * (A-01..D-03), but the migration's interest rows reference moorings * across A-01..E-18. This loads the full set so interest→berth links * resolve cleanly on the next migration run. */ import 'dotenv/config'; import { eq, and, sql, inArray } from 'drizzle-orm'; import { db } from '@/lib/db'; import { ports } from '@/lib/db/schema/ports'; import { berths } from '@/lib/db/schema/berths'; import berthSnapshot from '@/lib/db/seed-data/berths.json'; interface SnapshotBerth { mooringNumber: string; area: string; status: 'available' | 'under_offer' | 'sold'; lengthFt: number | null; widthFt: number | null; draftFt: number | null; lengthM: number | null; widthM: number | null; draftM: number | null; widthIsMinimum: boolean; nominalBoatSize: number | null; nominalBoatSizeM: number | null; waterDepth: number | null; waterDepthM: number | null; waterDepthIsMinimum: boolean; sidePontoon: string | null; powerCapacity: number | null; voltage: number | null; mooringType: string | null; cleatType: string | null; cleatCapacity: string | null; bollardType: string | null; bollardCapacity: string | null; access: string | null; price: number | null; bowFacing: string | null; berthApproved: boolean; statusOverrideMode: string | null; } async function main() { const [port] = await db .select({ id: ports.id }) .from(ports) .where(eq(ports.slug, 'port-nimara')) .limit(1); if (!port) throw new Error('port-nimara not found'); const snapshot = berthSnapshot as unknown as SnapshotBerth[]; // Existing moorings — skip these. const existingRows = await db .select({ mooringNumber: berths.mooringNumber }) .from(berths) .where(eq(berths.portId, port.id)); const existingMoorings = new Set(existingRows.map((r) => r.mooringNumber)); const toInsert = snapshot.filter((b) => !existingMoorings.has(b.mooringNumber)); console.log( `Snapshot: ${snapshot.length} berths, existing in port-nimara: ${existingRows.length}, to insert: ${toInsert.length}`, ); if (toInsert.length === 0) { console.log('Nothing to do.'); return; } const inserted = await db .insert(berths) .values( toInsert.map((b) => ({ portId: port.id, mooringNumber: b.mooringNumber, area: b.area, status: b.status, lengthFt: b.lengthFt != null ? String(b.lengthFt) : null, widthFt: b.widthFt != null ? String(b.widthFt) : null, draftFt: b.draftFt != null ? String(b.draftFt) : null, lengthM: b.lengthM != null ? String(b.lengthM) : null, widthM: b.widthM != null ? String(b.widthM) : null, draftM: b.draftM != null ? String(b.draftM) : null, widthIsMinimum: b.widthIsMinimum, nominalBoatSize: b.nominalBoatSize != null ? String(b.nominalBoatSize) : null, nominalBoatSizeM: b.nominalBoatSizeM != null ? String(b.nominalBoatSizeM) : null, waterDepth: b.waterDepth != null ? String(b.waterDepth) : null, waterDepthM: b.waterDepthM != null ? String(b.waterDepthM) : null, waterDepthIsMinimum: b.waterDepthIsMinimum, sidePontoon: b.sidePontoon, powerCapacity: b.powerCapacity != null ? String(b.powerCapacity) : null, voltage: b.voltage != null ? String(b.voltage) : null, mooringType: b.mooringType, cleatType: b.cleatType, cleatCapacity: b.cleatCapacity, bollardType: b.bollardType, bollardCapacity: b.bollardCapacity, access: b.access, price: b.price != null ? String(b.price) : null, priceCurrency: 'USD', bowFacing: b.bowFacing, berthApproved: b.berthApproved, statusOverrideMode: b.statusOverrideMode, tenureType: 'permanent' as const, })), ) .returning({ id: berths.id, mooringNumber: berths.mooringNumber }); console.log(`Inserted ${inserted.length} berths.`); // Suppress unused-import warning if eslint is strict. void and; void sql; void inArray; } main().catch((e) => { console.error(e); process.exit(1); });