import fs from "fs"; import path from "path"; import { parse } from "csv-parse/sync"; import { pool } from "./db"; interface CsvRow { date: string; month: string; day: string; event: string; distance_km: string; } function slugify(text: string): string { return text .toLowerCase() .replace(/[«»"]/g, "") .replace(/[^a-zа-яё0-9]+/gi, "-") .replace(/(^-|-$)/g, "") .substring(0, 60); } function makeId(date: string, title: string): string { return `${date}-${slugify(title)}`; } async function seed() { const csvPath = path.resolve(__dirname, "../../import/races_2026_calendar.csv"); if (!fs.existsSync(csvPath)) { console.error(`[seed] CSV not found: ${csvPath}`); process.exit(1); } const raw = fs.readFileSync(csvPath, "utf-8"); const records: CsvRow[] = parse(raw, { columns: true, skip_empty_lines: true, trim: true, }); console.log(`[seed] Parsed ${records.length} rows from CSV`); const client = await pool.connect(); try { for (const row of records) { const id = makeId(row.date, row.event); const distanceKm = parseFloat(row.distance_km); await client.query( `INSERT INTO races (id, race_date, title, distance_km, status) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (id) DO UPDATE SET race_date = EXCLUDED.race_date, title = EXCLUDED.title, distance_km = EXCLUDED.distance_km, status = EXCLUDED.status, updated_at = NOW()`, [id, row.date, row.event, distanceKm, "planned"], ); console.log(`[seed] Upserted: ${id}`); } console.log("[seed] Done."); } finally { client.release(); await pool.end(); } } seed().catch((err) => { console.error("[seed] FAILED:", err.message); process.exit(1); });