#!/usr/bin/env node /** * FreightDesk Seed Script * Reads supabase/seed_data.json and inserts into Supabase * Also runs the schema migrations */ require('dotenv').config(); const { createClient } = require('@supabase/supabase-js'); const fs = require('fs'); const path = require('path'); const supabaseUrl = process.env.SUPABASE_URL; const supabaseKey = process.env.SUPABASE_SERVICE_KEY || process.env.SUPABASE_KEY; if (!supabaseUrl || !supabaseKey) { console.error('Missing SUPABASE_URL or SUPABASE_KEY in .env'); process.exit(1); } const supabase = createClient(supabaseUrl, supabaseKey); async function runMigrations() { const migrationsDir = path.join(__dirname, '..', 'supabase', 'migrations'); const files = fs.readdirSync(migrationsDir).filter(f => f.endsWith('.sql')).sort(); for (const file of files) { if (file.includes('seed')) continue; // Skip seed placeholder console.log(`Running migration: ${file}`); const sql = fs.readFileSync(path.join(migrationsDir, file), 'utf8'); // Split by semicolons and execute each statement const statements = sql.split(';').filter(s => s.trim() && !s.trim().startsWith('--')); for (const stmt of statements) { if (stmt.trim()) { const { error } = await supabase.rpc('exec_sql', { sql: stmt.trim() }); if (error && !error.message.includes('already exists')) { console.warn(` Warning: ${error.message}`); } } } console.log(` Done.`); } } async function seedData() { const seedFile = path.join(__dirname, '..', 'supabase', 'seed_data.json'); if (!fs.existsSync(seedFile)) { console.log('No seed_data.json found, skipping seed.'); return; } const seed = JSON.parse(fs.readFileSync(seedFile, 'utf-8')); // Insert shippers if (seed.shippers && seed.shippers.length > 0) { console.log(`Inserting ${seed.shippers.length} shippers...`); const { error } = await supabase.from('shippers').upsert(seed.shippers, { onConflict: 'id' }); if (error) console.error('Shippers error:', error.message); else console.log(' Done.'); } // Insert vehicles if (seed.vehicles && seed.vehicles.length > 0) { console.log(`Inserting ${seed.vehicles.length} vehicles...`); const { error } = await supabase.from('vehicles').upsert(seed.vehicles, { onConflict: 'id' }); if (error) console.error('Vehicles error:', error.message); else console.log(' Done.'); } // Insert loads in batches if (seed.loads && seed.loads.length > 0) { console.log(`Inserting ${seed.loads.length} loads...`); const batchSize = 20; for (let i = 0; i < seed.loads.length; i += batchSize) { const batch = seed.loads.slice(i, i + batchSize); const { error } = await supabase.from('loads').upsert(batch, { onConflict: 'id' }); if (error) console.error(`Loads batch error (${i}-${i + batchSize}):`, error.message); else console.log(` Batch ${Math.floor(i / batchSize) + 1} done.`); } } // Update shipper totals console.log('Updating shipper totals...'); for (const shipper of seed.shippers) { const shipperLoads = seed.loads.filter(l => l.shipper_id === shipper.id); const totals = shipperLoads.reduce((acc, l) => ({ freight: acc.freight + (l.freight_charged || 0), commission: acc.commission + (l.commission || 0), pending: acc.pending + (l.pending_from_shipper || 0), }), { freight: 0, commission: 0, pending: 0 }); await supabase.from('shippers').update({ total_freight: totals.freight, total_commission: totals.commission, pending_amount: totals.pending, }).eq('id', shipper.id); } console.log(' Done.'); } async function main() { console.log('=== FreightDesk Seeder ===\n'); try { console.log('Step 1: Running migrations...'); // Note: For actual migration execution, use Supabase CLI or Dashboard SQL editor // This is a simplified approach - run migrations manually in Supabase SQL Editor console.log(' Please run the SQL migrations in Supabase SQL Editor first:'); console.log(' - supabase/migrations/001_initial_schema.sql\n'); console.log('Step 2: Seeding data...'); await seedData(); console.log('\n=== Seed complete! ==='); } catch (err) { console.error('Fatal error:', err); process.exit(1); } } main();