index.ts
1 #!/usr/bin/env node 2 3 import { Command } from 'commander'; 4 import * as dotenv from 'dotenv'; 5 import { CSVParser } from './csv-parser'; 6 import { GoogleMapsResolver } from './google-maps-resolver'; 7 import { KMLGenerator } from './kml-generator'; 8 9 // Load environment variables 10 dotenv.config(); 11 12 const program = new Command(); 13 14 program 15 .name('csv2kml') 16 .description('Convert Google Maps CSV exports to KML format for Organic Maps') 17 .version('1.0.0'); 18 19 program 20 .command('convert') 21 .description('Convert CSV files to KML format') 22 .option('-i, --input <directory>', 'Input directory containing CSV files', './csv') 23 .option('-o, --output <directory>', 'Output directory for KML files', './output') 24 .option('-f, --file <filename>', 'Convert specific CSV file only') 25 .action(async (options) => { 26 const apiKey = process.env.GOOGLE_MAPS_API_KEY; 27 28 if (!apiKey) { 29 console.error('Error: GOOGLE_MAPS_API_KEY environment variable is required'); 30 console.error('Please add your Google Maps API key to the .env file'); 31 process.exit(1); 32 } 33 34 try { 35 console.log('Starting CSV to KML conversion...'); 36 37 const csvParser = new CSVParser(options.input); 38 const mapsResolver = new GoogleMapsResolver(apiKey); 39 const kmlGenerator = new KMLGenerator(options.output); 40 41 let placesMap: Map<string, any[]>; 42 43 if (options.file) { 44 // Convert specific file 45 console.log(`Converting file: ${options.file}`); 46 const places = await csvParser.parseCSVFile(options.file); 47 placesMap = new Map([[options.file, places]]); 48 } else { 49 // Convert all files 50 console.log(`Reading CSV files from: ${options.input}`); 51 placesMap = await csvParser.parseAllCSVFiles(); 52 } 53 54 if (placesMap.size === 0) { 55 console.log('No CSV files found to process'); 56 return; 57 } 58 59 // Process each CSV file 60 for (const [filename, places] of placesMap.entries()) { 61 console.log(`\\nProcessing ${filename}...`); 62 console.log(`Resolving coordinates for ${places.length} places...`); 63 64 // Resolve coordinates using Google Maps API 65 const placesWithCoords = await mapsResolver.resolveAllCoordinates(places); 66 67 // Update the map with resolved coordinates 68 placesMap.set(filename, placesWithCoords); 69 70 const validPlaces = placesWithCoords.filter(place => place.latitude && place.longitude); 71 console.log(`Successfully resolved ${validPlaces.length}/${places.length} places`); 72 } 73 74 // Generate KML files 75 console.log('\\nGenerating KML files...'); 76 const generatedFiles = await kmlGenerator.generateAllKMLFiles(placesMap); 77 78 console.log('\\nā Conversion completed!'); 79 console.log(`Generated ${generatedFiles.length} KML files:`); 80 generatedFiles.forEach(file => console.log(` - ${file}`)); 81 82 } catch (error) { 83 console.error('ā Error during conversion:', error); 84 process.exit(1); 85 } 86 }); 87 88 program 89 .command('list') 90 .description('List available CSV files') 91 .option('-i, --input <directory>', 'Input directory containing CSV files', './csv') 92 .action(async (options) => { 93 try { 94 const csvParser = new CSVParser(options.input); 95 const files = await csvParser.getAllCSVFiles(); 96 97 if (files.length === 0) { 98 console.log(`No CSV files found in ${options.input}`); 99 } else { 100 console.log(`Found ${files.length} CSV files in ${options.input}:`); 101 files.forEach(file => console.log(` - ${file}`)); 102 } 103 } catch (error) { 104 console.error('Error listing files:', error); 105 process.exit(1); 106 } 107 }); 108 109 // Show help if no command provided 110 if (process.argv.length <= 2) { 111 program.help(); 112 } 113 114 program.parse();